diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 0b70042..4fed78f 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.0\\\\","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.0\\\\","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-08-26 18:14:06.211747","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.0\\\\","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.0\\\\","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-08-31 17:20:34.430999","version":"3.0.3"} \ No newline at end of file diff --git a/.packages b/.packages index 7c3c5e0..2a5f97f 100644 --- a/.packages +++ b/.packages @@ -3,7 +3,7 @@ # # For more info see: https://dart.dev/go/dot-packages-deprecation # -# Generated by pub on 2022-08-11 17:42:29.200149. +# Generated by pub on 2022-08-31 16:18:04.785377. _fe_analyzer_shared:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/_fe_analyzer_shared-31.0.0/lib/ analyzer:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/analyzer-2.8.0/lib/ args:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/args-2.3.1/lib/ @@ -18,6 +18,7 @@ build_runner:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang. build_runner_core:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/build_runner_core-6.1.12/lib/ built_collection:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/built_collection-5.1.1/lib/ built_value:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/built_value-8.4.0/lib/ +carousel_slider:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/carousel_slider-4.1.1/lib/ characters:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/characters-1.2.0/lib/ charcode:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/charcode-1.3.1/lib/ checked_yaml:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/checked_yaml-2.0.1/lib/ @@ -63,6 +64,7 @@ path_drawing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang. path_parsing:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/path_parsing-1.0.1/lib/ pedantic:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pedantic-1.11.1/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/ pool:file:///C:/Users/thoma/AppData/Local/Pub/Cache/hosted/pub.dartlang.org/pool-1.5.1/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/ diff --git a/lib/Components/ScannerBouton.dart b/lib/Components/ScannerBouton.dart index d8f00a2..f08de93 100644 --- a/lib/Components/ScannerBouton.dart +++ b/lib/Components/ScannerBouton.dart @@ -16,7 +16,7 @@ class _ScannerBoutonState extends State { void _onItemTapped() { setState(() { - showScannerDialog("nn rien", context); + showScannerDialog(context); /*if(widget.isReplacement) { Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => const ScannerPage(), diff --git a/lib/Components/ScannerDialog.dart b/lib/Components/ScannerDialog.dart index 463fda7..13e5853 100644 --- a/lib/Components/ScannerDialog.dart +++ b/lib/Components/ScannerDialog.dart @@ -224,9 +224,9 @@ class _ScannerTESTState extends State { if(result!.format == BarcodeFormat.qrcode) { controller.pauseCamera(); print("QR CODE FOUND"); - ScaffoldMessenger.of(context).showSnackBar( + /*ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('QR CODE FOUND - ${code.toString()}')), - ); + );*/ // TODO search in local if data == Id of Article //Navigator.of(context).pop(); @@ -263,7 +263,7 @@ class _ScannerTESTState extends State { } } -showScannerDialog (String question, BuildContext context) { +showScannerDialog (BuildContext context) { showDialog( builder: (BuildContext context) => const AlertDialog( shape: RoundedRectangleBorder( diff --git a/lib/Components/SliderImages.dart b/lib/Components/SliderImages.dart new file mode 100644 index 0000000..7a53cbc --- /dev/null +++ b/lib/Components/SliderImages.dart @@ -0,0 +1,189 @@ +import 'dart:convert'; +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.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'; +import 'package:photo_view/photo_view.dart'; + +class SliderImagesWidget extends StatefulWidget { + final List resources; + final double height; + SliderImagesWidget({required this.resources, required this.height}); + + @override + _SliderImagesWidget createState() => _SliderImagesWidget(); +} + +class _SliderImagesWidget extends State { + late CarouselController? sliderController; + int currentIndex = 1; + + @override + void initState() { + sliderController = CarouselController(); + super.initState(); + } + + @override + void dispose() { + print("COUCOU DISPOSE"); + sliderController = null; + super.dispose(); + print("COUCOU DISPOSE AFTER"); + } + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + Size size = MediaQuery.of(context).size; + return Stack( + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + if(widget.resources.isNotEmpty) + CarouselSlider( + carouselController: sliderController, + options: CarouselOptions( + onPageChanged: (int index, CarouselPageChangedReason reason) { + setState(() { + currentIndex = index + 1; + }); + }, + height: widget.height * 0.95, + enlargeCenterPage: true, + reverse: false, + ), + items: widget.resources.map((i) { + return Builder( + builder: (BuildContext context) { + return Container( + width: size.width, + height: widget.height, + /*decoration: BoxDecoration( + //color: appContext.getContext().configuration == null ? kBackgroundGrey : appContext.getContext().configuration.secondaryColor != null ? new Color(int.parse(appContext.getContext().configuration.secondaryColor.split('(0x')[1].split(')')[0], radix: 16)): kBackgroundGrey, + borderRadius: BorderRadius.circular(5.0), + //border: Border.all(width: 0.3, color: kSecondGrey), + ),*/ + child: Container( + height: widget.height * 1, + width: size.width * 0.95, + child: AspectRatio( + aspectRatio: 16 / 9, + child: ClipRRect( + borderRadius: BorderRadius.circular(35.0), + child: 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),*/ + ), + ), + ), + ), + ),/*Column( + //crossAxisAlignment: CrossAxisAlignment.center, + //mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Padding( + padding: const EdgeInsets.all(10.0), + child: Container( + height: widget.height * 0.5, + width: size.width * 1, + child: Stack( + children: [ + Center( + child: /*Container( + height: widget.height * 1, + width: size.width * 0.95, + child: AspectRatio( + aspectRatio: 16 / 9, + child: ClipRect( + child: PhotoView( + imageProvider: Image.memory(base64Decode(i!.data!)).image, + minScale: PhotoViewComputedScale.contained * 0.8, + maxScale: PhotoViewComputedScale.contained * 3.0, + backgroundDecoration: BoxDecoration( + color: kBackgroundSecondGrey, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(15.0), + ), + ), + ), + ), + ),*/ + ), + ] + ), + ), + ), + ], + )*/ + ); + }, + ); + }).toList(), + ), + ], + ), + if(widget.resources.length > 1) + Positioned( + top: widget.height * 0.45, + right: 0, + child: InkWell( + onTap: () { + sliderController!.nextPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); + }, + child: const Icon( + Icons.chevron_right, + size: 45, + color: kMainColor, + ), + ) + ), + if(widget.resources.length > 1) + Positioned( + top: widget.height * 0.45, + left: 0, + child: InkWell( + onTap: () { + if (widget.resources.isNotEmpty) { + sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); + } + }, + child: const Icon( + Icons.chevron_left, + size: 45, + color: kMainColor, + ), + ) + ), + if(widget.resources.isNotEmpty) + Padding( + padding: const EdgeInsets.only(bottom: 2.5), + child: Align( + alignment: Alignment.bottomCenter, + child: InkWell( + onTap: () { + sliderController!.previousPage(duration: const Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); + }, + child: Text( + currentIndex.toString()+'/'+widget.resources.length.toString(), + style: const TextStyle(fontSize: kArticleContentSize, fontWeight: FontWeight.w500, color: kMainColor), + ), + ) + ), + ), + if(widget.resources.isEmpty) + const Center(child: Text("Aucune image à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect),)) + ] + ); + } +} \ No newline at end of file diff --git a/lib/Screens/Article/article.dart b/lib/Screens/Article/article.dart index 8f8dacd..0aa264d 100644 --- a/lib/Screens/Article/article.dart +++ b/lib/Screens/Article/article.dart @@ -3,14 +3,13 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; -import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/Loading.dart'; import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; +import 'package:mymuseum_visitapp/Components/SliderImages.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/resourceModel.dart'; -import 'package:mymuseum_visitapp/Screens/Scanner/scanner_old.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; @@ -28,33 +27,111 @@ class ArticlePage extends StatefulWidget { class _ArticlePageState extends State { SectionDTO? sectionDTO; ArticleDTO? articleDTO; - ResourceModel? resourceModel; + ResourceModel? mainResource; + List resourcesModel = []; + final GlobalKey _scaffoldKey = GlobalKey(); @override Widget build(BuildContext context) { final appContext = Provider.of(context); + Size size = MediaQuery.of(context).size; return Scaffold( - appBar: CustomAppBar( - title: "ArticlePage", + key: _scaffoldKey, + /*appBar: CustomAppBar( + title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, appContext) : "", isHomeButton: false, - ), + ),*/ body: FutureBuilder( future: getArticle(appContext.clientAPI, widget.articleId), builder: (context, AsyncSnapshot snapshot) { if(articleDTO != null && sectionDTO != null) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(TranslationHelper.get(sectionDTO!.title, appContext)), - Text( - TranslationHelper.get(articleDTO!.content, appContext), - style: Theme.of(context).textTheme.headline4, - textAlign: TextAlign.center, + return Column( + children: [ + if(mainResource != null) + Container( + height: size.height * 0.2, + width: size.width, + child: Stack( + 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 + ), + ) + ], + ), + 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: 0, + left: 0, + child: Text("Coucou")) + ], + ), + decoration: BoxDecoration( + image: DecorationImage( + opacity: 0.45, + image: Image.memory(base64Decode(mainResource!.data!)).image, + fit: BoxFit.cover, + ), + //color: kMainColor + ), ), - resourceModel != null ? Image.memory(base64Decode(resourceModel!.data!)) : const Text("image"), - ], - ), + + + + if(articleDTO!.isContentTop!) + getContent(size, appContext), + if(articleDTO!.isContentTop!) + getImages(size), + + if(!articleDTO!.isContentTop!) + getImages(size), + if(!articleDTO!.isContentTop!) + getContent(size, appContext), + + ], ); } else { return const Loading(); @@ -62,25 +139,101 @@ class _ArticlePageState extends State { } ), - floatingActionButton: const ScannerBouton(isReplacement: true), + //floatingActionButton: const ScannerBouton(isReplacement: true), + ); + } + + + + Widget getImages(Size size) { + return SizedBox( + width: size.width, + height: size.height * 0.3, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + decoration: BoxDecoration( + color: kBackgroundGrey, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(5.0), + boxShadow: const [ + BoxShadow( + color: kBackgroundGrey, + spreadRadius: 0.15, + blurRadius: 3.5, + offset: Offset(0, 1), // changes position of shadow + ), + ], + ), + child: SliderImagesWidget(resources: resourcesModel, height: size.height * 0.29) + ) + ) + ); + } + + Widget getContent(Size size, AppContext appContext) { + return SizedBox( + width: size.width, + height: size.height * 0.49, + child: Padding( + padding: const EdgeInsets.only(left: 8.0, right: 8.0, top: 8.0), + child: Container( + decoration: BoxDecoration( + color: kBackgroundGrey, + shape: BoxShape.rectangle, + borderRadius: BorderRadius.circular(5.0), + boxShadow: const [ + BoxShadow( + color: kBackgroundGrey, + spreadRadius: 0.15, + blurRadius: 3.5, + offset: Offset(0, 1), // changes position of shadow + ), + ], + ), + 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 { try { bool isOnline = await hasNetwork(); - if(true) { + if(sectionDTO == null || articleDTO == null) { await DatabaseHelper.instance.queryWithId(DatabaseTableType.sections, articleId).then((value) async { - sectionDTO = DatabaseHelper.instance.getSectionFromDB(value.first); - if(sectionDTO!.type == SectionType.Article) { - articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!)); - if(articleDTO!.images!.isNotEmpty) { - await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, articleDTO!.images!.first.resourceId!).then((value) { - resourceModel = DatabaseHelper.instance.getResourceFromDB(value.first); + setState(() { + sectionDTO = DatabaseHelper.instance.getSectionFromDB(value.first); + if(sectionDTO!.type == SectionType.Article) { + articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!)); + } + }); + if(sectionDTO!.imageId != null) { + await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) { + mainResource = DatabaseHelper.instance.getResourceFromDB(value.first); + }); + } + if(articleDTO!.images!.isNotEmpty) { + for (var image in articleDTO!.images!) { + print(image); + await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, image.resourceId!).then((value) { + resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(value.first)); }); } - } + if(mainResource == null && resourcesModel.isNotEmpty) { + mainResource = resourcesModel.first; + } + } }); } else { // TODO ONLINE diff --git a/lib/constants.dart b/lib/constants.dart index d98bd39..32ec41b 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -6,7 +6,9 @@ const kMainColor = Color(0xFF306bac); const kSecondColor = Color(0xFF309cb0); const kConfigurationColor = Color(0xFF2F4858); - +const kArticleTitleSize = 25.0; +const kArticleDescriptionSize = 12.5; +const kArticleContentSize = 16.0; const List languages = ["FR", "NL", "EN", "DE"]; // hmmmm depends on config.. @@ -17,8 +19,6 @@ const kHeadingTextStyle = TextStyle( color: Color(0xFFFFFFFF) ); - - const kMainGrey = Color(0xFF424242); const kSecondGrey = Color(0xFF555457); const kTestSecondColor = Color(0xFF2F4858); diff --git a/pubspec.lock b/pubspec.lock index bb30553..98dafc6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -99,6 +99,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "8.4.0" + carousel_slider: + dependency: "direct main" + description: + name: carousel_slider + url: "https://pub.dartlang.org" + source: hosted + version: "4.1.1" characters: dependency: transitive description: @@ -408,6 +415,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "5.0.0" + photo_view: + dependency: "direct main" + description: + name: photo_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.0" pool: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index aa5b239..b966d16 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,7 +36,9 @@ dependencies: openapi_generator_annotations: ^4.0.0 sqflite: provider: ^5.0.0 + carousel_slider: ^4.0.0 flutter_svg: ^1.1.3 + photo_view: ^0.13.0 manager_api: path: manager_api