336 lines
13 KiB
Dart
336 lines
13 KiB
Dart
import 'dart:convert';
|
|
import 'dart:typed_data';
|
|
|
|
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/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';
|
|
|
|
class ArticlePage extends StatefulWidget {
|
|
const ArticlePage({Key? key, required this.articleId}) : super(key: key);
|
|
|
|
final String articleId;
|
|
|
|
@override
|
|
State<ArticlePage> createState() => _ArticlePageState();
|
|
}
|
|
|
|
class _ArticlePageState extends State<ArticlePage> {
|
|
SectionDTO? sectionDTO;
|
|
ArticleDTO? articleDTO;
|
|
List<ResourceModel?> resourcesModel = <ResourceModel?>[];
|
|
ResourceModel? audioResourceModel;
|
|
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
|
late Uint8List audiobytes;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final appContext = Provider.of<AppContext>(context);
|
|
Size size = MediaQuery.of(context).size;
|
|
final notchInset = MediaQuery.of(context).padding;
|
|
|
|
return Scaffold(
|
|
key: _scaffoldKey,
|
|
appBar: CustomAppBar(
|
|
title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, appContext) : "",
|
|
isHomeButton: false,
|
|
),
|
|
body: FutureBuilder(
|
|
future: getArticle(appContext, appContext.clientAPI, widget.articleId),
|
|
builder: (context, AsyncSnapshot<dynamic> 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 Container(
|
|
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 Loading();
|
|
}
|
|
}
|
|
),
|
|
//floatingActionButton: const ScannerBouton(isReplacement: true),
|
|
);
|
|
}
|
|
|
|
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: 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!,
|
|
)
|
|
)
|
|
)
|
|
);
|
|
} 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<ArticleDTO?> getArticle(AppContext appContext, Client client, String articleId) async {
|
|
try {
|
|
if(sectionDTO == null || articleDTO == null) {
|
|
print("ARTCILE DTO GET ARTICLE");
|
|
bool isConfigOffline = (appContext.getContext() as VisitAppContext).configuration!.isOffline!;
|
|
|
|
if(isConfigOffline)
|
|
{
|
|
// OFFLINE
|
|
List<Map<String, dynamic>> sectionTest = await DatabaseHelper.instance.queryWithColumnId(DatabaseTableType.sections, articleId);
|
|
if(sectionTest.isNotEmpty) {
|
|
sectionDTO = DatabaseHelper.instance.getSectionFromDB(sectionTest.first);
|
|
print("sectionDTO!.datasectionDTO!.datasectionDTO!.datasectionDTO!.data");
|
|
} else {
|
|
print("EMPTY SECTION");
|
|
}
|
|
} else
|
|
{
|
|
// ONLINE
|
|
SectionDTO? sectionOnline = await client.sectionApi!.sectionGetDetail(articleId);
|
|
if(sectionOnline != null) {
|
|
sectionDTO = sectionOnline;
|
|
} else {
|
|
print("EMPTY SECTION");
|
|
}
|
|
}
|
|
|
|
if(sectionDTO!.type == SectionType.Article) {
|
|
print("set article __ !!");
|
|
print(sectionDTO!.data!);
|
|
articleDTO = ArticleDTO.fromJson(jsonDecode(sectionDTO!.data!));
|
|
}
|
|
|
|
if(articleDTO != null) {
|
|
if(articleDTO!.audioId != null) {
|
|
if(isConfigOffline)
|
|
{
|
|
// OFFLINE
|
|
List<Map<String, dynamic>> 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");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ONLINE
|
|
ResourceModel? resourceAudioOnline = await ApiService.downloadAudio(client, articleDTO!.audioId!);
|
|
if(resourceAudioOnline != null) {
|
|
audioResourceModel = resourceAudioOnline;
|
|
Uint8List base64String = base64Decode(resourceAudioOnline.data!);
|
|
audiobytes = base64String;
|
|
} else {
|
|
print("EMPTY resourcesModel online - audio");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(articleDTO!.images!.isNotEmpty) {
|
|
for (var image in articleDTO!.images!) {
|
|
if(image.resourceId != null) {
|
|
if(isConfigOffline)
|
|
{
|
|
// OFFLINE
|
|
List<Map<String, dynamic>> 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.source_, 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;
|
|
}
|
|
}
|
|
}
|