Working Web, Pdf and Video type + misc and clean code
This commit is contained in:
parent
4946247812
commit
bddde86974
@ -4,8 +4,6 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Quizz/quizz_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/section_page.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
|
||||
@ -32,10 +32,11 @@ class _SearchBoxState extends State<SearchBox> {
|
||||
vertical: kDefaultPadding / 4, // 5 top and bottom
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.4),
|
||||
color: Colors.white.withValues(alpha: 0.4),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: TextFormField(
|
||||
cursorColor: kMainColor,
|
||||
controller: _controller,
|
||||
onChanged: widget.onChanged,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
|
||||
@ -26,10 +26,11 @@ class _SearchNumberBoxState extends State<SearchNumberBox> {
|
||||
vertical: kDefaultPadding / 4, // 5 top and bottom
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.4),
|
||||
color: Colors.white.withValues(alpha: 0.4),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: TextFormField(
|
||||
cursorColor: kMainColor,
|
||||
controller: _controller,
|
||||
onChanged: widget.onChanged,
|
||||
keyboardType: TextInputType.number,
|
||||
|
||||
@ -6,9 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Components/CustomAppBar.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/section_page.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:qr_code_scanner/qr_code_scanner.dart';
|
||||
|
||||
// NOT USED ANYMORE
|
||||
|
||||
@ -13,7 +13,7 @@ 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/Screens/Sections/Article/audio_player.dart';
|
||||
import 'package:mymuseum_visitapp/Services/apiService.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/client.dart';
|
||||
124
lib/Screens/Sections/PDF/pdf_filter.dart
Normal file
124
lib/Screens/Sections/PDF/pdf_filter.dart
Normal file
@ -0,0 +1,124 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class PdfFilter extends StatefulWidget {
|
||||
final List<OrderedTranslationAndResourceDTO> pdfsList;
|
||||
final Function(int?) onPDFSelected;
|
||||
|
||||
PdfFilter({required this.pdfsList, required this.onPDFSelected});
|
||||
|
||||
@override
|
||||
_PdfFilterState createState() => _PdfFilterState();
|
||||
}
|
||||
|
||||
class _PdfFilterState extends State<PdfFilter> with SingleTickerProviderStateMixin {
|
||||
bool isExpanded = false;
|
||||
int _selectedOrderPdf = 0;
|
||||
late AnimationController _controller;
|
||||
late Animation<double> _widthAnimation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
|
||||
_widthAnimation = Tween<double>(begin: 40, end: 250).animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
|
||||
}
|
||||
|
||||
void toggleExpand() {
|
||||
setState(() {
|
||||
isExpanded = !isExpanded;
|
||||
isExpanded ? _controller.forward() : _controller.reverse();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appContext = Provider.of<AppContext>(context);
|
||||
VisitAppContext visitAppContext = appContext.getContext();
|
||||
var currentLanguage = visitAppContext.language;
|
||||
|
||||
var primaryColor = visitAppContext.configuration?.primaryColor != null
|
||||
? Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16))
|
||||
: kSecondColor;
|
||||
|
||||
double rounded = visitAppContext.configuration?.roundedValue?.toDouble() ?? 20.0;
|
||||
|
||||
return AnimatedBuilder(
|
||||
animation: _widthAnimation,
|
||||
builder: (context, child) {
|
||||
return Container(
|
||||
width: _widthAnimation.value,
|
||||
height: isExpanded ? 300 : 75,
|
||||
decoration: BoxDecoration(
|
||||
color: isExpanded ? primaryColor.withValues(alpha: 0.9) : primaryColor.withValues(alpha: 0.5) ,
|
||||
borderRadius: BorderRadius.only(
|
||||
topRight: Radius.circular(rounded),
|
||||
bottomRight: Radius.circular(rounded),
|
||||
),
|
||||
),
|
||||
child: isExpanded
|
||||
? Column(
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close, color: Colors.white),
|
||||
onPressed: toggleExpand,
|
||||
),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: widget.pdfsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
var pdfItem = widget.pdfsList[index];
|
||||
var title = pdfItem.translationAndResourceDTOs!
|
||||
.firstWhere((pfat) => pfat.language == currentLanguage)
|
||||
.value;
|
||||
|
||||
bool isSelected = _selectedOrderPdf == pdfItem.order;
|
||||
|
||||
return ListTile(
|
||||
title: HtmlWidget(
|
||||
title!,
|
||||
textStyle: TextStyle(
|
||||
fontSize: 15.0,
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
color: isSelected ? Colors.white : Colors.black,
|
||||
fontFamily: 'Roboto',
|
||||
),
|
||||
customStylesBuilder: (element)
|
||||
{
|
||||
return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"};
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedOrderPdf = pdfItem.order!;
|
||||
});
|
||||
widget.onPDFSelected(_selectedOrderPdf);
|
||||
toggleExpand(); // collapse after selection
|
||||
},
|
||||
tileColor: isSelected ? primaryColor.withValues(alpha: 0.6) : null,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: IconButton(
|
||||
icon: const Icon(Icons.menu, color: Colors.white),
|
||||
onPressed: toggleExpand,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
349
lib/Screens/Sections/PDF/pdf_view.dart
Normal file
349
lib/Screens/Sections/PDF/pdf_view.dart
Normal file
@ -0,0 +1,349 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
//import 'dart:html';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_pdfview/flutter_pdfview.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Components/loading_common.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/PDF/pdf_filter.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
||||
class PDFPage extends StatefulWidget {
|
||||
final PdfDTO section;
|
||||
const PDFPage({super.key, required this.section});
|
||||
|
||||
@override
|
||||
_PDFPage createState() => _PDFPage();
|
||||
}
|
||||
|
||||
class _PDFPage extends State<PDFPage> {
|
||||
PdfDTO pdfDTO = PdfDTO();
|
||||
String remotePDFpath = "";
|
||||
final Completer<PDFViewController> _controller = Completer<PDFViewController>();
|
||||
int? pages = 0;
|
||||
int? currentPage = 0;
|
||||
bool isReady = false;
|
||||
String errorMessage = '';
|
||||
late ValueNotifier<OrderedTranslationAndResourceDTO?> selectedPdf = ValueNotifier<OrderedTranslationAndResourceDTO?>(pdfDTO.pdfs!.first);
|
||||
ValueNotifier<Map<String, int>> currentState = ValueNotifier<Map<String, int>>({'page': 0, 'total': 1});
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
/*print(widget.section!.data);
|
||||
pdfDTO = PdfDTO.fromJson(jsonDecode(widget.section!.data!))!;
|
||||
print(pdfDTO);*/
|
||||
pdfDTO = widget.section;
|
||||
pdfDTO.pdfs!.sort((a, b) => a.order!.compareTo(b.order!));
|
||||
|
||||
super.initState();
|
||||
|
||||
/*createFileOfPdfUrl(pdfDTO.source_!).then((f) {
|
||||
setState(() {
|
||||
remotePDFpath = f.path;
|
||||
print("paaath");
|
||||
print(remotePDFpath);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
|
||||
Future<File?> createFileOfPdfUrl(VisitAppContext visitAppContext, OrderedTranslationAndResourceDTO pdfFileDTO) async {
|
||||
Completer<File?> completer = Completer();
|
||||
|
||||
if(pdfFileDTO.translationAndResourceDTOs!.firstWhere((pfat) => pfat.language == visitAppContext.language).resourceId == null) {
|
||||
completer.complete(null);
|
||||
} else {
|
||||
var file = await _checkIfLocalResourceExists(visitAppContext, pdfFileDTO.translationAndResourceDTOs!.firstWhere((pfat) => pfat.language == visitAppContext.language).resourceId!);
|
||||
|
||||
if(file == null) {
|
||||
print("Start download file from internet!");
|
||||
try {
|
||||
// "https://berlin2017.droidcon.cod.newthinking.net/sites/global.droidcon.cod.newthinking.net/files/media/documents/Flutter%20-%2060FPS%20UI%20of%20the%20future%20%20-%20DroidconDE%2017.pdf";
|
||||
// final url = "https://pdfkit.org/docs/guide.pdf";
|
||||
final url = pdfFileDTO.translationAndResourceDTOs!.firstWhere((pfat) => pfat.language == visitAppContext.language).resource!.url!;
|
||||
final filename = url.substring(url.lastIndexOf("/") + 1);
|
||||
var request = await HttpClient().getUrl(Uri.parse(url));
|
||||
var response = await request.close();
|
||||
var bytes = await consolidateHttpClientResponseBytes(response);
|
||||
var dir = await getApplicationDocumentsDirectory();
|
||||
print("Download files");
|
||||
print("${dir.path}/$filename");
|
||||
File file = File("${dir.path}/$filename");
|
||||
|
||||
await file.writeAsBytes(bytes, flush: true);
|
||||
completer.complete(file);
|
||||
} catch (e) {
|
||||
throw Exception('Error parsing asset file!');
|
||||
}
|
||||
} else {
|
||||
print("FOUND FILE PDF");
|
||||
completer.complete(file);
|
||||
}
|
||||
}
|
||||
|
||||
return completer.future;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
//_webView = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final appContext = Provider.of<AppContext>(context);
|
||||
VisitAppContext visitAppContext = appContext.getContext();
|
||||
|
||||
var primaryColor = visitAppContext.configuration != null ? visitAppContext.configuration!.primaryColor != null ? new Color(int.parse(visitAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)) : kSecondColor : kSecondColor;
|
||||
|
||||
pdfDTO.pdfs!.sort((a, b) => a.order!.compareTo(b.order!));
|
||||
Size size = MediaQuery.of(context).size;
|
||||
|
||||
var title = TranslationHelper.get(widget.section.title, appContext.getContext());
|
||||
String cleanedTitle = title.replaceAll('\n', ' ').replaceAll('<br>', ' ');
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: size.height * 0.28,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 5,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
colors: [
|
||||
/*Color(0xFFDD79C2),
|
||||
Color(0xFFB65FBE),
|
||||
Color(0xFF9146BA),
|
||||
Color(0xFF7633B8),
|
||||
Color(0xFF6528B6),
|
||||
Color(0xFF6025B6)*/
|
||||
kMainColor0, //Color(0xFFf6b3c4)
|
||||
kMainColor1,
|
||||
kMainColor2,
|
||||
|
||||
],
|
||||
),
|
||||
image: widget.section.imageSource != null ? DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.65,
|
||||
image: NetworkImage(
|
||||
widget.section.imageSource!,
|
||||
),
|
||||
): null,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: size.height * 0.11,
|
||||
width: size.width,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 22.0),
|
||||
child: SizedBox(
|
||||
width: size.width *0.7,
|
||||
child: HtmlWidget(
|
||||
cleanedTitle,
|
||||
textStyle: const TextStyle(color: Colors.white, fontFamily: 'Roboto', fontSize: 20),
|
||||
customStylesBuilder: (element)
|
||||
{
|
||||
return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"};
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 35,
|
||||
left: 10,
|
||||
child: SizedBox(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kMainColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.arrow_back, size: 23, color: Colors.white)
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(child: Container(
|
||||
margin: const EdgeInsets.only(top: 0),
|
||||
decoration: const BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 2,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
color: kBackgroundColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
),
|
||||
child: pdfDTO.pdfs != null && pdfDTO.pdfs!.isNotEmpty ?
|
||||
Center(
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: ValueListenableBuilder<OrderedTranslationAndResourceDTO?>(
|
||||
valueListenable: selectedPdf,
|
||||
builder: (context, value, _) {
|
||||
return FutureBuilder(
|
||||
future: createFileOfPdfUrl(visitAppContext, value!),
|
||||
builder: (context, AsyncSnapshot<dynamic> snapshot) {
|
||||
print("snapshot.data");
|
||||
print(snapshot.data);
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if(snapshot.data == null) {
|
||||
return Center(child: Text("Aucun fichier à afficher"));
|
||||
} else {
|
||||
return Stack(
|
||||
children: [
|
||||
PDFView(
|
||||
filePath: snapshot.data.path,
|
||||
enableSwipe: true,
|
||||
fitEachPage: true,
|
||||
swipeHorizontal: true,
|
||||
autoSpacing: false,
|
||||
pageFling: true,
|
||||
fitPolicy: FitPolicy.HEIGHT,
|
||||
onRender: (_pages) {
|
||||
//setState(() {
|
||||
pages = _pages;
|
||||
isReady = true;
|
||||
//});
|
||||
},
|
||||
onError: (error) {
|
||||
print(error.toString());
|
||||
},
|
||||
onPageError: (page, error) {
|
||||
print('$page: ${error.toString()}');
|
||||
},
|
||||
onViewCreated: (PDFViewController pdfViewController) {
|
||||
//_controller.complete(pdfViewController);
|
||||
},
|
||||
onPageChanged: (int? page, int? total) {
|
||||
currentPage = page;
|
||||
pages = total;
|
||||
currentState.value = {'page': page!, 'total': total!};
|
||||
|
||||
print('page change: $page/$total');
|
||||
},
|
||||
),
|
||||
Positioned(
|
||||
bottom: 20,
|
||||
left: 20,
|
||||
child: ValueListenableBuilder<Map<String, int>>(
|
||||
valueListenable: currentState,
|
||||
builder: (context, value, _) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(visitAppContext.configuration!.roundedValue?.toDouble() ?? 20.0)),
|
||||
color: primaryColor
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(6.0),
|
||||
child: Text("${value["page"]!+1}/${value["total"]!}",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 20)),
|
||||
)
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return Center(
|
||||
child: Container(
|
||||
child: LoadingCommon()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
pdfDTO.pdfs!.length > 1 ? Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: PdfFilter(
|
||||
pdfsList: pdfDTO.pdfs!,
|
||||
onPDFSelected: (selectedOrder) {
|
||||
selectedPdf.value = pdfDTO.pdfs!.firstWhere((pdf) => pdf.order == selectedOrder);
|
||||
}),
|
||||
): const SizedBox(),
|
||||
],
|
||||
),
|
||||
) :
|
||||
Center(child: Text("Aucun pdf à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect))))
|
||||
)
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
);
|
||||
|
||||
/**/
|
||||
}
|
||||
} //_webView
|
||||
|
||||
Future<File?> _checkIfLocalResourceExists(VisitAppContext visitAppContext, String resourceId) async {
|
||||
try {
|
||||
Directory? appDocumentsDirectory = Platform.isIOS ? await getApplicationDocumentsDirectory() : await getDownloadsDirectory();
|
||||
String localPath = appDocumentsDirectory!.path;
|
||||
Directory configurationDirectory = Directory('$localPath/${visitAppContext.configuration!.id}');
|
||||
List<FileSystemEntity> fileList = configurationDirectory.listSync();
|
||||
|
||||
if(fileList.any((fileL) => fileL.uri.pathSegments.last.contains(resourceId))) {
|
||||
File file = File(fileList.firstWhere((fileL) => fileL.uri.pathSegments.last.contains(resourceId)).path);
|
||||
return file;
|
||||
}
|
||||
} catch (e) {
|
||||
print("ERROR _checkIfLocalResourceExists PDF");
|
||||
print(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -15,7 +15,7 @@ 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/Quizz/drawPath.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Quizz/questions_list.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Quiz/questions_list.dart';
|
||||
//import 'package:mymuseum_visitapp/Screens/Quizz/showResponses.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/client.dart';
|
||||
263
lib/Screens/Sections/Video/video_view.dart
Normal file
263
lib/Screens/Sections/Video/video_view.dart
Normal file
@ -0,0 +1,263 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
//import 'package:youtube_player_iframe/youtube_player_iframe.dart' as iframe;
|
||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||
|
||||
class VideoPage extends StatefulWidget {
|
||||
final VideoDTO section;
|
||||
VideoPage({required this.section});
|
||||
|
||||
@override
|
||||
_VideoPage createState() => _VideoPage();
|
||||
}
|
||||
|
||||
class _VideoPage extends State<VideoPage> {
|
||||
//iframe.YoutubePlayer? _videoViewWeb;
|
||||
YoutubePlayer? _videoView;
|
||||
VideoDTO? videoDTO;
|
||||
late YoutubePlayerController _controller;
|
||||
bool isFullScreen = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
//print(widget.section!.data);
|
||||
//videoDTO = VideoDTO.fromJson(jsonDecode(widget.section!.data!));
|
||||
//print(videoDTO);
|
||||
videoDTO= widget.section;
|
||||
|
||||
String? videoId;
|
||||
if (videoDTO!.source_ != null && videoDTO!.source_!.isNotEmpty) {
|
||||
videoId = YoutubePlayer.convertUrlToId(videoDTO!.source_!);
|
||||
|
||||
/*if (false) {
|
||||
final _controllerWeb = iframe.YoutubePlayerController(
|
||||
params: iframe.YoutubePlayerParams(
|
||||
mute: false,
|
||||
showControls: true,
|
||||
showFullscreenButton: false,
|
||||
loop: true,
|
||||
showVideoAnnotations: false,
|
||||
strictRelatedVideos: false,
|
||||
enableKeyboard: false,
|
||||
enableCaption: false,
|
||||
pointerEvents: iframe.PointerEvents.auto
|
||||
),
|
||||
);
|
||||
|
||||
_controllerWeb.loadVideo(videoDTO!.source_!);
|
||||
|
||||
_videoViewWeb = iframe.YoutubePlayer(
|
||||
controller: _controllerWeb,
|
||||
//showVideoProgressIndicator: false,
|
||||
/*progressIndicatorColor: Colors.amber,
|
||||
progressColors: ProgressBarColors(
|
||||
playedColor: Colors.amber,
|
||||
handleColor: Colors.amberAccent,
|
||||
),*/
|
||||
);
|
||||
} else {*/
|
||||
videoId = YoutubePlayer.convertUrlToId(videoDTO!.source_!);
|
||||
_controller = YoutubePlayerController(
|
||||
initialVideoId: videoId!,
|
||||
flags: const YoutubePlayerFlags(
|
||||
autoPlay: true,
|
||||
controlsVisibleAtStart: false,
|
||||
loop: true,
|
||||
hideControls: false,
|
||||
hideThumbnail: true,
|
||||
),
|
||||
)..addListener(_onYoutubePlayerChanged);
|
||||
|
||||
_videoView = YoutubePlayer(
|
||||
controller: _controller,
|
||||
//showVideoProgressIndicator: false,
|
||||
progressIndicatorColor: kMainColor,
|
||||
progressColors: const ProgressBarColors(
|
||||
playedColor: kMainColor,
|
||||
handleColor: kSecondColor,
|
||||
),
|
||||
);
|
||||
//}
|
||||
_controller.toggleFullScreenMode();
|
||||
super.initState();
|
||||
}
|
||||
}
|
||||
|
||||
void _onYoutubePlayerChanged() {
|
||||
if (_controller.value.isFullScreen) {
|
||||
setState(() {
|
||||
isFullScreen = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
isFullScreen = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_videoView = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
final appContext = Provider.of<AppContext>(context);
|
||||
|
||||
var title = TranslationHelper.get(widget.section.title, appContext.getContext());
|
||||
String cleanedTitle = title.replaceAll('\n', ' ').replaceAll('<br>', ' ');
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
!isFullScreen ? Container(
|
||||
height: size.height * 0.28,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 5,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
colors: [
|
||||
/*Color(0xFFDD79C2),
|
||||
Color(0xFFB65FBE),
|
||||
Color(0xFF9146BA),
|
||||
Color(0xFF7633B8),
|
||||
Color(0xFF6528B6),
|
||||
Color(0xFF6025B6)*/
|
||||
kMainColor0, //Color(0xFFf6b3c4)
|
||||
kMainColor1,
|
||||
kMainColor2,
|
||||
|
||||
],
|
||||
),
|
||||
image: widget.section.imageSource != null ? DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.65,
|
||||
image: NetworkImage(
|
||||
widget.section.imageSource!,
|
||||
),
|
||||
): null,
|
||||
),
|
||||
) : const SizedBox(),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
!isFullScreen ? SizedBox(
|
||||
height: size.height * 0.11,
|
||||
width: size.width,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 22.0),
|
||||
child: SizedBox(
|
||||
width: size.width *0.7,
|
||||
child: HtmlWidget(
|
||||
cleanedTitle,
|
||||
textStyle: const TextStyle(color: Colors.white, fontFamily: 'Roboto', fontSize: 20),
|
||||
customStylesBuilder: (element)
|
||||
{
|
||||
return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"};
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 35,
|
||||
left: 10,
|
||||
child: SizedBox(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_controller.dispose();
|
||||
_videoView = null;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kMainColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.arrow_back, size: 23, color: Colors.white)
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
): const SizedBox(),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(top: 0),
|
||||
decoration: const BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 2,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
color: kBackgroundColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: !isFullScreen ? const BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
): BorderRadius.zero,
|
||||
child: videoDTO!.source_ != null && videoDTO!.source_!.isNotEmpty ?
|
||||
_videoView :
|
||||
const Center(child: Text("La vidéo ne peut pas être affichée, l'url est incorrecte", style: TextStyle(fontSize: kNoneInfoOrIncorrect))))
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
isFullScreen ? Positioned(
|
||||
top: 35,
|
||||
left: 10,
|
||||
child: SizedBox(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_controller.toggleFullScreenMode();
|
||||
_controller.dispose();
|
||||
_videoView = null;
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kMainColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.arrow_back, size: 23, color: Colors.white)
|
||||
),
|
||||
)
|
||||
),
|
||||
): const SizedBox(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
242
lib/Screens/Sections/Web/web_page.dart
Normal file
242
lib/Screens/Sections/Web/web_page.dart
Normal file
@ -0,0 +1,242 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Components/loading_common.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:webview_flutter/webview_flutter.dart';
|
||||
import 'package:webview_flutter_platform_interface/webview_flutter_platform_interface.dart';
|
||||
|
||||
class WebPage extends StatefulWidget {
|
||||
final WebDTO section;
|
||||
WebPage({required this.section});
|
||||
|
||||
@override
|
||||
_WebPage createState() => _WebPage();
|
||||
}
|
||||
|
||||
class _WebPage extends State<WebPage> {
|
||||
//final IFrameElement _iframeElement = IFrameElement();
|
||||
//WebView _webView;
|
||||
WebDTO webDTO = WebDTO();
|
||||
WebViewController? controller;
|
||||
PlatformWebViewController? controllerWeb;
|
||||
bool isLoading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
//print(widget.section!.data);
|
||||
webDTO = widget.section;
|
||||
//webDTO = WebDTO.fromJson(jsonDecode(widget.section!.data!))!;
|
||||
print(webDTO);
|
||||
|
||||
|
||||
if(kIsWeb) {
|
||||
/*_iframeElement.src = webDTO.source_!;
|
||||
_iframeElement.style.border = 'none';
|
||||
|
||||
//ignore: undefined_prefixed_name
|
||||
ui.platformViewRegistry.registerViewFactory(
|
||||
webDTO.source_!, //use source as registered key to ensure uniqueness
|
||||
(int viewId) => _iframeElement,
|
||||
);*/
|
||||
} else {
|
||||
|
||||
if(webDTO.source_ != null && webDTO.source_!.length > 0) {
|
||||
try {
|
||||
controller = WebViewController()
|
||||
..setJavaScriptMode(JavaScriptMode.unrestricted)
|
||||
..setBackgroundColor(const Color(0x00000000))
|
||||
..setNavigationDelegate(
|
||||
NavigationDelegate(
|
||||
onProgress: (int progress) {
|
||||
// Update loading bar.
|
||||
},
|
||||
onPageStarted: (String url) {},
|
||||
onPageFinished: (String url) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
},
|
||||
onWebResourceError: (WebResourceError error) {},
|
||||
onNavigationRequest: (NavigationRequest request) {
|
||||
Uri sourceUri = Uri.parse(webDTO.source_!);
|
||||
Uri requestUri = Uri.parse(request.url);
|
||||
|
||||
if (requestUri.host != sourceUri.host) { // handle navigation to site
|
||||
print('blocking navigation to $request}');
|
||||
return NavigationDecision.prevent;
|
||||
}
|
||||
return NavigationDecision.navigate;
|
||||
},
|
||||
),
|
||||
)
|
||||
..loadRequest(Uri.parse(webDTO.source_!));
|
||||
} catch (e) {
|
||||
print("Invalid source ${webDTO.source_}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.initState();
|
||||
/*_webView = WebView(
|
||||
initialUrl: webDTO.source_, //"https://my.matterport.com/show/?m=k8bvdezfHbT"
|
||||
javascriptMode: JavascriptMode.unrestricted,
|
||||
navigationDelegate: (NavigationRequest request) {
|
||||
print(request.url);
|
||||
print(webDTO.source_);
|
||||
if (request.url != webDTO.source_) {
|
||||
print('blocking navigation to $request}');
|
||||
return NavigationDecision.prevent;
|
||||
}
|
||||
print('allowing navigation to $request');
|
||||
return NavigationDecision.navigate;
|
||||
}
|
||||
);*/
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
//_webView = null;
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Size size = MediaQuery.of(context).size;
|
||||
final appContext = Provider.of<AppContext>(context);
|
||||
|
||||
var title = TranslationHelper.get(widget.section.title, appContext.getContext());
|
||||
String cleanedTitle = title.replaceAll('\n', ' ').replaceAll('<br>', ' ');
|
||||
|
||||
return webDTO.source_ != null && webDTO.source_!.isNotEmpty ?
|
||||
kIsWeb ?
|
||||
HtmlElementView(
|
||||
key: UniqueKey(),
|
||||
viewType: webDTO.source_!,
|
||||
) :
|
||||
Stack(
|
||||
children: [
|
||||
Container(
|
||||
height: size.height * 0.28,
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 5,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
colors: [
|
||||
/*Color(0xFFDD79C2),
|
||||
Color(0xFFB65FBE),
|
||||
Color(0xFF9146BA),
|
||||
Color(0xFF7633B8),
|
||||
Color(0xFF6528B6),
|
||||
Color(0xFF6025B6)*/
|
||||
kMainColor0, //Color(0xFFf6b3c4)
|
||||
kMainColor1,
|
||||
kMainColor2,
|
||||
|
||||
],
|
||||
),
|
||||
image: widget.section.imageSource != null ? DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.65,
|
||||
image: NetworkImage(
|
||||
widget.section.imageSource!,
|
||||
),
|
||||
): null,
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
height: size.height * 0.11,
|
||||
width: size.width,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 22.0),
|
||||
child: SizedBox(
|
||||
width: size.width *0.7,
|
||||
child: HtmlWidget(
|
||||
cleanedTitle,
|
||||
textStyle: const TextStyle(color: Colors.white, fontFamily: 'Roboto', fontSize: 20),
|
||||
customStylesBuilder: (element)
|
||||
{
|
||||
return {'text-align': 'center', 'font-family': "Roboto", '-webkit-line-clamp': "2"};
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
top: 35,
|
||||
left: 10,
|
||||
child: SizedBox(
|
||||
width: 50,
|
||||
height: 50,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: kMainColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(Icons.arrow_back, size: 23, color: Colors.white)
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.only(top: 0),
|
||||
decoration: const BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: kMainGrey,
|
||||
spreadRadius: 0.5,
|
||||
blurRadius: 2,
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
color: kBackgroundColor,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
),
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(30),
|
||||
topRight: Radius.circular(30),
|
||||
),
|
||||
child: isLoading ? Center(child: SizedBox(height: size.height * 0.15, child: const LoadingCommon())) : WebViewWidget(controller: controller!))
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
) :
|
||||
const Center(child: Text("La page internet ne peut pas être affichée, l'url est incorrecte ou vide", style: TextStyle(fontSize: kNoneInfoOrIncorrect)));
|
||||
}
|
||||
} //_webView
|
||||
@ -12,7 +12,7 @@ import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Models/beaconSection.dart';
|
||||
import 'package:mymuseum_visitapp/Models/resourceModel.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Services/apiService.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/client.dart';
|
||||
|
||||
@ -69,6 +69,22 @@ class _BodyState extends State<Body> {
|
||||
offset: Offset(0, 1), // changes position of shadow
|
||||
),
|
||||
],
|
||||
gradient: widget.configuration.imageSource == null ? const LinearGradient(
|
||||
begin: Alignment.centerRight,
|
||||
end: Alignment.centerLeft,
|
||||
colors: [
|
||||
/*Color(0xFFDD79C2),
|
||||
Color(0xFFB65FBE),
|
||||
Color(0xFF9146BA),
|
||||
Color(0xFF7633B8),
|
||||
Color(0xFF6528B6),
|
||||
Color(0xFF6025B6)*/
|
||||
kMainColor0, //Color(0xFFf6b3c4)
|
||||
kMainColor1,
|
||||
kMainColor2,
|
||||
|
||||
],
|
||||
) : null,
|
||||
image: widget.configuration.imageSource != null ? DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
opacity: 0.65,
|
||||
@ -170,6 +186,7 @@ class _BodyState extends State<Body> {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 0),
|
||||
child: RefreshIndicator(
|
||||
color: kMainColor,
|
||||
onRefresh: () async {
|
||||
if(!widget.configuration.isOffline!) {
|
||||
setState(() {
|
||||
|
||||
@ -13,8 +13,8 @@ import 'package:mymuseum_visitapp/Helpers/requirement_state_controller.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Models/beaconSection.dart';
|
||||
import 'package:mymuseum_visitapp/Models/visitContext.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Quizz/quizz_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Quiz/quizz_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Visit/beaconArticleFound.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/section_page.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
|
||||
@ -7,20 +7,17 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:manager_api_new/api.dart';
|
||||
import 'package:mymuseum_visitapp/Components/CustomAppBar.dart';
|
||||
import 'package:mymuseum_visitapp/Components/Loading.dart';
|
||||
import 'package:mymuseum_visitapp/Components/loading_common.dart';
|
||||
import 'package:mymuseum_visitapp/Components/rounded_button.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Helpers/translationHelper.dart';
|
||||
import 'package:mymuseum_visitapp/Models/ResponseSubDTO.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/article_page.dart';
|
||||
//import 'package:mymuseum_visitapp/Screens/Quizz/drawPath.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Quizz/questions_list.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Quizz/quizz_page.dart';
|
||||
//import 'package:mymuseum_visitapp/Screens/Quizz/showResponses.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Article/article_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/PDF/pdf_view.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Quiz/quizz_page.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Video/video_view.dart';
|
||||
import 'package:mymuseum_visitapp/Screens/Sections/Web/web_page.dart';
|
||||
import 'package:mymuseum_visitapp/app_context.dart';
|
||||
import 'package:mymuseum_visitapp/client.dart';
|
||||
import 'package:mymuseum_visitapp/constants.dart';
|
||||
@ -67,7 +64,7 @@ class _SectionPageState extends State<SectionPage> {
|
||||
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: test!.type != SectionType.Quiz && test.type != SectionType.Article ? CustomAppBar(
|
||||
appBar: test!.type != SectionType.Quiz && test.type != SectionType.Article && test.type != SectionType.Web && test.type != SectionType.Pdf && test.type != SectionType.Video ? CustomAppBar(
|
||||
title: sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, visitAppContext) : "",
|
||||
isHomeButton: false,
|
||||
) : null,
|
||||
@ -85,6 +82,15 @@ class _SectionPageState extends State<SectionPage> {
|
||||
case SectionType.Quiz:
|
||||
QuizDTO quizDTO = QuizDTO.fromJson(sectionResult)!;
|
||||
return QuizPage(visitAppContextIn: widget.visitAppContextIn, quizDTO: quizDTO, resourcesModel: resourcesModel);
|
||||
case SectionType.Web:
|
||||
WebDTO webDTO = WebDTO.fromJson(sectionResult)!;
|
||||
return WebPage(section: webDTO);
|
||||
case SectionType.Pdf:
|
||||
PdfDTO pdfDTO = PdfDTO.fromJson(sectionResult)!;
|
||||
return PDFPage(section: pdfDTO);
|
||||
case SectionType.Video:
|
||||
VideoDTO videoDTO = VideoDTO.fromJson(sectionResult)!;
|
||||
return VideoPage(section: videoDTO);
|
||||
default:
|
||||
return const Center(child: Text("Unsupported type"));
|
||||
}
|
||||
|
||||
152
pubspec.lock
152
pubspec.lock
@ -318,6 +318,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.2"
|
||||
flutter_inappwebview:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview
|
||||
sha256: "80092d13d3e29b6227e25b67973c67c7210bd5e35c4b747ca908e31eb71a46d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.5"
|
||||
flutter_inappwebview_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_android
|
||||
sha256: "62557c15a5c2db5d195cb3892aab74fcaec266d7b86d59a6f0027abd672cddba"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.3"
|
||||
flutter_inappwebview_internal_annotations:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_internal_annotations
|
||||
sha256: "787171d43f8af67864740b6f04166c13190aa74a1468a1f1f1e9ee5b90c359cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
flutter_inappwebview_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_ios
|
||||
sha256: "5818cf9b26cf0cbb0f62ff50772217d41ea8d3d9cc00279c45f8aabaa1b4025d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_inappwebview_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_macos
|
||||
sha256: c1fbb86af1a3738e3541364d7d1866315ffb0468a1a77e34198c9be571287da1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_inappwebview_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_platform_interface
|
||||
sha256: cf5323e194096b6ede7a1ca808c3e0a078e4b33cc3f6338977d75b4024ba2500
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0+1"
|
||||
flutter_inappwebview_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_web
|
||||
sha256: "55f89c83b0a0d3b7893306b3bb545ba4770a4df018204917148ebb42dc14a598"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
flutter_inappwebview_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_inappwebview_windows
|
||||
sha256: "8b4d3a46078a2cdc636c4a3d10d10f2a16882f6be607962dbfff8874d1642055"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -331,6 +395,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_pdfview:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_pdfview
|
||||
sha256: "51413e36ab3f1a2fe0edf97ebfa770e20182ea4a066bc9f292920330d9245c9d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0+1"
|
||||
flutter_staggered_grid_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -377,10 +449,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: fluttertoast
|
||||
sha256: "7eae679e596a44fdf761853a706f74979f8dd3cd92cf4e23cae161fda091b847"
|
||||
sha256: "25e51620424d92d3db3832464774a6143b5053f15e382d8ffbfd40b6e795dcf1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.2.6"
|
||||
version: "8.2.12"
|
||||
frontend_server_client:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -521,10 +593,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
|
||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.4.0"
|
||||
http_multi_server:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -601,10 +673,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: just_audio_web
|
||||
sha256: "0edb481ad4aa1ff38f8c40f1a3576013c3420bf6669b686fe661627d49bc606c"
|
||||
sha256: "9a98035b8b24b40749507687520ec5ab404e291d2b0937823ff45d92cb18d448"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.11"
|
||||
version: "0.4.13"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -736,18 +808,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus
|
||||
sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
|
||||
sha256: a75164ade98cb7d24cfd0a13c6408927c6b217fa60dee5a7ff5c116a58f28918
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
version: "8.0.2"
|
||||
package_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_info_plus_platform_interface
|
||||
sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
|
||||
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.2.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -976,10 +1048,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
|
||||
sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.2.1"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1125,10 +1197,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3"
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.3.1"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1173,10 +1245,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a"
|
||||
sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.3.3"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1261,10 +1333,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: ff4d69a6614b03f055397c27a71c9d3ddea2b2a23d71b2ba0164f59ca32b8fe2
|
||||
sha256: "881b375a934d8ebf868c7fb1423b2bfaa393a0a265fa3f733079a86536064a10"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
version: "2.3.3"
|
||||
vm_service:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1277,18 +1349,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus
|
||||
sha256: "14758533319a462ffb5aa3b7ddb198e59b29ac3b02da14173a1715d65d4e6e68"
|
||||
sha256: "775c50f226ab43ff859b479acc73f11c0744bf345a782e83355c4d25df758803"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.5"
|
||||
version: "1.3.0"
|
||||
wakelock_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wakelock_plus_platform_interface
|
||||
sha256: "422d1cdbb448079a8a62a5a770b69baa489f8f7ca21aef47800c726d404f9d16"
|
||||
sha256: e10444072e50dbc4999d7316fd303f7ea53d31c824aa5eb05d7ccbdd98985207
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
version: "1.2.3"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1301,26 +1373,26 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "1.1.1"
|
||||
web_socket:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket
|
||||
sha256: "24301d8c293ce6fe327ffe6f59d8fd8834735f0ec36e4fd383ec7ff8a64aa078"
|
||||
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.5"
|
||||
version: "1.0.1"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web_socket_channel
|
||||
sha256: a2d56211ee4d35d9b344d9d4ce60f362e4f5d1aafb988302906bd732bc731276
|
||||
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
version: "3.0.3"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1385,6 +1457,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
youtube_player_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: youtube_player_flutter
|
||||
sha256: "4d14aa47f9c84929b5400a87ade4dcfdab87a2ca2e0b18ecc2ef852b1440e123"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.1"
|
||||
youtube_player_iframe:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: youtube_player_iframe
|
||||
sha256: "66020f7756accfb22b3297565d845f9bef14249c730dd51e1ec648fa155fb24a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.2.1"
|
||||
youtube_player_iframe_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: youtube_player_iframe_web
|
||||
sha256: "05222a228937932e7ee7a6171e8020fee4cd23d1c7bf6b4128c569484338c593"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
||||
flutter: ">=3.24.0"
|
||||
|
||||
@ -50,6 +50,10 @@ dependencies:
|
||||
webview_flutter: ^4.10.0
|
||||
ar_flutter_plugin: ^0.7.3
|
||||
|
||||
flutter_pdfview: ^1.4.0+1
|
||||
youtube_player_flutter: ^9.1.1
|
||||
youtube_player_iframe: ^5.2.1
|
||||
|
||||
# Specific mobile
|
||||
qr_code_scanner: ^1.0.1 #not in web
|
||||
sqflite: #not in web
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user