You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

213 lines
8.0 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:image_picker/image_picker.dart';
  4. import 'package:my_flutter_puzzle/application/states/image_splitter_state.dart';
  5. import 'package:my_flutter_puzzle/application/states/puzzle_state.dart';
  6. import 'package:my_flutter_puzzle/models/puzzle_data.dart';
  7. import 'package:my_flutter_puzzle/providers.dart';
  8. import 'package:my_flutter_puzzle/res/puzzle_constants.dart';
  9. import 'package:my_flutter_puzzle/utils/puzzle_solver.dart';
  10. import 'package:my_flutter_puzzle/widgets/photo_screen/image_viewer.dart';
  11. import 'package:my_flutter_puzzle/widgets/photo_screen/pick_image_button.dart';
  12. import 'package:my_flutter_puzzle/widgets/solo_screen/solo_screen_export.dart';
  13. import 'package:palette_generator/palette_generator.dart';
  14. import 'package:rive/rive.dart';
  15. class PhotoScreenLarge extends ConsumerStatefulWidget {
  16. const PhotoScreenLarge({
  17. required this.solverClient,
  18. required this.initialPuzzleData,
  19. required this.puzzleSize,
  20. required this.riveController,
  21. Key? key,
  22. }) : super(key: key);
  23. final PuzzleSolverClient solverClient;
  24. final PuzzleData initialPuzzleData;
  25. final int puzzleSize;
  26. final RiveAnimationController riveController;
  27. @override
  28. ConsumerState<ConsumerStatefulWidget> createState() => _SoloScreenLargeState();
  29. }
  30. class _SoloScreenLargeState extends ConsumerState<PhotoScreenLarge> {
  31. late final PuzzleSolverClient _solverClient;
  32. late final int _puzzleSize;
  33. late final PuzzleData _initialPuzzleData;
  34. late final RiveAnimationController _riveController;
  35. bool _isStartPressed = false;
  36. final _imagePicker = ImagePicker();
  37. List<Image>? _previousImages;
  38. Image? _previousImage;
  39. PaletteGenerator? _previousPalette;
  40. @override
  41. void initState() {
  42. _solverClient = widget.solverClient;
  43. _puzzleSize = widget.puzzleSize;
  44. _initialPuzzleData = widget.initialPuzzleData;
  45. _riveController = widget.riveController;
  46. super.initState();
  47. }
  48. @override
  49. Widget build(BuildContext context) {
  50. ref.listen(puzzleNotifierProvider(_solverClient), (previous, PuzzleState next) {
  51. if (next is PuzzleInitializing) {
  52. setState(() {
  53. _isStartPressed = true;
  54. });
  55. }
  56. });
  57. ref.listen(imageSplitterNotifierProvider, (previous, next) {
  58. if (next is ImageSplitterComplete) {
  59. setState(() {
  60. _previousImages = next.images;
  61. _previousImage = next.image;
  62. _previousPalette = next.palette;
  63. });
  64. }
  65. });
  66. var fontSize = 70.0;
  67. var boardSize = 280.0;
  68. var spacing = 4;
  69. var eachBoxSize = (boardSize / _puzzleSize) - (spacing * (_puzzleSize - 1));
  70. return Scaffold(
  71. backgroundColor: Theme.of(context).colorScheme.background,
  72. body: SafeArea(
  73. child: Row(
  74. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  75. children: [
  76. Padding(
  77. padding: const EdgeInsetsDirectional.symmetric(horizontal: 10),
  78. child: Column(
  79. mainAxisAlignment: MainAxisAlignment.center,
  80. crossAxisAlignment: CrossAxisAlignment.center,
  81. children: [
  82. const SizedBox(height: 32),
  83. MovesTilesWidget(solverClient: _solverClient, fontSize: 16),
  84. const SizedBox(height: 32),
  85. GameButtonWidget(
  86. solverClient: _solverClient,
  87. initialPuzzleData: _initialPuzzleData,
  88. ),
  89. ],
  90. ),
  91. ),
  92. SingleChildScrollView(
  93. child: Column(
  94. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  95. children: [
  96. const TimerWidget(fontSize: 30),
  97. const SizedBox(height: 12),
  98. Consumer(
  99. builder: (context, ref, child) {
  100. final state = ref.watch(imageSplitterNotifierProvider);
  101. return state.maybeWhen(
  102. () => PuzzleWidget(
  103. solverClient: _solverClient,
  104. boardSize: boardSize,
  105. eachBoxSize: eachBoxSize,
  106. initialPuzzleData: _initialPuzzleData,
  107. fontSize: fontSize,
  108. images: _previousImages,
  109. kInitialSpeed: kInitialSpeed,
  110. ),
  111. complete: (image, images, palette) {
  112. _previousImages = images;
  113. _previousImage = image;
  114. _previousPalette = palette;
  115. return PuzzleWidget(
  116. solverClient: _solverClient,
  117. boardSize: boardSize,
  118. eachBoxSize: eachBoxSize,
  119. initialPuzzleData: _initialPuzzleData,
  120. fontSize: fontSize,
  121. images: images,
  122. kInitialSpeed: kInitialSpeed,
  123. );
  124. },
  125. orElse: () => PuzzleWidget(
  126. solverClient: _solverClient,
  127. boardSize: boardSize,
  128. eachBoxSize: eachBoxSize,
  129. initialPuzzleData: _initialPuzzleData,
  130. fontSize: fontSize,
  131. images: _previousImages,
  132. kInitialSpeed: kInitialSpeed,
  133. ),
  134. );
  135. },
  136. ),
  137. const SizedBox(height: 30),
  138. ],
  139. ),
  140. ),
  141. Padding(
  142. padding: const EdgeInsetsDirectional.symmetric(horizontal: 10),
  143. child: Stack(
  144. children: [
  145. AnimatedDash(
  146. boardSize: boardSize * 0.8,
  147. riveController: _riveController,
  148. onInit: (_) => setState(() {}),
  149. ),
  150. Column(
  151. mainAxisSize: MainAxisSize.max,
  152. crossAxisAlignment: CrossAxisAlignment.end,
  153. mainAxisAlignment: MainAxisAlignment.center,
  154. children: [
  155. CountdownWidget(
  156. isStartPressed: _isStartPressed,
  157. onFinish: () {
  158. ref.read(timerNotifierProvider.notifier).startTimer();
  159. setState(() {
  160. _isStartPressed = false;
  161. });
  162. },
  163. initialSpeed: kInitialSpeed,
  164. ),
  165. Visibility(
  166. visible: !_isStartPressed,
  167. child: Column(
  168. children: [
  169. ImageViewer(
  170. imagePicker: _imagePicker,
  171. puzzleSize: _puzzleSize,
  172. previousImage: _previousImage,
  173. previousPalette: _previousPalette,
  174. imageSize: 200,
  175. ),
  176. PickImageButton(
  177. text: 'Pick Image',
  178. onTap: ref.read(imageSplitterNotifierProvider) is ImageSplitterComplete
  179. ? () => ref.read(imageSplitterNotifierProvider.notifier).generateImages(
  180. picker: _imagePicker,
  181. puzzleSize: _puzzleSize,
  182. )
  183. : null,
  184. ),
  185. ],
  186. ),
  187. ),
  188. ],
  189. ),
  190. ],
  191. ),
  192. ),
  193. // SizedBox(),
  194. ],
  195. ),
  196. ),
  197. );
  198. }
  199. }