import 'dart:convert'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/LanguageSelection.dart'; import 'package:mymuseum_visitapp/Components/Loading.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; @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: kBlue2), ); } else { // Update context visitAppContext.configuration = configurations[index]; visitAppContext.sectionIds = configurations[index].sectionIds; appContext.setContext(visitAppContext); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => VisitPage(configurationId: configurations[index].id!), )); /*Navigator.push( context, MaterialPageRoute( builder: (context) => VisitPage(configurationId: configurations[index].id!) ), );*/ /**/ } } else { if (configurations[index].isOffline!) { // Not already downloaded ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(TranslationHelper.getFromLocale( "visitDownloadWarning", appContext.getContext())), backgroundColor: kBlue2), ); } else { // Online mode // Update context visitAppContext.configuration = configurations[index]; visitAppContext.sectionIds = configurations[index].sectionIds; /*Navigator.push( context, MaterialPageRoute( builder: (context) => VisitPage(configurationId: configurations[index].id!) ), );*/ Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => VisitPage(configurationId: configurations[index].id!), )); } } }, 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].imageId!), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { return snapshot.data != null ? ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(20), bottomLeft: Radius.circular(20)), child: snapshot.data.data != null ? Image.memory( base64Decode( snapshot.data.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: kBlue1, value: loadingProgress .expectedTotalBytes != null ? loadingProgress .cumulativeBytesLoaded / loadingProgress .expectedTotalBytes! : null, ), ); }, ), ) : const Text(""); } 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 Loading())); } }), ), Align( alignment: Alignment.topLeft, child: Container( width: size.width * 0.45, child: Center( child: Padding( padding: const EdgeInsets.only(left: 10), child: AutoSizeText( TranslationHelper.get( configurations[index].title, appContext.getContext()), style: const TextStyle( fontSize: kMenuTitleDetailSize), 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: kBlue1, borderRadius: BorderRadius.circular(20.0), ), margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { await downloadClicked( 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( 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: TextStyle(color: kMainColor), textAlign: TextAlign.center), ), const SizedBox( height: 15, ), Text( TranslationHelper.getFromLocale( "downloadLanguage", appContext.getContext()), style: TextStyle(color: kMainColor), textAlign: TextAlign.center), const SizedBox( height: 25, ), LanguageSelection() ], ), ), actions: [ TextButton( child: Text( TranslationHelper.getFromLocale( "close", appContext.getContext()), style: TextStyle(color: kMainColor)), onPressed: () { isCancel = true; Navigator.of(context).pop(); }, ), TextButton( child: Text( TranslationHelper.getFromLocale( "download", appContext.getContext()), style: TextStyle(color: kMainColor)), 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) ], ), ), ); }); var isFinish = await DownloadConfiguration.download(appContext, configuration); print("C'EST FINI."); print(isFinish); Navigator.of(context).pop(); } } } boxDecoration(ConfigurationDTO configuration, bool isSelected) { return BoxDecoration( color: Colors.white, shape: BoxShape.rectangle, borderRadius: BorderRadius.circular(20.0), border: Border.all( color: kBlue0.withOpacity(0.35), width: 0.2, ), boxShadow: [ BoxShadow( color: kBlue0.withOpacity(0.35), //spreadRadius: 0.15, blurRadius: 27, offset: const Offset(0, 15), // changes position of shadow ), ], ); }