From 6709726208c49df64eb3e16eb4e9079cbee96f35 Mon Sep 17 00:00:00 2001 From: Thomas Fransolet Date: Wed, 9 Sep 2026 16:47:27 +0200 Subject: [PATCH] Splash, loader et mode hors ligne : ce qui etait invisible le reste MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le fil rouge de ces corrections : des replis silencieux. Une exception rattrapee, une image absente, un fichier local jamais rattache — rien ne plantait, mais rien ne marchait non plus, et aucun message ne le disait. Splash et loader - assets/splash et assets/loader ne contenaient que des PNG 1x1 transparents. errorBuilder ne se declenche pas : le fichier est valide, juste vide. Logo et loader etaient donc invisibles PARTOUT, splash comme ecrans de chargement. assets/loader est supprime, kLoaderAsset avec. - Le splash natif etait blanc (launch_background en @android:color/white, theme Light) puis l'app basculait en sombre. Fond unifie sur #111111, cote natif comme Dart, avec values-v31 : Android 12+ ignore windowBackground et repart sur le theme sans ces attributs. - Le loader et l'image principale viennent maintenant du manager (Applications -> Mobile). InstanceImages les garde sur le device : le splash s'affiche avant tout appel API, il ne peut lire qu'un cache. Alimente au boot depuis instanceGetDetail, qui porte deja les ApplicationInstances — aucun appel supplementaire. - Ouvrir une section montrait une page blanche avec un loader au milieu. SlideFromRightRoute devient non opaque et SectionPage garde un fond transparent tant que la section n'est pas prete : le visiteur garde sous les yeux l'ecran d'ou il vient. Hors ligne - L'audio d'un article ne repartait jamais du MP3 local : audioFile n'etait jamais renseigne, le lecteur retombait toujours sur l'URL. - L'image de titre d'un article passait par NetworkImage, donc une croix rouge des que le reseau manque, alors que le fichier est sur le device. - L'accueil ne gardait en base que order/gridSpan : une visite jamais telechargee disparaissait de la grille hors ligne. La visite entiere est desormais mise en cache, et une visite injoignable reste affichee, ternie et non ouvrable, plutot qu'absente. - L'etat reseau datait du premier chargement et n'etait jamais remesure. WidgetsBindingObserver etait declare mais jamais enregistre : aucun rappel n'arrivait. L'accueil se recharge au retour dans l'app et remesure avant de refuser l'ouverture d'une visite. Divers - Le futur de getSectionDetail etait construit dans future:, donc relance a chaque rebuild — chaque rotation d'ecran refaisait l'appel reseau. - ImageCustomProvider listait le repertoire d'une visite non telechargee : exception a chaque construction de chaque image, pour finir de toute facon sur le reseau. - Scanner un QR d'une autre visite empilait les ConfigurationPage. pushAndRemoveUntil : une visite est une destination de premier niveau. - Le scanner arrive sur l'accueil, en pastille de verre comme les autres actions de cet ecran. ScannerBouton prend size et transparent, et garde son apparence d'origine ailleurs. - Le titre d'un article n'etait pas centre : customStylesBuilder ne s'applique qu'aux elements, et un titre sans balise n'en a aucun. - Le lecteur audio replie ne lancait pas la lecture au premier appui, il ouvrait le panneau. Il lit, puis ouvre. En lecture auto il reste replie. - Le dialogue de telechargement faisait la hauteur de l'ecran : un Center prend toute la hauteur maximale que lui donne un AlertDialog. Co-Authored-By: Claude Opus 5 (1M context) --- .../res/drawable-v21/launch_background.xml | 10 +- .../main/res/drawable/launch_background.xml | 10 +- .../app/src/main/res/values-night/styles.xml | 2 +- .../app/src/main/res/values-v31/styles.xml | 14 + android/app/src/main/res/values/colors.xml | 5 +- android/app/src/main/res/values/styles.xml | 8 +- assets/loader/dev.png | Bin 68 -> 0 bytes assets/loader/fortsaintheribert.png | Bin 68 -> 0 bytes assets/loader/mdlf.png | Bin 68 -> 0 bytes assets/splash/dev.png | Bin 68 -> 63361 bytes assets/splash/fortsaintheribert.png | Bin 68 -> 63361 bytes assets/splash/mdlf.png | Bin 68 -> 1443 bytes ios/Runner/Base.lproj/LaunchScreen.storyboard | 2 +- lib/Components/ScannerBouton.dart | 28 +- lib/Components/ScannerDialog.dart | 10 +- lib/Components/SlideFromRouteRight.dart | 6 + lib/Components/loading_common.dart | 183 +++++++------ lib/Helpers/ImageCustomProvider.dart | 6 + lib/Helpers/instanceImages.dart | 105 ++++++++ .../ConfigurationPage/configuration_page.dart | 12 +- lib/Screens/Home/home_3.0.dart | 253 ++++++++++++++---- .../Sections/Article/article_page.dart | 32 ++- .../Sections/Article/audio_player_tab.dart | 17 +- lib/Screens/section_page.dart | 62 +++-- lib/Screens/splash_screen.dart | 95 +++---- lib/Services/downloadConfiguration.dart | 31 ++- lib/constants.dart | 11 +- lib/main.dart | 18 ++ pubspec.lock | 2 +- pubspec.yaml | 4 +- 30 files changed, 653 insertions(+), 273 deletions(-) create mode 100644 android/app/src/main/res/values-v31/styles.xml delete mode 100644 assets/loader/dev.png delete mode 100644 assets/loader/fortsaintheribert.png delete mode 100644 assets/loader/mdlf.png create mode 100644 lib/Helpers/instanceImages.dart diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..cddc370 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,12 +1,10 @@ - - + - - + android:src="@mipmap/ic_launcher" /> + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..cddc370 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,12 +1,10 @@ - - + - - + android:src="@mipmap/ic_launcher" /> + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..5f1c793 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -13,6 +13,6 @@ This Theme is only used starting with V2 of Flutter's Android embedding. --> diff --git a/android/app/src/main/res/values-v31/styles.xml b/android/app/src/main/res/values-v31/styles.xml new file mode 100644 index 0000000..ba7289e --- /dev/null +++ b/android/app/src/main/res/values-v31/styles.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml index 9d8361e..5a7a063 100644 --- a/android/app/src/main/res/values/colors.xml +++ b/android/app/src/main/res/values/colors.xml @@ -1,4 +1,7 @@ #FF8535 - \ No newline at end of file + + #111111 + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..7984f3b 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -1,7 +1,7 @@ - diff --git a/assets/loader/dev.png b/assets/loader/dev.png deleted file mode 100644 index 35a340b6565bfc92ef9d53ef01e30267f65d4ec2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 68 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 literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k8}blZci7-kcv6U2@FgO46F={RdK8B Pfx--)u6{1-oD!M - + diff --git a/lib/Components/ScannerBouton.dart b/lib/Components/ScannerBouton.dart index dee65ff..f7ee14f 100644 --- a/lib/Components/ScannerBouton.dart +++ b/lib/Components/ScannerBouton.dart @@ -1,14 +1,28 @@ import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/GlassPill.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'ScannerDialog.dart'; class ScannerBouton extends StatefulWidget { - const ScannerBouton({Key? key, required this.appContext}) : super(key: key); + const ScannerBouton({ + Key? key, + required this.appContext, + this.size = 85.0, + this.transparent = false, + }) : super(key: key); final AppContext appContext; + /// Diametre du bouton. 85 dans une visite, plus petit sur l'accueil ou il + /// cohabite avec les autres pastilles. + final double size; + + /// Pastille en verre depoli plutot que disque plein, pour se poser sur le + /// contenu de l'accueil sans le masquer. + final bool transparent; + @override State createState() => _ScannerBoutonState(); } @@ -23,6 +37,12 @@ class _ScannerBoutonState extends State { @override Widget build(BuildContext context) { + final icon = Icon(Icons.qr_code_scanner, color: Colors.white, size: widget.size * 0.47); + + if (widget.transparent) { + return GlassPill(size: widget.size, onTap: _onItemTapped, child: icon); + } + return InkWell( onTap: _onItemTapped, child: Container( @@ -37,9 +57,9 @@ class _ScannerBoutonState extends State { ) ], ), - height: 85.0, - width: 85.0, - child: const Icon(Icons.qr_code_scanner, color: Colors.white, size: 40), + height: widget.size, + width: widget.size, + child: icon, ), ); } diff --git a/lib/Components/ScannerDialog.dart b/lib/Components/ScannerDialog.dart index c744a64..fce876e 100644 --- a/lib/Components/ScannerDialog.dart +++ b/lib/Components/ScannerDialog.dart @@ -235,7 +235,14 @@ class _ScannerDialogState extends State { visitAppContext.configuration = other; visitAppContext.sectionIds = null; widget.appContext!.setContext(visitAppContext); - navigator.push( + // `pushAndRemoveUntil` jusqu'à l'accueil, et non `push` : une visite + // est une destination de premier niveau, pas quelque chose qui + // s'empile. En scannant des QR de trois visites différentes, le + // visiteur se retrouvait avec trois ConfigurationPage superposées et + // autant de retours à faire pour revenir à l'accueil — en gardant en + // mémoire des visites qu'il a quittées. Ici la pile reste + // « accueil → visite en cours ». + navigator.pushAndRemoveUntil( SlideFromRightRoute( page: ConfigurationPage( configuration: other, @@ -243,6 +250,7 @@ class _ScannerDialogState extends State { openSectionId: sectionId, ), ), + (route) => route.isFirst, ); }, child: Text(TranslationHelper.getFromLocale('open', visitAppContext)), diff --git a/lib/Components/SlideFromRouteRight.dart b/lib/Components/SlideFromRouteRight.dart index 79b3813..d5b06fa 100644 --- a/lib/Components/SlideFromRouteRight.dart +++ b/lib/Components/SlideFromRouteRight.dart @@ -5,6 +5,12 @@ class SlideFromRightRoute extends PageRouteBuilder { SlideFromRightRoute({required this.page}) : super( + // Non opaque : l'écran d'où vient le visiteur continue d'être peint sous + // celui-ci. C'est ce qui permet à une page encore en chargement de se + // présenter comme un voile par-dessus ce qu'il regardait, au lieu d'une + // page blanche avec un loader au milieu. Dès que la page est prête, elle + // peint son propre fond et recouvre tout. + opaque: false, pageBuilder: (context, animation, secondaryAnimation) => page, transitionsBuilder: (context, animation, secondaryAnimation, child) { const begin = Offset(1.0, 0.0); // départ à droite (hors écran) diff --git a/lib/Components/loading_common.dart b/lib/Components/loading_common.dart index d3315ea..7f65047 100644 --- a/lib/Components/loading_common.dart +++ b/lib/Components/loading_common.dart @@ -2,116 +2,135 @@ import 'dart:io'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -import 'package:manager_api_new/api.dart'; +import 'package:mymuseum_visitapp/Helpers/instanceImages.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; -import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; -class LoadingCommon extends StatefulWidget { - const LoadingCommon({Key? key}) : super(key: key); +/// Le loader lui-même, sans rien savoir du contexte : le splash s'affiche avant +/// que le `Provider` n'existe et ne peut donc pas passer par `LoadingCommon`. +/// +/// L'image vient du manager (Applications → Mobile). Tant qu'elle n'est pas +/// connue, on tourne sur l'indicateur natif plutôt que sur `assets/loader/`, qui +/// ne contient que des PNG 1x1 transparents — invisibles, et `errorBuilder` ne +/// se déclenche pas puisque le fichier est valide. +class RotatingLoader extends StatefulWidget { + const RotatingLoader({Key? key, this.file, this.imageUrl, this.size, this.color}) + : super(key: key); + + final File? file; + final String? imageUrl; + final double? size; + final Color? color; @override - State createState() => _LoadingCommonState(); + State createState() => _RotatingLoaderState(); } -class _LoadingCommonState extends State with TickerProviderStateMixin { - AnimationController? _controller; - - @override - void initState() { - _controller = AnimationController( - duration: const Duration(milliseconds: 5000), - vsync: this, - )..repeat(); - super.initState(); - } +class _RotatingLoaderState extends State + with SingleTickerProviderStateMixin { + late final AnimationController _controller = AnimationController( + duration: const Duration(seconds: 3), + vsync: this, + )..repeat(); @override void dispose() { - _controller!.dispose(); + _controller.dispose(); super.dispose(); } + @override + Widget build(BuildContext context) { + final size = widget.size ?? MediaQuery.of(context).size.height * 0.1; + final color = widget.color ?? kMainColor1; + + Widget? image; + if (widget.file != null) { + image = Image.file(widget.file!, width: size, height: size, fit: BoxFit.contain); + } else if (widget.imageUrl != null) { + image = CachedNetworkImage( + imageUrl: widget.imageUrl!, + width: size, + height: size, + fit: BoxFit.contain, + progressIndicatorBuilder: (context, url, progress) => + CircularProgressIndicator(value: progress.progress, color: color), + errorWidget: (context, url, error) => CircularProgressIndicator(color: color), + ); + } + + if (image == null) { + return SizedBox( + width: size, + height: size, + child: Center(child: CircularProgressIndicator(color: color)), + ); + } + + return SizedBox( + width: size, + height: size, + child: RotationTransition(turns: _controller, child: image), + ); + } +} + +/// Loader des écrans de l'app. Ordre de préférence, celui de `visitapp-web` : +/// l'image de la visite si elle en définit une, sinon celle de l'instance mise +/// en cache au démarrage. +class LoadingCommon extends StatelessWidget { + const LoadingCommon({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { final appContext = Provider.of(context); - VisitAppContext visitAppContext = appContext.getContext(); + final VisitAppContext visitAppContext = appContext.getContext(); + final configuration = visitAppContext.configuration; - Size size = MediaQuery.of(context).size; - _controller!.forward(from: 0.0); - _controller!.addListener(() { - if (_controller!.isCompleted) { - _controller!.reverse(); - } - if(_controller!.isDismissed){ - _controller!.forward(); - } - }); + final primaryColor = configuration?.primaryColor != null + ? Color(int.parse( + configuration!.primaryColor!.split('(0x')[1].split(')')[0], + radix: 16)) + : kMainColor1; - var primaryColor = visitAppContext.configuration != null ? visitAppContext.configuration!.primaryColor != null ? new Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kMainColor1 : kMainColor1; return Center( - child: SizedBox( - height: size.height * 0.1, - child: RotationTransition( - turns: Tween(begin: 0.0, end: 3.0).animate(_controller!), - child: visitAppContext.configuration != null && visitAppContext.configuration!.loaderImageUrl != null ? - //Image.network(tabletAppContext.configuration!.loaderImageUrl!) - // TODO Replace by CustomCacheResource.. - FutureBuilder( - future: _checkIfLocalResourceExists(visitAppContext, visitAppContext.configuration!.loaderImageId!), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - // Loader ou indicateur de chargement pendant la vérification - return const CircularProgressIndicator(); - } else if (snapshot.hasError || snapshot.data == null) { - // Si la ressource locale n'existe pas ou s'il y a une erreur - print("not a local loader succck"); - return CachedNetworkImage( - imageUrl: visitAppContext.configuration!.loaderImageUrl!, - progressIndicatorBuilder: (context, url, downloadProgress) => CircularProgressIndicator(value: downloadProgress.progress, color: primaryColor), - errorWidget: (context, url, error) => const Icon(Icons.error), - ); - } else { - print("Its a local loaaader yeah"); - return Image.file( - snapshot.data!, - ); - } - }, - ) - : Image.asset( - kLoaderAsset, - width: size.height * 0.1, - height: size.height * 0.1, - fit: BoxFit.contain, - errorBuilder: (_, __, ___) => - Icon(Icons.museum_outlined, color: kMainColor2, size: size.height * 0.1), - ), - ), + child: FutureBuilder( + future: InstanceImages.restore(), + builder: (context, _) { + final localConfigLoader = configuration?.loaderImageId != null + ? _localResource(visitAppContext, configuration!.loaderImageId!) + : null; + + return RotatingLoader( + file: localConfigLoader ?? InstanceImages.loader, + imageUrl: localConfigLoader == null ? configuration?.loaderImageUrl : null, + color: primaryColor, + ); + }, ), ); } } -Future _checkIfLocalResourceExists(VisitAppContext visitAppContext, String resourceId) async { +/// Fichier déjà téléchargé pour la visite en cours, s'il existe. Lecture +/// synchrone : le répertoire est local et l'écran de chargement ne peut pas se +/// permettre une frame vide pour aller le vérifier. +File? _localResource(VisitAppContext visitAppContext, String resourceId) { try { - Directory? appDocumentsDirectory = Platform.isIOS ? await getApplicationDocumentsDirectory() : await getDownloadsDirectory(); - String localPath = appDocumentsDirectory!.path; - Directory configurationDirectory = Directory('$localPath/${visitAppContext.configuration!.id}'); - List fileList = configurationDirectory.listSync(); - - if(fileList.any((fileL) => fileL.uri.pathSegments.last.contains(resourceId))) { - File file = File(fileList.firstWhere((fileL) => fileL.uri.pathSegments.last.contains(resourceId)).path); - return file; + if (visitAppContext.localPath == null || visitAppContext.configuration?.id == null) { + return null; } - } catch(e) { - print("ERROR _checkIfLocalResourceExists CachedCustomResource"); - print(e); - } + final directory = + Directory('${visitAppContext.localPath}/${visitAppContext.configuration!.id}'); + if (!directory.existsSync()) return null; + for (final entity in directory.listSync()) { + if (entity.uri.pathSegments.last.contains(resourceId)) return File(entity.path); + } + } catch (e) { + debugPrint('[loader] ressource locale illisible : $e'); + } return null; } - - diff --git a/lib/Helpers/ImageCustomProvider.dart b/lib/Helpers/ImageCustomProvider.dart index 2d3c2bf..efcbeb4 100644 --- a/lib/Helpers/ImageCustomProvider.dart +++ b/lib/Helpers/ImageCustomProvider.dart @@ -11,6 +11,12 @@ class ImageCustomProvider { try { if(appContext.getContext().localPath != null && visitAppContext.configuration != null) { Directory configurationDirectory = Directory('${visitAppContext.localPath!}/${visitAppContext.configuration!.id!}'); + // Une visite jamais téléchargée n'a pas de répertoire : `listSync` levait + // alors une PathNotFoundException, rattrapée plus bas — à chaque + // construction de chaque image, pour finir de toute façon sur le réseau. + if (!configurationDirectory.existsSync()) { + return CachedNetworkImageProvider(imageSource); + } List fileList = configurationDirectory.listSync(); if(imageId != null && fileList.any((fileL) => fileL.uri.pathSegments.last.contains(imageId))) { diff --git a/lib/Helpers/instanceImages.dart b/lib/Helpers/instanceImages.dart new file mode 100644 index 0000000..dd47f6c --- /dev/null +++ b/lib/Helpers/instanceImages.dart @@ -0,0 +1,105 @@ +import 'dart:io'; + +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; +import 'package:path_provider/path_provider.dart'; + +/// Images définies dans le manager (Applications → Mobile) gardées sur le device. +/// +/// Elles sont réclamées avant que quoi que ce soit d'autre existe : le splash +/// s'affiche pendant le boot, donc avant le premier appel API, avant le contexte +/// et avant le `Provider`. Et hors ligne, il n'y a plus d'URL à interroger du +/// tout. Un cache fichier, relu à froid, est la seule chose qui réponde aux deux. +/// +/// Volontairement à part du répertoire d'une visite (`localPath//`) : +/// ces images appartiennent à l'instance, pas à une configuration, et doivent +/// survivre à la suppression d'une visite téléchargée. +class InstanceImages { + static const _loaderSlot = 'loader'; + static const _mainSlot = 'main'; + + /// Loader tournant des écrans de chargement et du splash. + static File? loader; + + /// Image principale de l'app, utilisée comme logo de démarrage. + static File? main; + + static Future? _restoring; + + /// Relit ce qu'un lancement précédent a mis en cache. Idempotent : le splash et + /// les écrans de chargement l'appellent sans avoir à se coordonner. + static Future restore() => _restoring ??= _restore(); + + static Future _restore() async { + loader = await _cachedFile(_loaderSlot); + main = await _cachedFile(_mainSlot); + } + + /// Aligne le cache sur ce que le manager expose aujourd'hui. Best-effort : un + /// échec réseau laisse en place l'image du lancement précédent. + static Future refresh({String? loaderUrl, String? mainImageUrl}) async { + await restore(); + loader = await _sync(_loaderSlot, loaderUrl); + main = await _sync(_mainSlot, mainImageUrl); + } + + static Future _directory() async { + try { + final base = Platform.isIOS + ? await getApplicationDocumentsDirectory() + : await getDownloadsDirectory(); + if (base == null) return null; + final dir = Directory('${base.path}/instance_images'); + if (!dir.existsSync()) dir.createSync(recursive: true); + return dir; + } catch (e) { + debugPrint('[instanceImages] répertoire indisponible : $e'); + return null; + } + } + + static Future _cachedFile(String slot) async { + final dir = await _directory(); + if (dir == null) return null; + final file = File('${dir.path}/$slot'); + return file.existsSync() ? file : null; + } + + /// L'URL source est écrite à côté du fichier : c'est elle qui dit si l'image a + /// changé dans le manager. Sans elle, il faudrait re-télécharger à chaque + /// démarrage — ou ne jamais voir un changement. + static Future _sync(String slot, String? url) async { + final dir = await _directory(); + if (dir == null) return null; + + final file = File('${dir.path}/$slot'); + final sourceFile = File('${dir.path}/$slot.url'); + + if (url == null) { + // Image retirée côté manager : le device ne doit pas continuer à servir + // l'ancienne indéfiniment. + try { + if (file.existsSync()) file.deleteSync(); + if (sourceFile.existsSync()) sourceFile.deleteSync(); + } catch (_) {} + return null; + } + + final knownSource = sourceFile.existsSync() ? sourceFile.readAsStringSync() : null; + if (file.existsSync() && knownSource == url) return file; + + try { + final response = await http.get(Uri.parse(url)).timeout(const Duration(seconds: 10)); + if (response.statusCode != 200) { + debugPrint('[instanceImages] $slot : HTTP ${response.statusCode}'); + return file.existsSync() ? file : null; + } + await file.writeAsBytes(response.bodyBytes); + await sourceFile.writeAsString(url); + return file; + } catch (e) { + debugPrint('[instanceImages] $slot non téléchargée : $e'); + return file.existsSync() ? file : null; + } + } +} diff --git a/lib/Screens/ConfigurationPage/configuration_page.dart b/lib/Screens/ConfigurationPage/configuration_page.dart index 7a398c8..f71c5db 100644 --- a/lib/Screens/ConfigurationPage/configuration_page.dart +++ b/lib/Screens/ConfigurationPage/configuration_page.dart @@ -19,6 +19,7 @@ import 'package:mymuseum_visitapp/Screens/Sections/Article/article_page.dart'; import 'package:mymuseum_visitapp/Services/pushNotificationService.dart'; import 'package:mymuseum_visitapp/Screens/Sections/Quiz/quizz_page.dart'; import 'package:mymuseum_visitapp/Screens/section_page.dart'; +import 'package:mymuseum_visitapp/Components/SlideFromRouteRight.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -301,10 +302,13 @@ class _ConfigurationPageState extends State with WidgetsBindi //visitAppContext.isArticleCurrentlyShown = true; lastTimePopUpWasClosed = DateTime.now(); + // `SlideFromRightRoute` et non `MaterialPageRoute` : elle seule + // est non opaque, donc seule elle laisse le voile de chargement + // de la section se poser sur l'ecran d'ou vient le visiteur. Navigator.push( context, - MaterialPageRoute( - builder: (context) => SectionPage( + SlideFromRightRoute( + page: SectionPage( configuration: widget.configuration, rawSection: null, visitAppContextIn: visitAppContext, @@ -364,8 +368,8 @@ class _ConfigurationPageState extends State with WidgetsBindi visitAppContext: visitAppContext, configurationId: widget.configuration.id, onNavigateToSection: (sectionId, sectionTitle) { - Navigator.push(context, MaterialPageRoute( - builder: (_) => SectionPage( + Navigator.push(context, SlideFromRightRoute( + page: SectionPage( configuration: widget.configuration, rawSection: null, visitAppContextIn: visitAppContext, diff --git a/lib/Screens/Home/home_3.0.dart b/lib/Screens/Home/home_3.0.dart index f0309f4..580cb1b 100644 --- a/lib/Screens/Home/home_3.0.dart +++ b/lib/Screens/Home/home_3.0.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/services.dart'; @@ -17,6 +18,7 @@ import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; import 'package:mymuseum_visitapp/Services/pushNotificationService.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Helpers/instanceImages.dart'; import 'package:mymuseum_visitapp/Helpers/modelsHelper.dart'; import 'package:mymuseum_visitapp/Helpers/networkCheck.dart'; import 'package:mymuseum_visitapp/Helpers/requirement_state_controller.dart'; @@ -76,6 +78,11 @@ class _HomePage3State extends State with WidgetsBindingObserver { /// visite pour cacher `order`/`gridSpan`, donc « la ligne existe » ne veut /// pas dire « le contenu est là ». Set downloadedConfigIds = {}; + + /// État réseau au dernier chargement de l'accueil. Une visite non téléchargée + /// n'a rien à montrer sans réseau : elle reste affichée — titre et image sont + /// en cache — mais ternie et non ouvrable, plutôt que disparue de la grille. + bool isOnline = true; late VisitAppContext visitAppContext; late Future?> _futureConfigurations; @@ -84,10 +91,39 @@ class _HomePage3State extends State with WidgetsBindingObserver { void initState() { SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); super.initState(); + // `WidgetsBindingObserver` était déclaré mais jamais enregistré : aucun des + // rappels de cycle de vie n'arrivait. + WidgetsBinding.instance.addObserver(this); final appContext = Provider.of(context, listen: false); _futureConfigurations = getConfigurationsCall(appContext); } + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // Le visiteur qui coupe le mode avion ou rejoint le wifi du site revient dans + // l'app par là. Sans ce rappel, l'accueil gardait l'état réseau de son premier + // chargement : tuiles ternies et visites refusées alors que le réseau est revenu. + if (state == AppLifecycleState.resumed) _reloadIfNetworkChanged(); + } + + /// Reteste le réseau et, s'il a changé, relance le chargement de l'accueil — + /// images et titres compris, qui viennent du même appel. + Future _reloadIfNetworkChanged() async { + final online = await hasNetwork(); + if (!mounted || online == isOnline) return; + setState(() { + isOnline = online; + _futureConfigurations = getConfigurationsCall( + Provider.of(context, listen: false)); + }); + } + Widget _buildCard(BuildContext context, ConfigurationDTO config) { final lang = visitAppContext.language ?? "FR"; final titleEntry = config.title?.firstWhere( @@ -103,6 +139,9 @@ class _HomePage3State extends State with WidgetsBindingObserver { final isOffline = config.isOffline == true; final needsDownload = isOffline && !downloadedConfigIds.contains(config.id); + // Sans réseau, seul ce qui est sur le device s'ouvre — y compris pour une + // visite qui n'est pas en mode hors ligne. + final unreachable = !isOnline && !downloadedConfigIds.contains(config.id); return InkWell( borderRadius: BorderRadius.circular(16), @@ -124,10 +163,13 @@ class _HomePage3State extends State with WidgetsBindingObserver { offset: Offset(0, 2), ), ], + // En cache disque : une fois la vignette vue en ligne, elle + // s'affiche encore sans réseau. `NetworkImage` la re-demandait à + // chaque ouverture et rendait une croix rouge hors ligne. image: config.imageSource != null ? DecorationImage( fit: BoxFit.cover, - image: NetworkImage(config.imageSource!), + image: CachedNetworkImageProvider(config.imageSource!), ) : null, ), @@ -152,26 +194,34 @@ class _HomePage3State extends State with WidgetsBindingObserver { ), // Une visite hors ligne pas encore récupérée est volontairement // ternie : la tuile dit qu'elle n'est pas prête avant toute lecture. - if (needsDownload) + if (needsDownload || unreachable) Positioned.fill( child: DecoratedBox( decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), - color: Colors.black.withValues(alpha: 0.3), + color: Colors.black.withValues(alpha: unreachable ? 0.55 : 0.3), ), ), ), - if (isOffline) + if (isOffline || unreachable) Positioned( top: 8, right: 8, child: GlassPill( size: 32, - onTap: () => _promptDownload(context, config), + // Une visite injoignable ne se télécharge pas non plus : + // proposer l'export sans réseau n'ouvrirait qu'un échec. + onTap: () => unreachable && !isOffline + ? _showOfflineNotice(context) + : _promptDownload(context, config), child: Icon( - needsDownload ? Icons.arrow_downward_rounded : Icons.check_rounded, + unreachable && !isOffline + ? Icons.wifi_off_rounded + : needsDownload + ? Icons.arrow_downward_rounded + : Icons.check_rounded, size: 17, - color: needsDownload ? Colors.white : Colors.greenAccent, + color: needsDownload || unreachable ? Colors.white : Colors.greenAccent, ), ), ), @@ -219,10 +269,35 @@ class _HomePage3State extends State with WidgetsBindingObserver { ); } + void _showOfflineNotice(BuildContext context) { + final ctx = Provider.of(context, listen: false).getContext(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(TranslationHelper.getFromLocale("noInternet", ctx)), + backgroundColor: kMainColor2, + ), + ); + } + Future _openConfiguration(BuildContext context, ConfigurationDTO config) async { final appCtx = Provider.of(context, listen: false); final ctx = appCtx.getContext() as VisitAppContext; + // Le détail lit l'API dès qu'il n'est pas servi par la base locale : sans + // réseau ni contenu téléchargé, la visite s'ouvrirait vide. + // + // Deuxième mesure du réseau avant de refuser : la première date du chargement + // de l'accueil, et refuser sur une mesure périmée est le pire des cas — le + // visiteur voit ses barres de réseau et l'app lui dit qu'il est hors ligne. + if (!isOnline && !downloadedConfigIds.contains(config.id)) { + await _reloadIfNetworkChanged(); + if (!context.mounted) return; + if (!isOnline) { + _showOfflineNotice(context); + return; + } + } + // Une visite hors ligne non téléchargée ouvrait un détail vide : `body.dart` // lit ses sections uniquement en base locale quand `isOffline` est vrai. if (config.isOffline == true && !downloadedConfigIds.contains(config.id)) { @@ -537,19 +612,27 @@ class _HomePage3State extends State with WidgetsBindingObserver { return Scaffold( extendBody: true, + // Le fond de l'accueil, pas le blanc du theme : pendant un rechargement, + // l'ecran virait au blanc le temps de la requete. + backgroundColor: _kBackground, body: FutureBuilder( future: _futureConfigurations, builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { + // Un rechargement (retour du reseau) ne renvoie pas le visiteur sur un + // ecran vide : tant qu'on a les visites du chargement precedent, la + // grille reste affichee et se met a jour quand la reponse arrive. + if (snapshot.connectionState == ConnectionState.done || weightedConfigs.isNotEmpty) { final mobileConfigIds = visitAppContext.applicationInstanceDTO ?.configurations ?.where((c) => c.isActive == true) .map((c) => c.configurationId) .toSet() ?? {}; - weightedConfigs = List<_WeightedConfig>.from(snapshot.data) - .where((w) => mobileConfigIds.isEmpty || mobileConfigIds.contains(w.configuration.id)) - .toList(); - configurations = weightedConfigs.map((w) => w.configuration).toList(); + if (snapshot.hasData) { + weightedConfigs = List<_WeightedConfig>.from(snapshot.data) + .where((w) => mobileConfigIds.isEmpty || mobileConfigIds.contains(w.configuration.id)) + .toList(); + configurations = weightedConfigs.map((w) => w.configuration).toList(); + } final lang = visitAppContext.language ?? "FR"; final headerTitleEntry = configurations.isNotEmpty @@ -600,12 +683,36 @@ class _HomePage3State extends State with WidgetsBindingObserver { child: Stack( fit: StackFit.expand, children: [ + // Ordre : l'événement à la une s'il y en a un — il + // remplace tout l'en-tête, titre et bouton compris — + // puis l'image principale de l'app définie dans le + // manager (Applications → Mobile). L'image de la + // première visite ne reste qu'en dernier recours : + // prendre la vignette d'une visite pour bannière de + // l'app était un choix par défaut, pas une intention. + // + // Le fichier local d'abord : `InstanceImages` l'a mis + // en cache au démarrage, donc la bannière tient hors + // ligne. `Image.network` y laissait une croix rouge. if (featuredEvent?.imageSource != null) - Image.network(featuredEvent!.imageSource!, fit: BoxFit.cover) - else if (configurations.isNotEmpty && configurations[0].imageSource != null) - Image.network( - configurations[0].imageSource!, + CachedNetworkImage( + imageUrl: featuredEvent!.imageSource!, fit: BoxFit.cover, + errorWidget: (_, __, ___) => const SizedBox.shrink(), + ) + else if (InstanceImages.main != null) + Image.file(InstanceImages.main!, fit: BoxFit.cover) + else if (visitAppContext.applicationInstanceDTO?.mainImageUrl != null) + CachedNetworkImage( + imageUrl: visitAppContext.applicationInstanceDTO!.mainImageUrl!, + fit: BoxFit.cover, + errorWidget: (_, __, ___) => const SizedBox.shrink(), + ) + else if (configurations.isNotEmpty && configurations[0].imageSource != null) + CachedNetworkImage( + imageUrl: configurations[0].imageSource!, + fit: BoxFit.cover, + errorWidget: (_, __, ___) => const SizedBox.shrink(), ), // Bottom gradient for title readability const DecoratedBox( @@ -849,14 +956,60 @@ class _HomePage3State extends State with WidgetsBindingObserver { ], ), ), - if (visitAppContext.applicationInstanceDTO?.isAssistant == true) - Positioned( - bottom: 24, - right: 16, - child: FloatingActionButton( - heroTag: 'assistant_home', - backgroundColor: kMainColor1, - onPressed: () { + // Scanner et assistant empiles dans le meme coin. Le scanner est + // en bas : c'est le geste le plus frequent, donc le plus a portee + // de pouce. Depuis que le scan d'un QR d'une autre visite bascule + // proprement dessus, il n'y a plus de raison de le reserver a + // l'interieur d'une visite. + Positioned( + bottom: 20, + right: 14, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + if (visitAppContext.applicationInstanceDTO?.isAssistant == true) ...[ + _assistantButton(context), + const SizedBox(height: 12), + ], + // Meme pastille de verre que le reglage de langue et le badge + // de telechargement d'une tuile : sur l'accueil, les actions + // se posent sur le contenu, elles ne s'y superposent pas en + // disque plein. Le `Padding` recentre la pastille de 46 sous + // le bouton d'assistant, plus large de 10. + Padding( + padding: const EdgeInsets.only(right: 5), + child: ScannerBouton(appContext: appContext, size: 46, transparent: true), + ), + ], + ), + ), + ], + ); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text(TranslationHelper.getFromLocale("noData", appContext.getContext())); + } else { + return Center( + child: SizedBox( + height: size.height * 0.15, + child: const LoadingCommon(), + ), + ); + } + }, + ), + ); + } + + + /// Sorti du `build` pour que le coin bas-droit se lise comme ce qu'il est : + /// une pile de deux boutons. + Widget _assistantButton(BuildContext context) { + return FloatingActionButton( + heroTag: 'assistant_home', + backgroundColor: kMainColor1, + onPressed: () { + AssistantChatSheet.show( context, visitAppContext: visitAppContext, @@ -878,24 +1031,8 @@ class _HomePage3State extends State with WidgetsBindingObserver { } }, ); - }, - child: const Icon(Icons.chat_bubble_outline, color: Colors.white), - ), - ), - ], - ); - } else if (snapshot.connectionState == ConnectionState.none) { - return Text(TranslationHelper.getFromLocale("noData", appContext.getContext())); - } else { - return Center( - child: SizedBox( - height: size.height * 0.15, - child: const LoadingCommon(), - ), - ); - } - }, - ), + }, + child: const Icon(Icons.chat_bubble_outline, color: Colors.white), ); } @@ -919,6 +1056,7 @@ class _HomePage3State extends State with WidgetsBindingObserver { Future?> _fetchConfigurations(AppContext appContext) async { bool isOnline = await hasNetwork(); + this.isOnline = isOnline; VisitAppContext visitAppContext = appContext.getContext(); List? configurations; @@ -997,6 +1135,12 @@ class _HomePage3State extends State with WidgetsBindingObserver { final mobileInstance = instances?.where((e) => e.appType == AppType.Mobile).firstOrNull; if (mobileInstance != null) { visitAppContext.applicationInstanceDTO = mobileInstance; + // Deuxième point d'alimentation du cache d'images, avec le boot : c'est + // ici que l'ApplicationInstance est lue de façon certaine. + InstanceImages.refresh( + loaderUrl: mobileInstance.loaderImageUrl, + mainImageUrl: mobileInstance.mainImageUrl, + ); if (mobileInstance.hasStats == true) { visitAppContext.statisticsService = StatisticsService( clientAPI: visitAppContext.clientAPI, @@ -1031,29 +1175,28 @@ class _HomePage3State extends State with WidgetsBindingObserver { []; weightedConfigs.sort((a, b) => (a.order ?? 0).compareTo(b.order ?? 0)); - // Best-effort : garde order/spans en cache local pour que le rendu - // hors-ligne reste cohérent avec ce qui vient d'être vu en ligne. - // - // `update` et non `insert` : ce dernier bascule sur un INSERT quand la - // ligne n'existe pas, et ces quatre colonnes ne suffisent pas à satisfaire - // les NOT NULL de la table. Toute visite pas encore téléchargée levait donc - // « NOT NULL constraint failed: configurations.instanceId » à chaque - // démarrage. Un UPDATE sans ligne cible ne touche rien, ce qui est la - // bonne sémantique : ces spans complètent une visite en cache, ils ne la - // créent pas. + // Best-effort : garde la visite entière — titre, image, couleurs, spans — + // en cache local, et pas seulement order/spans comme avant. Hors ligne, + // la table `configurations` est la seule source de l'accueil : une visite + // jamais téléchargée en était absente et disparaissait purement de la + // grille. Elle y reste maintenant, ternie et non ouvrable, et l'image + // suit via le cache disque de `CachedNetworkImageProvider`. for (final w in weightedConfigs) { try { - await DatabaseHelper.instance.update( + await DatabaseHelper.instance.insert( DatabaseTableType.configurations, { + ...ModelsHelper.configurationToMap(w.configuration), + // Colonne NOT NULL : un `isOffline` absent du DTO ferait échouer + // l'insertion, donc perdre la visite pour l'accueil hors ligne. + DatabaseHelper.columnIsOffline: w.configuration.isOffline == true, DatabaseHelper.columnConfigOrder: w.order, DatabaseHelper.columnGridColSpan: w.colSpan, DatabaseHelper.columnGridRowSpan: w.rowSpan, }, - w.configuration.id!, ); } catch (e) { - print("Could not cache order/spans for configuration ${w.configuration.id}: $e"); + print("Could not cache configuration ${w.configuration.id}: $e"); } } diff --git a/lib/Screens/Sections/Article/article_page.dart b/lib/Screens/Sections/Article/article_page.dart index 78e53a6..4fd888f 100644 --- a/lib/Screens/Sections/Article/article_page.dart +++ b/lib/Screens/Sections/Article/article_page.dart @@ -10,6 +10,7 @@ import 'package:mymuseum_visitapp/Components/GlassPill.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Components/SliderImages.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Helpers/ImageCustomProvider.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/articleRead.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; @@ -51,6 +52,14 @@ class _ArticlePageState extends State { audioResourceModel = widget.resourcesModel.firstWhere((r) => r?.id == widget.mainAudioId, orElse: () => null); resourcesModelToShow = widget.resourcesModel.where((r) => r?.id != widget.mainAudioId).toList(); + // Le fichier local n'était jamais rattaché : `audioFile` restait null et le + // lecteur retombait toujours sur l'URL, donc plus d'audio dès que le réseau + // manque — alors que le MP3 est bien sur le device depuis le téléchargement. + final audioPath = audioResourceModel?.path; + if (audioPath != null && audioPath.isNotEmpty && File(audioPath).existsSync()) { + audioFile = File(audioPath); + } + WidgetsBinding.instance.addPostFrameCallback((_) { widget.visitAppContextIn.statisticsService?.track( VisitEventType.articleRead, @@ -102,10 +111,16 @@ class _ArticlePageState extends State { kMainColor2, ], ), + // `NetworkImage` ne connaît que l'URL : hors ligne, l'en-tête tombait + // sur une SocketException alors que l'image est sur le device. + // `ImageCustomProvider` sert le fichier local et ne repasse par le + // réseau (en cache) que s'il est absent. image: widget.articleDTO.imageSource != null ? DecorationImage( fit: BoxFit.cover, opacity: 0.65, - image: NetworkImage( + image: ImageCustomProvider.getImageProvider( + appContext, + widget.articleDTO.imageId, widget.articleDTO.imageSource!, ), ): null, @@ -139,8 +154,11 @@ class _ArticlePageState extends State { Expanded( child: Padding( padding: const EdgeInsets.symmetric(horizontal: 8), + // Le centrage passe par un `div` porteur et non par + // `customStylesBuilder` : un titre sans balise n'a pas + // d'élément à styler, il restait donc aligné à gauche. child: HtmlWidget( - cleanedTitle, + '

$cleanedTitle
', // Blanc sur photo : sans ombre portée, un titre posé sur // une zone claire de l'image devient illisible. textStyle: const TextStyle( @@ -165,12 +183,14 @@ class _ArticlePageState extends State { appContext.setContext(visitAppContext); }); }, + // 40 + 12 des deux côtés : le titre est centré sur l'écran, + // pas sur ce qui reste entre deux marges inégales. child: SizedBox( - width: 50, + width: 40, child: visitAppContext.isMaximizeTextSize ? const Icon(Icons.text_fields, size: 30, color: Colors.white) : const Icon(Icons.format_size, size: 30, color: Colors.white) ), ), - const SizedBox(width: 4), + const SizedBox(width: 12), ], ), ), @@ -249,10 +269,10 @@ class _ArticlePageState extends State { // s'étire vers la gauche par-dessus la page pour laisser régler l'écoute. // En `floatingActionButton`/`miniEndFloat`, le bouton couvrait en // permanence les dernières lignes du texte. - if (audioResourceModel != null && audioResourceModel!.source != null) + if (audioFile != null || audioResourceModel?.source != null) AudioPlayerTab( file: audioFile, - resourceURl: audioResourceModel!.source!, + resourceURl: audioResourceModel?.source, isAuto: widget.articleDTO.isReadAudioAuto!, ), ], diff --git a/lib/Screens/Sections/Article/audio_player_tab.dart b/lib/Screens/Sections/Article/audio_player_tab.dart index 45d7ee4..5d72688 100644 --- a/lib/Screens/Sections/Article/audio_player_tab.dart +++ b/lib/Screens/Sections/Article/audio_player_tab.dart @@ -14,7 +14,10 @@ class AudioPlayerTab extends StatefulWidget { const AudioPlayerTab({Key? key, required this.file, required this.resourceURl, required this.isAuto}) : super(key: key); final File? file; - final String resourceURl; + + /// Nulle quand la ressource n'est connue que par son fichier local : une visite + /// hors ligne n'a pas toujours d'URL à jour, et le lecteur ne doit pas en dépendre. + final String? resourceURl; final bool isAuto; @override @@ -137,9 +140,9 @@ class _AudioPlayerTabState extends State if(audiobytes != null) { print("GOT AUDIOBYYYTES - LOCALLY SOSO"); await player.setAudioSource(LoadedSource(audiobytes!)); - } else { + } else if (widget.resourceURl != null) { print("GET SOUND BY URL"); - await player.dynamicSet(url: widget.resourceURl); + await player.dynamicSet(url: widget.resourceURl!); } if(widget.isAuto) { @@ -150,6 +153,9 @@ class _AudioPlayerTabState extends State isplaying = true; audioplayed = true; }); + // La pastille reste repliée : en lecture auto le visiteur vient lire, pas + // régler l'écoute, et le panneau déplié couvrirait le texte d'entrée de + // jeu. Un appui l'ouvre quand il en a besoin. } }); super.initState(); @@ -256,7 +262,10 @@ class _AudioPlayerTabState extends State : IconButton( icon: Icon(isplaying ? Icons.pause : Icons.play_arrow, color: Colors.white), - onPressed: _toggleExpansion, + // Repliée, la pastille montre une icône « lecture » : le + // premier appui doit lancer le son, pas ouvrir un panneau. + // Une fois l'écoute commencée, elle donne accès aux réglages. + onPressed: isplaying || audioplayed ? _toggleExpansion : _togglePlay, ), ), ), diff --git a/lib/Screens/section_page.dart b/lib/Screens/section_page.dart index 5ef2681..9b64449 100644 --- a/lib/Screens/section_page.dart +++ b/lib/Screens/section_page.dart @@ -57,6 +57,9 @@ class _SectionPageState extends State { List>? icons; String? mainAudioId; + + /// Memorise : sans lui, `future:` reconstruisait l'appel a chaque rebuild. + Future? _sectionDetail; DateTime? _sectionOpenTime; @override @@ -96,20 +99,38 @@ class _SectionPageState extends State { var test = SectionDTO.fromJson(jsonDecode(jsonEncode(widget.rawSection))); - return Scaffold( - key: _scaffoldKey, - resizeToAvoidBottomInset: false, - body: MediaQuery.removeViewInsets( - context: context, - removeBottom: true, - child: OrientationBuilder( - builder: (context, orientation) { - return FutureBuilder( - future: getSectionDetail(appContext, visitAppContext.clientAPI, widget.sectionId), - builder: (context, AsyncSnapshot snapshot) { - var sectionResult = snapshot.data; - if(sectionDTO != null && sectionResult != null) { - switch(sectionDTO!.type) { + // Le `FutureBuilder` passe au-dessus du `Scaffold` : c'est le seul endroit + // d'où l'on sait si la section est prête, et c'est cette information qui + // décide de la couleur du fond. + // + // Le futur est aussi mémorisé ici. Il était construit dans `future:`, donc + // relancé à chaque rebuild : chaque changement d'orientation, chaque + // `setState` refaisait l'appel réseau de la section. + return FutureBuilder( + future: _sectionDetail ??= + getSectionDetail(appContext, visitAppContext.clientAPI, widget.sectionId), + builder: (context, AsyncSnapshot snapshot) { + var sectionResult = snapshot.data; + final isReady = sectionDTO != null && sectionResult != null; + + return Scaffold( + key: _scaffoldKey, + resizeToAvoidBottomInset: false, + // Transparent tant que la section n'est pas prête. Combiné à la route + // non opaque, le visiteur garde sous les yeux l'écran d'où il vient, + // assombri, avec le loader par-dessus — plutôt qu'une page blanche. + backgroundColor: isReady ? null : Colors.transparent, + body: MediaQuery.removeViewInsets( + context: context, + removeBottom: true, + child: OrientationBuilder( + builder: (context, orientation) { + // Rien d'autre que le loader : pas de voile. La page d'où vient + // le visiteur reste lisible telle quelle, le temps du chargement. + if (!isReady) { + return const Center(child: LoadingCommon()); + } + switch(sectionDTO!.type) { case SectionType.Agenda: AgendaDTO agendaDTO = AgendaDTO.fromJson(sectionResult)!; return AgendaPage(section: agendaDTO); @@ -166,14 +187,11 @@ class _SectionPageState extends State { default: return const Center(child: Text("Unsupported type")); } - } else { - return const LoadingCommon(); - } - } - ); - } - ), - ) + }, + ), + ), + ); + }, ); } diff --git a/lib/Screens/splash_screen.dart b/lib/Screens/splash_screen.dart index 25610d4..9707c20 100644 --- a/lib/Screens/splash_screen.dart +++ b/lib/Screens/splash_screen.dart @@ -1,65 +1,54 @@ import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/loading_common.dart'; +import 'package:mymuseum_visitapp/Helpers/instanceImages.dart'; import 'package:mymuseum_visitapp/constants.dart'; -class SplashScreen extends StatefulWidget { +class SplashScreen extends StatelessWidget { const SplashScreen({Key? key}) : super(key: key); - @override - State createState() => _SplashScreenState(); -} - -class _SplashScreenState extends State with SingleTickerProviderStateMixin { - late AnimationController _controller; - - @override - void initState() { - super.initState(); - _controller = AnimationController( - duration: const Duration(milliseconds: 1200), - vsync: this, - )..repeat(reverse: true); - } - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - @override Widget build(BuildContext context) { - final size = MediaQuery.of(context).size; return Scaffold( - backgroundColor: kBackgroundColor, - body: Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Image.asset( - kSplashLogoAsset, - width: 200, - height: 200, - fit: BoxFit.contain, - errorBuilder: (_, __, ___) => Icon( - Icons.museum_outlined, - size: 100, - color: kMainColor1, - ), + backgroundColor: kSplashBackground, + // Le splash s'affiche pendant le boot, avant tout appel API : il ne peut + // lire que ce qu'un lancement précédent a mis en cache. Au tout premier + // démarrage, le logo retombe donc sur l'image du flavor. + body: FutureBuilder( + future: InstanceImages.restore(), + builder: (context, _) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(32), + child: InstanceImages.main != null + ? Image.file(InstanceImages.main!, + width: 160, height: 160, fit: BoxFit.contain) + : Image.asset( + kSplashLogoAsset, + width: 160, + height: 160, + fit: BoxFit.contain, + errorBuilder: (_, __, ___) => const Icon( + Icons.museum_outlined, + size: 100, + color: kMainColor1, + ), + ), + ), + const SizedBox(height: 24), + const Text( + kAppTitle, + style: TextStyle( + color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 40), + RotatingLoader(file: InstanceImages.loader, size: 64), + ], ), - const SizedBox(height: 48), - RotationTransition( - turns: Tween(begin: 0.0, end: 3.0).animate(_controller), - child: Image.asset( - kLoaderAsset, - width: size.height * 0.07, - height: size.height * 0.07, - fit: BoxFit.contain, - errorBuilder: (_, __, ___) => - CircularProgressIndicator(color: kMainColor1), - ), - ), - ], - ), + ); + }, ), ); } diff --git a/lib/Services/downloadConfiguration.dart b/lib/Services/downloadConfiguration.dart index 56c794e..6e44e86 100644 --- a/lib/Services/downloadConfiguration.dart +++ b/lib/Services/downloadConfiguration.dart @@ -418,27 +418,26 @@ class _DownloadConfigurationWidgetState extends State { } localContext.guideVoiceId = instanceDto?.guideVoiceId; + + // Loader et image principale définis dans le manager (Applications → + // Mobile). `instanceGetDetail` porte déjà les ApplicationInstances : pas + // d'appel supplémentaire, et le cache est prêt pour le splash du + // lancement suivant. + final mobileInstance = instanceDto?.applicationInstanceDTOs + ?.where((a) => a.appType == AppType.Mobile) + .firstOrNull; + // Sans `await` : le boot n'a pas à attendre un téléchargement d'image. + // Le splash affiche ce qui est déjà en cache, et l'app le rattrape. + if (mobileInstance != null) { + InstanceImages.refresh( + loaderUrl: mobileInstance.loaderImageUrl, + mainImageUrl: mobileInstance.mainImageUrl, + ); + } } catch (e) { // Hors ligne : la voix retombe sur le repli du build, le reste de l'app tourne. print('Could not load instance detail: $e'); diff --git a/pubspec.lock b/pubspec.lock index 9dad4f0..766c8c6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -210,7 +210,7 @@ packages: source: hosted version: "8.9.2" cached_network_image: - dependency: transitive + dependency: "direct main" description: name: cached_network_image sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f" diff --git a/pubspec.yaml b/pubspec.yaml index 2235dff..def69a4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,9 @@ dependencies: provider: ^6.1.2 fluttertoast: carousel_slider: ^5.0.0 + # Utilisé directement (accueil, CachedCustomResource, ImageCustomProvider) : + # il n'était tiré que comme dépendance transitive. + cached_network_image: ^3.3.1 #flutter_svg_provider: ^1.0.3 photo_view: ^0.15.0 intl: ^0.20.2 @@ -125,7 +128,6 @@ flutter: assets: - assets/splash/ - - assets/loader/ - assets/icons/ - assets/images/ - assets/images/old/