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.

269 lines
10 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
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:flutter_svg/flutter_svg.dart';
  5. import 'package:my_flutter_puzzle/application/states/image_splitter_state.dart';
  6. import 'package:my_flutter_puzzle/application/states/puzzle_state.dart';
  7. import 'package:my_flutter_puzzle/cubits/count_down_timer_cubit.dart';
  8. import 'package:my_flutter_puzzle/models/puzzle_data.dart';
  9. import 'package:my_flutter_puzzle/providers.dart';
  10. import 'package:my_flutter_puzzle/res/puzzle_constants.dart';
  11. import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart';
  12. import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
  13. import 'package:my_flutter_puzzle/utils/puzzle_solver.dart';
  14. import 'package:my_flutter_puzzle/utils/utils.dart';
  15. import 'package:my_flutter_puzzle/widgets/photo_screen/image_viewer.dart';
  16. import 'package:my_flutter_puzzle/widgets/solo_screen/animated_dash.dart';
  17. import 'package:my_flutter_puzzle/widgets/solo_screen/count_down_timer_widget.dart';
  18. import 'package:my_flutter_puzzle/widgets/solo_screen/countdown_widget.dart';
  19. import 'package:my_flutter_puzzle/widgets/solo_screen/moves_tiles_widget.dart';
  20. import 'package:my_flutter_puzzle/widgets/solo_screen/puzzle_widget.dart';
  21. import 'package:palette_generator/palette_generator.dart';
  22. import 'package:rive/rive.dart';
  23. class PhotoScreenLarge extends ConsumerStatefulWidget {
  24. const PhotoScreenLarge({
  25. required this.solverClient,
  26. required this.initialPuzzleData,
  27. required this.puzzleSize,
  28. required this.riveController,
  29. required this.duration,
  30. required this.level,
  31. Key? key,
  32. }) : super(key: key);
  33. final PuzzleSolverClient solverClient;
  34. final PuzzleData initialPuzzleData;
  35. final int puzzleSize;
  36. final int duration;
  37. final int level;
  38. final RiveAnimationController riveController;
  39. @override
  40. ConsumerState<ConsumerStatefulWidget> createState() =>
  41. _SoloScreenLargeState();
  42. }
  43. class _SoloScreenLargeState extends ConsumerState<PhotoScreenLarge> {
  44. late final PuzzleSolverClient _solverClient;
  45. late final int _puzzleSize;
  46. late final PuzzleData _initialPuzzleData;
  47. late final RiveAnimationController _riveController;
  48. bool _puzzleSolved = false;
  49. bool _isStartPressed = false;
  50. final double _fontSize = 70.0;
  51. final double _boardSize = 280.0;
  52. final int _spacing = 4;
  53. late double _eachBoxSize;
  54. List<Image>? _previousImages;
  55. Image? _previousImage;
  56. PaletteGenerator? _previousPalette;
  57. @override
  58. void initState() {
  59. _solverClient = widget.solverClient;
  60. _puzzleSize = widget.puzzleSize;
  61. _eachBoxSize = (_boardSize / _puzzleSize) - (_spacing * (_puzzleSize - 1));
  62. _initialPuzzleData = widget.initialPuzzleData;
  63. _riveController = widget.riveController;
  64. super.initState();
  65. }
  66. @override
  67. Widget build(BuildContext context) {
  68. ref.listen(puzzleNotifierProvider(_solverClient),
  69. (previous, PuzzleState next) {
  70. if (next is PuzzleInitializing) {
  71. setState(() {
  72. _isStartPressed = true;
  73. });
  74. }
  75. if (next is PuzzleSolved) {
  76. _puzzleSolved = true;
  77. }
  78. });
  79. ref.listen(imageSplitterNotifierProvider, (previous, next) {
  80. if (next is ImageSplitterComplete) {
  81. setState(() {
  82. _previousImages = next.images;
  83. _previousImage = next.image;
  84. _previousPalette = next.palette;
  85. });
  86. ref
  87. .read(puzzleNotifierProvider(_solverClient).notifier)
  88. .initializePuzzle(
  89. initialPuzzleData: _initialPuzzleData,
  90. );
  91. }
  92. });
  93. return WillPopScope(
  94. onWillPop: () async {
  95. BlocProvider.of<CountDownTimerCubit>(context).stop();
  96. return true;
  97. },
  98. child: Scaffold(
  99. backgroundColor: const Color(0xff4400CE),
  100. body: SafeArea(
  101. child: Padding(
  102. padding: EdgeInsets.symmetric(
  103. horizontal: context.width * 30 / 812,
  104. vertical: context.height * 20 / 375,
  105. ),
  106. child: Row(
  107. children: [
  108. Column(
  109. mainAxisAlignment: MainAxisAlignment.center,
  110. crossAxisAlignment: CrossAxisAlignment.start,
  111. children: [
  112. Row(
  113. children: [
  114. SvgPicture.asset('flash'.svgPath),
  115. const SizedBox(width: 8),
  116. Text(
  117. 'Level ${widget.level}',
  118. style: const TextStyle(
  119. color: Colors.white,
  120. fontWeight: FontWeight.bold,
  121. fontSize: 16,
  122. ),
  123. ),
  124. const SizedBox(width: 18),
  125. GestureDetector(
  126. onTap: _resetTimer,
  127. child: Container(
  128. width: context.width * 22 / 540,
  129. height: context.width * 22 / 540,
  130. padding: const EdgeInsets.all(5),
  131. margin: const EdgeInsets.symmetric(vertical: 3),
  132. decoration: const BoxDecoration(
  133. color: Colors.white,
  134. shape: BoxShape.circle,
  135. ),
  136. child: SvgPicture.asset('refresh'.svgPath),
  137. ),
  138. ),
  139. ],
  140. ),
  141. const SizedBox(height: 21),
  142. ImageViewer(
  143. puzzleSize: _puzzleSize,
  144. previousImage: _previousImage,
  145. previousPalette: _previousPalette,
  146. imageSize: 200,
  147. ),
  148. const SizedBox(height: 12),
  149. MovesTilesWidget(
  150. solverClient: _solverClient,
  151. fontSize: 16,
  152. ),
  153. ],
  154. ),
  155. SizedBox(width: context.width * 60 / 812),
  156. SingleChildScrollView(
  157. child: Column(
  158. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  159. children: [
  160. CountDownTimerWidget(
  161. duration: widget.duration,
  162. finishCallback: _finishTime,
  163. ),
  164. const SizedBox(height: 23),
  165. Consumer(
  166. builder: (context, ref, child) {
  167. final state = ref.watch(
  168. imageSplitterNotifierProvider,
  169. );
  170. return state.maybeWhen(
  171. () => PuzzleWidget(
  172. solverClient: _solverClient,
  173. boardSize: _boardSize,
  174. eachBoxSize: _eachBoxSize,
  175. initialPuzzleData: _initialPuzzleData,
  176. fontSize: _fontSize,
  177. images: _previousImages,
  178. kInitialSpeed: kInitialSpeed,
  179. ),
  180. complete: (image, images, palette) {
  181. _previousImages = images;
  182. _previousImage = image;
  183. _previousPalette = palette;
  184. return PuzzleWidget(
  185. solverClient: _solverClient,
  186. boardSize: _boardSize,
  187. eachBoxSize: _eachBoxSize,
  188. initialPuzzleData: _initialPuzzleData,
  189. fontSize: _fontSize,
  190. images: images,
  191. kInitialSpeed: kInitialSpeed,
  192. );
  193. },
  194. orElse: () => PuzzleWidget(
  195. solverClient: _solverClient,
  196. boardSize: _boardSize,
  197. eachBoxSize: _eachBoxSize,
  198. initialPuzzleData: _initialPuzzleData,
  199. fontSize: _fontSize,
  200. images: _previousImages,
  201. kInitialSpeed: kInitialSpeed,
  202. ),
  203. );
  204. },
  205. ),
  206. ],
  207. ),
  208. ),
  209. SizedBox(width: context.width * 38 / 812),
  210. Stack(
  211. alignment: Alignment.center,
  212. children: [
  213. SizedBox(
  214. width: context.width * 126 / 812,
  215. height: context.height * 251 / 375,
  216. child: Image(
  217. image: AssetImage('avatar'.pngPath),
  218. ),
  219. ),
  220. Column(
  221. mainAxisSize: MainAxisSize.max,
  222. crossAxisAlignment: CrossAxisAlignment.end,
  223. mainAxisAlignment: MainAxisAlignment.center,
  224. children: [
  225. CountdownWidget(
  226. isStartPressed: _isStartPressed,
  227. onFinish: () {
  228. BlocProvider.of<CountDownTimerCubit>(context)
  229. .start();
  230. setState(() {
  231. _isStartPressed = false;
  232. });
  233. },
  234. initialSpeed: kInitialSpeed,
  235. ),
  236. ],
  237. ),
  238. ],
  239. ),
  240. ],
  241. ),
  242. ),
  243. ),
  244. ),
  245. );
  246. }
  247. void _finishTime() {
  248. if (!_puzzleSolved) {
  249. Utils.instance.showToast(context, 'TimeOut');
  250. Future.delayed(const Duration(milliseconds: 1500), () {
  251. Navigator.pop(context);
  252. });
  253. }
  254. }
  255. void _resetTimer() {
  256. BlocProvider.of<CountDownTimerCubit>(context).reset();
  257. }
  258. }