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.

217 lines
8.1 KiB

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