Puzzle (handle cols rows + message) + show element for resource

This commit is contained in:
Thomas Fransolet 2023-12-29 15:06:09 +01:00
parent e67880bc50
commit cad16a35d3
38 changed files with 1284 additions and 357 deletions

View File

@ -0,0 +1,245 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:just_audio/just_audio.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/app_context.dart';
class AudioPlayerFloatingContainer extends StatefulWidget {
const AudioPlayerFloatingContainer({Key? key, required this.audioBytes, required this.resourceURl, required this.isAuto}) : super(key: key);
final Uint8List? audioBytes;
final String resourceURl;
final bool isAuto;
@override
State<AudioPlayerFloatingContainer> createState() => _AudioPlayerFloatingContainerState();
}
class _AudioPlayerFloatingContainerState extends State<AudioPlayerFloatingContainer> {
AudioPlayer player = AudioPlayer();
late Uint8List audiobytes;
bool isplaying = false;
bool audioplayed = false;
int currentpos = 0;
int maxduration = 100;
Duration? durationAudio;
String currentpostlabel = "00:00";
@override
void initState() {
Future.delayed(Duration.zero, () async {
if(widget.audioBytes != null) {
audiobytes = widget.audioBytes!;
}
player.durationStream.listen((Duration? d) { //get the duration of audio
if(d != null) {
maxduration = d.inSeconds;
durationAudio = d;
}
});
//player.bufferedPositionStream
player.positionStream.listen((event) {
if(durationAudio != null) {
currentpos = event.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inHours;
int sminutes = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inMinutes;
int sseconds = Duration(milliseconds:durationAudio!.inMilliseconds - currentpos).inSeconds;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
String minutesToShow = rminutes < 10 ? '0$rminutes': rminutes.toString();
String secondsToShow = rseconds < 10 ? '0$rseconds': rseconds.toString();
currentpostlabel = "$minutesToShow:$secondsToShow";
setState(() {
//refresh the UI
if(currentpos > player.duration!.inMilliseconds) {
print("RESET ALL");
player.stop();
player.seek(const Duration(seconds: 0));
isplaying = false;
audioplayed = false;
currentpostlabel = "00:00";
}
});
}
});
/*player.onPositionChanged.listen((Duration p){
currentpos = p.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:currentpos).inHours;
int sminutes = Duration(milliseconds:currentpos).inMinutes;
int sseconds = Duration(milliseconds:currentpos).inSeconds;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
String minutesToShow = rminutes < 10 ? '0$rminutes': rminutes.toString();
String secondsToShow = rseconds < 10 ? '0$rseconds': rseconds.toString();
currentpostlabel = "$minutesToShow:$secondsToShow";
setState(() {
//refresh the UI
});
});*/
if(widget.isAuto) {
//player.play(BytesSource(audiobytes));
//await player.setAudioSource(LoadedSource(audiobytes));
await player.setUrl(widget.resourceURl);
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}
});
super.initState();
}
@override
void dispose() {
player.stop();
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext();
return FloatingActionButton(
backgroundColor: new Color(int.parse(tabletAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16)).withOpacity(0.7),
onPressed: () async {
if(!isplaying && !audioplayed){
//player.play(BytesSource(audiobytes));
await player.setAudioSource(LoadedSource(audiobytes));
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else if(audioplayed && !isplaying){
//player.resume();
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
player.pause();
setState(() {
isplaying = false;
});
}
},
child: isplaying ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.pause),
Text(currentpostlabel),
],
) : audioplayed ? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.play_arrow),
Text(currentpostlabel),
],
): const Icon(Icons.play_arrow),
/*Column(
children: [
//Text(currentpostlabel, style: const TextStyle(fontSize: 25)),
Wrap(
spacing: 10,
children: [
ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: kSecondColor, // Background color
),
onPressed: () async {
if(!isplaying && !audioplayed){
//player.play(BytesSource(audiobytes));
await player.setAudioSource(LoadedSource(audiobytes));
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else if(audioplayed && !isplaying){
//player.resume();
player.play();
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
player.pause();
setState(() {
isplaying = false;
});
}
},
icon: Icon(isplaying?Icons.pause:Icons.play_arrow),
//label:Text(isplaying?TranslationHelper.getFromLocale("pause", appContext.getContext()):TranslationHelper.getFromLocale("play", appContext.getContext()))
),
/*ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: kSecondColor, // Background color
),
onPressed: () async {
player.stop();
player.seek(const Duration(seconds: 0));
setState(() {
isplaying = false;
audioplayed = false;
currentpostlabel = "00:00";
});
},
icon: const Icon(Icons.stop),
//label: Text(TranslationHelper.getFromLocale("stop", appContext.getContext()))
),*/
],
)
],
),*/
);
}
}
// Feed your own stream of bytes into the player
class LoadedSource extends StreamAudioSource {
final List<int> bytes;
LoadedSource(this.bytes);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= bytes.length;
return StreamAudioResponse(
sourceLength: bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(bytes.sublist(start, end)),
contentType: 'audio/mpeg',
);
}
}

View File

@ -1,4 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
class LoadingCommon extends StatefulWidget { class LoadingCommon extends StatefulWidget {
@ -28,6 +31,9 @@ class _LoadingCommonState extends State<LoadingCommon> with TickerProviderStateM
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext();
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
_controller!.forward(from: 0.0); _controller!.forward(from: 0.0);
_controller!.addListener(() { _controller!.addListener(() {
@ -39,9 +45,14 @@ class _LoadingCommonState extends State<LoadingCommon> with TickerProviderStateM
} }
}); });
return Center( return Center(
child: RotationTransition( child: SizedBox(
turns: Tween(begin: 0.0, end: 3.0).animate(_controller!), height: size.height * 0.1,
child: Icon(Icons.museum_outlined, color: kTestSecondColor, size: size.height*0.1), child: RotationTransition(
turns: Tween(begin: 0.0, end: 3.0).animate(_controller!),
child: tabletAppContext.configuration != null && tabletAppContext.configuration!.loaderImageUrl != null ?
Image.network(tabletAppContext.configuration!.loaderImageUrl!)
: Icon(Icons.museum_outlined, color: kTestSecondColor, size: size.height*0.1),
),
), ),
); );
} }

View File

@ -0,0 +1,100 @@
import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:manager_api/api.dart';
import 'package:tablet_app/Components/audio_player.dart';
import 'package:tablet_app/Components/video_viewer.dart';
import 'package:tablet_app/Components/video_viewer_youtube.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/app_context.dart';
showElementForResource(ResourceDTO resourceDTO, AppContext appContext) {
TabletAppContext tabletAppContext = appContext.getContext();
Color primaryColor = new Color(int.parse(tabletAppContext.configuration!.primaryColor!.split('(0x')[1].split(')')[0], radix: 16));
switch(resourceDTO.type) {
case ResourceType.Image:
return Image.network(
resourceDTO.url!,
fit:BoxFit.fill,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
color: primaryColor,
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
},
);
break;
case ResourceType.ImageUrl:
return Image.network(
resourceDTO.url!,
fit:BoxFit.fill,
loadingBuilder: (BuildContext context, Widget child,
ImageChunkEvent? loadingProgress) {
if (loadingProgress == null) {
return child;
}
return Center(
child: CircularProgressIndicator(
color: primaryColor,
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
),
);
},
);
case ResourceType.Audio:
return AudioPlayerFloatingContainer(audioBytes: null, resourceURl: resourceDTO.url!, isAuto: true);
/*return FutureBuilder(
future: getAudio(resourceDTO.url, appContext),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
Size size = MediaQuery.of(context).size;
if (snapshot.connectionState == ConnectionState.done) {
var audioBytes;
if(snapshot.data != null) {
print("snapshot.data");
print(snapshot.data);
audioBytes = snapshot.data;
//this.player.playBytes(audiobytes);
}
return AudioPlayerFloatingContainer(audioBytes: audioBytes, resourceURl: resourceDTO.url, isAuto: true);
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
} else {
return Center(
child: Container(
//height: size.height * 0.2,
width: size.width * 0.2,
child: LoadingCommon()
)
);
}
}
);*/
case ResourceType.Video:
if(resourceDTO.url == null) {
return Center(child: Text("Error loading video"));
} else {
return VideoViewer(videoUrl: resourceDTO.url!);
}
case ResourceType.VideoUrl:
if(resourceDTO.url == null) {
return Center(child: Text("Error loading video"));
} else {
return VideoViewerYoutube(videoUrl: resourceDTO.url!);
}
}
}

View File

@ -0,0 +1,93 @@
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:manager_api/api.dart';
import 'package:tablet_app/constants.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart' as iframe;
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class VideoViewerYoutube extends StatefulWidget {
final String videoUrl;
VideoViewerYoutube({required this.videoUrl});
@override
_VideoViewerYoutube createState() => _VideoViewerYoutube();
}
class _VideoViewerYoutube extends State<VideoViewerYoutube> {
iframe.YoutubePlayer? _videoViewWeb;
YoutubePlayer? _videoView;
@override
void initState() {
String? videoId;
if (widget.videoUrl.length > 0 ) {
videoId = YoutubePlayer.convertUrlToId(widget.videoUrl);
if (kIsWeb) {
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(widget.videoUrl);
_videoViewWeb = iframe.YoutubePlayer(
controller: _controllerWeb,
//showVideoProgressIndicator: false,
/*progressIndicatorColor: Colors.amber,
progressColors: ProgressBarColors(
playedColor: Colors.amber,
handleColor: Colors.amberAccent,
),*/
);
} else {
videoId = YoutubePlayer.convertUrlToId(widget.videoUrl);
YoutubePlayerController _controller = YoutubePlayerController(
initialVideoId: videoId!,
flags: YoutubePlayerFlags(
autoPlay: true,
controlsVisibleAtStart: false,
loop: true,
hideControls: false,
hideThumbnail: false,
),
);
_videoView = YoutubePlayer(
controller: _controller,
//showVideoProgressIndicator: false,
progressIndicatorColor: Colors.amber,
progressColors: ProgressBarColors(
playedColor: Colors.amber,
handleColor: Colors.amberAccent,
),
);
}
super.initState();
}
}
@override
void dispose() {
_videoView = null;
_videoViewWeb = null;
super.dispose();
}
@override
Widget build(BuildContext context) => widget.videoUrl.length > 0 ?
(kIsWeb ? _videoViewWeb! : _videoView!):
Center(child: Text("La vidéo ne peut pas être affichée, l'url est incorrecte", style: new TextStyle(fontSize: kNoneInfoOrIncorrect)));
}

View File

@ -1,7 +1,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
class ResponseSubDTO { class ResponseSubDTO {
List<TranslationDTO>? label; List<TranslationAndResourceDTO>? label;
bool? isGood; bool? isGood;
int? order; int? order;
@ -25,14 +25,14 @@ class ResponseSubDTO {
} }
class QuestionSubDTO { class QuestionSubDTO {
List<TranslationDTO>? label; List<TranslationAndResourceDTO>? label;
List<ResponseSubDTO>? responsesSubDTO; List<ResponseSubDTO>? responsesSubDTO;
int? chosen; int? chosen;
String? resourceId; String? resourceId;
String? source_; String? resourceUrl;
int? order; int? order;
QuestionSubDTO({this.label, this.responsesSubDTO, this.chosen, this.resourceId, this.source_, this.order}); QuestionSubDTO({this.label, this.responsesSubDTO, this.chosen, this.resourceId, this.resourceUrl, this.order});
List<QuestionSubDTO> fromJSON(List<QuestionDTO> questionsDTO) { List<QuestionSubDTO> fromJSON(List<QuestionDTO> questionsDTO) {
List<QuestionSubDTO> questionSubDTO = <QuestionSubDTO>[]; List<QuestionSubDTO> questionSubDTO = <QuestionSubDTO>[];
@ -42,8 +42,8 @@ class QuestionSubDTO {
chosen: null, chosen: null,
label: questionDTO.label, label: questionDTO.label,
responsesSubDTO: ResponseSubDTO().fromJSON(questionDTO.responses!), responsesSubDTO: ResponseSubDTO().fromJSON(questionDTO.responses!),
resourceId: questionDTO.resourceId, resourceId: questionDTO.imageBackgroundResourceId,
source_: questionDTO.source_, resourceUrl: questionDTO.imageBackgroundResourceUrl,
order: questionDTO.order, order: questionDTO.order,
)); ));
} }

View File

@ -4,18 +4,18 @@ class MapMarker {
int? id; int? id;
String? title; String? title;
String? description; String? description;
List<ImageGeoPoint>? images; List<ContentGeoPoint>? contents;
String? latitude; String? latitude;
String? longitude; String? longitude;
MapMarker({this.id, this.title, this.description, this.images, this.latitude, this.longitude}); MapMarker({this.id, this.title, this.description, this.contents, this.latitude, this.longitude});
factory MapMarker.fromJson(Map<String, dynamic> json) { factory MapMarker.fromJson(Map<String, dynamic> json) {
return new MapMarker( return new MapMarker(
id: json['id'] as int, id: json['id'] as int,
title: json['title'] as String, title: json['title'] as String,
description: json['description'] as String, description: json['description'] as String,
images: json['image'] as List<ImageGeoPoint>, contents: json['contents'] as List<ContentGeoPoint>,
latitude: json['latitude'] as String, latitude: json['latitude'] as String,
longitude: json['longitude'] as String, longitude: json['longitude'] as String,
); );
@ -23,6 +23,6 @@ class MapMarker {
@override @override
String toString() { String toString() {
return 'MapMarker{id: $id, title: $title, description: $description, images: $images, latitude: $latitude, longitude: $longitude}'; return 'MapMarker{id: $id, title: $title, description: $description, contents: $contents, latitude: $latitude, longitude: $longitude}';
} }
} }

View File

@ -16,6 +16,7 @@ class TabletAppContext with ChangeNotifier{
String? language; String? language;
String? deviceId; String? deviceId;
String? instanceId; String? instanceId;
Size? puzzleSize;
TabletAppContext({this.id, this.deviceId, this.host, this.configuration, this.language, this.instanceId, this.clientAPI}); TabletAppContext({this.id, this.deviceId, this.host, this.configuration, this.language, this.instanceId, this.clientAPI});

View File

@ -0,0 +1,45 @@
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:manager_api/api.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tablet_app/Components/loading_common.dart';
class AgendaView extends StatefulWidget {
final SectionDTO? section;
AgendaView({this.section});
@override
_AgendaView createState() => _AgendaView();
}
class _AgendaView extends State<AgendaView> {
AgendaDTO agendaDTO = AgendaDTO();
@override
void initState() {
print(widget.section!.data);
agendaDTO = AgendaDTO.fromJson(jsonDecode(widget.section!.data!))!;
print(agendaDTO);
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Center(
child: Text("TODO Agenda"),
);
}
} //_webView

View File

@ -0,0 +1,46 @@
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:manager_api/api.dart';
import 'package:path_provider/path_provider.dart';
import 'package:tablet_app/Components/loading_common.dart';
class ArticleView extends StatefulWidget {
final SectionDTO? section;
ArticleView({this.section});
@override
_ArticleView createState() => _ArticleView();
}
class _ArticleView extends State<ArticleView> {
AgendaDTO agendaDTO = AgendaDTO();
@override
void initState() {
print(widget.section!.data);
agendaDTO = AgendaDTO.fromJson(jsonDecode(widget.section!.data!))!;
print(agendaDTO);
super.initState();
}
@override
void dispose() {
//_webView = null;
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Center(
child: Text("TODO Agenda"),
);
}
} //_webView

View File

@ -84,30 +84,33 @@ class _LanguageSelection extends State<LanguageSelection> with TickerProviderSta
left: _leftLanguage, left: _leftLanguage,
right: _rightLanguage, right: _rightLanguage,
bottom: _bottomLanguage, bottom: _bottomLanguage,
child: ListView( child: Padding(
children: [ padding: const EdgeInsets.only(top: 25.0),
if(minimized) ... [ child: ListView(
for(var language in languagesEnable!.where((element) => element.toUpperCase() != selectedLanguage )) children: [
InkWell( if(minimized) ... [
onTap: () { for(var language in languagesEnable!.where((element) => element.toUpperCase() != selectedLanguage ))
setState(() { InkWell(
TabletAppContext tabletAppContext = appContext.getContext(); onTap: () {
tabletAppContext.language = language; setState(() {
appContext.setContext(tabletAppContext); TabletAppContext tabletAppContext = appContext.getContext();
minimizedAnimation(size); tabletAppContext.language = language;
}); appContext.setContext(tabletAppContext);
}, minimizedAnimation(size);
child: Padding( });
padding: const EdgeInsets.all(8.0), },
child: Container( child: Padding(
width: 75, padding: const EdgeInsets.all(8.0),
height: 75, child: Container(
decoration: flagDecoration(language), width: 35,
height: 35,
decoration: flagDecoration(language),
),
), ),
), )
) ]
] ],
], ),
), ),
), ),
], ],

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
@ -7,13 +9,18 @@ import 'package:manager_api/api.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tablet_app/Components/loading.dart'; import 'package:tablet_app/Components/loading.dart';
import 'package:tablet_app/Components/loading_common.dart'; import 'package:tablet_app/Components/loading_common.dart';
import 'package:tablet_app/Helpers/DatabaseHelper.dart';
import 'package:tablet_app/Helpers/MQTTHelper.dart'; import 'package:tablet_app/Helpers/MQTTHelper.dart';
import 'package:tablet_app/Screens/Agenda/agenda_view.dart';
import 'package:tablet_app/Screens/Article/article_view.dart';
import 'package:tablet_app/Screens/Configuration/config_view.dart'; import 'package:tablet_app/Screens/Configuration/config_view.dart';
import 'package:tablet_app/Screens/Map/map_context.dart'; import 'package:tablet_app/Screens/Map/map_context.dart';
import 'package:tablet_app/Screens/Map/map_view.dart'; import 'package:tablet_app/Screens/Map/map_view.dart';
import 'package:tablet_app/Models/map-marker.dart'; import 'package:tablet_app/Models/map-marker.dart';
import 'package:tablet_app/Models/tabletContext.dart'; import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Menu/menu_view.dart'; import 'package:tablet_app/Screens/Menu/menu_view.dart';
import 'package:tablet_app/Screens/PDF/pdf_view.dart';
import 'package:tablet_app/Screens/Puzzle/puzzle_view.dart';
import 'package:tablet_app/Screens/Slider/slider_view.dart'; import 'package:tablet_app/Screens/Slider/slider_view.dart';
import 'package:tablet_app/Screens/Video/video_view.dart'; import 'package:tablet_app/Screens/Video/video_view.dart';
import 'package:tablet_app/Screens/Web/web_view.dart'; import 'package:tablet_app/Screens/Web/web_view.dart';
@ -42,11 +49,11 @@ class _MainViewWidget extends State<MainViewWidget> {
final appContext = Provider.of<AppContext>(context); final appContext = Provider.of<AppContext>(context);
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []);
Size size = MediaQuery.of(context).size; Size size = MediaQuery.of(context).size;
configurationDTO = appContext.getContext().configuration; configurationDTO = appContext.getContext().configuration;
if (!MQTTHelper.instance.isInstantiated) // TODO REMOVE
MQTTHelper.instance.connect(appContext); /*if (!MQTTHelper.instance.isInstantiated)
MQTTHelper.instance.connect(appContext);*/
if(sectionSelected != null) { if(sectionSelected != null) {
var elementToShow; var elementToShow;
@ -70,17 +77,29 @@ class _MainViewWidget extends State<MainViewWidget> {
elementToShow = WebView(section: sectionSelected); elementToShow = WebView(section: sectionSelected);
break; break;
case SectionType.video : // Video case SectionType.video : // Video
elementToShow = VideoViewWidget(section: sectionSelected); elementToShow = VideoView(section: sectionSelected);
break; break;
case SectionType.slider : case SectionType.slider :
elementToShow = SliderViewWidget(section: sectionSelected); elementToShow = SliderView(section: sectionSelected);
break; break;
case SectionType.menu : case SectionType.menu :
elementToShow = MenuViewWidget(section: sectionSelected!); elementToShow = MenuView(section: sectionSelected!);
break; break;
case SectionType.quizz : case SectionType.quizz :
elementToShow = QuizzViewWidget(section: sectionSelected); elementToShow = QuizzView(section: sectionSelected);
break; break;
case SectionType.pdf :
elementToShow = PDFViewWidget(section: sectionSelected);
break;
case SectionType.puzzle :
elementToShow = PuzzleView(section: sectionSelected);
break;
case SectionType.agenda :
elementToShow = AgendaView(section: sectionSelected);
break;
/*case SectionType.article : // TODO
elementToShow = ArticleView(section: sectionSelected);
break;*/
default: default:
elementToShow = Text("Ce type n'est pas supporté"); elementToShow = Text("Ce type n'est pas supporté");
break; break;
@ -132,7 +151,7 @@ class _MainViewWidget extends State<MainViewWidget> {
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: HtmlWidget( child: HtmlWidget(
sectionSelected!.title!.firstWhere((translation) => translation.language == appContext.getContext().language).value!, sectionSelected!.title!.firstWhere((translation) => translation.language == appContext.getContext().language).value!,
textStyle: new TextStyle(fontSize: kIsWeb ? kWebSectionTitleDetailSize : kSectionTitleDetailSize), textStyle: new TextStyle(fontSize: kIsWeb ? kWebSectionTitleDetailSize : kSectionTitleDetailSize, color: Colors.white),
) )
) )
), ),
@ -181,10 +200,10 @@ class _MainViewWidget extends State<MainViewWidget> {
), ),
floatingActionButtonLocation: FloatingActionButtonLocation.endTop, floatingActionButtonLocation: FloatingActionButtonLocation.endTop,
floatingActionButton: Padding( floatingActionButton: Padding(
padding: const EdgeInsets.only(top: kIsWeb ? 16.0 : 0.0), padding: const EdgeInsets.only(top: kIsWeb ? 16.0 : 16.0),
child: Container( child: Container(
height: kIsWeb ? size.height *0.08 : 185.0, height: kIsWeb ? size.height *0.08 : size.height *0.08,
width: kIsWeb ? size.width *0.08: 185.0, width: kIsWeb ? size.width *0.08: size.width *0.08,
child: FittedBox( child: FittedBox(
child: FloatingActionButton.extended( child: FloatingActionButton.extended(
backgroundColor: kBackgroundColor, backgroundColor: kBackgroundColor,
@ -196,7 +215,7 @@ class _MainViewWidget extends State<MainViewWidget> {
}); });
}, },
icon: Icon(Icons.arrow_back, color: Colors.grey), icon: Icon(Icons.arrow_back, color: Colors.grey),
label: Text("Menu") label: Text("Menu", style: TextStyle(color: Colors.black))
), ),
), ),
), ),
@ -218,28 +237,28 @@ class _MainViewWidget extends State<MainViewWidget> {
), ),
) : null, ) : null,
child: Stack( child: Stack(
children: [ children: [
LanguageSelection(size: size), LanguageSelection(size: size),
Center( Center(
child: Container( child: Container(
height: kIsWeb ? size.height : size.height * 0.85, height: kIsWeb ? size.height : size.height * 0.85,
width: size.width * 0.9, width: size.width * 0.9,
child: FutureBuilder( child: FutureBuilder(
future: getSections(appContext), future: getSections(appContext),
builder: (context, AsyncSnapshot<dynamic> snapshot) { builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) { if (snapshot.data == null) {
// Show select config // Show select config
return Text(""); return Text("");
} }
else { else {
return Center( return Center(
child: GridView.builder( child: GridView.builder(
shrinkWrap: true, shrinkWrap: true,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: rowCount), gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: rowCount),
itemCount: snapshot.data?.length, itemCount: snapshot.data?.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return InkWell( return InkWell(
onTap: () { onTap: () {
setState(() { setState(() {
sectionSelected = snapshot.data[index]; sectionSelected = snapshot.data[index];
@ -252,60 +271,134 @@ class _MainViewWidget extends State<MainViewWidget> {
child: Align( child: Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child: FractionallySizedBox( child: FractionallySizedBox(
heightFactor: 0.25, heightFactor: 0.35,
child: Column( child: Container(
children: [ color: Colors.green,
Align( child: Column(
alignment: Alignment.centerRight, children: [
child: HtmlWidget( Container(
snapshot.data[index].title.firstWhere((translation) => translation.language == appContext.getContext().language).value, color: Colors.blue,
customStylesBuilder: (element) { child: LayoutBuilder(
return {'text-align': 'right'}; builder: (BuildContext context, BoxConstraints constraints) {
}, return SizedBox(
textStyle: new TextStyle(fontSize: kIsWeb ? kWebMenuTitleDetailSize: kMenuTitleDetailSize), width: double.infinity,
child: FittedBox(
fit: BoxFit.fitWidth,
child: Align(
alignment: Alignment.centerRight,
child: HtmlWidget(
snapshot.data[index].title.firstWhere((translation) => translation.language == appContext.getContext().language).value,
customStylesBuilder: (element) {
return {'text-align': 'right'};
},
textStyle: TextStyle(fontSize: calculateFontSize(constraints.maxWidth, constraints.maxHeight, kIsWeb ? kWebMenuTitleDetailSize : kMenuTitleDetailSize)),
),
),
),
);
},
),
), ),
), Container(color: Colors.orange, child: Text("ds")),
Align(
alignment: Alignment.centerRight, /*Container(
child: HtmlWidget( color: Colors.orange,
snapshot.data[index].description.firstWhere((translation) => translation.language == appContext.getContext().language).value, child: FittedBox(
customStylesBuilder: (element) { fit: BoxFit.fitWidth,
return {'text-align': 'right'}; child: Align(
}, alignment: Alignment.centerRight,
textStyle: new TextStyle(fontSize: kIsWeb ? kWebMenuDescriptionDetailSize: kMenuDescriptionDetailSize, fontFamily: ""), child: HtmlWidget(
), snapshot.data[index].title.firstWhere((translation) => translation.language == appContext.getContext().language).value,
), customStylesBuilder: (element) {
], return {'text-align': 'right'};
},
textStyle: new TextStyle(fontSize: calculateFontSize(context, kIsWeb ? kWebMenuTitleDetailSize: kMenuTitleDetailSize)),
),
),
),
),
FittedBox(
fit: BoxFit.fill,
child: Align(
alignment: Alignment.centerRight,
child: HtmlWidget(
snapshot.data[index].description.firstWhere((translation) => translation.language == appContext.getContext().language).value,
customStylesBuilder: (element) {
return {'text-align': 'right'};
},
textStyle: new TextStyle(fontSize: calculateFontSize(context, kIsWeb ? kWebMenuDescriptionDetailSize: kMenuDescriptionDetailSize), fontFamily: ""),
),
),
),*/
],
),
) )
), ),
), ),
), ),
); );
} }
), ),
);
}
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
} else {
return Center(
child: Container(
child: LoadingCommon()
)
); );
} }
} else if (snapshot.connectionState == ConnectionState.none) {
return Text("No data");
} else {
return Center(
child: Container(
child: LoadingCommon()
)
);
} }
} ),
), ),
), ),
), ]),
]),
) )
); );
} }
} }
Future<ConfigurationDTO?> getCurrentConfiguration(dynamic appContext) async {
TabletAppContext tabletAppContext = await appContext.getContext();
try {
ConfigurationDTO? configurationDTO = await tabletAppContext.clientAPI!.configurationApi!.configurationGetDetail(tabletAppContext.configuration!.id!);
tabletAppContext.configuration = configurationDTO;
TabletAppContext? localContext = await DatabaseHelper.instance.getData();
if (localContext != null) { // Check if sql DB exist
await DatabaseHelper.instance.update(tabletAppContext);
} else {
await DatabaseHelper.instance.insert(tabletAppContext);
}
/*
appContext.setContext(tabletAppContext);
// STORE IT LOCALLY (SQLite)
TabletAppContext? localContext = await DatabaseHelper.instance.getData();
if (localContext != null) { // Check if sql DB exist
await DatabaseHelper.instance.update(tabletAppContext);
} else {
await DatabaseHelper.instance.insert(tabletAppContext);
}*/
return configurationDTO;
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Une erreur est survenue lors de la récupération de la configuration'),
),
);
}
}
Future<List<SectionDTO>?> getSections(dynamic appContext) async { Future<List<SectionDTO>?> getSections(dynamic appContext) async {
TabletAppContext tabletAppContext = await appContext.getContext(); TabletAppContext tabletAppContext = await appContext.getContext();
await getCurrentConfiguration(appContext);
try { try {
List<SectionDTO>? sections = await tabletAppContext.clientAPI!.sectionApi!.sectionGetFromConfiguration(tabletAppContext.configuration!.id!); List<SectionDTO>? sections = await tabletAppContext.clientAPI!.sectionApi!.sectionGetFromConfiguration(tabletAppContext.configuration!.id!);
sections!.sort((a, b) => a.order!.compareTo(b.order!)); sections!.sort((a, b) => a.order!.compareTo(b.order!));
@ -326,6 +419,21 @@ class _MainViewWidget extends State<MainViewWidget> {
} }
} }
double calculateFontSize(double parentWidth, double parentHeight, double baseSize) {
// La taille de base est basée sur la taille définie dans vos constantes (kWebMenuTitleDetailSize ou kMenuTitleDetailSize).
// Vous pouvez ajuster ce facteur en fonction de vos besoins.
double scaleFactor = 0.8;
// Calculez la taille de la police en fonction de la largeur et de la hauteur maximales disponibles
//double calculatedFontSize = parentWidth * scaleFactor;
// Vous pouvez également prendre en compte la hauteur ici si nécessaire
double calculatedFontSize = min(parentWidth, parentHeight) * scaleFactor;
// Utilisez la plus petite valeur entre la taille de base et la taille calculée
return calculatedFontSize < baseSize ? calculatedFontSize : baseSize;
}
boxDecoration(SectionDTO section, bool isSelected) { boxDecoration(SectionDTO section, bool isSelected) {
return BoxDecoration( return BoxDecoration(
color: kBackgroundLight, color: kBackgroundLight,

View File

@ -42,7 +42,7 @@ class _GoogleMapViewState extends State<GoogleMapView> {
description: point.description!.firstWhere((translation) => translation.language == language).value, description: point.description!.firstWhere((translation) => translation.language == language).value,
longitude: point.longitude, longitude: point.longitude,
latitude: point.latitude, latitude: point.latitude,
images: point.images contents: point.contents
); );
markersList.add(mapMarker); markersList.add(mapMarker);
}); });
@ -65,7 +65,7 @@ class _GoogleMapViewState extends State<GoogleMapView> {
mapContext.setSelectedMarker( mapContext.setSelectedMarker(
new MapMarker( new MapMarker(
title: element.title, title: element.title,
images: element.images, contents: element.contents,
description: element.description, description: element.description,
longitude: element.longitude, longitude: element.longitude,
latitude: element.latitude, latitude: element.latitude,
@ -145,7 +145,7 @@ class _GoogleMapViewState extends State<GoogleMapView> {
new MapMarker( new MapMarker(
title: '', title: '',
description: '', description: '',
images: null, contents: null,
longitude: null, longitude: null,
latitude: null latitude: null
)); ));

View File

@ -65,12 +65,12 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
child: Stack( child: Stack(
children: <Widget> [ children: <Widget> [
Positioned( Positioned(
right: 15, right: 5,
top: 15, top: 5,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
setState(() { setState(() {
mapContext.setSelectedMarker(new MapMarker(longitude: null, latitude: null, title: '', images: null, description: '')); mapContext.setSelectedMarker(new MapMarker(longitude: null, latitude: null, title: '', contents: null, description: ''));
}); });
}, },
child: Container( child: Container(
@ -90,7 +90,7 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
), ),
child: Icon( child: Icon(
Icons.close, Icons.close,
size: 35, size: 25,
color: Colors.white, color: Colors.white,
), ),
), ),
@ -223,8 +223,8 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
}, },
child: Icon( child: Icon(
Icons.chevron_right, Icons.chevron_right,
size: kIsWeb ? 100 : 150, size: kIsWeb ? 100 : 85,
color: kMainRed, color: kTestSecondColor,
), ),
) )
), ),
@ -239,8 +239,8 @@ class _MarkerInfoWidget extends State<MarkerViewWidget> {
}, },
child: Icon( child: Icon(
Icons.chevron_left, Icons.chevron_left,
size: kIsWeb ? 100 : 150, size: kIsWeb ? 100 : 85,
color: kMainRed, color: kTestSecondColor,
), ),
) )
), ),

View File

@ -7,8 +7,11 @@ import 'package:manager_api/api.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tablet_app/Models/map-marker.dart'; import 'package:tablet_app/Models/map-marker.dart';
import 'package:tablet_app/Models/tabletContext.dart'; import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Agenda/agenda_view.dart';
import 'package:tablet_app/Screens/Map/map_context.dart'; import 'package:tablet_app/Screens/Map/map_context.dart';
import 'package:tablet_app/Screens/Map/map_view.dart'; import 'package:tablet_app/Screens/Map/map_view.dart';
import 'package:tablet_app/Screens/PDF/pdf_view.dart';
import 'package:tablet_app/Screens/Puzzle/puzzle_view.dart';
import 'package:tablet_app/Screens/Quizz/quizz_view.dart'; import 'package:tablet_app/Screens/Quizz/quizz_view.dart';
import 'package:tablet_app/Screens/Slider/slider_view.dart'; import 'package:tablet_app/Screens/Slider/slider_view.dart';
import 'package:tablet_app/Screens/Video/video_view.dart'; import 'package:tablet_app/Screens/Video/video_view.dart';
@ -16,15 +19,15 @@ import 'package:tablet_app/Screens/Web/web_view.dart';
import 'package:tablet_app/app_context.dart'; import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
class MenuViewWidget extends StatefulWidget { class MenuView extends StatefulWidget {
final SectionDTO? section; final SectionDTO? section;
MenuViewWidget({this.section}); MenuView({this.section});
@override @override
_MenuViewWidget createState() => _MenuViewWidget(); _MenuView createState() => _MenuView();
} }
class _MenuViewWidget extends State<MenuViewWidget> { class _MenuView extends State<MenuView> {
MenuDTO menuDTO = MenuDTO(); MenuDTO menuDTO = MenuDTO();
SectionDTO? selectedSection; SectionDTO? selectedSection;
@override @override
@ -68,14 +71,26 @@ class _MenuViewWidget extends State<MenuViewWidget> {
elementToShow = WebView(section: selectedSection); elementToShow = WebView(section: selectedSection);
break; break;
case SectionType.video : // Video case SectionType.video : // Video
elementToShow = VideoViewWidget(section: selectedSection); elementToShow = VideoView(section: selectedSection);
break; break;
case SectionType.slider : // Slider: case SectionType.slider : // Slider
elementToShow = SliderViewWidget(section: selectedSection); elementToShow = SliderView(section: selectedSection);
break; break;
case SectionType.quizz : // Slider: case SectionType.quizz : // Quizz
elementToShow = QuizzViewWidget(section: selectedSection); elementToShow = QuizzView(section: selectedSection);
break; break;
case SectionType.pdf : // Pdf
elementToShow = PDFViewWidget(section: selectedSection);
break;
case SectionType.puzzle : // Puzzle
elementToShow = PuzzleView(section: selectedSection);
break;
case SectionType.agenda : // Agenda
elementToShow = AgendaView(section: selectedSection);
break;
/*case SectionType.article : // Article
elementToShow = ArticleView(section: selectedSection);
break;*/
default: default:
elementToShow = Text('Section type not supported'); elementToShow = Text('Section type not supported');
break; break;

View File

@ -28,12 +28,12 @@ class _PDFViewWidget extends State<PDFViewWidget> {
int? currentPage = 0; int? currentPage = 0;
bool isReady = false; bool isReady = false;
String errorMessage = ''; String errorMessage = '';
ValueNotifier<Map<String, int>> currentState = ValueNotifier<Map<String, int>>({'page': 0, 'total': 0});
@override @override
void initState() { void initState() {
print(widget.section!.data); print(widget.section!.data);
pdfDTO = PdfDTO.fromJson(jsonDecode(widget.section!.data!))!; pdfDTO = PdfDTO.fromJson(jsonDecode(widget.section!.data!))!;
pdfDTO.source_ = "todo";
print(pdfDTO); print(pdfDTO);
super.initState(); super.initState();
@ -52,8 +52,7 @@ class _PDFViewWidget extends State<PDFViewWidget> {
try { 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"; // "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 = "https://pdfkit.org/docs/guide.pdf";
final url = "http://www.pdf995.com/samples/pdf.pdf"; final url = source_;
// TODO replace by source_
final filename = url.substring(url.lastIndexOf("/") + 1); final filename = url.substring(url.lastIndexOf("/") + 1);
var request = await HttpClient().getUrl(Uri.parse(url)); var request = await HttpClient().getUrl(Uri.parse(url));
var response = await request.close(); var response = await request.close();
@ -80,37 +79,60 @@ class _PDFViewWidget extends State<PDFViewWidget> {
@override @override
Widget build(BuildContext context) => pdfDTO.source_ != null && pdfDTO.source_!.length > 0 ? Widget build(BuildContext context) => pdfDTO.resourceUrl != null && pdfDTO.resourceUrl!.length > 0 ?
FutureBuilder( FutureBuilder(
future: createFileOfPdfUrl(""), future: createFileOfPdfUrl(pdfDTO.resourceUrl!),
builder: (context, AsyncSnapshot<dynamic> snapshot) { builder: (context, AsyncSnapshot<dynamic> snapshot) {
print("snapshot.data"); print("snapshot.data");
print(snapshot.data); print(snapshot.data);
if (snapshot.connectionState == ConnectionState.done) { if (snapshot.connectionState == ConnectionState.done) {
return PDFView( return Stack(
filePath: snapshot.data.path, children: [
enableSwipe: true, PDFView(
swipeHorizontal: true, filePath: snapshot.data.path,
autoSpacing: true, enableSwipe: true,
pageFling: true, swipeHorizontal: true,
onRender: (_pages) { autoSpacing: true,
//setState(() { pageFling: true,
pages = _pages; fitPolicy: FitPolicy.HEIGHT,
isReady = true; onRender: (_pages) {
//}); //setState(() {
}, pages = _pages;
onError: (error) { isReady = true;
print(error.toString()); //});
}, },
onPageError: (page, error) { onError: (error) {
print('$page: ${error.toString()}'); print(error.toString());
}, },
onViewCreated: (PDFViewController pdfViewController) { onPageError: (page, error) {
//_controller.complete(pdfViewController); print('$page: ${error.toString()}');
}, },
onPageChanged: (int? page, int? total) { onViewCreated: (PDFViewController pdfViewController) {
print('page change: $page/$total'); //_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,
right: 20,
child: ValueListenableBuilder<Map<String, int>>(
valueListenable: currentState,
builder: (context, value, _) {
return Container(
//color: Colors.blueAccent,
child: Text("${value["page"]!+1}/${value["total"]!}",
style: TextStyle(color: Colors.black, fontSize: 30))
);
},
),
),
],
); );
} else { } else {
return Center( return Center(

View File

@ -35,7 +35,7 @@ class CorrectOverlayState extends State<CorrectOverlay>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Material( return new Container(
color: Colors.black54, color: Colors.black54,
child: new InkWell( child: new InkWell(
onTap: () => widget._onTap(), onTap: () => widget._onTap(),
@ -44,7 +44,7 @@ class CorrectOverlayState extends State<CorrectOverlay>
children: <Widget>[ children: <Widget>[
new Container( new Container(
decoration: new BoxDecoration( decoration: new BoxDecoration(
color: Colors.white, shape: BoxShape.circle), color: Colors.blueAccent, shape: BoxShape.circle),
child: new Transform.rotate( child: new Transform.rotate(
angle: _iconAnimation.value * 2 * math.pi, angle: _iconAnimation.value * 2 * math.pi,
child: new Icon( child: new Icon(

View File

@ -0,0 +1,89 @@
import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:manager_api/api.dart';
import 'package:tablet_app/Components/show_element_for_resource.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart';
void showMessage(TranslationAndResourceDTO translationAndResourceDTO, AppContext appContext, BuildContext context, Size size) {
print("translationAndResourceDTO");
print(translationAndResourceDTO);
showDialog(
builder: (BuildContext context) => AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0))
),
content: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if(translationAndResourceDTO.resourceId != null)
Container(
//color: Colors.cyan,
height: size.height *0.45,
width: size.width *0.5,
child: Center(
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
//border: Border.all(width: 3, color: Colors.black)
),
child: showElementForResource(ResourceDTO(id: translationAndResourceDTO.resourceId, type: translationAndResourceDTO.resourceType, url: translationAndResourceDTO.resourceUrl), appContext),
),
),
),
Container(
//color: Colors.green,
height: size.height *0.3,
width: size.width *0.5,
child: Center(
child: Align(
alignment: Alignment.center,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: HtmlWidget(
translationAndResourceDTO.value!,
customStylesBuilder: (element) {
return {'text-align': 'center'};
},
textStyle: TextStyle(fontSize: kDescriptionSize),
),/*Text(
resourceDTO.label == null ? "" : resourceDTO.label,
style: new TextStyle(fontSize: 25, fontWeight: FontWeight.w400)),*/
),
),
),
),
],
),
),
/*actions: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
alignment: AlignmentDirectional.bottomEnd,
child: Container(
width: 175,
height: 70,
child: RoundedButton(
text: "Merci",
icon: Icons.undo,
color: kSecondGrey,
press: () {
Navigator.of(context).pop();
},
fontSize: 20,
),
),
),
),
],
),
],*/
), context: context
);
}

View File

@ -1,6 +1,10 @@
import 'dart:math'; import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart';
class PuzzlePiece extends StatefulWidget { class PuzzlePiece extends StatefulWidget {
final Image image; final Image image;
@ -49,14 +53,38 @@ class _PuzzlePieceState extends State<PuzzlePiece> {
// can we move the piece ? // can we move the piece ?
bool isMovable = true; bool isMovable = true;
GlobalKey _widgetPieceKey = GlobalKey();
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
RenderBox renderBox = _widgetPieceKey.currentContext?.findRenderObject() as RenderBox;
Size size = renderBox.size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
tabletAppContext.puzzleSize = size;
appContext.setContext(tabletAppContext);
if(widget.row == 0 && widget.col == 0) {
widget.sendToBack(widget);
}
});
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// the image width
final imageWidth = MediaQuery.of(context).size.width; var isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;
// the image height
final imageHeight = MediaQuery.of(context).size.height * var imageHeight = isPortrait ? widget.imageSize.width/1.5 : widget.imageSize.width;
MediaQuery.of(context).size.width / var imageWidth = isPortrait ? widget.imageSize.width/1.5: widget.imageSize.height;
widget.imageSize.width;
final pieceWidth = imageWidth / widget.maxCol; final pieceWidth = imageWidth / widget.maxCol;
final pieceHeight = imageHeight / widget.maxRow; final pieceHeight = imageHeight / widget.maxRow;
@ -64,60 +92,74 @@ class _PuzzlePieceState extends State<PuzzlePiece> {
top = Random().nextInt((imageHeight - pieceHeight).ceil()).toDouble(); top = Random().nextInt((imageHeight - pieceHeight).ceil()).toDouble();
var test = top!; var test = top!;
test -= widget.row * pieceHeight; test -= widget.row * pieceHeight;
top = test; top = test /2.2; // TODO change ?
} }
if (left == null) { if (left == null) {
left = Random().nextInt((imageWidth - pieceWidth).ceil()).toDouble(); left = Random().nextInt((imageWidth - pieceWidth).ceil()).toDouble();
var test = left!; var test = left!;
test -= widget.col * pieceWidth; test -= widget.col * pieceWidth;
left = test; left = test /2.2; // TODO change ?
}
if(widget.row == 0 && widget.col == 0) {
top = 0;
left = 0;
isMovable = false;
} }
return Positioned( return Positioned(
top: top, top: top,
left: left, left: left,
width: imageWidth, width: imageWidth,
child: GestureDetector( child: Container(
onTap: () { key: _widgetPieceKey,
if (isMovable) { decoration: widget.col == 0 && widget.row == 0 ? BoxDecoration(
widget.bringToTop(widget); border: Border.all(
} color: Colors.black,
}, width: 0.5,
onPanStart: (_) { ),
if (isMovable) { ) : null,
widget.bringToTop(widget); child: GestureDetector(
} onTap: () {
}, if (isMovable) {
onPanUpdate: (dragUpdateDetails) { widget.bringToTop(widget);
if (isMovable) { }
setState(() { },
var testTop = top!; onPanStart: (_) {
var testLeft = left!; if (isMovable) {
testTop = top!; widget.bringToTop(widget);
testLeft = left!; }
testTop += dragUpdateDetails.delta.dy; },
testLeft += dragUpdateDetails.delta.dx; onPanUpdate: (dragUpdateDetails) {
top = testTop!; if (isMovable) {
left = testLeft!; setState(() {
var testTop = top!;
var testLeft = left!;
testTop = top!;
testLeft = left!;
testTop += dragUpdateDetails.delta.dy;
testLeft += dragUpdateDetails.delta.dx;
top = testTop;
left = testLeft;
if (-10 < top! && top! < 10 && -10 < left! && left! < 10) { if (-10 < top! && top! < 10 && -10 < left! && left! < 10) {
top = 0; top = 0;
left = 0; left = 0;
isMovable = false; isMovable = false;
widget.sendToBack(widget); widget.sendToBack(widget);
}
//ScoreWidget.of(context).allInPlaceCount++; });
} }
}); },
} child: ClipPath(
}, child: CustomPaint(
child: ClipPath( foregroundPainter: PuzzlePiecePainter(
child: CustomPaint( widget.row, widget.col, widget.maxRow, widget.maxCol),
foregroundPainter: PuzzlePiecePainter( child: widget.image),
widget.row, widget.col, widget.maxRow, widget.maxCol), clipper: PuzzlePieceClipper(
child: widget.image), widget.row, widget.col, widget.maxRow, widget.maxCol),
clipper: PuzzlePieceClipper( ),
widget.row, widget.col, widget.maxRow, widget.maxCol),
), ),
)); ));
} }
@ -153,9 +195,9 @@ class PuzzlePiecePainter extends CustomPainter {
@override @override
void paint(Canvas canvas, Size size) { void paint(Canvas canvas, Size size) {
final Paint paint = Paint() final Paint paint = Paint()
..color = Color(0x80FFFFFF) ..color = Colors.black//Color(0x80FFFFFF)
..style = PaintingStyle.stroke ..style = PaintingStyle.stroke
..strokeWidth = 1.0; ..strokeWidth = 2.5;
canvas.drawPath(getPiecePath(size, row, col, maxRow, maxCol), paint); canvas.drawPath(getPiecePath(size, row, col, maxRow, maxCol), paint);
} }

View File

@ -4,6 +4,11 @@ import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
import 'package:provider/provider.dart';
import 'package:tablet_app/Components/loading_common.dart';
import 'package:tablet_app/Models/tabletContext.dart';
import 'package:tablet_app/Screens/Puzzle/message_dialog.dart';
import 'package:tablet_app/app_context.dart';
import 'puzzle_piece.dart'; import 'puzzle_piece.dart';
import 'score_widget.dart'; import 'score_widget.dart';
@ -14,49 +19,61 @@ class PuzzleView extends StatefulWidget {
PuzzleView({this.section}); PuzzleView({this.section});
@override @override
_PuzzleViewWidget createState() => _PuzzleViewWidget(); _PuzzleView createState() => _PuzzleView();
} }
class _PuzzleViewWidget extends State<PuzzleView> { class _PuzzleView extends State<PuzzleView> {
SliderDTO sliderDTO = SliderDTO(); PuzzleDTO puzzleDTO = PuzzleDTO();
final int rows = 3;
final int cols = 3; int allInPlaceCount = 0;
bool isFinished = false;
GlobalKey _widgetKey = GlobalKey();
Size? realWidgetSize;
//File? _image; //File? _image;
String? _imagePath; String? _imagePath;
List<Widget> pieces = []; List<Widget> pieces = [];
bool _overlayVisible = true; bool isSplittingImage = true;
@override @override
void initState() { void initState() {
sliderDTO = SliderDTO.fromJson(jsonDecode(widget.section!.data!))!; puzzleDTO = PuzzleDTO.fromJson(jsonDecode(widget.section!.data!))!;
puzzleDTO.rows = puzzleDTO.rows != null ? puzzleDTO.rows : 3;
puzzleDTO.cols = puzzleDTO.cols != null ? puzzleDTO.cols : 3;
WidgetsBinding.instance.addPostFrameCallback((_) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
TranslationAndResourceDTO? messageDebut = puzzleDTO.messageDebut != null ? puzzleDTO.messageDebut!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
if(messageDebut != null) {
showMessage(messageDebut, appContext, context, size);
}
getRealWidgetSize();
});
sliderDTO.images!.sort((a, b) => a.order!.compareTo(b.order!));
super.initState(); super.initState();
splitImage(Image.network(sliderDTO.images![1].source_!));
if(puzzleDTO.image != null && puzzleDTO.image!.resourceUrl != null) {
splitImage(Image.network(puzzleDTO.image!.resourceUrl!));
}
} }
/*void savePrefs() async { Future<void> getRealWidgetSize() async {
await prefs!.setString(IMAGE_PATH, _imagePath!); RenderBox renderBox = _widgetKey.currentContext?.findRenderObject() as RenderBox;
}*/ Size size = renderBox.size;
/*Future getImage(ImageSource source) async { setState(() {
var image = await ImagePicker.platform.(source: source); realWidgetSize = size;
});
if (image != null) { print("Taille réelle du widget : $size");
setState(() { }
_image = image;
_imagePath = _image!.path;
pieces.clear();
ScoreWidget
.of(context)
.allInPlaceCount = 0;
});
}
splitImage(Image.file(image));
savePrefs();
}*/
// we need to find out the image size, to be used in the PuzzlePiece widget // we need to find out the image size, to be used in the PuzzlePiece widget
Future<Size> getImageSize(Image image) async { Future<Size> getImageSize(Image image) async {
@ -78,9 +95,11 @@ class _PuzzleViewWidget extends State<PuzzleView> {
// using the rows and columns defined above; each piece will be added to a stack // using the rows and columns defined above; each piece will be added to a stack
void splitImage(Image image) async { void splitImage(Image image) async {
Size imageSize = await getImageSize(image); Size imageSize = await getImageSize(image);
//imageSize = realWidgetSize!;
imageSize = Size(realWidgetSize!.width * 1.25, realWidgetSize!.height * 1.25);
for (int x = 0; x < rows; x++) { for (int x = 0; x < puzzleDTO.rows!; x++) {
for (int y = 0; y < cols; y++) { for (int y = 0; y < puzzleDTO.cols!; y++) {
setState(() { setState(() {
pieces.add( pieces.add(
PuzzlePiece( PuzzlePiece(
@ -89,8 +108,8 @@ class _PuzzleViewWidget extends State<PuzzleView> {
imageSize: imageSize, imageSize: imageSize,
row: x, row: x,
col: y, col: y,
maxRow: rows, maxRow: puzzleDTO.rows!,
maxCol: cols, maxCol: puzzleDTO.cols!,
bringToTop: this.bringToTop, bringToTop: this.bringToTop,
sendToBack: this.sendToBack, sendToBack: this.sendToBack,
), ),
@ -98,6 +117,10 @@ class _PuzzleViewWidget extends State<PuzzleView> {
}); });
} }
} }
setState(() {
isSplittingImage = false;
});
} }
// when the pan of a piece starts, we need to bring it to the front of the stack // when the pan of a piece starts, we need to bring it to the front of the stack
@ -112,38 +135,61 @@ class _PuzzleViewWidget extends State<PuzzleView> {
// it will be sent to the back of the stack to not get in the way of other, still movable, pieces // it will be sent to the back of the stack to not get in the way of other, still movable, pieces
void sendToBack(Widget widget) { void sendToBack(Widget widget) {
setState(() { setState(() {
allInPlaceCount++;
isFinished = allInPlaceCount == puzzleDTO.rows! * puzzleDTO.cols!;
pieces.remove(widget); pieces.remove(widget);
pieces.insert(0, widget); pieces.insert(0, widget);
if(isFinished) {
Size size = MediaQuery.of(context).size;
final appContext = Provider.of<AppContext>(context, listen: false);
TabletAppContext tabletAppContext = appContext.getContext();
TranslationAndResourceDTO? messageFin = puzzleDTO.messageFin != null ? puzzleDTO.messageFin!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
if(messageFin != null) {
showMessage(messageFin, appContext, context, size);
}
}
}); });
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
//savePrefs(); final appContext = Provider.of<AppContext>(context);
TabletAppContext tabletAppContext = appContext.getContext();
return SafeArea( return Padding(
child: sliderDTO.images![0].source_! == null key: _widgetKey,
? Center(child: Text('No image selected.')) padding: const EdgeInsets.all(10.0),
: Stack( child: isSplittingImage ? Center(child: LoadingCommon()) :
children: pieces, puzzleDTO.image!.resourceUrl == null || realWidgetSize == null
), ? Container(
); /*ScoreWidget width: 50,
.of(context) height: 50,
.allInPlaceCount == color: Colors.cyan,
rows * cols child: InkWell(onTap: () {
? Overlay( Size size = MediaQuery.of(context).size;
initialEntries: [ final appContext = Provider.of<AppContext>(context, listen: false);
OverlayEntry(builder: (context) { TabletAppContext tabletAppContext = appContext.getContext();
return CorrectOverlay(true, () { TranslationAndResourceDTO? messageFin = puzzleDTO.messageFin != null ? puzzleDTO.messageFin!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
setState(() {
ScoreWidget if(messageFin != null) {
.of(context) // Alert dialog
.allInPlaceCount = 0; showMessage(messageFin, appContext, context, size);
}); }
}); },),)//Center(child: Text("Invalid image"))
}) : Center(
], child: Padding(
) padding: const EdgeInsets.all(8.0),
:*/ child: Container(
width: tabletAppContext.puzzleSize != null ? tabletAppContext.puzzleSize!.width : realWidgetSize!.width * 0.8,
height: tabletAppContext.puzzleSize != null ? tabletAppContext.puzzleSize!.height +1.5 : realWidgetSize!.height * 0.8,
child: Stack(
children: pieces,
),
),
),
),
);
} }
} }

View File

@ -17,16 +17,16 @@ import 'package:tablet_app/constants.dart';
import 'drawStrawberry.dart'; import 'drawStrawberry.dart';
class QuizzViewWidget extends StatefulWidget { class QuizzView extends StatefulWidget {
final SectionDTO? section; final SectionDTO? section;
GlobalKey<ScaffoldState>? key; GlobalKey<ScaffoldState>? key;
QuizzViewWidget({this.section, this.key}); QuizzView({this.section, this.key});
@override @override
_QuizzViewWidget createState() => _QuizzViewWidget(); _QuizzView createState() => _QuizzView();
} }
class _QuizzViewWidget extends State<QuizzViewWidget> { class _QuizzView extends State<QuizzView> {
ConfettiController? _controllerCenter; ConfettiController? _controllerCenter;
QuizzDTO quizzDTO = QuizzDTO(); QuizzDTO quizzDTO = QuizzDTO();
List<QuestionSubDTO> _questionsSubDTO = <QuestionSubDTO>[]; List<QuestionSubDTO> _questionsSubDTO = <QuestionSubDTO>[];
@ -303,11 +303,11 @@ class _QuizzViewWidget extends State<QuizzViewWidget> {
color: kBackgroundLight, color: kBackgroundLight,
shape: BoxShape.rectangle, shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(20.0), borderRadius: BorderRadius.circular(20.0),
image: i.source_ != null ? new DecorationImage( image: i.resourceUrl != null ? new DecorationImage(
fit: BoxFit.contain, fit: BoxFit.cover,
opacity: 0.35, opacity: 0.35,
image: new NetworkImage( image: new NetworkImage(
i.source_!, i.resourceUrl!,
), ),
): null, ): null,
boxShadow: [ boxShadow: [
@ -382,9 +382,9 @@ class _QuizzViewWidget extends State<QuizzViewWidget> {
child: GridView.builder( child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2, crossAxisCount: 2,
mainAxisExtent: kIsWeb ? 75 : 150, // TODO depends on percentage mainAxisExtent: kIsWeb ? 75 : 100, // TODO depends on percentage 150
mainAxisSpacing: kIsWeb ? 75 : 150, // TODO depends on percentage mainAxisSpacing: kIsWeb ? 75 : 45, // TODO depends on percentage
crossAxisSpacing: kIsWeb ? 75 : 150, // TODO depends on percentage crossAxisSpacing: kIsWeb ? 75 : 20, // TODO depends on percentage
), ),
itemCount: i.responsesSubDTO!.length, itemCount: i.responsesSubDTO!.length,
itemBuilder: (BuildContext ctx, index) { itemBuilder: (BuildContext ctx, index) {
@ -464,8 +464,8 @@ class _QuizzViewWidget extends State<QuizzViewWidget> {
}, },
child: Icon( child: Icon(
Icons.chevron_right, Icons.chevron_right,
size: kIsWeb ? 100 : 150, size: kIsWeb ? 100 : 95,
color: kMainRed, color: kTestSecondColor,
), ),
) )
), ),
@ -480,8 +480,8 @@ class _QuizzViewWidget extends State<QuizzViewWidget> {
}, },
child: Icon( child: Icon(
Icons.chevron_left, Icons.chevron_left,
size: kIsWeb ? 100 : 150, size: kIsWeb ? 100 : 95,
color: kMainRed, color: kTestSecondColor,
), ),
) )
), ),
@ -493,7 +493,7 @@ class _QuizzViewWidget extends State<QuizzViewWidget> {
child: InkWell( child: InkWell(
child: Text( child: Text(
currentIndex.toString()+'/'+quizzDTO.questions!.length.toString(), currentIndex.toString()+'/'+quizzDTO.questions!.length.toString(),
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500), style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
), ),
) )
), ),

View File

@ -76,11 +76,11 @@ class _ShowReponsesWidget extends State<ShowReponsesWidget> {
color: kBackgroundLight, color: kBackgroundLight,
shape: BoxShape.rectangle, shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(20.0), borderRadius: BorderRadius.circular(20.0),
image: i.source_ != null ? new DecorationImage( image: i.resourceUrl != null ? new DecorationImage(
fit: BoxFit.contain, fit: BoxFit.contain,
opacity: 0.35, opacity: 0.35,
image: new NetworkImage( image: new NetworkImage(
i.source_!, i.resourceUrl!,
), ),
): null, ): null,
boxShadow: [ boxShadow: [

View File

@ -6,19 +6,20 @@ import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tablet_app/Components/video_viewer.dart';
import 'package:tablet_app/app_context.dart'; import 'package:tablet_app/app_context.dart';
import 'package:tablet_app/constants.dart'; import 'package:tablet_app/constants.dart';
import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view.dart';
class SliderViewWidget extends StatefulWidget { class SliderView extends StatefulWidget {
final SectionDTO? section; final SectionDTO? section;
SliderViewWidget({this.section}); SliderView({this.section});
@override @override
_SliderViewWidget createState() => _SliderViewWidget(); _SliderView createState() => _SliderView();
} }
class _SliderViewWidget extends State<SliderViewWidget> { class _SliderView extends State<SliderView> {
SliderDTO sliderDTO = SliderDTO(); SliderDTO sliderDTO = SliderDTO();
CarouselController? sliderController; CarouselController? sliderController;
int currentIndex = 1; int currentIndex = 1;
@ -30,7 +31,7 @@ class _SliderViewWidget extends State<SliderViewWidget> {
sliderController = CarouselController(); sliderController = CarouselController();
sliderDTO = SliderDTO.fromJson(jsonDecode(widget.section!.data!))!; sliderDTO = SliderDTO.fromJson(jsonDecode(widget.section!.data!))!;
sliderDTO.images!.sort((a, b) => a.order!.compareTo(b.order!)); sliderDTO.contents!.sort((a, b) => a.order!.compareTo(b.order!));
super.initState(); super.initState();
} }
@ -54,7 +55,7 @@ class _SliderViewWidget extends State<SliderViewWidget> {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
if(sliderDTO.images != null && sliderDTO.images!.length > 0) if(sliderDTO.contents != null && sliderDTO.contents!.length > 0)
CarouselSlider( CarouselSlider(
carouselController: sliderController, carouselController: sliderController,
options: CarouselOptions( options: CarouselOptions(
@ -67,7 +68,7 @@ class _SliderViewWidget extends State<SliderViewWidget> {
enlargeCenterPage: true, enlargeCenterPage: true,
reverse: false, reverse: false,
), ),
items: sliderDTO.images!.map<Widget>((i) { items: sliderDTO.contents!.map<Widget>((i) {
return Builder( return Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
return Container( return Container(
@ -116,18 +117,18 @@ class _SliderViewWidget extends State<SliderViewWidget> {
child: AspectRatio( child: AspectRatio(
aspectRatio: 16 / 9, aspectRatio: 16 / 9,
child: ClipRect( child: ClipRect(
child: PhotoView( child: VideoViewer(videoUrl: "https://firebasestorage.googleapis.com/v0/b/mymuseum-3b97f.appspot.com/o/All%2024%20Cybertruck%20Accessories%20Revealed!.mp4?alt=media&token=fc178259-10fc-4167-b496-cf7d04aaae5e")/*PhotoView(
imageProvider: new NetworkImage( imageProvider: new NetworkImage(
i.source_!, i.source_!,
), ),
minScale: PhotoViewComputedScale.contained * 0.8, minScale: PhotoViewComputedScale.contained * 0.8,
maxScale: PhotoViewComputedScale.contained * 3.0, maxScale: PhotoViewComputedScale.contained * 3.0,
backgroundDecoration: BoxDecoration( backgroundDecoration: BoxDecoration(
color: kBackgroundSecondGrey, color: kBackgroundSecondGrey,
shape: BoxShape.rectangle, shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(15.0), borderRadius: BorderRadius.circular(15.0),
), ),
), ),*/
), ),
), ),
), ),
@ -190,39 +191,39 @@ class _SliderViewWidget extends State<SliderViewWidget> {
), ),
], ],
), ),
if(sliderDTO.images != null && sliderDTO.images!.length > 1) if(sliderDTO.contents != null && sliderDTO.contents!.length > 1)
Positioned( Positioned(
top: MediaQuery.of(context).size.height * 0.35, top: MediaQuery.of(context).size.height * 0.35,
right: 60, right: 60,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
if (sliderDTO.images!.length > 0) if (sliderDTO.contents!.length > 0)
sliderController!.nextPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); sliderController!.nextPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
}, },
child: Icon( child: Icon(
Icons.chevron_right, Icons.chevron_right,
size: 150, size: 90,
color: kMainRed, color: Colors.white,
), ),
) )
), ),
if(sliderDTO.images != null && sliderDTO.images!.length > 1) if(sliderDTO.contents != null && sliderDTO.contents!.length > 1)
Positioned( Positioned(
top: MediaQuery.of(context).size.height * 0.35, top: MediaQuery.of(context).size.height * 0.35,
left: 60, left: 60,
child: InkWell( child: InkWell(
onTap: () { onTap: () {
if (sliderDTO.images!.length > 0) if (sliderDTO.contents!.length > 0)
sliderController!.previousPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); sliderController!.previousPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
}, },
child: Icon( child: Icon(
Icons.chevron_left, Icons.chevron_left,
size: 150, size: 90,
color: kMainRed, color: Colors.white,
), ),
) )
), ),
if(sliderDTO.images != null && sliderDTO.images!.length > 0) if(sliderDTO.contents != null && sliderDTO.contents!.length > 0)
Padding( Padding(
padding: widget.section!.parentId == null ? EdgeInsets.only() : const EdgeInsets.only(left: 15, bottom: 10), padding: widget.section!.parentId == null ? EdgeInsets.only() : const EdgeInsets.only(left: 15, bottom: 10),
child: Align( child: Align(
@ -232,14 +233,14 @@ class _SliderViewWidget extends State<SliderViewWidget> {
sliderController!.previousPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn); sliderController!.previousPage(duration: new Duration(milliseconds: 500), curve: Curves.fastOutSlowIn);
}, },
child: Text( child: Text(
currentIndex.toString()+'/'+sliderDTO.images!.length.toString(), currentIndex.toString()+'/'+sliderDTO.contents!.length.toString(),
style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500), style: TextStyle(fontSize: 25, fontWeight: FontWeight.w500),
), ),
) )
), ),
), ),
if(sliderDTO.images == null || sliderDTO.images!.length == 0) if(sliderDTO.contents == null || sliderDTO.contents!.length == 0)
Center(child: Text("Aucune image à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect),)) Center(child: Text("Aucun contenu à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect),))
// Description // Description
/*Container( /*Container(
height: sliderDTO.images != null && sliderDTO.images.length > 0 ? size.height *0.3 : size.height *0.6, height: sliderDTO.images != null && sliderDTO.images.length > 0 ? size.height *0.3 : size.height *0.6,

View File

@ -7,15 +7,15 @@ import 'package:tablet_app/constants.dart';
import 'package:youtube_player_iframe/youtube_player_iframe.dart' as iframe; import 'package:youtube_player_iframe/youtube_player_iframe.dart' as iframe;
import 'package:youtube_player_flutter/youtube_player_flutter.dart'; import 'package:youtube_player_flutter/youtube_player_flutter.dart';
class VideoViewWidget extends StatefulWidget { class VideoView extends StatefulWidget {
final SectionDTO? section; final SectionDTO? section;
VideoViewWidget({this.section}); VideoView({this.section});
@override @override
_VideoViewWidget createState() => _VideoViewWidget(); _VideoView createState() => _VideoView();
} }
class _VideoViewWidget extends State<VideoViewWidget> { class _VideoView extends State<VideoView> {
iframe.YoutubePlayer? _videoViewWeb; iframe.YoutubePlayer? _videoViewWeb;
YoutubePlayer? _videoView; YoutubePlayer? _videoView;
VideoDTO? videoDTO; VideoDTO? videoDTO;

View File

@ -14,10 +14,10 @@ class WebView extends StatefulWidget {
WebView({this.section}); WebView({this.section});
@override @override
_WebViewWidget createState() => _WebViewWidget(); _WebView createState() => _WebView();
} }
class _WebViewWidget extends State<WebView> { class _WebView extends State<WebView> {
//final IFrameElement _iframeElement = IFrameElement(); //final IFrameElement _iframeElement = IFrameElement();
//WebView _webView; //WebView _webView;
WebDTO webDTO = WebDTO(); WebDTO webDTO = WebDTO();

View File

@ -5,7 +5,7 @@ info:
description: API Manager Service description: API Manager Service
version: Version Alpha version: Version Alpha
servers: servers:
- url: http://localhost:5000 - url: https://api.myinfomate.be
paths: paths:
/api/Configuration: /api/Configuration:
get: get:
@ -2400,6 +2400,12 @@ components:
nullable: true nullable: true
oneOf: oneOf:
- $ref: '#/components/schemas/ContentDTO' - $ref: '#/components/schemas/ContentDTO'
rows:
type: integer
format: int32
cols:
type: integer
format: int32
AgendaDTO: AgendaDTO:
type: object type: object
additionalProperties: false additionalProperties: false

View File

@ -17,20 +17,20 @@ const kBackgroundLight = Color(0xfff3f3f3);
const List<String> languages = ["FR", "NL", "EN", "DE", "IT", "ES", "PL", "CN", "AR", "UK"]; // hmmmm depends on config.. const List<String> languages = ["FR", "NL", "EN", "DE", "IT", "ES", "PL", "CN", "AR", "UK"]; // hmmmm depends on config..
const kTitleSize = 40.0; const kTitleSize = 32.0;
const kDescriptionSize = 25.0; const kDescriptionSize = 15.0;
const kSectionTitleDetailSize = 50.0; const kSectionTitleDetailSize = 30.0;
const kSectionDescriptionDetailSize = 35.0; const kSectionDescriptionDetailSize = 18.0;
const kMenuTitleDetailSize = 45.0; const kMenuTitleDetailSize = 30.0;
const kMenuDescriptionDetailSize = 28.0; const kMenuDescriptionDetailSize = 15.0;
// WEB // WEB
const kWebMenuTitleDetailSize = 30.0; const kWebMenuTitleDetailSize = 30.0;
const kWebMenuDescriptionDetailSize = 14.0; const kWebMenuDescriptionDetailSize = 14.0;
const kWebSectionTitleDetailSize = 35.0; const kWebSectionTitleDetailSize = 30.0;
const kWebSectionDescriptionDetailSize = 20.0; const kWebSectionDescriptionDetailSize = 15.0;
const kWebTitleSize = 30.0; const kWebTitleSize = 30.0;
const kWebDescriptionSize = 14.0; const kWebDescriptionSize = 14.0;

View File

@ -45,7 +45,7 @@ void main() async {
} }
} else { } else {
print("NO LOCAL DB !"); print("NO LOCAL DB !");
localContext = TabletAppContext(host: "https://api.mymuseum.be"); localContext = TabletAppContext(host: "https://api.myinfomate.be");
} }
if(kIsWeb) { if(kIsWeb) {

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -11,6 +11,8 @@ Name | Type | Description | Notes
**messageDebut** | [**List<TranslationAndResourceDTO>**](TranslationAndResourceDTO.md) | | [optional] [default to const []] **messageDebut** | [**List<TranslationAndResourceDTO>**](TranslationAndResourceDTO.md) | | [optional] [default to const []]
**messageFin** | [**List<TranslationAndResourceDTO>**](TranslationAndResourceDTO.md) | | [optional] [default to const []] **messageFin** | [**List<TranslationAndResourceDTO>**](TranslationAndResourceDTO.md) | | [optional] [default to const []]
**image** | [**PuzzleDTOImage**](PuzzleDTOImage.md) | | [optional] **image** | [**PuzzleDTOImage**](PuzzleDTOImage.md) | | [optional]
**rows** | **int** | | [optional]
**cols** | **int** | | [optional]
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -5,7 +5,7 @@
import 'package:manager_api/api.dart'; import 'package:manager_api/api.dart';
``` ```
All URIs are relative to *http://localhost:5000* All URIs are relative to *https://api.myinfomate.be*
Method | HTTP request | Description Method | HTTP request | Description
------------- | ------------- | ------------- ------------- | ------------- | -------------

View File

@ -11,7 +11,7 @@
part of openapi.api; part of openapi.api;
class ApiClient { class ApiClient {
ApiClient({this.basePath = 'http://localhost:5000', this.authentication,}); ApiClient({this.basePath = 'https://api.myinfomate.be', this.authentication,});
final String basePath; final String basePath;
final Authentication? authentication; final Authentication? authentication;

View File

@ -16,6 +16,8 @@ class PuzzleDTO {
this.messageDebut = const [], this.messageDebut = const [],
this.messageFin = const [], this.messageFin = const [],
this.image, this.image,
this.rows,
this.cols,
}); });
List<TranslationAndResourceDTO>? messageDebut; List<TranslationAndResourceDTO>? messageDebut;
@ -24,21 +26,41 @@ class PuzzleDTO {
PuzzleDTOImage? image; PuzzleDTOImage? image;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
int? rows;
///
/// Please note: This property should have been non-nullable! Since the specification file
/// does not include a default value (using the "default:" property), however, the generated
/// source code must fall back to having a nullable type.
/// Consider adding a "default:" property in the specification file to hide this note.
///
int? cols;
@override @override
bool operator ==(Object other) => identical(this, other) || other is PuzzleDTO && bool operator ==(Object other) => identical(this, other) || other is PuzzleDTO &&
other.messageDebut == messageDebut && other.messageDebut == messageDebut &&
other.messageFin == messageFin && other.messageFin == messageFin &&
other.image == image; other.image == image &&
other.rows == rows &&
other.cols == cols;
@override @override
int get hashCode => int get hashCode =>
// ignore: unnecessary_parenthesis // ignore: unnecessary_parenthesis
(messageDebut == null ? 0 : messageDebut!.hashCode) + (messageDebut == null ? 0 : messageDebut!.hashCode) +
(messageFin == null ? 0 : messageFin!.hashCode) + (messageFin == null ? 0 : messageFin!.hashCode) +
(image == null ? 0 : image!.hashCode); (image == null ? 0 : image!.hashCode) +
(rows == null ? 0 : rows!.hashCode) +
(cols == null ? 0 : cols!.hashCode);
@override @override
String toString() => 'PuzzleDTO[messageDebut=$messageDebut, messageFin=$messageFin, image=$image]'; String toString() => 'PuzzleDTO[messageDebut=$messageDebut, messageFin=$messageFin, image=$image, rows=$rows, cols=$cols]';
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final json = <String, dynamic>{}; final json = <String, dynamic>{};
@ -57,6 +79,16 @@ class PuzzleDTO {
} else { } else {
json[r'image'] = null; json[r'image'] = null;
} }
if (this.rows != null) {
json[r'rows'] = this.rows;
} else {
json[r'rows'] = null;
}
if (this.cols != null) {
json[r'cols'] = this.cols;
} else {
json[r'cols'] = null;
}
return json; return json;
} }
@ -82,6 +114,8 @@ class PuzzleDTO {
messageDebut: TranslationAndResourceDTO.listFromJson(json[r'messageDebut']), messageDebut: TranslationAndResourceDTO.listFromJson(json[r'messageDebut']),
messageFin: TranslationAndResourceDTO.listFromJson(json[r'messageFin']), messageFin: TranslationAndResourceDTO.listFromJson(json[r'messageFin']),
image: PuzzleDTOImage.fromJson(json[r'image']), image: PuzzleDTOImage.fromJson(json[r'image']),
rows: mapValueOfType<int>(json, r'rows'),
cols: mapValueOfType<int>(json, r'cols'),
); );
} }
return null; return null;

View File

@ -23,28 +23,28 @@ class ResourceType {
int toJson() => value; int toJson() => value;
static const image = ResourceType._(0); static const Image = ResourceType._(0);
static const video = ResourceType._(1); static const Video = ResourceType._(1);
static const imageUrl = ResourceType._(2); static const ImageUrl = ResourceType._(2);
static const videoUrl = ResourceType._(3); static const VideoUrl = ResourceType._(3);
static const audio = ResourceType._(4); static const Audio = ResourceType._(4);
static const PDF = ResourceType._(5); static const Pdf = ResourceType._(5);
static const JSON = ResourceType._(6); static const Json = ResourceType._(6);
/// List of all possible values in this [enum][ResourceType]. /// List of all possible values in this [enum][ResourceType].
static const values = <ResourceType>[ static const values = <ResourceType>[
image, Image,
video, Video,
imageUrl, ImageUrl,
videoUrl, VideoUrl,
audio, Audio,
PDF, Pdf,
JSON Json
]; ];
static ResourceType? fromJson(dynamic value) => ResourceTypeTypeTransformer().decode(value); static ResourceType? fromJson(dynamic value) => ResourceTypeTypeTransformer().decode(value);
static List<ResourceType> listFromJson(dynamic json, {bool growable = false,}) { static List<ResourceType>? listFromJson(dynamic json, {bool growable = false,}) {
final result = <ResourceType>[]; final result = <ResourceType>[];
if (json is List && json.isNotEmpty) { if (json is List && json.isNotEmpty) {
for (final row in json) { for (final row in json) {
@ -77,18 +77,36 @@ class ResourceTypeTypeTransformer {
/// and users are still using an old app with the old code. /// and users are still using an old app with the old code.
ResourceType? decode(dynamic data, {bool allowNull = true}) { ResourceType? decode(dynamic data, {bool allowNull = true}) {
if (data != null) { if (data != null) {
switch (data.toString()) { if(data.runtimeType == String) {
case r'Image': return ResourceType.image; switch (data.toString()) {
case r'Video': return ResourceType.video; case "Image": return ResourceType.Image;
case r'ImageUrl': return ResourceType.imageUrl; case "Video": return ResourceType.Video;
case r'VideoUrl': return ResourceType.videoUrl; case "ImageUrl": return ResourceType.ImageUrl;
case r'Audio': return ResourceType.audio; case "VideoUrl": return ResourceType.VideoUrl;
case r'PDF': return ResourceType.PDF; case "Audio": return ResourceType.Audio;
case r'JSON': return ResourceType.JSON; case "PDF": return ResourceType.Pdf;
default: case "JSON": return ResourceType.Json;
if (!allowNull) { default:
throw ArgumentError('Unknown enum value to decode: $data'); if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
}
} else {
if(data.runtimeType == int) {
switch (data) {
case 0: return ResourceType.Image;
case 1: return ResourceType.Video;
case 2: return ResourceType.ImageUrl;
case 3: return ResourceType.VideoUrl;
case 4: return ResourceType.Audio;
case 5: return ResourceType.Pdf;
case 6: return ResourceType.Json;
default:
if (!allowNull) {
throw ArgumentError('Unknown enum value to decode: $data');
}
} }
}
} }
} }
return null; return null;