From d38cdffe5a56d50ce87e0be50409c0c3cb029cdb Mon Sep 17 00:00:00 2001 From: Fransolet Thomas Date: Thu, 6 Apr 2023 21:56:06 +0200 Subject: [PATCH] Download all languages if admin + show it in admin pop up + add isAllLanguages --- lib/Components/AdminPopup.dart | 62 +++++++++++-- lib/Components/LanguageSelection.dart | 4 +- lib/Components/check_input_container.dart | 88 +++++++++++++++++++ lib/Helpers/DatabaseHelper.dart | 14 ++- lib/Models/resourceModel.dart | 3 +- lib/Models/visitContext.dart | 6 +- .../Article/audio_player_floating.dart | 2 +- lib/Screens/Home/configurations_list.dart | 19 ++-- lib/Services/apiService.dart | 2 +- lib/Services/downloadConfiguration.dart | 85 +++++++++++++----- lib/main.dart | 2 +- 11 files changed, 241 insertions(+), 46 deletions(-) create mode 100644 lib/Components/check_input_container.dart diff --git a/lib/Components/AdminPopup.dart b/lib/Components/AdminPopup.dart index 2a540d3..4027fde 100644 --- a/lib/Components/AdminPopup.dart +++ b/lib/Components/AdminPopup.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Components/check_input_container.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; @@ -31,13 +32,64 @@ class _AdminPopupState extends State { isPasswordOk = visitAppContext!.isAdmin!; return Container( - width: size.width*0.65, - height: isPasswordOk ? size.height*0.1 : size.height*0.25, + width: size.width*0.7, + height: isPasswordOk ? size.height*0.45 : size.height*0.15, margin: const EdgeInsets.all(kDefaultPadding), child: isPasswordOk ? Column( children: [ - Text("Audios qui ne fonctionnent pas :"), - Text("TODO list"), + SizedBox( + height: size.height*0.06, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: CheckInputContainer(label: "Mode admin", isChecked: visitAppContext!.isAdmin, onChanged: (value) { + visitAppContext!.isAdmin = value; + appContext.setContext(visitAppContext!); + DatabaseHelper.instance.updateTableMain(DatabaseTableType.main, visitAppContext!); + }), + ), + ), + SizedBox( + height: size.height*0.06, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: CheckInputContainer(label: "Télécharger langues", isChecked: visitAppContext!.isAllLanguages, onChanged: (value) { + visitAppContext!.isAllLanguages = value; + appContext.setContext(visitAppContext!); + DatabaseHelper.instance.updateTableMain(DatabaseTableType.main, visitAppContext!); + }), + ), + ), + const Text("Audios qui ne fonctionnent pas :"), + const SizedBox( + height: 15, + ), + Container( + decoration: BoxDecoration( + shape: BoxShape.rectangle, + border: Border.all(width: 1.5, color: kSecondGrey), + borderRadius: BorderRadius.circular(10.0), + ), + height: size.height*0.25, + width: size.width*0.7, + child: SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + if(visitAppContext!.audiosNotWorking.isEmpty) + const Padding( + padding: EdgeInsets.all(8.0), + child: Text("Rien mais téléchargez la visite pour être sûr"), + ), + if(visitAppContext!.audiosNotWorking.isNotEmpty) + for(var audio in visitAppContext!.audiosNotWorking) + Padding( + padding: const EdgeInsets.all(8.0), + child: Text(audio.label!.isNotEmpty ? audio.label! : audio.id!), + ) + ], + ) + ), + ) ], ) : Column( @@ -47,7 +99,7 @@ class _AdminPopupState extends State { Text("Mot de passe admin"), SizedBox( width: size.width*0.65, - height: size.height *0.2, + height: size.height *0.1, child: TextFormField( controller: _controller, onChanged: (value) { diff --git a/lib/Components/LanguageSelection.dart b/lib/Components/LanguageSelection.dart index 67679f8..1fe4687 100644 --- a/lib/Components/LanguageSelection.dart +++ b/lib/Components/LanguageSelection.dart @@ -32,9 +32,9 @@ class _LanguageSelection extends State with TickerProviderSta //print(configurationLanguages); languagesEnable = configurationLanguages ?? languages; selectedLanguage = visitAppContext.language; - var isAdmin = visitAppContext.isAdmin ?? false; + var isAllLanguages = visitAppContext.isAllLanguages ?? false; - if((visitAppContext.configuration != null && visitAppContext.configuration!.isOffline! && !isAdmin) || widget.configurationDTO != null) + if((visitAppContext.configuration != null && visitAppContext.configuration!.isOffline! && !isAllLanguages) || widget.configurationDTO != null) { if(widget.configurationDTO != null) { languagesEnable = widget.configurationDTO!.languages ?? languages; diff --git a/lib/Components/check_input_container.dart b/lib/Components/check_input_container.dart new file mode 100644 index 0000000..6b03457 --- /dev/null +++ b/lib/Components/check_input_container.dart @@ -0,0 +1,88 @@ +import 'package:auto_size_text/auto_size_text.dart'; +import 'package:flutter/material.dart'; + +import '../constants.dart'; + +class CheckInputContainer extends StatefulWidget { + final bool? isChecked; + final IconData? icon; + final String label; + final ValueChanged onChanged; + final double fontSize; + const CheckInputContainer({ + Key? key, + this.isChecked, + this.icon, + required this.label, + required this.onChanged, + this.fontSize = 20 + }) : super(key: key); + + @override + _CheckInputContainerState createState() => _CheckInputContainerState(); +} + +class _CheckInputContainerState extends State { + bool? isChecked; + + @override + void initState() { + setState(() { + isChecked = widget.isChecked; + }); + super.initState(); + } + @override + Widget build(BuildContext context) { + + return Container( + child: Row( + children: [ + Align( + alignment: AlignmentDirectional.centerStart, + child: Row( + children: [ + if(widget.icon != null) + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: Icon( + widget.icon, + color: kMainColor, + size: 25.0, + ), + ), + if(widget.label != null) + AutoSizeText( + widget.label, + style: new TextStyle(fontSize: widget.fontSize, fontWeight: FontWeight.w300), + maxLines: 2, + maxFontSize: widget.fontSize, + textAlign: TextAlign.center, + ), + ], + ) + ), + Padding( + padding: const EdgeInsets.all(10.0), + child: Container( + width: 50, + height: 50, + child: Checkbox( + shape: CircleBorder(), + value: isChecked, + checkColor: Colors.white, + activeColor: kMainColor, + onChanged: (bool? value) { + setState(() { + isChecked = value; + }); + widget.onChanged(value!); + }, + ), + ), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/Helpers/DatabaseHelper.dart b/lib/Helpers/DatabaseHelper.dart index d44aae5..fde0c6f 100644 --- a/lib/Helpers/DatabaseHelper.dart +++ b/lib/Helpers/DatabaseHelper.dart @@ -63,6 +63,7 @@ class DatabaseHelper { static const columnSectionType = 'sectionType'; static const columnIsAdmin = 'isAdmin'; + static const columnIsAllLanguages = 'isAllLanguages'; DatabaseHelper._privateConstructor(); @@ -155,7 +156,8 @@ class DatabaseHelper { $columnId TEXT NOT NULL PRIMARY KEY, $columnLanguage TEXT NOT NULL, $columnInstanceId TEXT NOT NULL, - $columnIsAdmin BOOLEAN NOT NULL CHECK ($columnIsAdmin IN (0,1)) + $columnIsAdmin BOOLEAN NOT NULL CHECK ($columnIsAdmin IN (0,1)), + $columnIsAllLanguages BOOLEAN CHECK ($columnIsAllLanguages IN (0,1)) ) '''); break; @@ -241,9 +243,16 @@ class DatabaseHelper { var test = await db.rawQuery(checkQuery); if(test.where((e) => e.toString().contains(columnIsAdmin)).isEmpty) { + print("update .. columnIsAdmin"); await db.rawQuery("ALTER TABLE $nameOfTable Add $columnIsAdmin BOOLEAN CHECK ($columnIsAdmin IN (0,1))"); } else { - print("IN"); + print("IN columnIsAdmin"); + } + if(test.where((e) => e.toString().contains(columnIsAllLanguages)).isEmpty) { + print("update .. columnIsAllLanguages"); + await db.rawQuery("ALTER TABLE $nameOfTable Add $columnIsAllLanguages BOOLEAN CHECK ($columnIsAllLanguages IN (0,1))"); + } else { + print("IN columnIsAllLanguages"); } DatabaseHelper.instance.insert(DatabaseTableType.main, visitAppContext.toMap()); } catch (e) { @@ -310,6 +319,7 @@ class DatabaseHelper { instanceId: element["instanceId"], language: element["language"], isAdmin: element["isAdmin"] == 1 ? true : false, + isAllLanguages: element["isAllLanguages"] == 1 ? true : false, ); break; case DatabaseTableType.configurations: diff --git a/lib/Models/resourceModel.dart b/lib/Models/resourceModel.dart index 141c73c..6538753 100644 --- a/lib/Models/resourceModel.dart +++ b/lib/Models/resourceModel.dart @@ -5,6 +5,7 @@ class ResourceModel { String? id = ""; String? data = ""; String? source = ""; + String? label = ""; ResourceType? type; ResourceModel({this.id, this.data, this.source, this.type}); @@ -29,6 +30,6 @@ class ResourceModel { @override String toString() { - return 'ResourceModel{id: $id, type: $type, source: $source, data: $data}'; + return 'ResourceModel{id: $id, type: $type, source: $source, data: $data, label: $label}'; } } \ No newline at end of file diff --git a/lib/Models/visitContext.dart b/lib/Models/visitContext.dart index 4cf2ae8..bfc8bcb 100644 --- a/lib/Models/visitContext.dart +++ b/lib/Models/visitContext.dart @@ -22,15 +22,17 @@ class VisitAppContext with ChangeNotifier{ List audiosNotWorking = []; bool? isAdmin = false; + bool? isAllLanguages = false; - VisitAppContext({this.language, this.id, this.configuration, this.isAdmin, this.instanceId}); + VisitAppContext({this.language, this.id, this.configuration, this.isAdmin, this.isAllLanguages, this.instanceId}); Map toMap() { return { 'id': id, 'instanceId': instanceId, 'language': language, - 'isAdmin': isAdmin + 'isAdmin': isAdmin != null ? isAdmin! ? 1 : 0 : 0, + 'isAllLanguages': isAllLanguages != null ? isAllLanguages! ? 1 : 0 : 0 }; } diff --git a/lib/Screens/Article/audio_player_floating.dart b/lib/Screens/Article/audio_player_floating.dart index b66c9ad..1a5b8e8 100644 --- a/lib/Screens/Article/audio_player_floating.dart +++ b/lib/Screens/Article/audio_player_floating.dart @@ -45,7 +45,7 @@ class _AudioPlayerFloatingContainerState extends State { margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { - await downloadClicked( - appContext, configurations[index]); + await downloadClicked(context, appContext, configurations[index]); widget.requestRefresh(); }, child: configurations[index].isOffline! && @@ -245,8 +244,7 @@ class _ConfigurationsListState extends State { itemCount: configurations.length); } - Future downloadClicked( - AppContext appContext, ConfigurationDTO configuration) async { + Future downloadClicked(BuildContext buildContext, AppContext appContext, ConfigurationDTO configuration) async { bool isCancel = false; //if(!alreadyDownloaded.any((c) => c == configuration.id)) { await showDialog( @@ -340,12 +338,17 @@ class _ConfigurationsListState extends State { ); }); - var isFinish = - await DownloadConfiguration.download(appContext, configuration); - print("C'EST FINI."); - print(isFinish); + 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); } } } diff --git a/lib/Services/apiService.dart b/lib/Services/apiService.dart index b14c60d..ed70eee 100644 --- a/lib/Services/apiService.dart +++ b/lib/Services/apiService.dart @@ -177,7 +177,7 @@ class ApiService { } } - static Future exportConfiguration(Client client, String configurationId, String language) async { + static Future exportConfiguration(Client client, String configurationId, String? language) async { try { bool isOnline = await hasNetwork(); if(isOnline) { diff --git a/lib/Services/downloadConfiguration.dart b/lib/Services/downloadConfiguration.dart index 1e80c9a..6bdcd48 100644 --- a/lib/Services/downloadConfiguration.dart +++ b/lib/Services/downloadConfiguration.dart @@ -1,5 +1,7 @@ import 'dart:convert'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/modelsHelper.dart'; @@ -7,14 +9,41 @@ import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Services/apiService.dart'; import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; class DownloadConfiguration { - static Future download(AppContext appContext, ConfigurationDTO configuration) async { + static Future> download(BuildContext buildContext, AppContext appContext, ConfigurationDTO configuration) async { + + VisitAppContext visitAppContext = (appContext.getContext() as VisitAppContext); + bool isAllLanguages = false; + + List audiosNotWorking = []; + + if(visitAppContext.isAllLanguages != null) { + isAllLanguages = visitAppContext.isAllLanguages!; + if(isAllLanguages) { + print("Admin here and all download all audios !"); + ScaffoldMessenger.of(buildContext).showSnackBar( + const SnackBar( + content: Text("Tous les audios vont être téléchargés"), + backgroundColor: kMainColor), + ); + } + } + + print("Start export configuration to store it locally"); + + ExportConfigurationDTO? exportConfigurationDTO; + try{ + exportConfigurationDTO = await ApiService.exportConfiguration(appContext.clientAPI, configuration.id!, isAllLanguages ? null : visitAppContext.language!); + } catch(e) { + print("Erreur lors du téléchargement de la visite"); + print(e); + } - print("COUCOUCOU IIIIINNNN"); - ExportConfigurationDTO? exportConfigurationDTO = await ApiService.exportConfiguration(appContext.clientAPI, configuration.id!, (appContext.getContext() as VisitAppContext).language!); if(exportConfigurationDTO != null) { + // Delete all from local DB ref to this configurationId then add it all await DatabaseHelper.instance.insert(DatabaseTableType.configurations, ModelsHelper.configurationToMap(configuration)); @@ -84,25 +113,11 @@ class DownloadConfiguration { } } } - - var audioIdArticle = articleDTO.audioIds!.where((audioId) => audioId.language == currentLanguage); - if(audioIdArticle.isNotEmpty && audioIdArticle.first.value != null) - { - usedImageOrAudioIds.add(audioIdArticle.first.value!); - var audioData = exportConfigurationDTO.resources!.where((element) => element.id == audioIdArticle.first.value); - if(audioData.isNotEmpty) { - ResourceModel resourceModel = ResourceModel(id: audioData.first.id, source: "", data: audioData.first.data, type: audioData.first.type); - try { - await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); - } catch (e) { - print("We got an issue inserting audio data ${audioData.first.id}"); - - // Update context with not working audios - VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; - visitAppContext.audiosNotWorking.add(resourceModel); - visitAppContext.audiosNotWorking = visitAppContext.audiosNotWorking.toSet().toList(); // Remove duplicates - appContext.setContext(visitAppContext); - } + var audioIdsArticle = isAllLanguages ? articleDTO.audioIds! : articleDTO.audioIds!.where((audioId) => audioId.language == currentLanguage); + for(var audioId in audioIdsArticle) { + if(audioId.value != null) { + usedImageOrAudioIds.add(audioId.value!); + audiosNotWorking = await importAudio(visitAppContext, exportConfigurationDTO, audioId.value!, audiosNotWorking); } } } @@ -124,10 +139,34 @@ class DownloadConfiguration { cleanLocalResources(usedImageOrAudioIds, configuration); } } - return true; + return audiosNotWorking; } } +Future> importAudio(VisitAppContext visitAppContext, ExportConfigurationDTO exportConfigurationDTO, String audioId, List audiosNotWorking) async { + var audioData = exportConfigurationDTO.resources!.where((element) => element.id == audioId); + if(audioData.isNotEmpty) { + ResourceModel resourceModel = ResourceModel(id: audioData.first.id, source: "", data: audioData.first.data, type: audioData.first.type); + try { + await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); + return audiosNotWorking; + } catch (e) { + print("We got an issue inserting audio data ${audioData.first.id}"); + + resourceModel.label = audioData.first.label; + print(resourceModel.label); + + // Update context with not working audios + //VisitAppContext visitAppContext = appContext.getContext() as VisitAppContext; + audiosNotWorking.add(resourceModel); + audiosNotWorking = audiosNotWorking.toSet().toList(); // Remove duplicates + // appContext.setContext(visitAppContext); + return audiosNotWorking; + } + } + return audiosNotWorking; +} + void cleanLocalResources(List usedImageIds, ConfigurationDTO configuration) async { List> resourcesInDB = await DatabaseHelper.instance.queryAllRows(DatabaseTableType.resources); diff --git a/lib/main.dart b/lib/main.dart index 6611da0..ebb1ed0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -28,7 +28,7 @@ void main() async { List articleReadTest = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.articleRead)); localContext.readSections = articleReadTest; } else { - localContext = VisitAppContext(language: "FR", id: "UserId_Init", instanceId: "633ee379d9405f32f166f047"); + localContext = VisitAppContext(language: "FR", id: "UserId_Init", instanceId: "633ee379d9405f32f166f047", isAdmin: false, isAllLanguages: false); DatabaseHelper.instance.insert(DatabaseTableType.main, localContext.toMap()); List articleReadTest = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.articleRead));