diff --git a/assets/images/jpg/level-1.jpg b/assets/images/jpg/level-1.jpg new file mode 100644 index 0000000..31c2349 Binary files /dev/null and b/assets/images/jpg/level-1.jpg differ diff --git a/assets/images/jpg/level-2.jpg b/assets/images/jpg/level-2.jpg new file mode 100644 index 0000000..ff9f70b Binary files /dev/null and b/assets/images/jpg/level-2.jpg differ diff --git a/assets/images/jpg/level-3.jpg b/assets/images/jpg/level-3.jpg new file mode 100644 index 0000000..ac94565 Binary files /dev/null and b/assets/images/jpg/level-3.jpg differ diff --git a/assets/images/jpg/level-4.jpg b/assets/images/jpg/level-4.jpg new file mode 100644 index 0000000..a2a3038 Binary files /dev/null and b/assets/images/jpg/level-4.jpg differ diff --git a/assets/images/jpg/level-5.jpg b/assets/images/jpg/level-5.jpg new file mode 100644 index 0000000..b7acdac Binary files /dev/null and b/assets/images/jpg/level-5.jpg differ diff --git a/assets/images/jpg/level-6.jpg b/assets/images/jpg/level-6.jpg new file mode 100644 index 0000000..0f2af64 Binary files /dev/null and b/assets/images/jpg/level-6.jpg differ diff --git a/assets/images/jpg/level-7.jpg b/assets/images/jpg/level-7.jpg new file mode 100644 index 0000000..1985d7f Binary files /dev/null and b/assets/images/jpg/level-7.jpg differ diff --git a/assets/images/jpg/level-8.jpg b/assets/images/jpg/level-8.jpg new file mode 100644 index 0000000..2f01d12 Binary files /dev/null and b/assets/images/jpg/level-8.jpg differ diff --git a/assets/images/level_1_image.png b/assets/images/level_1_image.png deleted file mode 100644 index c591db0..0000000 Binary files a/assets/images/level_1_image.png and /dev/null differ diff --git a/assets/images/level_2_image.png b/assets/images/level_2_image.png deleted file mode 100644 index 7e8e3b3..0000000 Binary files a/assets/images/level_2_image.png and /dev/null differ diff --git a/assets/images/level_4_image.png b/assets/images/level_4_image.png deleted file mode 100644 index 450e231..0000000 Binary files a/assets/images/level_4_image.png and /dev/null differ diff --git a/assets/images/png/avatar.png b/assets/images/png/avatar.png new file mode 100644 index 0000000..723b362 Binary files /dev/null and b/assets/images/png/avatar.png differ diff --git a/assets/images/default_image.png b/assets/images/png/default_image.png similarity index 100% rename from assets/images/default_image.png rename to assets/images/png/default_image.png diff --git a/assets/images/level_screen_image.png b/assets/images/png/level_screen_image.png similarity index 100% rename from assets/images/level_screen_image.png rename to assets/images/png/level_screen_image.png diff --git a/assets/images/puzzle_side_image.png b/assets/images/png/puzzle_side_image.png similarity index 100% rename from assets/images/puzzle_side_image.png rename to assets/images/png/puzzle_side_image.png diff --git a/assets/images/splash_screen_image.png b/assets/images/png/splash_screen_image.png similarity index 100% rename from assets/images/splash_screen_image.png rename to assets/images/png/splash_screen_image.png diff --git a/assets/images/start.png b/assets/images/png/start.png similarity index 100% rename from assets/images/start.png rename to assets/images/png/start.png diff --git a/assets/images/svg/flash.svg b/assets/images/svg/flash.svg new file mode 100644 index 0000000..5eedea7 --- /dev/null +++ b/assets/images/svg/flash.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/images/svg/refresh.svg b/assets/images/svg/refresh.svg new file mode 100644 index 0000000..ffdd85a --- /dev/null +++ b/assets/images/svg/refresh.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/svg/timer.svg b/assets/images/svg/timer.svg new file mode 100644 index 0000000..dbc4064 --- /dev/null +++ b/assets/images/svg/timer.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/application/notifiers/image_splitter_notifier.dart b/lib/application/notifiers/image_splitter_notifier.dart index bb7a7f6..ba6af56 100644 --- a/lib/application/notifiers/image_splitter_notifier.dart +++ b/lib/application/notifiers/image_splitter_notifier.dart @@ -1,10 +1,7 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:my_flutter_puzzle/application/states/image_splitter_state.dart'; -import 'package:my_flutter_puzzle/res/strings.dart'; import 'package:my_flutter_puzzle/utils/image_splitter.dart'; class ImageSplitterNotifier extends StateNotifier { diff --git a/lib/cubits/count_down_timer_cubit.dart b/lib/cubits/count_down_timer_cubit.dart index 22de9c3..bf6ad5c 100644 --- a/lib/cubits/count_down_timer_cubit.dart +++ b/lib/cubits/count_down_timer_cubit.dart @@ -2,17 +2,25 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:my_flutter_puzzle/cubits/base_cubit_type.dart'; class CountDownTimerCubit extends Cubit> { - CountDownTimerCubit() : super(BaseCubitType(eventName: CountDownTimerState.empty)); + CountDownTimerCubit() + : super( + BaseCubitType( + eventName: CountDownTimerState.empty, + ), + ); void empty() => emit(BaseCubitType(eventName: CountDownTimerState.empty)); void start() => emit(BaseCubitType(eventName: CountDownTimerState.start)); void stop() => emit(BaseCubitType(eventName: CountDownTimerState.stop)); + + void reset() => emit(BaseCubitType(eventName: CountDownTimerState.reset)); } enum CountDownTimerState { empty, start, stop, + reset, } diff --git a/lib/main.dart b/lib/main.dart index 68d55b0..a55fa24 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,8 +5,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:my_flutter_puzzle/cubits/count_down_timer_cubit.dart'; import 'package:my_flutter_puzzle/res/palette.dart'; import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; +import 'package:my_flutter_puzzle/screens/puzzle/puzzle_starter_screen.dart'; import 'package:my_flutter_puzzle/screens/splash/screen/splash_screen.dart'; import 'package:my_flutter_puzzle/utils/color_brightness.dart'; +import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; import 'package:url_strategy/url_strategy.dart'; void main() async { @@ -26,6 +28,12 @@ class MyApp extends StatelessWidget { DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight, ]); + Level level = Level( + image: 'level-1'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 1, + ); SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: []); return BlocProvider( create: (context) => CountDownTimerCubit(), @@ -50,7 +58,12 @@ class MyApp extends StatelessWidget { onSurface: Colors.white38, ), ), - home: const SplashScreen(), + home: PuzzleStarterScreen( + duration: level.duration, + puzzleSize: level.puzzleSize, + image: level.image, + level: level.level, + ), ), ); } diff --git a/lib/screens/level_list/screen/level_list_screen.dart b/lib/screens/level_list/screen/level_list_screen.dart index 68aaf09..e43193f 100644 --- a/lib/screens/level_list/screen/level_list_screen.dart +++ b/lib/screens/level_list/screen/level_list_screen.dart @@ -18,15 +18,54 @@ class _LevelListScreenState extends State { @override void initState() { - _levelList.add(Level(image: 'level_1_image'.pngPath, duration: 4, puzzleSize: 3, level: 1)); - _levelList.add(Level(image: 'level_1_image'.pngPath, duration: 4, puzzleSize: 3, level: 2)); - _levelList.add(Level(image: 'level_1_image'.pngPath, duration: 4, puzzleSize: 3, level: 3)); - _levelList.add(Level(image: 'level_2_image'.pngPath, duration: 6, puzzleSize: 4, level: 4)); - _levelList.add(Level(image: 'level_2_image'.pngPath, duration: 6, puzzleSize: 4, level: 5)); - _levelList.add(Level(image: 'level_2_image'.pngPath, duration: 6, puzzleSize: 4, level: 6)); - _levelList.add(Level(image: 'level_4_image'.pngPath, duration: 8, puzzleSize: 5, level: 7)); - _levelList.add(Level(image: 'level_4_image'.pngPath, duration: 8, puzzleSize: 5, level: 8)); - _levelList.add(Level(image: 'level_4_image'.pngPath, duration: 8, puzzleSize: 5, level: 9)); + _levelList.add(Level( + image: 'level-1'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 1, + )); + _levelList.add(Level( + image: 'level-2'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 2, + )); + _levelList.add(Level( + image: 'level-3'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 3, + )); + _levelList.add(Level( + image: 'level-4'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 4, + )); + _levelList.add(Level( + image: 'level-5'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 5, + )); + _levelList.add(Level( + image: 'level-6'.jpgPath, + duration: 4, + puzzleSize: 3, + level: 6, + )); + _levelList.add(Level( + image: 'level-7'.jpgPath, + duration: 6, + puzzleSize: 4, + level: 7, + )); + _levelList.add(Level( + image: 'level-8'.jpgPath, + duration: 6, + puzzleSize: 4, + level: 8, + )); super.initState(); } @@ -51,7 +90,9 @@ class _LevelListScreenState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: EdgeInsets.only(top: context.height * 33 / 540, bottom: context.height * 12 / 540), + padding: EdgeInsets.only( + top: context.height * 33 / 540, + bottom: context.height * 12 / 540), child: const Text( 'Levels', style: TextStyle( @@ -103,6 +144,7 @@ class _LevelListScreenState extends State { duration: level.duration, puzzleSize: level.puzzleSize, image: level.image, + level: level.level, ); }, ), diff --git a/lib/screens/photo/photo_screen.dart b/lib/screens/photo/photo_screen.dart index ca2e06a..d0226a3 100644 --- a/lib/screens/photo/photo_screen.dart +++ b/lib/screens/photo/photo_screen.dart @@ -19,6 +19,7 @@ class PhotoScreen extends ConsumerStatefulWidget { required this.puzzleSize, required this.riveController, required this.duration, + required this.level, Key? key, }) : super(key: key); @@ -26,6 +27,7 @@ class PhotoScreen extends ConsumerStatefulWidget { final PuzzleData initialPuzzleData; final int duration; final int puzzleSize; + final int level; final RiveAnimationController riveController; @override @@ -50,7 +52,8 @@ class _PhotoScreenState extends ConsumerState { @override Widget build(BuildContext context) { - ref.listen(puzzleNotifierProvider(_solverClient), (previous, PuzzleState next) { + ref.listen(puzzleNotifierProvider(_solverClient), + (previous, PuzzleState next) { if (next is PuzzleSolved) { BlocProvider.of(context).stop(); } @@ -67,7 +70,8 @@ class _PhotoScreenState extends ConsumerState { onSecondary: Theme.of(context).colorScheme.onSecondary, error: Theme.of(context).colorScheme.error, onError: Theme.of(context).colorScheme.onError, - background: next.palette.darkMutedColor?.color ?? Palette.blue.darken(0.3), + background: + next.palette.darkMutedColor?.color ?? Palette.blue.darken(0.3), onBackground: Colors.white, surface: Theme.of(context).colorScheme.surface, onSurface: Theme.of(context).colorScheme.onSurface, @@ -88,6 +92,7 @@ class _PhotoScreenState extends ConsumerState { data: _themeData, child: PhotoScreenLarge( solverClient: _solverClient, + level: widget.level, initialPuzzleData: _initialPuzzleData, duration: widget.duration, puzzleSize: _puzzleSize, @@ -105,7 +110,8 @@ class _PhotoScreenState extends ConsumerState { onSecondary: Theme.of(context).colorScheme.onSecondary, error: Theme.of(context).colorScheme.error, onError: Theme.of(context).colorScheme.onError, - background: palette.darkMutedColor?.color ?? Palette.blue.darken(0.3), + background: + palette.darkMutedColor?.color ?? Palette.blue.darken(0.3), onBackground: Colors.white, surface: Theme.of(context).colorScheme.surface, onSurface: Theme.of(context).colorScheme.onSurface, @@ -117,6 +123,7 @@ class _PhotoScreenState extends ConsumerState { solverClient: _solverClient, initialPuzzleData: _initialPuzzleData, puzzleSize: _puzzleSize, + level: widget.level, riveController: _riveController, duration: widget.duration, ), @@ -128,6 +135,7 @@ class _PhotoScreenState extends ConsumerState { solverClient: _solverClient, initialPuzzleData: _initialPuzzleData, duration: widget.duration, + level: widget.level, puzzleSize: _puzzleSize, riveController: _riveController, ), diff --git a/lib/screens/photo/photo_screen_large.dart b/lib/screens/photo/photo_screen_large.dart index 4dd0a1e..7e2d870 100644 --- a/lib/screens/photo/photo_screen_large.dart +++ b/lib/screens/photo/photo_screen_large.dart @@ -1,12 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:my_flutter_puzzle/application/states/image_splitter_state.dart'; import 'package:my_flutter_puzzle/application/states/puzzle_state.dart'; import 'package:my_flutter_puzzle/cubits/count_down_timer_cubit.dart'; import 'package:my_flutter_puzzle/models/puzzle_data.dart'; import 'package:my_flutter_puzzle/providers.dart'; import 'package:my_flutter_puzzle/res/puzzle_constants.dart'; +import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; +import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; import 'package:my_flutter_puzzle/utils/puzzle_solver.dart'; import 'package:my_flutter_puzzle/utils/utils.dart'; import 'package:my_flutter_puzzle/widgets/photo_screen/image_viewer.dart'; @@ -25,6 +28,7 @@ class PhotoScreenLarge extends ConsumerStatefulWidget { required this.puzzleSize, required this.riveController, required this.duration, + required this.level, Key? key, }) : super(key: key); @@ -32,10 +36,12 @@ class PhotoScreenLarge extends ConsumerStatefulWidget { final PuzzleData initialPuzzleData; final int puzzleSize; final int duration; + final int level; final RiveAnimationController riveController; @override - ConsumerState createState() => _SoloScreenLargeState(); + ConsumerState createState() => + _SoloScreenLargeState(); } class _SoloScreenLargeState extends ConsumerState { @@ -65,7 +71,8 @@ class _SoloScreenLargeState extends ConsumerState { @override Widget build(BuildContext context) { - ref.listen(puzzleNotifierProvider(_solverClient), (previous, PuzzleState next) { + ref.listen(puzzleNotifierProvider(_solverClient), + (previous, PuzzleState next) { if (next is PuzzleInitializing) { setState(() { _isStartPressed = true; @@ -83,9 +90,11 @@ class _SoloScreenLargeState extends ConsumerState { _previousImage = next.image; _previousPalette = next.palette; }); - ref.read(puzzleNotifierProvider(_solverClient).notifier).initializePuzzle( - initialPuzzleData: _initialPuzzleData, - ); + ref + .read(puzzleNotifierProvider(_solverClient).notifier) + .initializePuzzle( + initialPuzzleData: _initialPuzzleData, + ); } }); @@ -95,101 +104,127 @@ class _SoloScreenLargeState extends ConsumerState { return true; }, child: Scaffold( - backgroundColor: Theme.of(context).colorScheme.background, + backgroundColor: const Color(0xff4400CE), body: SafeArea( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Padding( - padding: const EdgeInsetsDirectional.symmetric(horizontal: 10), - child: Column( + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: context.width * 30 / 812, + vertical: context.height * 20 / 375, + ), + child: Row( + children: [ + Column( mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Visibility( - visible: !_isStartPressed, - child: ImageViewer( - puzzleSize: _puzzleSize, - previousImage: _previousImage, - previousPalette: _previousPalette, - imageSize: 200, - ), + Row( + children: [ + SvgPicture.asset('flash'.svgPath), + const SizedBox(width: 8), + Text( + 'Level ${widget.level}', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 16, + ), + ), + const SizedBox(width: 18), + GestureDetector( + onTap: _resetTimer, + child: Container( + width: context.width * 22 / 540, + height: context.width * 22 / 540, + padding: const EdgeInsets.all(5), + margin: const EdgeInsets.symmetric(vertical: 3), + decoration: const BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + child: SvgPicture.asset('refresh'.svgPath), + ), + ), + ], ), - const SizedBox(height: 32), - MovesTilesWidget(solverClient: _solverClient, fontSize: 16), - const SizedBox(height: 32), - ], - ), - ), - SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - CountDownTimerWidget( - duration: widget.duration, - finishCallback: () { - if (!_puzzleSolved) { - Utils.instance.showToast(context, 'TimeOut'); - Future.delayed(const Duration(milliseconds: 1500), () { - Navigator.pop(context); - }); - } - }, + const SizedBox(height: 21), + ImageViewer( + puzzleSize: _puzzleSize, + previousImage: _previousImage, + previousPalette: _previousPalette, + imageSize: 200, ), const SizedBox(height: 12), - Consumer( - builder: (context, ref, child) { - final state = ref.watch(imageSplitterNotifierProvider); - - return state.maybeWhen( - () => PuzzleWidget( - solverClient: _solverClient, - boardSize: _boardSize, - eachBoxSize: _eachBoxSize, - initialPuzzleData: _initialPuzzleData, - fontSize: _fontSize, - images: _previousImages, - kInitialSpeed: kInitialSpeed, - ), - complete: (image, images, palette) { - _previousImages = images; - _previousImage = image; - _previousPalette = palette; + MovesTilesWidget( + solverClient: _solverClient, + fontSize: 16, + ), + ], + ), + SizedBox(width: context.width * 60 / 812), + SingleChildScrollView( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + CountDownTimerWidget( + duration: widget.duration, + finishCallback: _finishTime, + ), + const SizedBox(height: 23), + Consumer( + builder: (context, ref, child) { + final state = ref.watch( + imageSplitterNotifierProvider, + ); + return state.maybeWhen( + () => PuzzleWidget( + solverClient: _solverClient, + boardSize: _boardSize, + eachBoxSize: _eachBoxSize, + initialPuzzleData: _initialPuzzleData, + fontSize: _fontSize, + images: _previousImages, + kInitialSpeed: kInitialSpeed, + ), + complete: (image, images, palette) { + _previousImages = images; + _previousImage = image; + _previousPalette = palette; - return PuzzleWidget( + return PuzzleWidget( + solverClient: _solverClient, + boardSize: _boardSize, + eachBoxSize: _eachBoxSize, + initialPuzzleData: _initialPuzzleData, + fontSize: _fontSize, + images: images, + kInitialSpeed: kInitialSpeed, + ); + }, + orElse: () => PuzzleWidget( solverClient: _solverClient, boardSize: _boardSize, eachBoxSize: _eachBoxSize, initialPuzzleData: _initialPuzzleData, fontSize: _fontSize, - images: images, + images: _previousImages, kInitialSpeed: kInitialSpeed, - ); - }, - orElse: () => PuzzleWidget( - solverClient: _solverClient, - boardSize: _boardSize, - eachBoxSize: _eachBoxSize, - initialPuzzleData: _initialPuzzleData, - fontSize: _fontSize, - images: _previousImages, - kInitialSpeed: kInitialSpeed, - ), - ); - }, - ), - const SizedBox(height: 30), - ], + ), + ); + }, + ), + ], + ), ), - ), - Padding( - padding: const EdgeInsetsDirectional.symmetric(horizontal: 10), - child: Stack( + SizedBox(width: context.width * 38 / 812), + Stack( + alignment: Alignment.center, children: [ - AnimatedDash( - boardSize: _boardSize * 0.8, - riveController: _riveController, - onInit: (_) => setState(() {}), + SizedBox( + width: context.width * 126 / 812, + height: context.height * 251 / 375, + child: Image( + image: AssetImage('avatar'.pngPath), + ), ), Column( mainAxisSize: MainAxisSize.max, @@ -199,7 +234,8 @@ class _SoloScreenLargeState extends ConsumerState { CountdownWidget( isStartPressed: _isStartPressed, onFinish: () { - BlocProvider.of(context).start(); + BlocProvider.of(context) + .start(); setState(() { _isStartPressed = false; }); @@ -210,11 +246,24 @@ class _SoloScreenLargeState extends ConsumerState { ), ], ), - ), - ], + ], + ), ), ), ), ); } + + void _finishTime() { + if (!_puzzleSolved) { + Utils.instance.showToast(context, 'TimeOut'); + Future.delayed(const Duration(milliseconds: 1500), () { + Navigator.pop(context); + }); + } + } + + void _resetTimer() { + BlocProvider.of(context).reset(); + } } diff --git a/lib/screens/puzzle/puzzle_starter_screen.dart b/lib/screens/puzzle/puzzle_starter_screen.dart index d8bfd7c..fa45923 100644 --- a/lib/screens/puzzle/puzzle_starter_screen.dart +++ b/lib/screens/puzzle/puzzle_starter_screen.dart @@ -11,12 +11,14 @@ class PuzzleStarterScreen extends ConsumerStatefulWidget { final int puzzleSize; final String image; final int duration; + final int level; const PuzzleStarterScreen({ Key? key, required this.duration, required this.puzzleSize, required this.image, + required this.level, }) : super(key: key); @override @@ -57,6 +59,7 @@ class _SoloScreenState extends ConsumerState { child: PhotoScreen( solverClient: _solverClient, initialPuzzleData: _initialPuzzleData, + level: widget.level, duration: widget.duration, puzzleSize: _puzzleSize, riveController: _riveController, diff --git a/lib/screens/splash/screen/splash_screen.dart b/lib/screens/splash/screen/splash_screen.dart index 18f1cdc..577f031 100644 --- a/lib/screens/splash/screen/splash_screen.dart +++ b/lib/screens/splash/screen/splash_screen.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'package:flutter/material.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:my_flutter_puzzle/screens/level_list/screen/level_list_screen.dart'; import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; diff --git a/lib/utils/extensions/string_extensions.dart b/lib/utils/extensions/string_extensions.dart index 4ed93bc..72f72de 100644 --- a/lib/utils/extensions/string_extensions.dart +++ b/lib/utils/extensions/string_extensions.dart @@ -1,6 +1,10 @@ extension StringExtension on String { String get pngPath { - return 'assets/images/$this.png'; + return 'assets/images/png/$this.png'; + } + + String get jpgPath { + return 'assets/images/jpg/$this.jpg'; } String get rivePath { diff --git a/lib/utils/image_splitter.dart b/lib/utils/image_splitter.dart index 225ee8a..475c5c2 100644 --- a/lib/utils/image_splitter.dart +++ b/lib/utils/image_splitter.dart @@ -1,23 +1,16 @@ -import 'dart:developer'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:image/image.dart' as image_lib; import 'package:palette_generator/palette_generator.dart'; -import 'package:tuple/tuple.dart'; class ImageSplitter { List splitImage(Map mapData) { List input = mapData['input']; int size = mapData['size']; - // convert image to image from image package image_lib.Image image = image_lib.decodeImage(input)!; - int x = 0, y = 0; int width = (image.width / size).round(); int height = (image.height / size).round(); - - // split image to parts List parts = []; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { @@ -38,7 +31,8 @@ class ImageSplitter { } Future getImagePalette(ImageProvider imageProvider) async { - final paletteGenerator = await PaletteGenerator.fromImageProvider(imageProvider); + final paletteGenerator = + await PaletteGenerator.fromImageProvider(imageProvider); return paletteGenerator; } diff --git a/lib/utils/puzzle_solver.dart b/lib/utils/puzzle_solver.dart index 6fbeb9b..fe55522 100644 --- a/lib/utils/puzzle_solver.dart +++ b/lib/utils/puzzle_solver.dart @@ -128,14 +128,6 @@ class PuzzleSolverClient { return board; } - void plainPrint(List> b) { - for (var i in b) { - for (var j in i) { - print('$j '); - } - } - } - int nodeManhattan(List> board) { int sum = 0; int n = board.length; @@ -153,7 +145,6 @@ class PuzzleSolverClient { int manhattan(List> board, Set goalNums) { int sum = 0; - int count = 0; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (goalNums.contains(board[i][j])) { @@ -310,7 +301,6 @@ class PuzzleSolverClient { } List> goalStates = []; - int count = 1; String flag = 'A_STAR'; if (flag == 'A_STAR') { @@ -330,7 +320,6 @@ class PuzzleSolverClient { ); queue.add(Tuple2(root.depth + hScaleFactor * root.heuristic, root)); while (queue.isNotEmpty) { - count += 1; final node = queue.removeFirst().item2; if (isGoal(node.board, goalStates[currGoal])) { queue.clear(); diff --git a/lib/widgets/photo_screen/image_viewer.dart b/lib/widgets/photo_screen/image_viewer.dart index 7073dba..a5ca769 100644 --- a/lib/widgets/photo_screen/image_viewer.dart +++ b/lib/widgets/photo_screen/image_viewer.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:my_flutter_puzzle/providers.dart'; +import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; import 'package:palette_generator/palette_generator.dart'; class ImageViewer extends ConsumerWidget { @@ -24,18 +25,17 @@ class ImageViewer extends ConsumerWidget { final state = ref.watch(imageSplitterNotifierProvider); return state.maybeWhen( () => const SizedBox(), - complete: (image, images, palette) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(20), - child: Image( - image: image.image, - height: imageSize, - width: imageSize, - ), + complete: (image, images, palette) => SizedBox( + width: context.width * 202 / 812, + height: context.width * 202 / 812, + child: ClipRRect( + borderRadius: BorderRadius.circular(8), + child: Image( + image: image.image, + height: imageSize, + width: imageSize, ), - ], + ), ), orElse: () => previousImage != null ? Padding( diff --git a/lib/widgets/solo_screen/animated_dash.dart b/lib/widgets/solo_screen/animated_dash.dart index 7415ec5..9a9155c 100644 --- a/lib/widgets/solo_screen/animated_dash.dart +++ b/lib/widgets/solo_screen/animated_dash.dart @@ -22,20 +22,7 @@ class AnimatedDash extends StatelessWidget { Widget build(BuildContext context) { return Align( alignment: Alignment.bottomCenter, - child: Padding( - padding: _padding, - // child: SizedBox( - // width: boardSize * 0.75, - // height: boardSize * 0.75, - // child: RiveAnimation.asset( - // 'assets/rive/dash.riv', - // fit: BoxFit.contain, - // antialiasing: true, - // controllers: [_riveController], - // onInit: _onInit, - // ), - // ), - ), + child: Padding(padding: _padding), ); } } diff --git a/lib/widgets/solo_screen/count_down_timer_widget.dart b/lib/widgets/solo_screen/count_down_timer_widget.dart index a73e2e7..f443fd8 100644 --- a/lib/widgets/solo_screen/count_down_timer_widget.dart +++ b/lib/widgets/solo_screen/count_down_timer_widget.dart @@ -2,8 +2,10 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:my_flutter_puzzle/cubits/base_cubit_type.dart'; import 'package:my_flutter_puzzle/cubits/count_down_timer_cubit.dart'; +import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart'; class CountDownTimerWidget extends StatefulWidget { final int duration; @@ -41,7 +43,8 @@ class _CountDownTimerWidgetState extends State { void resetTimer() { stopTimer(); - setState(() => myDuration = const Duration(days: 5)); + setState(() => myDuration = Duration(minutes: widget.duration)); + startTimer(); } void setCountDown() { @@ -80,23 +83,25 @@ class _CountDownTimerWidgetState extends State { _cubit.empty(); }); break; + case CountDownTimerState.reset: + WidgetsBinding.instance.addPostFrameCallback((timeStamp) { + resetTimer(); + _cubit.empty(); + }); + break; } return Row( children: [ Text( '$hours:$minutes:$seconds', style: const TextStyle( - fontSize: 30, + fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(width: 8), - const Icon( - Icons.timer, - color: Colors.white, - size: 30, - ) + SvgPicture.asset('timer'.svgPath), ], ); }, diff --git a/lib/widgets/solo_screen/countdown_widget.dart b/lib/widgets/solo_screen/countdown_widget.dart index 37254db..348d31f 100644 --- a/lib/widgets/solo_screen/countdown_widget.dart +++ b/lib/widgets/solo_screen/countdown_widget.dart @@ -21,54 +21,51 @@ class CountdownWidget extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return Visibility( visible: _isStartPressed, - child: SizedBox( - width: 250.0, - child: DefaultTextStyle( - style: const TextStyle( - fontSize: 150.0, - color: Colors.white, - fontFamily: 'GoogleSans', - ), - child: AnimatedTextKit( - isRepeatingAnimation: false, - pause: const Duration(milliseconds: 0), - onFinished: _onFinish, - animatedTexts: [ - RotateAnimatedText( - '3', - transitionHeight: 100 * 2.5, - textStyle: const TextStyle( - color: Colors.white, - ), - duration: Duration(milliseconds: _kInitialSpeed), + child: DefaultTextStyle( + style: const TextStyle( + fontSize: 80, + color: Colors.white, + fontFamily: 'GoogleSans', + ), + child: AnimatedTextKit( + isRepeatingAnimation: false, + pause: const Duration(milliseconds: 0), + onFinished: _onFinish, + animatedTexts: [ + RotateAnimatedText( + '3', + transitionHeight: 100 * 2.5, + textStyle: const TextStyle( + color: Colors.white, ), - RotateAnimatedText( - '2', - transitionHeight: 100 * 2.5, - textStyle: const TextStyle( - color: Colors.white, - ), - duration: Duration(milliseconds: _kInitialSpeed), + duration: Duration(milliseconds: _kInitialSpeed), + ), + RotateAnimatedText( + '2', + transitionHeight: 100 * 2.5, + textStyle: const TextStyle( + color: Colors.white, ), - RotateAnimatedText( - '1', - transitionHeight: 100 * 2.5, - textStyle: const TextStyle( - color: Colors.white, - ), - duration: Duration(milliseconds: _kInitialSpeed), + duration: Duration(milliseconds: _kInitialSpeed), + ), + RotateAnimatedText( + '1', + transitionHeight: 100 * 2.5, + textStyle: const TextStyle( + color: Colors.white, ), - RotateAnimatedText( - 'GO!', - textStyle: const TextStyle( - fontSize: 120.0, - color: Colors.white, - ), - transitionHeight: 120 * 2.5, - duration: Duration(milliseconds: _kInitialSpeed), + duration: Duration(milliseconds: _kInitialSpeed), + ), + RotateAnimatedText( + 'GO!', + textStyle: const TextStyle( + fontSize: 60, + color: Colors.white, ), - ], - ), + transitionHeight: 120 * 2.5, + duration: Duration(milliseconds: _kInitialSpeed), + ), + ], ), ), ); diff --git a/lib/widgets/solo_screen/moves_tiles_widget.dart b/lib/widgets/solo_screen/moves_tiles_widget.dart index 18278b9..150b752 100644 --- a/lib/widgets/solo_screen/moves_tiles_widget.dart +++ b/lib/widgets/solo_screen/moves_tiles_widget.dart @@ -2,8 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:my_flutter_puzzle/providers.dart'; import 'package:my_flutter_puzzle/utils/puzzle_solver.dart'; - -import 'moves_tiles_widget/moves_tiles_text.dart'; +import 'package:my_flutter_puzzle/widgets/solo_screen/moves_tiles_widget/moves_tiles_text.dart'; class MovesTilesWidget extends StatelessWidget { const MovesTilesWidget({ @@ -21,7 +20,6 @@ class MovesTilesWidget extends StatelessWidget { return Consumer( builder: (context, ref, child) { final state = ref.watch(puzzleNotifierProvider(_solverClient)); - return state.when( () => MovesTilesText( moves: 0, diff --git a/lib/widgets/solo_screen/moves_tiles_widget/moves_tiles_text.dart b/lib/widgets/solo_screen/moves_tiles_widget/moves_tiles_text.dart index f0fee5f..9650642 100644 --- a/lib/widgets/solo_screen/moves_tiles_widget/moves_tiles_text.dart +++ b/lib/widgets/solo_screen/moves_tiles_widget/moves_tiles_text.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart'; class MovesTilesText extends StatelessWidget { final int moves; @@ -14,30 +15,86 @@ class MovesTilesText extends StatelessWidget { @override Widget build(BuildContext context) { - return RichText( - text: TextSpan( - style: TextStyle( - fontSize: fontSize, - // fontWeight: FontWeight.w500, - color: Colors.white, - ), - children: [ - TextSpan( - text: moves.toString(), - style: const TextStyle( - fontWeight: FontWeight.w600, + return Row( + children: [ + Container( + height: context.height * 32 / 375, + width: context.width * 94 / 812, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + border: Border.all(color: const Color(0xff6236FF), width: 1), + borderRadius: BorderRadius.circular(26), + gradient: const LinearGradient( + colors: [ + Color(0xff4824CB), + Color(0xff6236FF), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), - const TextSpan(text: ' Moves | '), - TextSpan( - text: tiles.toString(), - style: const TextStyle( - fontWeight: FontWeight.w600, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Tiles', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + Text( + '$tiles', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Container( + height: context.height * 32 / 375, + width: context.width * 94 / 812, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + decoration: BoxDecoration( + border: Border.all(color: const Color(0xff6236FF), width: 1), + borderRadius: BorderRadius.circular(26), + gradient: const LinearGradient( + colors: [ + Color(0xff4824CB), + Color(0xff6236FF), + ], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, ), ), - const TextSpan(text: ' Tiles'), - ], - ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Move', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + Text( + '$moves', + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 12, + ), + ), + ], + ), + ), + ], ); } } diff --git a/lib/widgets/solo_screen/puzzle_widget/puzzle_board.dart b/lib/widgets/solo_screen/puzzle_widget/puzzle_board.dart index 08b5433..daa48c1 100644 --- a/lib/widgets/solo_screen/puzzle_widget/puzzle_board.dart +++ b/lib/widgets/solo_screen/puzzle_widget/puzzle_board.dart @@ -59,7 +59,7 @@ class PuzzleBoard extends ConsumerWidget { elevation: 4, color: Theme.of(context).colorScheme.primary.withOpacity(isEnabled ? 1 : 0.5), shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(8), ), child: SizedBox( height: eachBoxSize, @@ -82,7 +82,7 @@ class PuzzleBoard extends ConsumerWidget { child: Opacity( opacity: isEnabled ? 1 : 0.5, child: ClipRRect( - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(8), child: images![int.parse(puzzleData.offsetMap.entries.toList()[i].key.toString()) - 1], ), diff --git a/pubspec.yaml b/pubspec.yaml index fdf443e..58e72a0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -36,6 +36,8 @@ flutter: assets: - assets/rive/dash.riv - assets/images/ + - assets/images/jpg/ + - assets/images/png/ - assets/images/svg/ fonts: - family: GoogleSans diff --git a/test/my_queue_test.dart b/test/my_queue_test.dart deleted file mode 100644 index 30fae35..0000000 --- a/test/my_queue_test.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -import 'package:tuple/tuple.dart'; - -void main() { - test('queue test', () { - final queue = HeapPriorityQueue>((a, b) => a.item1.compareTo(b.item1)); - queue.add(const Tuple2(5, 515)); - queue.add(const Tuple2(3, 245)); - queue.add(const Tuple2(8, 645)); - queue.add(const Tuple2(2, 345)); - }); -} diff --git a/test/puzzle_solver_test.dart b/test/puzzle_solver_test.dart deleted file mode 100644 index 725a5c3..0000000 --- a/test/puzzle_solver_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter_test/flutter_test.dart'; -import 'package:my_flutter_puzzle/utils/puzzle_solver.dart'; - -void main() { - test('solver logic test', () { - final solver = PuzzleSolverClient(size: 4); - final board = solver.createRandomBoard(); - - final boardStates = solver.runner(board); - if (boardStates != null) { - for (var board in boardStates) { - print(board); - } - } - }); -} diff --git a/test/widget_test.dart b/test/widget_test.dart deleted file mode 100644 index 2b89594..0000000 --- a/test/widget_test.dart +++ /dev/null @@ -1,29 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:my_flutter_puzzle/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -}