mirror of
https://bitbucket.org/FransoletThomas/tablet-app.git
synced 2025-12-06 16:41:19 +00:00
228 lines
7.8 KiB
Dart
228 lines
7.8 KiB
Dart
import 'dart:convert';
|
|
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:flutter/material.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 'package:tablet_app/constants.dart';
|
|
import 'puzzle_piece.dart';
|
|
|
|
const IMAGE_PATH = 'image_path';
|
|
|
|
class PuzzleView extends StatefulWidget {
|
|
final SectionDTO? section;
|
|
PuzzleView({this.section});
|
|
|
|
@override
|
|
_PuzzleView createState() => _PuzzleView();
|
|
}
|
|
|
|
class _PuzzleView extends State<PuzzleView> {
|
|
PuzzleDTO puzzleDTO = PuzzleDTO();
|
|
|
|
int allInPlaceCount = 0;
|
|
bool isFinished = false;
|
|
GlobalKey _widgetKey = GlobalKey();
|
|
Size? realWidgetSize;
|
|
List<Widget> pieces = [];
|
|
|
|
bool isSplittingImage = true;
|
|
|
|
@override
|
|
void initState() {
|
|
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();
|
|
|
|
print(puzzleDTO.messageDebut);
|
|
TranslationAndResourceDTO? messageDebut = puzzleDTO.messageDebut != null && puzzleDTO.messageDebut!.length > 0 ? puzzleDTO.messageDebut!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
|
|
|
|
if(messageDebut != null) {
|
|
showMessage(messageDebut, appContext, context, size);
|
|
}
|
|
|
|
getRealWidgetSize();
|
|
|
|
if(puzzleDTO.image != null && puzzleDTO.image!.resourceUrl != null) {
|
|
//splitImage(Image.network(puzzleDTO.image!.resourceUrl!));
|
|
splitImage(CachedNetworkImage(
|
|
imageUrl: puzzleDTO.image!.resourceUrl!,
|
|
fit: BoxFit.fill,
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
));
|
|
} else {
|
|
setState(() {
|
|
isSplittingImage = false;
|
|
});
|
|
}
|
|
});
|
|
|
|
super.initState();
|
|
}
|
|
|
|
Future<void> getRealWidgetSize() async {
|
|
RenderBox renderBox = _widgetKey.currentContext?.findRenderObject() as RenderBox;
|
|
Size size = renderBox.size;
|
|
|
|
setState(() {
|
|
realWidgetSize = size;
|
|
});
|
|
print("Taille réelle du widget : $size");
|
|
}
|
|
|
|
// we need to find out the image size, to be used in the PuzzlePiece widget
|
|
/*Future<Size> getImageSize(CachedNetworkImage image) async {
|
|
Completer<Size> completer = Completer<Size>();
|
|
|
|
/*image.image
|
|
.resolve(const ImageConfiguration())
|
|
.addListener(ImageStreamListener((ImageInfo info, bool _) {
|
|
completer.complete(
|
|
Size(info.image.width.toDouble(), info.image.height.toDouble()));
|
|
}));*/
|
|
|
|
CachedNetworkImage(
|
|
imageUrl: 'https://example.com/image.jpg',
|
|
placeholder: (context, url) => CircularProgressIndicator(),
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
imageBuilder: (BuildContext context, ImageProvider imageProvider) {
|
|
Completer<Size> completer = Completer<Size>();
|
|
|
|
imageProvider
|
|
.resolve(const ImageConfiguration())
|
|
.addListener(ImageStreamListener((ImageInfo info, bool _) {
|
|
completer.complete(
|
|
Size(info.image.width.toDouble(), info.image.height.toDouble()));
|
|
}));
|
|
|
|
return CachedNetworkImage(
|
|
imageUrl: 'https://example.com/image.jpg',
|
|
placeholder: (context, url) => CircularProgressIndicator(),
|
|
errorWidget: (context, url, error) => Icon(Icons.error),
|
|
imageBuilder: (context, imageProvider) {
|
|
return Image(
|
|
image: imageProvider,
|
|
loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) {
|
|
if (loadingProgress == null) {
|
|
return child;
|
|
} else {
|
|
return Center(
|
|
child: CircularProgressIndicator(
|
|
value: loadingProgress.expectedTotalBytes != null
|
|
? loadingProgress.cumulativeBytesLoaded / (loadingProgress.expectedTotalBytes ?? 1)
|
|
: null,
|
|
),
|
|
);
|
|
}
|
|
},
|
|
);
|
|
},
|
|
);
|
|
},
|
|
);
|
|
|
|
Size imageSize = await completer.future;
|
|
|
|
return imageSize;
|
|
}*/
|
|
|
|
// here we will split the image into small pieces
|
|
// using the rows and columns defined above; each piece will be added to a stack
|
|
void splitImage(CachedNetworkImage image) async {
|
|
//Size imageSize = await getImageSize(image);
|
|
//imageSize = realWidgetSize!;
|
|
Size imageSize = Size(realWidgetSize!.width * 1.25, realWidgetSize!.height * 1.25);
|
|
|
|
for (int x = 0; x < puzzleDTO.rows!; x++) {
|
|
for (int y = 0; y < puzzleDTO.cols!; y++) {
|
|
setState(() {
|
|
pieces.add(
|
|
PuzzlePiece(
|
|
key: GlobalKey(),
|
|
image: image,
|
|
imageSize: imageSize,
|
|
row: x,
|
|
col: y,
|
|
maxRow: puzzleDTO.rows!,
|
|
maxCol: puzzleDTO.cols!,
|
|
bringToTop: this.bringToTop,
|
|
sendToBack: this.sendToBack,
|
|
),
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
setState(() {
|
|
isSplittingImage = false;
|
|
});
|
|
}
|
|
|
|
// when the pan of a piece starts, we need to bring it to the front of the stack
|
|
void bringToTop(Widget widget) {
|
|
setState(() {
|
|
pieces.remove(widget);
|
|
pieces.add(widget);
|
|
});
|
|
}
|
|
|
|
// when a piece reaches its final position,
|
|
// 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) {
|
|
setState(() {
|
|
allInPlaceCount++;
|
|
isFinished = allInPlaceCount == puzzleDTO.rows! * puzzleDTO.cols!;
|
|
pieces.remove(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!.length > 0 ? puzzleDTO.messageFin!.firstWhere((message) => message.language!.toUpperCase() == tabletAppContext.language!.toUpperCase()) : null;
|
|
|
|
if(messageFin != null) {
|
|
showMessage(messageFin, appContext, context, size);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final appContext = Provider.of<AppContext>(context);
|
|
TabletAppContext tabletAppContext = appContext.getContext();
|
|
|
|
return Padding(
|
|
key: _widgetKey,
|
|
padding: const EdgeInsets.all(10.0),
|
|
child: isSplittingImage ? Center(child: LoadingCommon()) :
|
|
puzzleDTO.image == null || puzzleDTO.image!.resourceUrl == null || realWidgetSize == null
|
|
? Center(child: Text("Aucune image à afficher", style: TextStyle(fontSize: kNoneInfoOrIncorrect)))
|
|
: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Container(
|
|
width: tabletAppContext.puzzleSize != null && tabletAppContext.puzzleSize!.width > 0 ? tabletAppContext.puzzleSize!.width : realWidgetSize!.width * 0.8,
|
|
height: tabletAppContext.puzzleSize != null && tabletAppContext.puzzleSize!.height > 0 ? tabletAppContext.puzzleSize!.height +1.5 : realWidgetSize!.height * 0.85,
|
|
child: Stack(
|
|
children: pieces,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
} |