diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 9eba2d5..a34ffd2 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-10-19 17:45:15.549712","version":"3.0.3"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-10-20 16:40:20.714473","version":"3.0.3"} \ No newline at end of file diff --git a/lib/Helpers/DatabaseHelper.dart b/lib/Helpers/DatabaseHelper.dart index 752385d..5757e76 100644 --- a/lib/Helpers/DatabaseHelper.dart +++ b/lib/Helpers/DatabaseHelper.dart @@ -22,6 +22,7 @@ class DatabaseHelper { static final columnLabel = 'label'; static final columnId = 'id'; + static final columnInstanceId = 'instanceId'; static final columnData = 'data'; static final columnType = 'type'; static final columnDateCreation = 'dateCreation'; @@ -64,12 +65,14 @@ class DatabaseHelper { await db.execute(''' CREATE TABLE $mainTable ( $columnId TEXT NOT NULL PRIMARY KEY, - $columnLanguage TEXT NOT NULL + $columnLanguage TEXT NOT NULL, + $columnInstanceId TEXT NOT NULL ) '''); await db.execute(''' CREATE TABLE $configurationsTable ( $columnId TEXT NOT NULL PRIMARY KEY, + $columnInstanceId TEXT NOT NULL, $columnLabel TEXT NOT NULL, $columnTitle TEXT NOT NULL, $columnImageId TEXT, @@ -87,6 +90,7 @@ class DatabaseHelper { await db.execute(''' CREATE TABLE $sectionsTable ( $columnId TEXT NOT NULL PRIMARY KEY, + $columnInstanceId TEXT NOT NULL, $columnLabel TEXT NOT NULL, $columnTitle TEXT NOT NULL, $columnDescription TEXT, @@ -204,17 +208,25 @@ class DatabaseHelper { case DatabaseTableType.main: dataToReturn = VisitAppContext( id: element["id"], + instanceId: element["instanceId"], language: element["language"] ); break; case DatabaseTableType.configurations: + var test = getConfigurationFromDB(element); dataToReturn.add(getConfigurationFromDB(element)); + + print("DB - dataToReturn --- $test --> "); break; case DatabaseTableType.sections: + var test = getSectionFromDB(element); dataToReturn.add(getSectionFromDB(element)); + print("DB - dataToReturn --- $test --> "); break; case DatabaseTableType.resources: + var test = getResourceFromDB(element); dataToReturn.add(getResourceFromDB(element)); + print("DB - dataToReturn --- $test --> "); break; } }); @@ -241,6 +253,7 @@ class DatabaseHelper { var titles = List.from(json.decode(element['title']).map((q) => TranslationDTO.fromJson(q)).toList()); return ConfigurationDTO( id: element["id"], + instanceId: element["instanceId"], label: element["label"], title: titles, imageId: element["imageId"], @@ -260,6 +273,7 @@ class DatabaseHelper { var descriptions = List.from(json.decode(element['description']).map((q) => TranslationDTO.fromJson(q)).toList()); return SectionDTO( id: element["id"], + instanceId: element["instanceId"], label: element["label"], title: titles, description: descriptions, diff --git a/lib/Helpers/modelsHelper.dart b/lib/Helpers/modelsHelper.dart index d1a0241..1281fe0 100644 --- a/lib/Helpers/modelsHelper.dart +++ b/lib/Helpers/modelsHelper.dart @@ -6,6 +6,7 @@ class ModelsHelper { static Map configurationToMap(ConfigurationDTO configuration) { return { 'id': configuration.id, + 'instanceId': configuration.instanceId, 'label': configuration.label, 'title': jsonEncode(configuration.title), 'imageId': configuration.imageId, @@ -23,6 +24,7 @@ class ModelsHelper { static Map sectionToMap(SectionDTO section) { return { 'id': section.id, + 'instanceId': section.instanceId, 'label': section.label, 'title': jsonEncode(section.title), 'description': jsonEncode(section.description), diff --git a/lib/Models/visitContext.dart b/lib/Models/visitContext.dart index 17e94c4..ff6817d 100644 --- a/lib/Models/visitContext.dart +++ b/lib/Models/visitContext.dart @@ -4,16 +4,17 @@ import 'package:manager_api/api.dart'; class VisitAppContext with ChangeNotifier{ String? id = ""; String? language = ""; - String instanceId = "633ee379d9405f32f166f047"; + String? instanceId = "633ee379d9405f32f166f047"; List? configurations; ConfigurationDTO? configuration; List? sectionIds; // Use to valid QR code found - VisitAppContext({this.language, this.id, this.configuration}); + VisitAppContext({this.language, this.id, this.configuration, this.instanceId}); Map toMap() { return { 'id': id, + 'instanceId': instanceId, 'language': language, }; } @@ -21,6 +22,7 @@ class VisitAppContext with ChangeNotifier{ factory VisitAppContext.fromJson(Map json) { return VisitAppContext( id: json['id'] as String, + instanceId: json['instanceId'] as String, language: json['language'] as String, configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']), ); @@ -28,6 +30,6 @@ class VisitAppContext with ChangeNotifier{ @override String toString() { - return 'VisitAppContext{id: $id, language: $language, configuration: $configuration}'; + return 'VisitAppContext{id: $id, instanceId: $instanceId, language: $language, configuration: $configuration}'; } } \ No newline at end of file diff --git a/lib/Screens/Article/article.dart b/lib/Screens/Article/article.dart index 70cf880..215ae15 100644 --- a/lib/Screens/Article/article.dart +++ b/lib/Screens/Article/article.dart @@ -38,6 +38,9 @@ class _ArticlePageState extends State { Size size = MediaQuery.of(context).size; final notchInset = MediaQuery.of(context).padding; + print(" widget.articleId widget.articleId widget.articleId widget.articleId widget.articleId" ); + print( widget.articleId); + return Scaffold( key: _scaffoldKey, appBar: CustomAppBar( @@ -48,6 +51,9 @@ class _ArticlePageState extends State { future: getArticle(appContext.clientAPI, widget.articleId), builder: (context, AsyncSnapshot snapshot) { if(articleDTO != null && sectionDTO != null) { + print("INININININININ"); + print(articleDTO); + print(resourcesModel); return Column( children: [ /*if(mainResource != null) @@ -129,8 +135,7 @@ class _ArticlePageState extends State { ), ), */ - - + if(articleDTO!.isContentTop!) getContent(size, appContext), if(articleDTO!.isContentTop! && resourcesModel.isNotEmpty) @@ -240,7 +245,9 @@ class _ArticlePageState extends State { if(articleDTO!.images!.isNotEmpty) { for (var image in articleDTO!.images!) { if(image.resourceId != null) { + print("image.resourceId != nullimage.resourceId != nullimage.resourceId != null"); await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, image.resourceId!).then((value) { + print(value); if(value.isNotEmpty) { resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first)); } else { diff --git a/lib/Screens/Home/configurations_list.dart b/lib/Screens/Home/configurations_list.dart index bab7dd5..56da86d 100644 --- a/lib/Screens/Home/configurations_list.dart +++ b/lib/Screens/Home/configurations_list.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; @@ -9,6 +11,7 @@ import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/Article/article.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'; @@ -78,16 +81,56 @@ class _ConfigurationsListState extends State { margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), child: Stack( children: [ - Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only(top: 20, left: 10), - child: AutoSizeText( - TranslationHelper.get(configurations[index].title, appContext), - style: const TextStyle(fontSize: kMenuTitleDetailSize), - maxLines: 1, + 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(configurations[index].imageId!), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return snapshot.data != null ? Container( + child: ClipRRect( + borderRadius: const BorderRadius.only(topLeft: Radius.circular(20), bottomLeft: Radius.circular(20)), + child: Image.memory( + base64Decode(snapshot.data.data!), + fit: BoxFit.cover + ), + ), + ) : const Text(""); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text(TranslationHelper.getFromLocale("noData", appContext)); + } 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: Padding( + padding: const EdgeInsets.only(top: 45, left: 10), + child: AutoSizeText( + TranslationHelper.get(configurations[index].title, appContext), + style: const TextStyle(fontSize: kMenuTitleDetailSize), + maxFontSize: 20, + maxLines: 2, + ), + ), + ), ), - ), + ], ), if(configurations[index].isOffline!) Positioned( @@ -105,7 +148,7 @@ class _ConfigurationsListState extends State { child: InkWell( onTap: () async { downloadClicked(appContext, configurations[index]); - setState(() {}); // Force refresh + // TODO REFRESH }, 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), @@ -122,9 +165,34 @@ class _ConfigurationsListState extends State { } Future downloadClicked(AppContext appContext, ConfigurationDTO configuration) async { + String loadingtext = TranslationHelper.getFromLocale("downloadConfiguration", appContext); + 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.downloadClicked(appContext, configuration); print("C4EST FINIITO"); print(isFinish); + + Navigator.of(context).pop(); } } diff --git a/lib/Screens/Home/home.dart b/lib/Screens/Home/home.dart index edb04d6..b8ed56a 100644 --- a/lib/Screens/Home/home.dart +++ b/lib/Screens/Home/home.dart @@ -54,82 +54,7 @@ class _HomePageState extends State { return Future(() => null); }, color: kSecondColor, - child: ConfigurationsList(alreadyDownloaded: alreadyDownloaded, configurations: configurations),/*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 { - if(configurations[index].isOffline! && alreadyDownloaded.any((c) => c == configurations[index].id)) { - VisitAppContext visitAppContext = appContext.getContext(); - - if(!configurations[index].languages!.contains(visitAppContext.language)) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(TranslationHelper.getFromLocale("languageNotSupported", appContext)), backgroundColor: kBlue2), - ); - } else { - // Update context - visitAppContext.configuration = configurations[index]; - visitAppContext.sectionIds = List.from(await DatabaseHelper.instance.queryWithConfigurationId(DatabaseTableType.sections, visitAppContext.configuration!.id!)).map((e) => e.id).toList(); - appContext.setContext(visitAppContext); - - Navigator.of(context).pushReplacement(MaterialPageRoute( - builder: (context) => VisitPage(configurationId: configurations[index].id!), - )); - } - } else { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(TranslationHelper.getFromLocale("visitDownloadWarning", appContext)), backgroundColor: kBlue2), - ); - } - }, - child: Container( - height: size.height*0.15, - decoration: boxDecoration(configurations[index], false), - margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20), - child: Stack( - children: [ - Align( - alignment: Alignment.topLeft, - child: Padding( - padding: const EdgeInsets.only(top: 20, left: 10), - child: AutoSizeText( - TranslationHelper.get(configurations[index].title, appContext), - style: const TextStyle(fontSize: kMenuTitleDetailSize), - maxLines: 1, - ), - ), - ), - 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 { - downloadClicked(appContext, configurations[index]); - setState(() {}); // Force refresh - }, - 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 - ),*/ + child: ConfigurationsList(alreadyDownloaded: alreadyDownloaded, configurations: configurations), ); } else if (snapshot.connectionState == ConnectionState.none) { return Text(TranslationHelper.getFromLocale("noData", appContext)); @@ -156,30 +81,4 @@ class _HomePageState extends State { alreadyDownloaded = configurations.map((c) => c.id).toList(); return ApiService.getConfigurations(client, visitAppContext); } - - /*Future downloadClicked(AppContext appContext, ConfigurationDTO configuration) async { - var isFinish = await DownloadConfiguration.downloadClicked(appContext, configuration); - print("C4EST FINIITO"); - print(isFinish); - }*/ -} - -/*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 - ), - ], - ); -}*/ \ No newline at end of file +} \ No newline at end of file diff --git a/lib/Screens/Visit/components/body.dart b/lib/Screens/Visit/components/body.dart index fb1bdbc..abe0691 100644 --- a/lib/Screens/Visit/components/body.dart +++ b/lib/Screens/Visit/components/body.dart @@ -80,6 +80,8 @@ class _BodyState extends State { future: getSections(appContext), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { + print("SECTIONTODISPA"); + print(sectionsToDisplay); return Padding( padding: const EdgeInsets.only(bottom: 0), child: ListView.builder( diff --git a/lib/Screens/Visit/components/section_card.dart b/lib/Screens/Visit/components/section_card.dart index 9891089..8022703 100644 --- a/lib/Screens/Visit/components/section_card.dart +++ b/lib/Screens/Visit/components/section_card.dart @@ -6,6 +6,7 @@ import 'package:mymuseum_visitapp/Components/Loading.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/Services/apiService.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; @@ -31,12 +32,6 @@ class SectionCard extends StatelessWidget { final appContext = Provider.of(context); ResourceModel? resourceModel; - getResource(String? imageId) async { - await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, sectionDTO.imageId!).then((value) { - resourceModel = DatabaseHelper.instance.getResourceFromDB(value.first); - }); - } - return Container( margin: EdgeInsets.symmetric( horizontal: kDefaultPadding, @@ -70,45 +65,46 @@ class SectionCard extends StatelessWidget { ), ), ), - // section main image - Positioned( - top: kDefaultPadding +4.0, - right: -10, - child: /*Hero( - tag: '${sectionDTO.id}', - child:*/ Container( - padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding), - height: 136, - // image is square but we add extra 20 + 20 padding thats why width is 200 - width: size.width*0.5, - child: FutureBuilder( - future: getResource(sectionDTO.imageId), - builder: (context, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - return resourceModel != null ? Container( - child: ClipRRect( - borderRadius: const BorderRadius.only(topRight: Radius.circular(20), bottomRight: Radius.circular(20)), - child: Image.memory( - base64Decode(resourceModel!.data!), - fit: BoxFit.cover + if(sectionDTO.imageId != null) + // section main image + Positioned( + top: kDefaultPadding +4.0, + right: -10, + child: /*Hero( + tag: '${sectionDTO.id}', + child:*/ Container( + padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding), + height: 136, + // image is square but we add extra 20 + 20 padding thats why width is 200 + width: size.width*0.5, + child: FutureBuilder( + future: ApiService.getResource(sectionDTO.imageId!), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return snapshot.data != null ? Container( + child: ClipRRect( + borderRadius: const BorderRadius.only(topRight: Radius.circular(20), bottomRight: Radius.circular(20)), + child: Image.memory( + base64Decode(snapshot.data!.data!), + fit: BoxFit.cover + ), ), - ), - ) : const Text(""); - } else if (snapshot.connectionState == ConnectionState.none) { - return Text(TranslationHelper.getFromLocale("noData", appContext)); - } else { - return Center( - child: SizedBox( - height: size.height * 0.15, - child: const Loading() - ) - ); + ) : const Text(""); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text(TranslationHelper.getFromLocale("noData", appContext)); + } else { + return Center( + child: SizedBox( + height: size.height * 0.15, + child: const Loading() + ) + ); + } } - } - ) - ), - //), - ), + ) + ), + //), + ), // Section title and order Positioned( bottom: 0, diff --git a/lib/Screens/Visit/visit.dart b/lib/Screens/Visit/visit.dart index d2dc2c7..aac501f 100644 --- a/lib/Screens/Visit/visit.dart +++ b/lib/Screens/Visit/visit.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; +import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; @@ -29,7 +30,7 @@ class _VisitPageState extends State { return Scaffold( appBar:CustomAppBar( - title: configuration?.label ?? "", + title: TranslationHelper.get(configuration!.title, appContext), isHomeButton: true, ), backgroundColor: kBackgroundGrey, diff --git a/lib/Services/apiService.dart b/lib/Services/apiService.dart index 3d89b32..2b09c10 100644 --- a/lib/Services/apiService.dart +++ b/lib/Services/apiService.dart @@ -15,7 +15,18 @@ class ApiService { bool isOnline = await hasNetwork(); if(isOnline) { configurations = await client.configurationApi!.configurationGet(instanceId: visitAppContext?.instanceId); + + if(configurations != null) { + if(configurations.isNotEmpty) { + for(var configuration in configurations) { + if(configuration.imageId != null) { + await getAndDownloadImage(client, ImageDTO(source_: configuration.imageSource, resourceId: configuration.imageId)); + } + } + } + } } + return configurations; } catch (e) { @@ -29,6 +40,8 @@ class ApiService { try { bool isOnline = await hasNetwork(); if(isOnline) { + print("Isonlinnne"); + List? sections = await client.sectionApi!.sectionGetFromConfiguration(configurationId); return sections; } else { @@ -41,44 +54,52 @@ class ApiService { } } - static Future getAndDownloadImage(Client client, ImageDTO imageDTO) async { + static Future getAndDownloadImage(Client client, ImageDTO imageDTO) async { try { - bool isOnline = await hasNetwork(); - if(isOnline) { - var source = imageDTO.source_; - if(imageDTO.source_!.contains("localhost:5000")) { - source = imageDTO.source_!.replaceAll("http://localhost:5000", client.apiApi!.basePath); - } - HttpClient client2 = HttpClient(); - var _downloadData = []; - client2.getUrl(Uri.parse(source!)) - .then((HttpClientRequest request) { - return request.close(); - }) - .then((HttpClientResponse response) { - response.listen((d) => _downloadData.addAll(d), - onDone: () async { - final base64Str = base64.encode(_downloadData); - ResourceModel resourceModel = ResourceModel(id: imageDTO.resourceId, data: base64Str, type: ResourceType.Image); - await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); - //var test = base64.decode(base64Str); - //return base64Str; - /*setState(() { - base64TEST = base64Str; - });*/ - } - ); - }); - //return file; + // Test if already here or not.. + List> resourceTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, imageDTO.resourceId!); + if(resourceTest.isNotEmpty) { + return true; } else { - //return null; + bool isOnline = await hasNetwork(); + if(isOnline) { + var source = imageDTO.source_; + print("SOURCE getAndDownloadImage"); + print(source); + if(imageDTO.source_!.contains("localhost:5000")) { + print("Contains localhost:5000"); + source = imageDTO.source_!.replaceAll("http://localhost:5000", client.apiApi!.basePath); + } + HttpClient client2 = HttpClient(); + var _downloadData = []; + final HttpClientRequest request = await client2.getUrl(Uri.parse(source!)); + print("RESPONSE"); + HttpClientResponse response = await request.close(); + await for(dynamic d in response) { _downloadData.addAll(d); } + print("AFTER"); + final base64Str = base64.encode(_downloadData); + ResourceModel resourceModel = ResourceModel(id: imageDTO.resourceId, data: base64Str, type: ResourceType.Image); + await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); + return true; + } else { + return false; + } } } catch (e) { print(e); print("IN CATCH"); - //return []; + return false; } } + + static Future getResource(String imageId) async { + List> resourceTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, imageId); + if(resourceTest.isNotEmpty) { + return DatabaseHelper.instance.getResourceFromDB(resourceTest.first); + } else { + return null; + } + } } diff --git a/lib/Services/downloadConfiguration.dart b/lib/Services/downloadConfiguration.dart index 6d5327a..97e73a9 100644 --- a/lib/Services/downloadConfiguration.dart +++ b/lib/Services/downloadConfiguration.dart @@ -3,30 +3,31 @@ import 'dart:convert'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/modelsHelper.dart'; +import 'package:mymuseum_visitapp/Models/resourceModel.dart'; import 'package:mymuseum_visitapp/Services/apiService.dart'; import 'package:mymuseum_visitapp/app_context.dart'; class DownloadConfiguration { static Future downloadClicked(AppContext appContext, ConfigurationDTO configuration) async { - print("coucou downloadClicked"); // Update local DB - Configuration await DatabaseHelper.instance.insert(DatabaseTableType.configurations, ModelsHelper.configurationToMap(configuration)); - - - print("coucou downloadClicked 0"); + List usedImageIds = []; if(configuration.imageId != null) { ImageDTO image = ImageDTO(resourceId: configuration.imageId, source_: configuration.imageSource); + usedImageIds.add(configuration.imageId!); await ApiService.getAndDownloadImage(appContext.clientAPI, image); } - print("coucou downloadClicked 1"); - List? sections = await ApiService.getAllSections(appContext.clientAPI, configuration.id!); if(sections!.isNotEmpty) { + + List sectionsInDB = await DatabaseHelper.instance.queryWithConfigurationId(DatabaseTableType.sections, configuration.id!); + List sectionsToKeep = sections.where((s) => s.type == SectionType.Article).toList(); // TODO handle other type of section + sectionsToKeep.sort((a,b) => a.order!.compareTo(b.order!)); int newOrder = 0; // Update local DB - Sections @@ -34,18 +35,54 @@ class DownloadConfiguration { section.order = newOrder; await DatabaseHelper.instance.insert(DatabaseTableType.sections, ModelsHelper.sectionToMap(section)); + // Download section image + if(section.imageId != null) { + usedImageIds.add(section.imageId!); + await ApiService.getAndDownloadImage(appContext.clientAPI, ImageDTO(source_: section.imageSource, resourceId: section.imageId)); + } + // Download all images.. ArticleDTO? articleDTO = ArticleDTO.fromJson(jsonDecode(section.data!)); if(articleDTO != null) { for(var image in articleDTO.images!) { + usedImageIds.add(image.resourceId!); await ApiService.getAndDownloadImage(appContext.clientAPI, image); } } newOrder = newOrder + 1; } + + List sectionIdsToRemove = sectionsInDB.map((s) => s.id).where((sectionId) => !sectionsToKeep.map((sk) => sk.id).contains(sectionId)).toList(); + + for(var sectionIdToRemove in sectionIdsToRemove) { + print("section with id removed"); + print(sectionIdToRemove); + await DatabaseHelper.instance.delete(sectionIdToRemove!, DatabaseTableType.sections); + } + + cleanImages(usedImageIds, configuration); } return true; } } + +void cleanImages(List usedImageIds, ConfigurationDTO configuration) async { + + List> resourcesInDB = await DatabaseHelper.instance.queryAllRows(DatabaseTableType.resources); + List resourcesModel = []; + + for(var resource in resourcesInDB) { + resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(resource)); + } + + List resourceIdsToRemove = resourcesModel.map((r) => r.id).where((resourceId) => !usedImageIds.contains(resourceId)).toList(); + + /*for(var resourceIdToRemove in resourceIdsToRemove) { + print("resource with id removed ________________ !!!!!"); + print(resourceIdToRemove); + await DatabaseHelper.instance.delete(resourceIdToRemove!, DatabaseTableType.resources); + }*/ + +} diff --git a/lib/constants.dart b/lib/constants.dart index 78ab0f0..278aeaf 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -42,7 +42,7 @@ const kDescriptionSize = 25.0; const kSectionTitleDetailSize = 50.0; const kSectionDescriptionDetailSize = 35.0; -const kMenuTitleDetailSize = 30.0; +const kMenuTitleDetailSize = 25.0; const kMenuDescriptionDetailSize = 18.0; const kNoneInfoOrIncorrect = 35.0; diff --git a/lib/main.dart b/lib/main.dart index 55b6d1e..f185646 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,7 +17,7 @@ void main() async { print("we've got an local db !"); print(localContext); } else { - localContext = VisitAppContext(language: "FR", id: "UserId_Init"); + localContext = VisitAppContext(language: "FR", id: "UserId_Init", instanceId: "633ee379d9405f32f166f047"); DatabaseHelper.instance.insert(DatabaseTableType.main, localContext.toMap()); print("NO LOCAL DB !"); } diff --git a/lib/translations.dart b/lib/translations.dart index 85b99ab..2003a3f 100644 --- a/lib/translations.dart +++ b/lib/translations.dart @@ -6,55 +6,63 @@ List translations = [ "visitDownloadWarning": "Pour suivre cette visite, il faut d'abord la télécharger", "noData": "Pas de données", "invalidQRCode": "Code QR invalide", - "languageNotSupported": "Cette visite ne prend pas en charge votre langue" + "languageNotSupported": "Cette visite ne prend pas en charge votre langue", + "downloadConfiguration": "Chargement de la visite en cours..." }), Translation(language: "EN", data: { "visitTitle": "List of tours", "visitDownloadWarning": "To follow this tour, you must first download it", "noData": "No data", "invalidQRCode": "Invalid QR code", - "languageNotSupported": "This tour doesn't support your language" + "languageNotSupported": "This tour doesn't support your language", + "downloadConfiguration": "Loading tour..." }), Translation(language: "DE", data: { "visitTitle": "Liste der Touren", "visitDownloadWarning": "Um dieser Tour zu folgen, müssen Sie sie zuerst herunterladen", "noData": "keine Daten", "invalidQRCode": "Ungültiger QR-Code", - "languageNotSupported": "Diese Tour unterstützt Ihre Sprache nicht" + "languageNotSupported": "Diese Tour unterstützt Ihre Sprache nicht", + "downloadConfiguration": "Tour laden..." }), Translation(language: "NL", data: { "visitTitle": "Lijst met rondleidingen", "visitDownloadWarning": "Om deze tour te volgen, moet je deze eerst downloaden", "noData": "Geen gegevens", "invalidQRCode": "Ongeldige QR-code", - "languageNotSupported": "Deze tour ondersteunt je taal niet" + "languageNotSupported": "Deze tour ondersteunt je taal niet", + "downloadConfiguration": "De rondleiding laden..." }), Translation(language: "IT", data: { "visitTitle": "Elenco dei tour", "visitDownloadWarning": "Per seguire questo tour, devi prima scaricarlo", "noData": "Nessun dato", "invalidQRCode": "Codice QR non valido", - "languageNotSupported": "Questo tour non supporta la tua lingua" + "languageNotSupported": "Questo tour non supporta la tua lingua", + "downloadConfiguration": "Caricamento del tour..." }), Translation(language: "ES", data: { "visitTitle": "Lista de recorridos", "visitDownloadWarning": "Para realizar este recorrido, primero debe descargarlo", "noData": "Sin datos", "invalidQRCode": "Código QR no válido", - "languageNotSupported": "Este tour no es compatible con tu idioma" + "languageNotSupported": "Este tour no es compatible con tu idioma", + "downloadConfiguration": "Cargando el recorrido..." }), Translation(language: "PL", data: { "visitTitle": "Lista wycieczek", "visitDownloadWarning": "Aby wziąć udział w tej wycieczce, musisz ją najpierw pobrać", "noData": "Brak danych", "invalidQRCode": "Nieprawidłowy kod QR", - "languageNotSupported": "Ta wycieczka nie obsługuje Twojego języka" + "languageNotSupported": "Ta wycieczka nie obsługuje Twojego języka", + "downloadConfiguration": "Wczytuję prezentację..." }), Translation(language: "CN", data: { "visitTitle": "旅游清单", "visitDownloadWarning": "要参加此导览,您需要先下载它", "noData": "没有数据", "invalidQRCode": "二维码无效", - "languageNotSupported": "此导览不支持您的语言" + "languageNotSupported": "此导览不支持您的语言", + "downloadConfiguration": "正在加载导览..." }), ]; \ No newline at end of file