import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/loading_common.dart'; import 'package:mymuseum_visitapp/Components/SliderImages.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; import 'package:mymuseum_visitapp/Models/articleRead.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/Services/apiService.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; import 'package:path_provider/path_provider.dart'; import 'audio_player_floating.dart'; class ArticlePage extends StatefulWidget { const ArticlePage({Key? key, required this.visitAppContextIn, required this.articleId}) : super(key: key); final String articleId; final VisitAppContext visitAppContextIn; @override State createState() => _ArticlePageState(); } class _ArticlePageState extends State { SectionDTO? sectionDTO; ArticleDTO? articleDTO; List resourcesModel = []; ResourceModel? audioResourceModel; final GlobalKey _scaffoldKey = GlobalKey(); late File audioFile; late VisitAppContext visitAppContext; @override void initState() { widget.visitAppContextIn.isContentCurrentlyShown = true; super.initState(); } @override void dispose() { visitAppContext.isContentCurrentlyShown = false; super.dispose(); } @override Widget build(BuildContext context) { final appContext = Provider.of(context); Size size = MediaQuery.of(context).size; //final notchInset = MediaQuery.of(context).padding; visitAppContext = appContext.getContext(); return Scaffold( key: _scaffoldKey, appBar: CustomAppBar( title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, visitAppContext) : "", isHomeButton: false, isTextSizeButton: true, ), body: FutureBuilder( future: getArticle(appContext, visitAppContext.clientAPI, widget.articleId, false), builder: (context, AsyncSnapshot snapshot) { if(articleDTO != null && sectionDTO != null) { 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 SizedBox( height: size.height, width: size.width, child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, 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 const LoadingCommon(); } } ), floatingActionButton: FutureBuilder( future: getArticle(appContext, visitAppContext.clientAPI, widget.articleId, true), builder: (context, AsyncSnapshot snapshot) { return Padding( padding: EdgeInsets.only(right: 0, top: 0), //size.height*0.1 child: audioResourceModel != null && audioResourceModel!.source != null ? AudioPlayerFloatingContainer(file: audioFile, resourceURl: "", isAuto: articleDTO!.isReadAudioAuto!) : null, ); } ), floatingActionButtonLocation: FloatingActionButtonLocation.miniEndFloat, //miniEndTop ); } Widget getImages(Size size, bool isContentTop) { if(size.width > size.height) { return SizedBox( width: size.width *0.5, height: size.height * 0.75, 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: kMainColor2, 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, contentsDTO: articleDTO!.contents!, ) ) ) ); } 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: kMainColor2, 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, contentsDTO: articleDTO!.contents!, ) ) ) ); } } 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: kMainColor2, 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: HtmlWidget( TranslationHelper.get(articleDTO!.content, appContext.getContext()), textStyle: TextStyle(fontSize: (appContext.getContext() as VisitAppContext).isMaximizeTextSize ? kArticleContentBiggerSize : kArticleContentSize), customStylesBuilder: (element) { return {'font-family': "Roboto"}; } //textAlign: TextAlign.left, ), ), ) ) ) ), ); } 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: kMainColor2, 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: HtmlWidget( TranslationHelper.get(articleDTO!.content, appContext.getContext()), //textAlign: TextAlign.left, textStyle: TextStyle(fontSize: (appContext.getContext() as VisitAppContext).isMaximizeTextSize ? kArticleContentBiggerSize : kArticleContentSize, fontFamily: "Arial"), ), ), ) ) ) ), ); } } Future getArticle(AppContext appContext, Client client, String articleId, bool isAudio) async { try { if(sectionDTO == null || articleDTO == null) { bool isConfigOffline = (appContext.getContext() as VisitAppContext).configuration!.isOffline!; if(isConfigOffline) { // OFFLINE List> sectionTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, articleId); if(sectionTest.isNotEmpty) { sectionDTO = DatabaseHelper.instance.getSectionFromDB(sectionTest.first); try { SectionRead articleRead = SectionRead(id: sectionDTO!.id!, readTime: DateTime.now().millisecondsSinceEpoch); await DatabaseHelper.instance.insert(DatabaseTableType.articleRead, articleRead.toMap()); visitAppContext.readSections.add(articleRead); appContext.setContext(visitAppContext); } catch (e) { print("DATABASE ERROR ARTICLEREAD"); print(e); } } else { print("EMPTY SECTION"); } } else { // ONLINE SectionDTO? sectionOnline = await client.sectionApi!.sectionGetDetail(articleId); if(sectionOnline != null) { sectionDTO = sectionOnline; try { SectionRead articleRead = SectionRead(id: sectionDTO!.id!, readTime: DateTime.now().millisecondsSinceEpoch); await DatabaseHelper.instance.insert(DatabaseTableType.articleRead, articleRead.toMap()); visitAppContext.readSections.add(articleRead); appContext.setContext(visitAppContext); } catch (e) { print("DATABASE ERROR ARTICLEREAD"); print(e); } } else { print("EMPTY SECTION"); } } if(sectionDTO!.type == SectionType.Article) { articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!)); } if(articleDTO != null && isAudio) { var audioIdArticle = articleDTO!.audioIds!.where((audioId) => audioId.language == (appContext.getContext() as VisitAppContext).language); if(audioIdArticle.isNotEmpty && audioIdArticle.first.value != null) { if(isConfigOffline) { try{ // OFFLINE List> ressourceTest = await DatabaseHelper .instance.queryWithColumnId( DatabaseTableType.resources, audioIdArticle.first.value!); if (ressourceTest.isNotEmpty) { audioResourceModel = DatabaseHelper.instance.getResourceFromDB(ressourceTest.first); print(audioResourceModel!.id); if(audioResourceModel!.path != null) { audioFile = File(audioResourceModel!.path!); } } else { print("EMPTY resourcesModel - first"); } /*List> ressourceTest = await DatabaseHelper .instance.queryWithColumnId( DatabaseTableType.resources, audioIdArticle.first.value!); if (ressourceTest.isNotEmpty) { audioResourceModel = DatabaseHelper.instance.getResourceFromDB(ressourceTest.first); print(audioResourceModel!.id); Uint8List base64String = base64Decode(audioResourceModel!.path!); // TODO get from file audiobytes = base64String; } else { print("EMPTY resourcesModel - first"); }*/ } catch(e) { print("Error in audio loading: " + e.toString()); } } else { // TODO Get file instead.. if exist ResourceDTO? resourceDTO = await client.resourceApi!.resourceGetDetail(audioIdArticle.first.value!); if(resourceDTO != null && resourceDTO.url != null) { // ONLINE //ResourceModel? resourceAudioOnline = await ApiService.downloadAudio(client, resourceDTO.url!, resourceDTO.id!); ResourceModel resourceAudioOnline = ResourceModel(); resourceAudioOnline.source = resourceDTO.url; audioResourceModel = resourceAudioOnline; /*Uint8List base64String = base64Decode(resourceAudioOnline.path!); // GET FROM FILE audiobytes = base64String;*/ } else { print("EMPTY resourcesModel online - audio"); } } } } if(articleDTO!.contents!.isNotEmpty && !isAudio) { for (var image in articleDTO!.contents!) { if(image.resourceId != null) { if(isConfigOffline) { // OFFLINE List> ressourceArticle = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.resources, image.resourceId!); if(ressourceArticle.isNotEmpty) { resourcesModel.add(DatabaseHelper.instance.getResourceFromDB(ressourceArticle.first)); } else { print("EMPTY resourcesModel - second"); } } else { // ONLINE // Not needed as it's in display logic //ResourceModel? resourceImageOnline = await ApiService.downloadImage(client, image); //if(resourceImageOnline != null) { resourcesModel.add(ResourceModel(id: image.resourceId, source: image.resourceUrl, type: ResourceType.Image)); /*} else { print("EMPTY resourcesModel online - audio"); }*/ } } } } setState(() { //print(sectionDTO!.title); }); } else { return null; // TODO return local list.. } } catch (e) { print(e); print("IN CATCH"); return null; } } }