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.

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