diff --git a/.flutter-plugins b/.flutter-plugins index 6809194..bae1236 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,3 +1,15 @@ # This is a generated file; do not edit or check into version control. +audioplayers=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers-1.1.1\\ +audioplayers_android=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers_android-1.1.1\\ +audioplayers_darwin=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers_darwin-1.0.3\\ +audioplayers_linux=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers_linux-1.0.1\\ +audioplayers_web=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers_web-2.0.1\\ +audioplayers_windows=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\audioplayers_windows-1.1.0\\ +path_provider=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider-2.0.11\\ +path_provider_android=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_android-2.0.20\\ +path_provider_ios=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_ios-2.0.11\\ +path_provider_linux=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_linux-2.1.7\\ +path_provider_macos=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_macos-2.0.6\\ +path_provider_windows=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\path_provider_windows-2.1.3\\ qr_code_scanner=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\qr_code_scanner-1.0.1\\ sqflite=C:\\Users\\thoma\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dartlang.org\\sqflite-2.0.3+1\\ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index f8dfebd..db49c15 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-23 11:11:04.666376","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":"audioplayers_darwin","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_darwin-1.0.3\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_ios","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_ios-2.0.11\\\\","native_build":true,"dependencies":[]},{"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":"audioplayers_android","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_android-1.1.1\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_android-2.0.20\\\\","native_build":true,"dependencies":[]},{"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":"audioplayers_darwin","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_darwin-1.0.3\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_macos","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.6\\\\","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":[]}],"linux":[{"name":"audioplayers_linux","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_linux-1.0.1\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_linux","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.1.7\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"audioplayers_windows","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_windows-1.1.0\\\\","native_build":true,"dependencies":[]},{"name":"path_provider_windows","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.1.3\\\\","native_build":false,"dependencies":[]}],"web":[{"name":"audioplayers_web","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\audioplayers_web-2.0.1\\\\","dependencies":[]}]},"dependencyGraph":[{"name":"audioplayers","dependencies":["audioplayers_android","audioplayers_darwin","audioplayers_linux","audioplayers_web","audioplayers_windows","path_provider"]},{"name":"audioplayers_android","dependencies":[]},{"name":"audioplayers_darwin","dependencies":[]},{"name":"audioplayers_linux","dependencies":[]},{"name":"audioplayers_web","dependencies":[]},{"name":"audioplayers_windows","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_ios","path_provider_linux","path_provider_macos","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_ios","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-10-27 16:37:35.115460","version":"3.0.3"} \ No newline at end of file diff --git a/.packages b/.packages index fbb8cf0..9104353 100644 --- a/.packages +++ b/.packages @@ -3,12 +3,19 @@ # # For more info see: https://dart.dev/go/dot-packages-deprecation # -# Generated by pub on 2022-09-15 16:08:41.495247. +# Generated by pub on 2022-10-27 16:37:19.522767. _fe_analyzer_shared:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/_fe_analyzer_shared-47.0.0/lib/ analyzer:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/analyzer-4.7.0/lib/ archive:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/archive-3.3.1/lib/ args:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/args-2.3.1/lib/ async:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/async-2.8.2/lib/ +audioplayers:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers-1.1.1/lib/ +audioplayers_android:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_android-1.1.1/lib/ +audioplayers_darwin:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_darwin-1.0.3/lib/ +audioplayers_linux:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_linux-1.0.1/lib/ +audioplayers_platform_interface:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_platform_interface-2.0.0/lib/ +audioplayers_web:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_web-2.0.1/lib/ +audioplayers_windows:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/audioplayers_windows-1.1.0/lib/ auto_size_text:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/auto_size_text-3.0.0/lib/ boolean_selector:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/ build:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/build-2.3.0/lib/ @@ -32,6 +39,7 @@ crypto:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/cr cupertino_icons:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/cupertino_icons-1.0.5/lib/ dart_style:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/dart_style-2.2.3/lib/ fake_async:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/fake_async-1.3.0/lib/ +ffi:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/ffi-2.0.1/lib/ file:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/file-6.1.4/lib/ fixnum:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/fixnum-1.0.1/lib/ flutter:file:///C:/Users/thoma/Documents/flutter/packages/flutter/lib/ @@ -68,9 +76,19 @@ package_config:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlan path:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path-1.8.1/lib/ path_drawing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_drawing-1.0.1/lib/ path_parsing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_parsing-1.0.1/lib/ +path_provider:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider-2.0.11/lib/ +path_provider_android:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_android-2.0.20/lib/ +path_provider_ios:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_ios-2.0.11/lib/ +path_provider_linux:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_linux-2.1.7/lib/ +path_provider_macos:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_macos-2.0.6/lib/ +path_provider_platform_interface:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_platform_interface-2.0.5/lib/ +path_provider_windows:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_provider_windows-2.1.3/lib/ petitparser:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/petitparser-5.0.0/lib/ -photo_view:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/photo_view-0.13.0/lib/ +photo_view:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/photo_view-0.14.0/lib/ +platform:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/platform-3.1.0/lib/ +plugin_platform_interface:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/plugin_platform_interface-2.1.3/lib/ pool:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pool-1.5.1/lib/ +process:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/process-4.2.4/lib/ provider:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/provider-5.0.0/lib/ pub_semver:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pub_semver-2.1.1/lib/ pubspec_parse:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pubspec_parse-1.2.1/lib/ @@ -91,9 +109,12 @@ term_glyph:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.or test_api:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/test_api-0.4.9/lib/ timing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/timing-1.0.0/lib/ typed_data:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/typed_data-1.3.1/lib/ +uuid:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/uuid-3.0.6/lib/ vector_math:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/vector_math-2.1.2/lib/ watcher:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/watcher-1.0.1/lib/ web_socket_channel:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/web_socket_channel-2.2.0/lib/ +win32:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/win32-3.0.1/lib/ +xdg_directories:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/xdg_directories-0.2.0+2/lib/ xml:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/xml-6.1.0/lib/ yaml:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/yaml-3.1.1/lib/ mymuseum_visitapp:lib/ diff --git a/lib/Components/BuilderImageSlider.dart b/lib/Components/BuilderImageSlider.dart new file mode 100644 index 0000000..82e1983 --- /dev/null +++ b/lib/Components/BuilderImageSlider.dart @@ -0,0 +1,56 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/ShowImagePopup.dart'; +import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; + +class BuilderImageSlider extends StatelessWidget { + const BuilderImageSlider( + {Key? key, + required this.appContext, + required this.currentIndex, + required this.imagesDTO, + required this.size, + required this.i} + ) : super(key: key); + + final AppContext appContext; + final int currentIndex; + final List imagesDTO; + final Size size; + final ResourceModel i; + + @override + Widget build(BuildContext context) { + /*return Builder( + builder: (BuildContext context) {*/ + return InkWell( + onTap: () { + showImagePopup(imagesDTO[currentIndex-1]!, i, appContext, context, size); + }, + child: Container( + //color: Colors.red, + //height: widget.height * 1, + //width: size.width * 0.95, + child: ClipRRect( + borderRadius: BorderRadius.circular(15.0), + child: Image.memory(base64Decode(i.data!))/*PhotoView( + imageProvider: Image.memory(base64Decode(i!.data!)).image, + minScale: PhotoViewComputedScale.contained * 0.8, + maxScale: PhotoViewComputedScale.contained * 3.0, + backgroundDecoration: BoxDecoration( + color: Colors.transparent, + /*shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(15.0),*/ + ), + )*/, + ), + ), + ); + //}, + //); + } +} + diff --git a/lib/Components/ShowImagePopup.dart b/lib/Components/ShowImagePopup.dart new file mode 100644 index 0000000..995ca33 --- /dev/null +++ b/lib/Components/ShowImagePopup.dart @@ -0,0 +1,52 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; +import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +import 'package:photo_view/photo_view.dart'; + +void showImagePopup(ImageDTO imageDTO, ResourceModel resourceModel, AppContext appContext, BuildContext context, Size size) { + showDialog( + builder: (BuildContext context) => AlertDialog( + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(10.0)) + ), + content: SingleChildScrollView( + child: Column( + children: [ + SizedBox( + height: size.height *0.3, + width: size.width * 0.9, + child: Center( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: PhotoView( + imageProvider: Image.memory(base64Decode(resourceModel.data!)).image, + minScale: PhotoViewComputedScale.contained * 1.0, + maxScale: PhotoViewComputedScale.contained * 3.0, + backgroundDecoration: const BoxDecoration( + color: Colors.transparent, + /*shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(15.0),*/ + ), + ),/*Image.memory(base64Decode(resourceModel!.data!)),*/ + + ), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationHelper.get(imageDTO.title, appContext), + style: const TextStyle(fontSize: kArticleContentSize, fontWeight: FontWeight.w400)), + ), + ], + ), + ), + contentPadding: EdgeInsets.zero, + ), context: context + ); +} diff --git a/lib/Components/SliderImages.dart b/lib/Components/SliderImages.dart index 8b31071..04165cf 100644 --- a/lib/Components/SliderImages.dart +++ b/lib/Components/SliderImages.dart @@ -1,25 +1,32 @@ import 'dart:convert'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/ShowImagePopup.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; class SliderImagesWidget extends StatefulWidget { final List resources; + final List imagesDTO; final double height; - SliderImagesWidget({required this.resources, required this.height}); + SliderImagesWidget({required this.resources, required this.height, required this.imagesDTO}); @override _SliderImagesWidget createState() => _SliderImagesWidget(); } class _SliderImagesWidget extends State { + List resourcesInWidget = []; late CarouselController? sliderController; int currentIndex = 1; @override void initState() { sliderController = CarouselController(); + resourcesInWidget = widget.resources; super.initState(); } @@ -31,6 +38,7 @@ class _SliderImagesWidget extends State { @override Widget build(BuildContext context) { + final appContext = Provider.of(context); Size size = MediaQuery.of(context).size; return Stack( children: [ @@ -38,12 +46,13 @@ class _SliderImagesWidget extends State { crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - if(widget.resources.isNotEmpty) + if(resourcesInWidget.isNotEmpty) CarouselSlider( carouselController: sliderController, options: CarouselOptions( onPageChanged: (int index, CarouselPageChangedReason reason) { setState(() { + print("SET STATE"); currentIndex = index + 1; }); }, @@ -51,25 +60,30 @@ class _SliderImagesWidget extends State { enlargeCenterPage: true, reverse: false, ), - items: widget.resources.map((i) { + items: resourcesInWidget.map((i) { return Builder( builder: (BuildContext context) { - return Container( - //color: Colors.red, - //height: widget.height * 1, - //width: size.width * 0.95, - child: ClipRRect( - borderRadius: BorderRadius.circular(15.0), - child: Image.memory(base64Decode(i!.data!))/*PhotoView( - imageProvider: Image.memory(base64Decode(i!.data!)).image, - minScale: PhotoViewComputedScale.contained * 0.8, - maxScale: PhotoViewComputedScale.contained * 3.0, - backgroundDecoration: BoxDecoration( - color: Colors.transparent, - /*shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(15.0),*/ - ), - )*/, + return InkWell( + onTap: () { + showImagePopup(widget.imagesDTO[currentIndex-1]!, i!, appContext, context, size); + }, + child: Container( + //color: Colors.red, + //height: widget.height * 1, + //width: size.width * 0.95, + child: ClipRRect( + borderRadius: BorderRadius.circular(15.0), + child: Image.memory(base64Decode(i!.data!))/*PhotoView( + imageProvider: Image.memory(base64Decode(i!.data!)).image, + minScale: PhotoViewComputedScale.contained * 0.8, + maxScale: PhotoViewComputedScale.contained * 3.0, + backgroundDecoration: BoxDecoration( + color: Colors.transparent, + /*shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(15.0),*/ + ), + )*/, + ), ), ); }, @@ -78,7 +92,7 @@ class _SliderImagesWidget extends State { ), ], ), - if(widget.resources.length > 1) + if(resourcesInWidget.length > 1) Positioned( top: widget.height * 0.45, right: 0, @@ -93,13 +107,13 @@ class _SliderImagesWidget extends State { ), ) ), - if(widget.resources.length > 1) + if(resourcesInWidget.length > 1) Positioned( top: widget.height * 0.45, left: 0, child: InkWell( onTap: () { - if (widget.resources.isNotEmpty) { + if (resourcesInWidget.isNotEmpty) { sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); } }, @@ -110,7 +124,7 @@ class _SliderImagesWidget extends State { ), ) ), - if(widget.resources.isNotEmpty) + if(resourcesInWidget.isNotEmpty) Padding( padding: const EdgeInsets.only(bottom: 0), child: Align( @@ -120,13 +134,13 @@ class _SliderImagesWidget extends State { sliderController!.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); }, child: Text( - currentIndex.toString()+'/'+widget.resources.length.toString(), + currentIndex.toString()+'/'+resourcesInWidget.length.toString(), style: const TextStyle(fontSize: kArticleContentSize, fontWeight: FontWeight.w500, color: kBlue2), ), ) ), ), - if(widget.resources.isEmpty) + if(resourcesInWidget.isEmpty) const Center(child: Text("Aucune image à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect),)) ] ); diff --git a/lib/Helpers/networkCheck.dart b/lib/Helpers/networkCheck.dart index cc7fb19..a2ca896 100644 --- a/lib/Helpers/networkCheck.dart +++ b/lib/Helpers/networkCheck.dart @@ -2,7 +2,7 @@ import 'dart:io'; Future hasNetwork() async { try { - final result = await InternetAddress.lookup('example.com'); + final result = await InternetAddress.lookup('google.be'); return result.isNotEmpty && result[0].rawAddress.isNotEmpty; } on SocketException catch (_) { return false; diff --git a/lib/Screens/Article/article.dart b/lib/Screens/Article/article.dart index 4634438..1d43fd9 100644 --- a/lib/Screens/Article/article.dart +++ b/lib/Screens/Article/article.dart @@ -1,5 +1,5 @@ - import 'dart:convert'; +import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; @@ -11,7 +11,7 @@ import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/networkCheck.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; -import 'package:mymuseum_visitapp/Models/visitContext.dart'; +import 'package:mymuseum_visitapp/Screens/Article/audio_player.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; @@ -30,17 +30,16 @@ class _ArticlePageState extends State { SectionDTO? sectionDTO; ArticleDTO? articleDTO; List resourcesModel = []; + ResourceModel? audioResourceModel; final GlobalKey _scaffoldKey = GlobalKey(); - + late Uint8List audiobytes; + @override Widget build(BuildContext context) { final appContext = Provider.of(context); 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( @@ -51,146 +50,65 @@ 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) - Container( - height: size.height * 0.1, - width: size.width, - child: Stack( + if(size.height > size.width) { + return Column( + children: [ + if(articleDTO!.isContentTop!) + getContent(size, appContext), + if(articleDTO!.isContentTop! && resourcesModel.isNotEmpty) + getImages(size, articleDTO!.isContentTop!), + + if(!articleDTO!.isContentTop! && resourcesModel.isNotEmpty) + getImages(size, articleDTO!.isContentTop!), + if(!articleDTO!.isContentTop!) + getContent(size, appContext), + + if(audioResourceModel != null) + AudioPlayerContainer(audioBytes: audiobytes, isAuto: articleDTO!.isReadAudioAuto!), + ], + ); + } else { + return Container( + height: size.height, + width: size.width, + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Positioned( - bottom: 0, - left: 0, - child: Row( - children: [ - Container( - height: size.height*0.08, - width: size.width, - //color: Colors.blueAccent, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10), - child: Text( - TranslationHelper.get(sectionDTO!.title, appContext), - style: const TextStyle(fontSize: kArticleTitleSize), - textAlign: TextAlign.left - ), - ), - Padding( - padding: const EdgeInsets.only(left: 10.0, top: 10.0), - child: Text( - TranslationHelper.get(sectionDTO!.description, appContext), - style: const TextStyle(fontSize: kArticleDescriptionSize), - textAlign: TextAlign.left - ), - ) - ], - ), - if(articleDTO!.audioId != null) - InkWell( - onTap: () { - print("play push"); - }, - child: const Center( - child: Padding( - padding: EdgeInsets.only(right: 20.0), - child: Icon(Icons.play_arrow, size: 35, color: kMainColor), - ), - ), - ) - ], - ), - ) - ], - ), - ), - /*Positioned( - top: notchInset.top, - left: 0, - child: InkWell( - onTap: () { - setState(() { - Navigator.of(context).pop(); - }); - }, - child: Text("Coucou")))*/ + if(articleDTO!.isContentTop!) + getContent(size, appContext), + if(articleDTO!.isContentTop! && resourcesModel.isNotEmpty) + getImages(size, articleDTO!.isContentTop!), + + if(!articleDTO!.isContentTop! && resourcesModel.isNotEmpty) + getImages(size, articleDTO!.isContentTop!), + if(!articleDTO!.isContentTop!) + getContent(size, appContext), ], ), - decoration: BoxDecoration( - image: DecorationImage( - opacity: 0.45, - image: Image.memory(base64Decode(mainResource!.data!)).image, - fit: BoxFit.cover, - ), - //color: kMainColor - ), - ), - */ - - if(articleDTO!.isContentTop!) - getContent(size, appContext), - if(articleDTO!.isContentTop! && resourcesModel.isNotEmpty) - getImages(size, articleDTO!.isContentTop!), - - if(!articleDTO!.isContentTop! && resourcesModel.isNotEmpty) - getImages(size, articleDTO!.isContentTop!), - if(!articleDTO!.isContentTop!) - getContent(size, appContext), - - ], - ); + if(audioResourceModel != null) + AudioPlayerContainer(audioBytes: audiobytes, isAuto: articleDTO!.isReadAudioAuto!) + ], + ), + ); + } } else { return const Loading(); } - } ), //floatingActionButton: const ScannerBouton(isReplacement: true), ); } - - Widget getImages(Size size, bool isContentTop) { - return SizedBox( - width: size.width, - height: size.height * 0.3, - child: Padding( - padding: isContentTop ? const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0): const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), - child: Container( - decoration: BoxDecoration( - border: Border.all( - color: kBlue2, - width: 0.5, - ), - color: Colors.white, - shape: BoxShape.rectangle, - borderRadius: BorderRadius.circular(5.0), - boxShadow: const [kDefaultShadow], - ), - child: SliderImagesWidget(resources: resourcesModel, height: size.height * 0.29) - ) - ) - ); - } - - Widget getContent(Size size, AppContext appContext) { - return Expanded( - child: Container( - width: size.width, - //height: size.height * 0.65, - //color: Colors.blueAccent, + if(size.width > size.height) { + return SizedBox( + width: size.width *0.5, + height: size.height * 0.75, child: Padding( - padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 8.0), + padding: isContentTop ? const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0): const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), child: Container( decoration: BoxDecoration( border: Border.all( @@ -202,20 +120,110 @@ class _ArticlePageState extends State { borderRadius: BorderRadius.circular(5.0), boxShadow: const [kDefaultShadow], ), - child: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - TranslationHelper.get(articleDTO!.content, appContext), - textAlign: TextAlign.left, - style: const TextStyle(fontSize: kArticleContentSize) - ), - ), + child: SliderImagesWidget( + resources: resourcesModel, + height: size.height * 0.29, + imagesDTO: articleDTO!.images!, ) ) ) - ), - ); + ); + } else { + return SizedBox( + width: size.width, + height: size.height * 0.3, + child: Padding( + padding: isContentTop ? const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0): const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: kBlue2, + width: 0.5, + ), + color: Colors.white, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(5.0), + boxShadow: const [kDefaultShadow], + ), + child: SliderImagesWidget( + resources: resourcesModel, + height: size.height * 0.29, + imagesDTO: articleDTO!.images!, + ) + ) + ) + ); + } + } + + Widget getContent(Size size, AppContext appContext) { + if(size.width > size.height) { + return SingleChildScrollView( + child: Container( + width: size.width *0.5, + height: size.height * 0.76, + //color: Colors.blueAccent, + child: Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 8.0), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: kBlue2, + width: 0.5, + ), + color: Colors.white, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(5.0), + boxShadow: const [kDefaultShadow], + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationHelper.get(articleDTO!.content, appContext), + textAlign: TextAlign.left, + style: const TextStyle(fontSize: kArticleContentSize) + ), + ), + ) + ) + ) + ), + ); + } else { + return Expanded( + child: Container( + width: size.width, + //height: size.height * 0.65, + //color: Colors.blueAccent, + child: Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0, bottom: 8.0), + child: Container( + decoration: BoxDecoration( + border: Border.all( + color: kBlue2, + width: 0.5, + ), + color: Colors.white, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(5.0), + boxShadow: const [kDefaultShadow], + ), + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + TranslationHelper.get(articleDTO!.content, appContext), + textAlign: TextAlign.left, + style: const TextStyle(fontSize: kArticleContentSize) + ), + ), + ) + ) + ) + ), + ); + } } Future getArticle(Client client, String articleId) async { @@ -227,18 +235,33 @@ class _ArticlePageState extends State { List> sectionTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, articleId); if(sectionTest.isNotEmpty) { sectionDTO = DatabaseHelper.instance.getSectionFromDB(sectionTest.first); - print(sectionDTO!.data); + print("sectionDTO!.datasectionDTO!.datasectionDTO!.datasectionDTO!.data"); } else { print("EMPTY SECTION"); } + if(sectionDTO!.type == SectionType.Article) { print("set article __ !!"); print(sectionDTO!.data!); articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!)); - print(articleDTO); } - if(sectionDTO!.imageId != null) { + if(articleDTO != null) { + if(articleDTO!.audioId != null) { + List> ressourceTest = await DatabaseHelper + .instance.queryWithColumnId( + DatabaseTableType.resources, articleDTO!.audioId!); + if (ressourceTest.isNotEmpty) { + audioResourceModel = DatabaseHelper.instance.getResourceFromDB(ressourceTest.first); + Uint8List base64String = base64Decode(audioResourceModel!.data!); + audiobytes = base64String; + } else { + print("EMPTY resourcesModel - first"); + } + } + } + + /*if(sectionDTO!.imageId != null) { List> ressourceTest = await DatabaseHelper .instance.queryWithColumnId( DatabaseTableType.resources, sectionDTO!.imageId!); @@ -247,13 +270,11 @@ class _ArticlePageState extends State { } else { print("EMPTY resourcesModel - first"); } - } + }*/ if(articleDTO!.images!.isNotEmpty) { for (var image in articleDTO!.images!) { if(image.resourceId != null) { - print("image.resourceId != nullimage.resourceId != nullimage.resourceId != null"); - List> ressourceArticle = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, image.resourceId!); if(ressourceArticle.isNotEmpty) { resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(ressourceArticle.first)); @@ -261,76 +282,13 @@ class _ArticlePageState extends State { print("EMPTY resourcesModel - second"); } - /*await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, image.resourceId!).then((value) { - print(value); - if(value.isNotEmpty) { - resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first)); - } else { - print("EMPTY resourcesModel - second"); - } - });*/ } } - - /*if(mainResource == null && resourcesModel.isNotEmpty) { - mainResource = resourcesModel.first; - }*/ } - - /*await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) { - if(value.isNotEmpty) { - resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first)); - } else { - print("EMPTY resourcesModel - first"); - } - });*/ - //} - - /*await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, articleId).then((value) async { - setState(() { - if(value.isNotEmpty) { - sectionDTO = DatabaseHelper.instance.getSectionFromDB(value.first); - print(sectionDTO!.data); - } else { - print("EMPTY SECTION"); - } - if(sectionDTO!.type == SectionType.Article) { - print("set article __ !!"); - articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!)); - print(articleDTO); - } - }); - */ - /*if(sectionDTO!.imageId != null) { - await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) { - if(value.isNotEmpty) { - resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first)); - } else { - print("EMPTY resourcesModel - first"); - } - }); - }*/ - /*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 { - print("EMPTY resourcesModel - second"); - } - }); - } - }*/ - - /*if(mainResource == null && resourcesModel.isNotEmpty) { - mainResource = resourcesModel.first; - }*/ - //} - //}); + setState(() { + print(sectionDTO!.title); + }); } else { // TODO ONLINE return null; // TODO return local list.. diff --git a/lib/Screens/Article/audio_player.dart b/lib/Screens/Article/audio_player.dart new file mode 100644 index 0000000..ee1b52e --- /dev/null +++ b/lib/Screens/Article/audio_player.dart @@ -0,0 +1,147 @@ +import 'dart:typed_data'; + +import 'package:audioplayers/audioplayers.dart'; +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; + +class AudioPlayerContainer extends StatefulWidget { + const AudioPlayerContainer({Key? key, required this.audioBytes, required this.isAuto}) : super(key: key); + + final Uint8List audioBytes; + final bool isAuto; + + @override + State createState() => _AudioPlayerContainerState(); +} + +class _AudioPlayerContainerState extends State { + AudioPlayer player = AudioPlayer(); + late Uint8List audiobytes; + bool isplaying = false; + bool audioplayed = false; + int currentpos = 0; + int maxduration = 100; + String currentpostlabel = "00:00"; + + @override + void initState() { + Future.delayed(Duration.zero, () async { + + audiobytes = widget.audioBytes; + player.onDurationChanged.listen((Duration d) { //get the duration of audio + maxduration = d.inSeconds; + setState(() { + }); + }); + + player.onPositionChanged.listen((Duration p){ + currentpos = p.inMilliseconds; //get the current position of playing audio + + //generating the duration label + int shours = Duration(milliseconds:currentpos).inHours; + int sminutes = Duration(milliseconds:currentpos).inMinutes; + int sseconds = Duration(milliseconds:currentpos).inSeconds; + + int rminutes = sminutes - (shours * 60); + int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60); + + String minutesToShow = rminutes < 10 ? '0$rminutes': rminutes.toString(); + String secondsToShow = rseconds < 10 ? '0$rseconds': rseconds.toString(); + + currentpostlabel = "$minutesToShow:$secondsToShow"; + + setState(() { + //refresh the UI + }); + }); + + if(widget.isAuto) { + player.play(BytesSource(audiobytes)); + setState(() { + isplaying = true; + audioplayed = true; + }); + } + }); + super.initState(); + } + + @override + void dispose() { + player.stop(); + player.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + + + return Container( + child: Column( + children: [ + + Container( + child: Text(currentpostlabel, style: TextStyle(fontSize: 25),), + ), + + Container( + child: Wrap( + spacing: 10, + children: [ + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + primary: kMainColor, // Background color + ), + onPressed: () async { + print(isplaying); + print(audioplayed); + if(!isplaying && !audioplayed){ + player.play(BytesSource(audiobytes)); + setState(() { + isplaying = true; + audioplayed = true; + }); + }else if(audioplayed && !isplaying){ + player.resume(); + setState(() { + isplaying = true; + audioplayed = true; + }); + }else{ + player.pause(); + setState(() { + isplaying = false; + }); + } + }, + icon: Icon(isplaying?Icons.pause:Icons.play_arrow), + label:Text(isplaying?"Pause":"Play") + ), + + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + primary: kMainColor, // Background color + ), + onPressed: () async { + player.stop(); + setState(() { + isplaying = false; + audioplayed = false; + currentpostlabel = "00:00"; + }); + }, + icon: Icon(Icons.stop), + label:Text("Stop") + ), + ], + ), + ) + ], + ), + ); + } +} diff --git a/lib/Screens/Home/configurations_list.dart b/lib/Screens/Home/configurations_list.dart index 56da86d..1f42c43 100644 --- a/lib/Screens/Home/configurations_list.dart +++ b/lib/Screens/Home/configurations_list.dart @@ -19,10 +19,11 @@ import 'package:provider/provider.dart'; class ConfigurationsList extends StatefulWidget { - const ConfigurationsList({Key? key, required this.configurations, required this.alreadyDownloaded}) : super(key: key); + 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(); @@ -147,8 +148,8 @@ class _ConfigurationsListState extends State { margin: const EdgeInsets.all(8), child: InkWell( onTap: () async { - downloadClicked(appContext, configurations[index]); - // TODO REFRESH + 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), diff --git a/lib/Screens/Home/home.dart b/lib/Screens/Home/home.dart index b8ed56a..cb8ecd8 100644 --- a/lib/Screens/Home/home.dart +++ b/lib/Screens/Home/home.dart @@ -4,6 +4,7 @@ import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/Loading.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Helpers/networkCheck.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/Visit/visit.dart'; @@ -44,7 +45,7 @@ class _HomePageState extends State { width: size.width, height: size.height, child: FutureBuilder( - future: getConfigurationsCall(appContext.clientAPI, visitAppContext), + future: getConfigurationsCall(appContext.clientAPI, appContext), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { configurations = List.from(snapshot.data).where((configuration) => configuration.isMobile!).toList(); @@ -54,7 +55,13 @@ class _HomePageState extends State { return Future(() => null); }, color: kSecondColor, - child: ConfigurationsList(alreadyDownloaded: alreadyDownloaded, configurations: configurations), + child: ConfigurationsList( + alreadyDownloaded: alreadyDownloaded, + configurations: configurations, + requestRefresh: () { + setState(() {}); // For refresh + }, + ), ); } else if (snapshot.connectionState == ConnectionState.none) { return Text(TranslationHelper.getFromLocale("noData", appContext)); @@ -75,10 +82,19 @@ class _HomePageState extends State { ); } - Future?> getConfigurationsCall(Client client, VisitAppContext? visitAppContext) async { + Future?> getConfigurationsCall(Client client, AppContext appContext) async { + bool isOnline = await hasNetwork(); + if(!isOnline) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(TranslationHelper.getFromLocale("noInternet", appContext)), backgroundColor: kBlue2), + ); + } + + VisitAppContext visitAppContext = appContext.getContext(); + List? configurations; configurations = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.configurations)); alreadyDownloaded = configurations.map((c) => c.id).toList(); - return ApiService.getConfigurations(client, visitAppContext); + return await ApiService.getConfigurations(client, visitAppContext); } } \ No newline at end of file diff --git a/lib/Screens/Visit/components/body.dart b/lib/Screens/Visit/components/body.dart index abe0691..caa1c6a 100644 --- a/lib/Screens/Visit/components/body.dart +++ b/lib/Screens/Visit/components/body.dart @@ -80,8 +80,8 @@ class _BodyState extends State { future: getSections(appContext), builder: (context, AsyncSnapshot snapshot) { if (snapshot.connectionState == ConnectionState.done) { - print("SECTIONTODISPA"); - print(sectionsToDisplay); + /*print("SECTIONTODISPA"); + print(sectionsToDisplay);*/ return Padding( padding: const EdgeInsets.only(bottom: 0), child: ListView.builder( diff --git a/lib/Screens/Visit/visit.dart b/lib/Screens/Visit/visit.dart index aac501f..9b63e57 100644 --- a/lib/Screens/Visit/visit.dart +++ b/lib/Screens/Visit/visit.dart @@ -23,19 +23,36 @@ class _VisitPageState extends State { ConfigurationDTO? configuration; @override + /*Widget build(BuildContext context) { + return new WillPopScope( + onWillPop: () async => false, + child: new Scaffold( + appBar: new AppBar( + title: new Text("data"), + leading: new IconButton( + icon: new Icon(Icons.ac_unit), + onPressed: () => Navigator.of(context).pop(), + ), + ), + ), + ); + }*/ Widget build(BuildContext context) { final appContext = Provider.of(context); VisitAppContext visitAppContext = appContext.getContext(); configuration = visitAppContext.configuration; - return Scaffold( - appBar:CustomAppBar( - title: TranslationHelper.get(configuration!.title, appContext), - isHomeButton: true, + return WillPopScope( + child: Scaffold( + appBar: CustomAppBar( + title: TranslationHelper.get(configuration!.title, appContext), + isHomeButton: true, + ), + backgroundColor: kBackgroundGrey, + body: Body(configurationId: configuration!.id), // TODO handle error.. + floatingActionButton: ScannerBouton(appContext: appContext), ), - backgroundColor: kBackgroundGrey, - body: Body(configurationId: configuration!.id), // TODO handle error.. - floatingActionButton: ScannerBouton(appContext: appContext), + onWillPop: () async => false, ); } } \ No newline at end of file diff --git a/lib/Services/apiService.dart b/lib/Services/apiService.dart index 2b09c10..ee15de4 100644 --- a/lib/Services/apiService.dart +++ b/lib/Services/apiService.dart @@ -25,6 +25,8 @@ class ApiService { } } } + } else { + return []; } return configurations; @@ -40,8 +42,6 @@ class ApiService { try { bool isOnline = await hasNetwork(); if(isOnline) { - print("Isonlinnne"); - List? sections = await client.sectionApi!.sectionGetFromConfiguration(configurationId); return sections; } else { @@ -65,8 +65,8 @@ class ApiService { bool isOnline = await hasNetwork(); if(isOnline) { var source = imageDTO.source_; - print("SOURCE getAndDownloadImage"); - print(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); @@ -74,10 +74,10 @@ class ApiService { HttpClient client2 = HttpClient(); var _downloadData = []; final HttpClientRequest request = await client2.getUrl(Uri.parse(source!)); - print("RESPONSE"); + //print("RESPONSE"); HttpClientResponse response = await request.close(); await for(dynamic d in response) { _downloadData.addAll(d); } - print("AFTER"); + //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()); @@ -93,6 +93,38 @@ class ApiService { } } + + static Future getAndDownloadAudio(Client client, String audioId) async { + try { + + // Test if already here or not.. + List> resourceTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, audioId); + if(resourceTest.isNotEmpty) { + return true; + } else { + bool isOnline = await hasNetwork(); + if(isOnline) { + var url = "https://api.mymuseum.be/api/Resource/"+audioId; // TO TEST TODO UPDATE ROUTE + HttpClient client2 = HttpClient(); + var _downloadData = []; + final HttpClientRequest request = await client2.getUrl(Uri.parse(url)); + HttpClientResponse response = await request.close(); + await for(dynamic d in response) { _downloadData.addAll(d); } + final base64Str = base64.encode(_downloadData); + ResourceModel resourceModel = ResourceModel(id: audioId, data: base64Str, type: ResourceType.Audio); + await DatabaseHelper.instance.insert(DatabaseTableType.resources, resourceModel.toMap()); + return true; + } else { + return false; + } + } + } catch (e) { + print(e); + print("IN CATCH"); + return false; + } + } + static Future getResource(String imageId) async { List> resourceTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, imageId); if(resourceTest.isNotEmpty) { diff --git a/lib/Services/downloadConfiguration.dart b/lib/Services/downloadConfiguration.dart index 97e73a9..14d4047 100644 --- a/lib/Services/downloadConfiguration.dart +++ b/lib/Services/downloadConfiguration.dart @@ -12,11 +12,11 @@ class DownloadConfiguration { // Update local DB - Configuration await DatabaseHelper.instance.insert(DatabaseTableType.configurations, ModelsHelper.configurationToMap(configuration)); - List usedImageIds = []; + List usedImageOrAudioIds = []; if(configuration.imageId != null) { ImageDTO image = ImageDTO(resourceId: configuration.imageId, source_: configuration.imageSource); - usedImageIds.add(configuration.imageId!); + usedImageOrAudioIds.add(configuration.imageId!); await ApiService.getAndDownloadImage(appContext.clientAPI, image); } @@ -37,7 +37,7 @@ class DownloadConfiguration { // Download section image if(section.imageId != null) { - usedImageIds.add(section.imageId!); + usedImageOrAudioIds.add(section.imageId!); await ApiService.getAndDownloadImage(appContext.clientAPI, ImageDTO(source_: section.imageSource, resourceId: section.imageId)); } @@ -46,9 +46,13 @@ class DownloadConfiguration { if(articleDTO != null) { for(var image in articleDTO.images!) { - usedImageIds.add(image.resourceId!); + usedImageOrAudioIds.add(image.resourceId!); await ApiService.getAndDownloadImage(appContext.clientAPI, image); } + if(articleDTO.audioId != null) { + usedImageOrAudioIds.add(articleDTO.audioId!); + await ApiService.getAndDownloadAudio(appContext.clientAPI, articleDTO.audioId!); + } } newOrder = newOrder + 1; } @@ -61,14 +65,14 @@ class DownloadConfiguration { await DatabaseHelper.instance.delete(sectionIdToRemove!, DatabaseTableType.sections); } - cleanImages(usedImageIds, configuration); + cleanLocalResources(usedImageOrAudioIds, configuration); } return true; } } -void cleanImages(List usedImageIds, ConfigurationDTO configuration) async { +void cleanLocalResources(List usedImageIds, ConfigurationDTO configuration) async { List> resourcesInDB = await DatabaseHelper.instance.queryAllRows(DatabaseTableType.resources); List resourcesModel = []; @@ -79,10 +83,10 @@ void cleanImages(List usedImageIds, ConfigurationDTO configuration) asyn List resourceIdsToRemove = resourcesModel.map((r) => r.id).where((resourceId) => !usedImageIds.contains(resourceId)).toList(); - /*for(var resourceIdToRemove in resourceIdsToRemove) { + for(var resourceIdToRemove in resourceIdsToRemove) { print("resource with id removed ________________ !!!!!"); print(resourceIdToRemove); await DatabaseHelper.instance.delete(resourceIdToRemove!, DatabaseTableType.resources); - }*/ + } } diff --git a/lib/translations.dart b/lib/translations.dart index 2003a3f..b8624e2 100644 --- a/lib/translations.dart +++ b/lib/translations.dart @@ -7,7 +7,8 @@ List translations = [ "noData": "Pas de données", "invalidQRCode": "Code QR invalide", "languageNotSupported": "Cette visite ne prend pas en charge votre langue", - "downloadConfiguration": "Chargement de la visite en cours..." + "downloadConfiguration": "Chargement de la visite en cours...", + "noInternet": "Aucune connexion internet détectée" }), Translation(language: "EN", data: { "visitTitle": "List of tours", @@ -15,7 +16,8 @@ List translations = [ "noData": "No data", "invalidQRCode": "Invalid QR code", "languageNotSupported": "This tour doesn't support your language", - "downloadConfiguration": "Loading tour..." + "downloadConfiguration": "Loading tour...", + "noInternet": "No internet connection detected" }), Translation(language: "DE", data: { "visitTitle": "Liste der Touren", @@ -23,7 +25,8 @@ List translations = [ "noData": "keine Daten", "invalidQRCode": "Ungültiger QR-Code", "languageNotSupported": "Diese Tour unterstützt Ihre Sprache nicht", - "downloadConfiguration": "Tour laden..." + "downloadConfiguration": "Tour laden...", + "noInternet": "Keine Internetverbindung erkannt" }), Translation(language: "NL", data: { "visitTitle": "Lijst met rondleidingen", @@ -31,7 +34,8 @@ List translations = [ "noData": "Geen gegevens", "invalidQRCode": "Ongeldige QR-code", "languageNotSupported": "Deze tour ondersteunt je taal niet", - "downloadConfiguration": "De rondleiding laden..." + "downloadConfiguration": "De rondleiding laden...", + "noInternet": "Geen internetverbinding gedetecteerd" }), Translation(language: "IT", data: { "visitTitle": "Elenco dei tour", @@ -39,7 +43,8 @@ List translations = [ "noData": "Nessun dato", "invalidQRCode": "Codice QR non valido", "languageNotSupported": "Questo tour non supporta la tua lingua", - "downloadConfiguration": "Caricamento del tour..." + "downloadConfiguration": "Caricamento del tour...", + "noInternet": "Nessuna connessione Internet rilevata" }), Translation(language: "ES", data: { "visitTitle": "Lista de recorridos", @@ -47,7 +52,8 @@ List translations = [ "noData": "Sin datos", "invalidQRCode": "Código QR no válido", "languageNotSupported": "Este tour no es compatible con tu idioma", - "downloadConfiguration": "Cargando el recorrido..." + "downloadConfiguration": "Cargando el recorrido...", + "noInternet": "No se detectó conexión a Internet" }), Translation(language: "PL", data: { "visitTitle": "Lista wycieczek", @@ -55,7 +61,8 @@ List translations = [ "noData": "Brak danych", "invalidQRCode": "Nieprawidłowy kod QR", "languageNotSupported": "Ta wycieczka nie obsługuje Twojego języka", - "downloadConfiguration": "Wczytuję prezentację..." + "downloadConfiguration": "Wczytuję prezentację...", + "noInternet": "Nie wykryto połączenia internetowego" }), Translation(language: "CN", data: { "visitTitle": "旅游清单", @@ -63,6 +70,7 @@ List translations = [ "noData": "没有数据", "invalidQRCode": "二维码无效", "languageNotSupported": "此导览不支持您的语言", - "downloadConfiguration": "正在加载导览..." + "downloadConfiguration": "正在加载导览...", + "noInternet": "未检测到互联网连接" }), ]; \ No newline at end of file diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index e71a16d..1830e5c 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,6 +6,10 @@ #include "generated_plugin_registrant.h" +#include void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) audioplayers_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "AudioplayersLinuxPlugin"); + audioplayers_linux_plugin_register_with_registrar(audioplayers_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 2e1de87..e9abb91 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + audioplayers_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/manager_api/lib/model/resource_type.dart b/manager_api/lib/model/resource_type.dart index cbdb6fa..a6bb08b 100644 --- a/manager_api/lib/model/resource_type.dart +++ b/manager_api/lib/model/resource_type.dart @@ -27,13 +27,15 @@ class ResourceType { static const Video = ResourceType._(1); static const ImageUrl = ResourceType._(2); static const VideoUrl = ResourceType._(3); + static const Audio = ResourceType._(4); /// List of all possible values in this [enum][ResourceType]. static const values = [ Image, Video, ImageUrl, - VideoUrl + VideoUrl, + Audio ]; static ResourceType? fromJson(dynamic value) => ResourceTypeTypeTransformer().decode(value); @@ -76,6 +78,7 @@ class ResourceTypeTypeTransformer { case "Video": return ResourceType.Video; case "ImageUrl": return ResourceType.ImageUrl; case "VideoUrl": return ResourceType.VideoUrl; + case "Audio": return ResourceType.Audio; default: if (!allowNull) { throw ArgumentError('Unknown enum value to decode: $data'); diff --git a/pubspec.lock b/pubspec.lock index 50d031e..03bd29c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -36,6 +36,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.2" + audioplayers: + dependency: "direct main" + description: + name: audioplayers + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + audioplayers_android: + dependency: transitive + description: + name: audioplayers_android + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + audioplayers_darwin: + dependency: transitive + description: + name: audioplayers_darwin + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + audioplayers_linux: + dependency: transitive + description: + name: audioplayers_linux + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + audioplayers_platform_interface: + dependency: transitive + description: + name: audioplayers_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + audioplayers_web: + dependency: transitive + description: + name: audioplayers_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + audioplayers_windows: + dependency: transitive + description: + name: audioplayers_windows + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" auto_size_text: dependency: "direct main" description: @@ -197,6 +246,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" file: dependency: transitive description: @@ -441,6 +497,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.1" + path_provider: + dependency: transitive + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.20" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.7" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.6" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" petitparser: dependency: transitive description: @@ -454,7 +559,21 @@ packages: name: photo_view url: "https://pub.dartlang.org" source: hosted - version: "0.13.0" + version: "0.14.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.3" pool: dependency: transitive description: @@ -462,6 +581,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.5.1" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" provider: dependency: "direct main" description: @@ -600,6 +726,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.6" vector_math: dependency: transitive description: @@ -621,6 +754,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.2.0" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+2" xml: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5b1047d..9a796b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,9 +40,10 @@ dependencies: provider: ^5.0.0 carousel_slider: ^4.0.0 flutter_svg_provider: ^1.0.3 - photo_view: ^0.13.0 + photo_view: ^0.14.0 intl: ^0.17.0 flutter_launcher_icons: ^0.10.0 + audioplayers: ^1.1.1 manager_api: path: manager_api