import 'dart:convert'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Components/LanguageSelection.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/Visit/visit.dart'; import 'package:mymuseum_visitapp/Services/apiService.dart'; import 'package:mymuseum_visitapp/Services/downloadConfiguration.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; class ConfigurationsList extends StatefulWidget { const ConfigurationsList( {Key? key, required this.configurations, required this.alreadyDownloaded, required this.requestRefresh}) : super(key: key); final List configurations; final List alreadyDownloaded; final Function requestRefresh; @override State createState() => _ConfigurationsListState(); } class _ConfigurationsListState extends State { List configurations = []; List alreadyDownloaded = []; VisitAppContext? visitAppContext; bool isDialogOpen = false; @override void initState() { configurations = widget.configurations; alreadyDownloaded = widget.alreadyDownloaded; super.initState(); } @override Widget build(BuildContext context) { Size size = MediaQuery.of(context).size; final appContext = Provider.of(context); visitAppContext = appContext.getContext(); return ListView.builder( shrinkWrap: true, //I've set this as true here depending on what your listview content is //physics: NeverScrollableScrollPhysics(),//This prevents scrolling, but may inhibit refresh indicator, remove as you need itemBuilder: (BuildContext context, int index) { return InkWell( onTap: () async { VisitAppContext visitAppContext = appContext.getContext(); if (configurations[index].isOffline! && alreadyDownloaded.any((c) => c == configurations[index].id)) { if (!configurations[index] .languages! .contains(visitAppContext.language)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(TranslationHelper.getFromLocale( "languageNotSupported", appContext.getContext())), backgroundColor: kMainColor2), ); } else { // Update context visitAppContext.configuration = configurations[index]; visitAppContext.sectionIds = configurations[index].sectionIds; appContext.setContext(visitAppContext); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => VisitPage(configuration: configurations[index], isAlreadyAllowed: visitAppContext.isScanBeaconAlreadyAllowed), )); } } else { if (configurations[index].isOffline!) { // Not already downloaded ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(TranslationHelper.getFromLocale( "visitDownloadWarning", appContext.getContext())), backgroundColor: kMainColor2), ); } else { // Online mode if(!configurations[index].languages!.contains(visitAppContext.language)) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(TranslationHelper.getFromLocale( "languageNotSupported", appContext.getContext())), backgroundColor: kMainColor2), ); } else { visitAppContext.configuration = configurations[index]; visitAppContext.sectionIds = configurations[index].sectionIds; appContext.setContext(visitAppContext); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => VisitPage(configuration: configurations[index], isAlreadyAllowed: visitAppContext.isScanBeaconAlreadyAllowed), )); } } } }, child: Container( height: size.height * 0.15, decoration: boxDecoration(configurations[index], false), margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: Stack( children: [ Row( children: [ if (configurations[index].imageId != null) Container( padding: const EdgeInsets.symmetric(horizontal: 0), height: 136, // image is square but we add extra 20 + 20 padding thats why width is 200 width: size.width * 0.3, child: FutureBuilder( future: ApiService.getResource( appContext, configurations[index], configurations[index].imageId!), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { return ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), bottomLeft: Radius.circular(20)), child: snapshot.data != null ? Image.file( snapshot.data!, fit: BoxFit.cover, ): Image.network( configurations[index] .imageSource!, fit: BoxFit.cover, loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { if (loadingProgress == null) { return child; } return Center( child: CircularProgressIndicator( color: kMainColor1, value: loadingProgress .expectedTotalBytes != null ? loadingProgress .cumulativeBytesLoaded / loadingProgress .expectedTotalBytes! : null, ), ); }, ), ); } 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())); } }), ), Align( alignment: Alignment.topLeft, child: Container( width: size.width * 0.45, child: Center( child: Padding( padding: const EdgeInsets.only(left: 10), child: HtmlWidget( TranslationHelper.get( configurations[index].title, appContext.getContext()), textStyle: const TextStyle( fontSize: kMenuDescriptionDetailSize, ), /*maxFontSize: 18, maxLines: 2,*/ ), ), ), ), ), ], ), if (configurations[index].isOffline!) Positioned( bottom: 0, right: 0, child: Container( width: 45, height: 45, decoration: BoxDecoration( shape: BoxShape.rectangle, color: kMainColor1, borderRadius: BorderRadius.circular(20.0), ), margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { await downloadClicked(context, appContext, configurations[index]); widget.requestRefresh(); }, child: configurations[index].isOffline! && !alreadyDownloaded.any( (c) => c == configurations[index].id) ? const Icon(Icons.download, color: Colors.white) : const Icon(Icons.refresh, color: Colors.white), ), )) ], ), ), ); }, itemCount: configurations.length); } Future downloadClicked(BuildContext buildContext, AppContext appContext, ConfigurationDTO configuration) async { bool isCancel = false; //if(!alreadyDownloaded.any((c) => c == configuration.id)) { await showDialog( context: context, barrierDismissible: false, builder: (_) { return AlertDialog( backgroundColor: Colors.white, content: Padding( padding: const EdgeInsets.symmetric(vertical: 20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Text( !alreadyDownloaded.any((c) => c == configuration.id) ? TranslationHelper.getFromLocale( "downloadPrompt", appContext.getContext()) : TranslationHelper.getFromLocale( "downloadPromptUpdate", appContext.getContext()), style: const TextStyle(color: kSecondGrey), textAlign: TextAlign.center), ), const SizedBox( height: 15, ), Text( TranslationHelper.getFromLocale( "downloadLanguage", appContext.getContext()), style: const TextStyle(color: kSecondGrey), textAlign: TextAlign.center), const SizedBox( height: 25, ), LanguageSelection(configurationDTO: configuration) ], ), ), actions: [ TextButton( child: Text( TranslationHelper.getFromLocale( "close", appContext.getContext()), style: TextStyle(color: kSecondGrey)), onPressed: () { isCancel = true; Navigator.of(context).pop(); }, ), TextButton( child: Text( TranslationHelper.getFromLocale( "download", appContext.getContext()), style: TextStyle(color: kSecondGrey)), onPressed: () async { Navigator.of(context).pop(); }, ) ], actionsAlignment: MainAxisAlignment.spaceAround, contentPadding: EdgeInsets.zero, ); }); //} if (!isCancel) { /*String loadingText = TranslationHelper.getFromLocale( "downloadConfiguration", appContext.getContext()); showDialog( barrierDismissible: false, context: context, builder: (_) { return Dialog( backgroundColor: Colors.white, child: Padding( padding: const EdgeInsets.symmetric(vertical: 20), child: Column( mainAxisSize: MainAxisSize.min, children: [ const CircularProgressIndicator(), const SizedBox( height: 15, ), Text(loadingText) ], ), ), ); });*/ // DIALOG HERE if(!isDialogOpen) { isDialogOpen = true; var result = await showDialog( builder: (BuildContext dialogContext) => AlertDialog( shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(20.0)) ), content: SizedBox( width: 350, height: 125, child: Center( child: DownloadConfigurationWidget(configuration: configuration) ), ), ), context: context ); isDialogOpen = false; } else { print("ALREADY OPEN LAAAA"); } //var audiosNotWorking = await DownloadConfiguration.download(buildContext, appContext, configuration); /*print("C'EST FINI. - nombre d'audios qui ne fonctionnent pas"); print(audiosNotWorking.length);*/ //Navigator.of(context).pop(); VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; visitAppContext.audiosNotWorking = []; //visitAppContext.audiosNotWorking = audiosNotWorking; appContext.setContext(visitAppContext); } } } boxDecoration(ConfigurationDTO configuration, bool isSelected) { return BoxDecoration( color: Colors.white, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(20.0), border: Border.all( color: kMainColor0.withOpacity(0.35), width: 0.2, ), boxShadow: [ BoxShadow( color: kBackgroundGrey.withOpacity(0.35), //spreadRadius: 0.15, blurRadius: 27, offset: const Offset(0, 15), // changes position of shadow ), ], ); }