Browse Source

add splash_screen.dart

add design of level list screen
master
mohsen zamani 2 years ago
parent
commit
494cd2e44f
  1. BIN
      assets/images/level_1_image.png
  2. BIN
      assets/images/level_2_image.png
  3. BIN
      assets/images/level_4_image.png
  4. BIN
      assets/images/level_screen_image.png
  5. BIN
      assets/images/splash_screen_image.png
  6. BIN
      assets/images/start.png
  7. 3
      assets/images/svg/check.svg
  8. 3
      assets/images/svg/lock.svg
  9. 3
      assets/images/svg/start.svg
  10. 3
      lib/main.dart
  11. 113
      lib/screens/level_list/screen/level_list_screen.dart
  12. 178
      lib/screens/level_list/widgets/level_widget.dart
  13. 140
      lib/screens/level_list/widgets/lock_level_widget.dart
  14. 143
      lib/screens/level_list/widgets/payed_level_widget.dart
  15. 54
      lib/screens/login_screen_name.dart
  16. 180
      lib/screens/menu_screen.dart
  17. 5
      lib/screens/photo/photo_screen_large.dart
  18. 152
      lib/screens/puzzle/top_bar.dart
  19. 220
      lib/screens/puzzle_screen.dart
  20. 489
      lib/screens/puzzle_solo_screen.dart
  21. 43
      lib/screens/splash/screen/splash_screen.dart
  22. 19
      lib/utils/extensions/context_extension.dart
  23. 4
      lib/utils/extensions/string_extensions.dart
  24. 308
      lib/widgets/animated_grid.dart
  25. 67
      lib/widgets/grid.dart
  26. 62
      lib/widgets/login_widgets/name_field.dart
  27. 72
      lib/widgets/login_widgets/start_game_widget.dart
  28. 39
      lib/widgets/login_widgets/start_game_widget/start_game_button.dart
  29. 2
      lib/widgets/menu_widgets/menu_widgets.dart
  30. 108
      lib/widgets/menu_widgets/multiplayer_button.dart
  31. 44
      lib/widgets/menu_widgets/solo_button.dart
  32. 53
      lib/widgets/photo_screen/pick_image_button.dart
  33. 28
      lib/widgets/puzzle_widgets/moves_text.dart
  34. 26
      lib/widgets/puzzle_widgets/player_text.dart
  35. 2
      lib/widgets/puzzle_widgets/puzzle_widgets.dart
  36. 73
      lib/widgets/puzzle_widgets/solo/timer_widget.dart
  37. 6
      lib/widgets/solo_screen/solo_screen_export.dart
  38. 42
      pubspec.lock
  39. 5
      pubspec.yaml

BIN
assets/images/level_1_image.png

After

Width: 70  |  Height: 70  |  Size: 10 KiB

BIN
assets/images/level_2_image.png

After

Width: 70  |  Height: 71  |  Size: 11 KiB

BIN
assets/images/level_4_image.png

After

Width: 70  |  Height: 71  |  Size: 13 KiB

BIN
assets/images/level_screen_image.png

After

Width: 214  |  Height: 296  |  Size: 54 KiB

BIN
assets/images/splash_screen_image.png

After

Width: 266  |  Height: 209  |  Size: 45 KiB

BIN
assets/images/start.png

After

Width: 63  |  Height: 63  |  Size: 1.8 KiB

3
assets/images/svg/check.svg

@ -0,0 +1,3 @@
<svg id="Icon_-_Check" data-name="Icon - Check" xmlns="http://www.w3.org/2000/svg" width="7.807" height="5.577" viewBox="0 0 7.807 5.577">
<path id="Vector_" data-name="Vector " d="M7.564.193a.744.744,0,0,1,.05,1.05L3.9,5.333a.744.744,0,0,1-.982.1L.311,3.579a.744.744,0,1,1,.864-1.21L3.24,3.844,6.514.243A.744.744,0,0,1,7.564.193Z" transform="translate(0 0)" fill="#5f34fa"/>
</svg>

3
assets/images/svg/lock.svg

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="6.643" height="8.636" viewBox="0 0 6.643 8.636">
<path id="Icon_ionic-ios-lock" data-name="Icon ionic-ios-lock" d="M12.562,6.364h-.5V5.394a1.993,1.993,0,1,0-3.986-.027v1h-.5a.833.833,0,0,0-.83.83V11.18a.833.833,0,0,0,.83.83h4.982a.833.833,0,0,0,.83-.83V7.194A.833.833,0,0,0,12.562,6.364Zm-2.2,2.591v1.428a.3.3,0,0,1-.276.3.291.291,0,0,1-.305-.291V8.955a.664.664,0,1,1,.581,0Zm1.121-2.591H8.66v-1a1.412,1.412,0,0,1,2.823,0Z" transform="translate(-6.75 -3.374)" fill="#6536f2"/>
</svg>

3
assets/images/svg/start.svg

@ -0,0 +1,3 @@
<svg id="icon-play" xmlns="http://www.w3.org/2000/svg" width="7.426" height="9.027" viewBox="0 0 7.426 9.027">
<path id="Shape" d="M1.095,8.811A2,2,0,0,1,0,7.025V2A2,2,0,0,1,3.184.388L6.608,2.9h0a2,2,0,0,1,0,3.226L3.183,8.638a2,2,0,0,1-2.088.173Z" transform="translate(0 0)" fill="#ff9a00"/>
</svg>

3
lib/main.dart

@ -5,6 +5,7 @@ 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/splash/screen/splash_screen.dart';
import 'package:my_flutter_puzzle/utils/color_brightness.dart';
import 'package:url_strategy/url_strategy.dart';
@ -49,7 +50,7 @@ class MyApp extends StatelessWidget {
onSurface: Colors.white38,
),
),
home: const LevelListScreen(),
home: const SplashScreen(),
),
);
}

113
lib/screens/level_list/screen/level_list_screen.dart

@ -1,5 +1,9 @@
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/screens/level_list/widgets/level_widget.dart';
import 'package:my_flutter_puzzle/screens/level_list/widgets/lock_level_widget.dart';
import 'package:my_flutter_puzzle/screens/level_list/widgets/payed_level_widget.dart';
import 'package:my_flutter_puzzle/screens/puzzle/puzzle_starter_screen.dart';
import 'package:my_flutter_puzzle/utils/extensions/context_extension.dart';
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
class LevelListScreen extends StatefulWidget {
@ -14,59 +18,86 @@ class _LevelListScreenState extends State<LevelListScreen> {
@override
void initState() {
_levelList.add(Level(image: 'default_image'.pngPath, duration: 4, puzzleSize: 3));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 4, puzzleSize: 3));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 4, puzzleSize: 3));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 6, puzzleSize: 4));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 6, puzzleSize: 4));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 6, puzzleSize: 4));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 8, puzzleSize: 5));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 8, puzzleSize: 5));
_levelList.add(Level(image: 'default_image'.pngPath, duration: 8, puzzleSize: 5));
_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));
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 5),
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(16),
backgroundColor: const Color(0xff6236FF),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 55),
child: Row(
children: [
Container(
width: context.width * 213 / 812,
height: context.height * 293 / 540,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('level_screen_image'.pngPath),
),
),
),
child: Column(
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('مرحله شماره ${index + 1}'),
const SizedBox(height: 8),
Text("زمان بازی : ${_levelList[index].duration} دقیقه"),
const SizedBox(height: 8),
GestureDetector(
child: const Text('شروع'),
onTap: () => _startLevel(_levelList[index]),
Padding(
padding: EdgeInsets.only(top: context.height * 33 / 540, bottom: context.height * 12 / 540),
child: const Text(
'Levels',
style: TextStyle(
color: Colors.white,
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
),
SizedBox(
width: context.width * 436 / 820,
height: context.height * 397 / 540,
child: ListView.builder(
itemBuilder: (context, index) {
if (index == 0 || index == 1) {
return LevelWidget(level: _levelList[index]);
}
if (index == 2) {
return LockLevelWidget(level: _levelList[index]);
}
return PayedLevelWidget(level: _levelList[index]);
},
itemCount: _levelList.length,
),
),
],
),
);
},
itemCount: _levelList.length,
],
),
),
);
}
void _startLevel(Level level) {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return PuzzleStarterScreen(
duration: level.duration,
puzzleSize: level.puzzleSize,
image: level.image,
);
},
));
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
return PuzzleStarterScreen(
duration: level.duration,
puzzleSize: level.puzzleSize,
image: level.image,
);
},
),
);
}
}
@ -74,6 +105,12 @@ class Level {
final String image;
final int puzzleSize;
final int duration;
final int level;
Level({required this.image, required this.duration, required this.puzzleSize});
Level({
required this.image,
required this.duration,
required this.puzzleSize,
required this.level,
});
}

178
lib/screens/level_list/widgets/level_widget.dart

@ -0,0 +1,178 @@
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/context_extension.dart';
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
class LevelWidget extends StatelessWidget {
final Level level;
const LevelWidget({Key? key, required this.level}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsetsDirectional.only(top: 10, start: 8, end: 8, bottom: 10),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: const LinearGradient(
colors: [
Color(0xff5E34F5),
Color(0xff4425B1),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
border: Border.all(
color: const Color(0xff6135FD),
width: 1,
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Stack(
alignment: AlignmentDirectional.centerEnd,
children: [
Container(
width: context.width * 70 / 820,
height: context.width * 70 / 820,
margin: const EdgeInsetsDirectional.only(end: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: DecorationImage(
image: AssetImage(level.image),
),
),
),
Container(
width: context.width * 28 / 820,
height: context.width * 28 / 820,
margin: const EdgeInsetsDirectional.only(end: 6),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
border: Border.all(
color: const Color(0xff6136FE),
),
gradient: const LinearGradient(
colors: [
Color(0xff6135FC),
Color(0xff4925CE),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Container(
padding: EdgeInsets.all(context.width * 5 / 820),
margin: EdgeInsets.all(context.width * 5 / 820),
decoration: const BoxDecoration(
color: Color(0xffF7B500),
shape: BoxShape.circle,
),
child: SvgPicture.asset('check'.svgPath),
),
),
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Level ${level.level}',
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 12),
Text(
'${level.puzzleSize}*${level.puzzleSize} | 00:56',
style: const TextStyle(
color: Color(0xffBCACF4),
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
const Text(
'Keyboard',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const Spacer(),
Container(
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: const Color(0xff5F358F),
borderRadius: BorderRadius.circular(36),
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(31),
gradient: const LinearGradient(
colors: [
Color(0xffFFC600),
Color(0xffFF5A00),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 6),
Container(
width: context.width * 26 / 540,
height: context.width * 26 / 540,
padding: const EdgeInsets.all(9),
margin: const EdgeInsets.symmetric(vertical: 3),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1,
),
gradient: const LinearGradient(
colors: [
Colors.white,
Color(0xffD5D5D5),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
shape: BoxShape.circle,
),
child: SvgPicture.asset('start'.svgPath),
),
const SizedBox(width: 8),
const Text(
'Start',
style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 14),
],
),
),
),
],
),
);
}
}

140
lib/screens/level_list/widgets/lock_level_widget.dart

@ -0,0 +1,140 @@
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/context_extension.dart';
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
class LockLevelWidget extends StatelessWidget {
final Level level;
const LockLevelWidget({Key? key, required this.level}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: LinearGradient(
colors: [
const Color(0xff6236FF).withOpacity(0.5),
const Color(0xff311B80).withOpacity(0.5),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
border: Border.all(
color: const Color(0xff6135FD),
width: 1,
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: context.width * 70 / 820,
height: context.width * 70 / 820,
margin: const EdgeInsetsDirectional.only(end: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: DecorationImage(
image: AssetImage(level.image),
opacity: 0.8,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Level ${level.level}',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 12),
Text(
'${level.puzzleSize}*${level.puzzleSize} | 00:56',
style: TextStyle(
color: const Color(0xffBCACF4).withOpacity(0.5),
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
Text(
'Keyboard',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const Spacer(),
Column(
children: [
Text(
'Solve lvl ${level.level - 1}',
style: const TextStyle(
color: Colors.white,
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: const Color(0xff5F358F).withOpacity(0.8),
borderRadius: BorderRadius.circular(36),
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(31),
color: const Color(0xff5D32DE),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 6),
Container(
width: context.width * 26 / 540,
height: context.width * 26 / 540,
padding: const EdgeInsets.all(10),
margin: const EdgeInsets.symmetric(vertical: 3),
decoration: const BoxDecoration(
color: Color(0xffAF99EF),
shape: BoxShape.circle,
),
child: SvgPicture.asset('lock'.svgPath),
),
const SizedBox(width: 8),
Text(
'Lock',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 14),
],
),
),
),
],
),
],
),
);
}
}

143
lib/screens/level_list/widgets/payed_level_widget.dart

@ -0,0 +1,143 @@
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/context_extension.dart';
import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
class PayedLevelWidget extends StatelessWidget {
final Level level;
const PayedLevelWidget({
Key? key,
required this.level,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(bottom: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: LinearGradient(
colors: [
const Color(0xff6236FF).withOpacity(0.5),
const Color(0xff311B80).withOpacity(0.5),
],
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
),
border: Border.all(
color: const Color(0xff6135FD),
width: 1,
),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
width: context.width * 70 / 820,
height: context.width * 70 / 820,
margin: const EdgeInsetsDirectional.only(end: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
image: DecorationImage(
image: AssetImage(level.image),
opacity: 0.8,
),
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(
'Level ${level.level}',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 12),
Text(
'${level.puzzleSize}*${level.puzzleSize} | 00:56',
style: TextStyle(
color: const Color(0xffBCACF4).withOpacity(0.5),
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
Text(
'Keyboard',
style: TextStyle(
color: Colors.white.withOpacity(0.5),
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
],
),
const Spacer(),
Column(
children: [
const Text(
'\$ 2',
style: TextStyle(
color: Colors.white,
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: const Color(0xff5F358F).withOpacity(0.8),
borderRadius: BorderRadius.circular(36),
),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(31),
color: const Color(0xff7853FF),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(width: 6),
Container(
width: context.width * 26 / 540,
height: context.width * 26 / 540,
padding: const EdgeInsets.all(10),
margin: const EdgeInsets.symmetric(vertical: 3),
decoration: const BoxDecoration(
color: Colors.white ,
shape: BoxShape.circle,
),
child: SvgPicture.asset('lock'.svgPath),
),
const SizedBox(width: 8),
Text(
'Buy',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 14),
],
),
),
),
],
),
],
),
);
}
}

54
lib/screens/login_screen_name.dart

@ -1,54 +0,0 @@
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/widgets/login_widgets/name_field.dart';
class LoginScreenName extends StatefulWidget {
const LoginScreenName({Key? key}) : super(key: key);
@override
State<LoginScreenName> createState() => _LoginScreenNameState();
}
class _LoginScreenNameState extends State<LoginScreenName> {
late final TextEditingController _nameTextController;
late final FocusNode _nameFocusNode;
String _nameString = '';
@override
void initState() {
super.initState();
_nameTextController = TextEditingController();
_nameFocusNode = FocusNode();
}
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
return GestureDetector(
onTap: () => _nameFocusNode.unfocus(),
child: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: SizedBox(
width: screenSize.width * 0.5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
NameField(
focusNode: _nameFocusNode,
onChange: (value) => setState(
() => _nameString = value,
),
),
const SizedBox(height: 24),
// StartGameWidget(
// nameString: _nameString,
// ),
],
),
),
),
),
);
}
}

180
lib/screens/menu_screen.dart

@ -1,180 +0,0 @@
// import 'package:cloud_firestore/cloud_firestore.dart';
// import 'package:flutter/material.dart';
// import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:my_flutter_puzzle/application/states/player_matching_state.dart';
// import 'package:my_flutter_puzzle/models/user_info.dart';
// import 'package:my_flutter_puzzle/providers.dart';
// import 'package:my_flutter_puzzle/res/palette.dart';
// import 'package:my_flutter_puzzle/utils/database_client.dart';
// import 'package:my_flutter_puzzle/screens/puzzle_screen.dart';
// import 'package:my_flutter_puzzle/widgets/menu_widgets/menu_widgets.dart';
// class MenuScreen extends ConsumerStatefulWidget {
// const MenuScreen({
// Key? key,
// required this.userData,
// }) : super(key: key);
// final UserData userData;
// @override
// ConsumerState<ConsumerStatefulWidget> createState() => _MenuScreenState();
// }
// class _MenuScreenState extends ConsumerState<MenuScreen> {
// final numberList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// late final UserData userData;
// @override
// void initState() {
// super.initState();
// userData = widget.userData;
// numberList.shuffle();
// }
// @override
// Widget build(BuildContext context) {
// var screenSize = MediaQuery.of(context).size;
// ref.listen(playerMatchingNotifierProvider, (previous, next) {
// if (next is PlayerMatched) {
// Navigator.of(context).push(
// MaterialPageRoute(
// builder: (context) => PuzzleScreen(
// initialList: numberList,
// id: next.id,
// myInfo: userData,
// ),
// ),
// );
// }
// });
// return Scaffold(
// backgroundColor: Colors.white,
// body: Center(
// child: SizedBox(
// width: screenSize.width * 0.5,
// child: Consumer(
// builder: (context, ref, child) {
// final state = ref.watch(playerMatchingNotifierProvider);
// return state.when(
// () => Column(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// const Text(
// 'Game Mode',
// style: TextStyle(
// fontSize: 30,
// // fontWeight: FontWeight.bold,
// color: Palette.crimson,
// ),
// ),
// const SizedBox(height: 24),
// MultiplayerButton(
// myInfo: userData,
// list: numberList,
// ),
// const SizedBox(height: 16),
// const SoloButton(),
// const SizedBox(height: 30),
// ],
// ),
// processing: () => Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: const [
// CircularProgressIndicator(
// valueColor:
// AlwaysStoppedAnimation<Color>(Palette.violet),
// ),
// SizedBox(width: 16),
// Text(
// 'Finding player ...',
// style: TextStyle(
// fontSize: 24,
// ),
// ),
// ],
// ),
// isMatched: (id) => Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: const [
// Icon(
// Icons.check_circle,
// color: Palette.violet,
// size: 50,
// ),
// SizedBox(width: 16),
// Text(
// 'Found player',
// style: TextStyle(
// fontSize: 24,
// ),
// ),
// ],
// ),
// isQueued: () => PlayerQueuedWidget(
// myInfo: userData,
// ),
// error: (message) => Text(
// message.toString(),
// style: const TextStyle(
// fontSize: 24,
// ),
// ),
// );
// },
// ),
// ),
// ));
// }
// }
// class PlayerQueuedWidget extends ConsumerWidget {
// PlayerQueuedWidget({
// Key? key,
// required this.myInfo,
// }) : super(key: key);
// final UserData myInfo;
// final _databaseClient = DatabaseClient();
// @override
// Widget build(BuildContext context, WidgetRef ref) {
// return StreamBuilder<DocumentSnapshot>(
// stream: _databaseClient.isMatched(myInfo: myInfo),
// builder: (context, snapshot) {
// if (snapshot.hasData && snapshot.data!.data() != null) {
// final queuedUserData =
// snapshot.data!.data() as Map<String, dynamic>;
// bool isMatched = queuedUserData['ismatched'];
// if (isMatched) {
// WidgetsBinding.instance?.addPostFrameCallback((_) {
// ref
// .read(playerMatchingNotifierProvider.notifier)
// .foundUser(myInfo: myInfo);
// });
// }
// }
// return Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: const [
// CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet),
// ),
// SizedBox(width: 16),
// Text(
// 'Your are in queue ...',
// style: TextStyle(
// fontSize: 24,
// ),
// ),
// ],
// );
// });
// }
// }

5
lib/screens/photo/photo_screen_large.dart

@ -10,8 +10,11 @@ import 'package:my_flutter_puzzle/res/puzzle_constants.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';
import 'package:my_flutter_puzzle/widgets/solo_screen/animated_dash.dart';
import 'package:my_flutter_puzzle/widgets/solo_screen/count_down_timer_widget.dart';
import 'package:my_flutter_puzzle/widgets/solo_screen/solo_screen_export.dart';
import 'package:my_flutter_puzzle/widgets/solo_screen/countdown_widget.dart';
import 'package:my_flutter_puzzle/widgets/solo_screen/moves_tiles_widget.dart';
import 'package:my_flutter_puzzle/widgets/solo_screen/puzzle_widget.dart';
import 'package:palette_generator/palette_generator.dart';
import 'package:rive/rive.dart';

152
lib/screens/puzzle/top_bar.dart

@ -1,152 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class TopBar extends ConsumerWidget {
const TopBar({
required Color color,
required int puzzleSize,
this.padding = const EdgeInsets.fromLTRB(24.0, 16.0, 24.0, 16.0),
this.tileGap = 16,
this.isCentered = false,
Key? key,
}) : _color = color,
_puzzleSize = puzzleSize,
super(key: key);
final Color _color;
final int _puzzleSize;
final EdgeInsets padding;
final double tileGap;
final bool isCentered;
@override
Widget build(BuildContext context, WidgetRef ref) {
return Container(
color: _color,
child: Padding(
padding: padding,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
isCentered ? const SizedBox() : const Spacer(),
// TextButton(
// style: _puzzleType == 'Normal'
// ? ButtonStyle(
// foregroundColor: MaterialStateProperty.resolveWith<Color>(
// (Set<MaterialState> states) {
// return Palette.blue;
// },
// ),
// )
// : null,
// onPressed: _puzzleType == 'Normal'
// ? null
// : () {
// ref.read(puzzleTypeNotifierProvider.notifier).changeToNormal();
// },
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// children: [
// Opacity(
// opacity: _puzzleType == 'Normal' ? 1 : 0.5,
// child: const FaIcon(FontAwesomeIcons.rocket),
// ),
// const SizedBox(width: 8),
// Text(
// 'Normal',
// style: TextStyle(
// fontSize: 16,
// color: Colors.white.withOpacity(_puzzleType == 'Normal' ? 1 : 0.5),
// ),
// ),
// ],
// ),
// ),
// ),
// SizedBox(width: tileGap),
// TextButton(
// style: _puzzleType == 'Photo'
// ? ButtonStyle(
// foregroundColor: MaterialStateProperty.resolveWith<Color>(
// (Set<MaterialState> states) {
// return Theme.of(context).colorScheme.primary;
// },
// ),
// )
// : null,
// onPressed: _puzzleType == 'Photo'
// ? null
// : () {
// final state = ref.read(imageSplitterNotifierProvider);
// if (state is! ImageSplitterComplete) {
// ref.read(imageSplitterNotifierProvider.notifier).getInitialImages(puzzleSize: _puzzleSize);
// }
//
// ref.read(puzzleTypeNotifierProvider.notifier).changeToPhoto();
// },
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// children: [
// Opacity(
// opacity: _puzzleType == 'Photo' ? 1 : 0.5,
// child: const FaIcon(FontAwesomeIcons.image),
// ),
// const SizedBox(width: 8),
// Text(
// 'Photo',
// style: TextStyle(
// fontSize: 16,
// color: Colors.white.withOpacity(_puzzleType == 'Photo' ? 1 : 0.5),
// ),
// ),
// ],
// ),
// ),
// ),
// SizedBox(width: tileGap),
// TextButton(
// style: _puzzleType == 'Multiplayer'
// ? ButtonStyle(
// foregroundColor: MaterialStateProperty.resolveWith<Color>(
// (Set<MaterialState> states) {
// return Palette.blue;
// },
// ),
// )
// : null,
// onPressed: _puzzleType == 'Multiplayer'
// ? null
// : () {
// // ref.read(puzzleTypeNotifierProvider.notifier).dispose();
//
// ref.read(puzzleTypeNotifierProvider.notifier).changeToMultiplayer();
// ref.read(emailAuthNotificationProvider.notifier).checkForSignedUser();
// },
// child: Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// children: [
// Opacity(
// opacity: _puzzleType == 'Multiplayer' ? 1 : 0.5,
// child: const FaIcon(FontAwesomeIcons.gamepad),
// ),
// const SizedBox(width: 8),
// Text(
// 'Multiplayer',
// style: TextStyle(
// fontSize: 16,
// color: Colors.white.withOpacity(_puzzleType == 'Multiplayer' ? 1 : 0.5),
// ),
// ),
// ],
// ),
// ),
// ),
],
),
),
);
}
}

220
lib/screens/puzzle_screen.dart

@ -1,220 +0,0 @@
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/models/user_info.dart';
import 'package:my_flutter_puzzle/widgets/puzzle_widgets/puzzle_widgets.dart';
class PuzzleScreen extends StatefulWidget {
const PuzzleScreen({
Key? key,
required this.initialList,
required this.id,
required this.myInfo,
}) : super(key: key);
final List<int> initialList;
final String id;
final UserData myInfo;
@override
_PuzzleScreenState createState() => _PuzzleScreenState();
}
class _PuzzleScreenState extends State<PuzzleScreen> {
late final List<int> myList;
late final List<int> opponentList;
int _moves = 0;
onClick(index) {
log('-----------------------');
log('Tapped index: $index');
int emptyTilePosIndex = myList.indexOf(0);
int emptyTilePosRow = emptyTilePosIndex ~/ 4;
int emptyTilePosCol = emptyTilePosIndex % 4;
int currentTileRow = index ~/ 4;
int currentTileCol = index % 4;
//current element moves up
if ((currentTileRow - 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) {
setState(() {
myList[emptyTilePosIndex] = myList[index];
myList[index] = 0;
_moves++;
});
}
//current element moves down
else if ((currentTileRow + 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) {
setState(() {
myList[emptyTilePosIndex] = myList[index];
myList[index] = 0;
_moves++;
});
}
//current element moves left
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol + 1 == emptyTilePosCol)) {
setState(() {
myList[emptyTilePosIndex] = myList[index];
myList[index] = 0;
_moves++;
});
}
//current element moves right
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol - 1 == emptyTilePosCol)) {
setState(() {
myList[emptyTilePosIndex] = myList[index];
myList[index] = 0;
_moves++;
});
} else {
if (currentTileCol == emptyTilePosCol) {
int low;
int high;
// multiple elements move up
if (emptyTilePosRow < currentTileRow) {
low = emptyTilePosRow;
high = currentTileRow;
int i = low;
while (i < high) {
setState(() {
myList[(i * 4) + emptyTilePosCol] = myList[(((i + 1) * 4) + emptyTilePosCol)];
});
i += 1;
}
setState(() {
myList[(high * 4) + emptyTilePosCol] = 0;
_moves++;
});
}
//multiple elements move down
else {
low = emptyTilePosRow;
high = currentTileRow;
int i = low;
while (i > high) {
setState(() {
myList[(i * 4) + emptyTilePosCol] = myList[(((i - 1) * 4) + emptyTilePosCol)];
});
i -= 1;
}
setState(() {
myList[(high * 4) + emptyTilePosCol] = 0;
_moves++;
});
}
}
// multiple elements move left
// multiple elements move right
if (currentTileRow == emptyTilePosRow) {
int low;
int high;
// multiple elements move left
if (emptyTilePosCol < currentTileCol) {
low = emptyTilePosCol;
high = currentTileCol;
int i = low;
while (i < high) {
setState(() {
myList[(emptyTilePosRow * 4) + i] = myList[(emptyTilePosRow * 4) + (i + 1)];
});
i += 1;
}
setState(() {
myList[high + (emptyTilePosRow * 4)] = 0;
_moves++;
});
}
//multiple elements move right
else {
low = emptyTilePosCol;
high = currentTileCol;
int i = low;
while (i > high) {
setState(() {
myList[(i + (emptyTilePosRow * 4))] = myList[(i - 1) + (emptyTilePosRow * 4)];
});
i -= 1;
}
setState(() {
myList[high + (emptyTilePosRow * 4)] = 0;
_moves++;
});
}
}
}
// _databaseClient.updateGameState(
// id: widget.id,
// mydata: widget.myInfo,
// numberList: myList,
// moves: _moves,
// );
log('List: $myList');
log('-----------------------');
}
@override
void initState() {
super.initState();
myList = widget.initialList;
opponentList = widget.initialList;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// PLAYER 1 puzzle --> my (own)
Column(
children: [
const PlayerText(
displayName: 'PLAYER 1',
),
// TODO: Change font size
MovesText(
moves: _moves,
fontSize: 60,
),
],
),
Container(
height: MediaQuery.of(context).size.height * 0.6,
width: 2,
color: Colors.black,
),
],
),
);
}
}

489
lib/screens/puzzle_solo_screen.dart

@ -1,489 +0,0 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/res/palette.dart';
import 'package:my_flutter_puzzle/utils/puzzle_solver.dart';
import 'package:my_flutter_puzzle/widgets/puzzle_widgets/puzzle_widgets.dart';
class PuzzleSoloScreen extends StatefulWidget {
const PuzzleSoloScreen({
Key? key,
}) : super(key: key);
@override
_PuzzleSoloScreenState createState() => _PuzzleSoloScreenState();
}
class _PuzzleSoloScreenState extends State<PuzzleSoloScreen> {
late final PuzzleSolverClient _solverClient;
List<List<int>>? _board2D;
List<int>? myList;
int _moves = 0;
final _puzzleSize = 3;
final int _animationSpeedInMilliseconds = 300;
bool _isComputing = false;
bool _isAutoSolving = false;
bool _isSolved = false;
Map<int, FractionalOffset>? _offsetMap;
List<int> _solvedList = [];
@override
void initState() {
super.initState();
_solverClient = PuzzleSolverClient(size: _puzzleSize);
initBoard();
generateSolvedList();
}
generateSolvedList() {
for (int i = 1; i < _puzzleSize * _puzzleSize; i++) {
_solvedList.add(i);
}
_solvedList.add(0);
}
scrambleBoard() {
final generated2DBoard = _solverClient.createRandomBoard();
final generated1DBoard = _solverClient.convertTo1D(generated2DBoard);
updateOffset(generated1DBoard);
setState(() {
_board2D = generated2DBoard;
myList = generated1DBoard;
_moves = 0;
_isSolved = false;
});
}
initBoard() {
final generated2DBoard = _solverClient.createRandomBoard();
final generated1DBoard = _solverClient.convertTo1D(generated2DBoard);
createOffset(generated1DBoard);
setState(() {
_board2D = generated2DBoard;
myList = generated1DBoard;
_moves = 0;
});
}
startAutoSolver() async {
if (_board2D != null) {
setState(() {
_isComputing = true;
});
List<List<int>>? boardStates = await compute(_solverClient.runner, _solverClient.convertTo2D(myList!));
setState(() {
_isComputing = false;
_isAutoSolving = true;
});
if (boardStates != null) {
for (var board in boardStates) {
await Future.delayed(Duration(
milliseconds: _animationSpeedInMilliseconds,
));
setState(() {
myList = board;
_moves++;
});
updateOffset(myList!);
}
}
}
setState(() {
_isAutoSolving = false;
_isSolved = true;
});
showCompleteDialogBox(context);
}
isSolved(List<int> currentBoard) {
if (listEquals(currentBoard, _solvedList)) {
setState(() {
_isSolved = true;
});
return true;
}
setState(() {
_isSolved = false;
});
return false;
}
onClick(index) {
log('-----------------------');
log('Tapped index: $index');
if (myList != null) {
int emptyTilePosIndex = myList!.indexOf(0);
int emptyTilePosRow = emptyTilePosIndex ~/ _puzzleSize;
int emptyTilePosCol = emptyTilePosIndex % _puzzleSize;
int currentTileRow = index ~/ _puzzleSize;
int currentTileCol = index % _puzzleSize;
//current element moves up
if ((currentTileRow - 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) {
myList![emptyTilePosIndex] = myList![index];
myList![index] = 0;
_moves++;
}
//current element moves down
else if ((currentTileRow + 1 == emptyTilePosRow) && (currentTileCol == emptyTilePosCol)) {
myList![emptyTilePosIndex] = myList![index];
myList![index] = 0;
_moves++;
}
//current element moves left
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol + 1 == emptyTilePosCol)) {
myList![emptyTilePosIndex] = myList![index];
myList![index] = 0;
_moves++;
}
//current element moves right
else if ((currentTileRow == emptyTilePosRow) && (currentTileCol - 1 == emptyTilePosCol)) {
myList![emptyTilePosIndex] = myList![index];
myList![index] = 0;
_moves++;
} else {
if (currentTileCol == emptyTilePosCol) {
int low;
int high;
// multiple elements move up
if (emptyTilePosRow < currentTileRow) {
low = emptyTilePosRow;
high = currentTileRow;
int i = low;
while (i < high) {
myList![(i * _puzzleSize) + emptyTilePosCol] = myList![(((i + 1) * _puzzleSize) + emptyTilePosCol)];
i += 1;
}
myList![(high * _puzzleSize) + emptyTilePosCol] = 0;
_moves++;
}
//multiple elements move down
else {
low = emptyTilePosRow;
high = currentTileRow;
int i = low;
while (i > high) {
myList![(i * _puzzleSize) + emptyTilePosCol] = myList![(((i - 1) * _puzzleSize) + emptyTilePosCol)];
i -= 1;
}
myList![(high * _puzzleSize) + emptyTilePosCol] = 0;
_moves++;
}
}
// multiple elements move left or right
if (currentTileRow == emptyTilePosRow) {
int low;
int high;
// multiple elements move left
if (emptyTilePosCol < currentTileCol) {
low = emptyTilePosCol;
high = currentTileCol;
int i = low;
while (i < high) {
myList![(emptyTilePosRow * _puzzleSize) + i] = myList![(emptyTilePosRow * _puzzleSize) + (i + 1)];
i += 1;
}
myList![high + (emptyTilePosRow * _puzzleSize)] = 0;
_moves++;
}
//multiple elements move right
else {
low = emptyTilePosCol;
high = currentTileCol;
int i = low;
while (i > high) {
myList![(i + (emptyTilePosRow * _puzzleSize))] = myList![(i - 1) + (emptyTilePosRow * _puzzleSize)];
i -= 1;
}
myList![high + (emptyTilePosRow * _puzzleSize)] = 0;
_moves++;
}
}
}
// Update Offset list
// setState(() {
// updateOffset(myList!);
// });
updateOffset(myList!);
setState(() {});
if (isSolved(myList!)) {
showCompleteDialogBox(context);
}
log('List: $myList');
log('-----------------------');
}
}
createOffset(List<int> board) {
Map<int, FractionalOffset> offsetMap = {};
int j = 0;
log('BOARD: $board');
for (int i = 0; i < board.length; i++) {
final xMod = i % _puzzleSize;
double x = xMod / (_puzzleSize - 1);
if (x % i == 0 && i != 0) j++;
int yMod = j % _puzzleSize;
double y = yMod / (_puzzleSize - 1);
offsetMap.addEntries([
MapEntry<int, FractionalOffset>(
board[i],
FractionalOffset(x, y),
)
]);
}
log('INITIAL OFFSET MAP: $offsetMap');
setState(() {
_offsetMap = offsetMap;
});
}
updateOffset(List<int> board) {
int j = 0;
for (int i = 0; i < board.length; i++) {
final xMod = i % _puzzleSize;
double x = xMod / (_puzzleSize - 1);
if (x % i == 0 && i != 0) j++;
int yMod = j % _puzzleSize;
double y = yMod / (_puzzleSize - 1);
_offsetMap![board[i]] = FractionalOffset(x, y);
}
log('OFFSET MAP: $_offsetMap');
}
showCompleteDialogBox(BuildContext context) {
showDialog(
context: context,
builder: (context) => Dialog(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
'Solved successfully!',
style: TextStyle(fontSize: 22),
),
const SizedBox(height: 16),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Palette.violet,
onSurface: Palette.violet,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
onPressed: () {
Navigator.of(context).pop();
},
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'OK',
style: TextStyle(fontSize: 22),
),
),
),
],
),
),
),
);
}
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
var boardSize = screenSize.height * 0.6;
var spacing = 4;
var eachBoxSize = (boardSize / _puzzleSize) - (spacing * (_puzzleSize - 1));
return Scaffold(
backgroundColor: Colors.white,
body: myList != null && _offsetMap != null
? Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Row(),
MovesText(
moves: _moves,
fontSize: 60,
),
SizedBox(
height: boardSize,
width: boardSize,
child: Stack(
children: [
for (int i = 0; i < _offsetMap!.length; i++)
_offsetMap!.entries.toList()[i].key != 0
? AnimatedAlign(
alignment: _offsetMap!.entries.toList()[i].value,
duration: Duration(
milliseconds: _animationSpeedInMilliseconds,
),
curve: Curves.easeInOut,
child: GestureDetector(
onTap: () => onClick(myList!.indexOf(_offsetMap!.entries.toList()[i].key)),
child: Card(
elevation: 4,
color: const Color(0xFF2868d7),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: SizedBox(
height: eachBoxSize,
width: eachBoxSize,
child: Center(
child: Text(
_offsetMap!.entries.toList()[i].key.toString(),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
),
),
)
: const SizedBox(),
],
),
),
// AnimatedGrid(
// puzzleSize: _puzzleSize,
// key: UniqueKey(),
// number: myList!,
// offsetList: _offsetList!,
// onTap: onClick,
// color: const Color(0xFF2868d7),
// ),
const SizedBox(height: 30),
Row(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 30.0),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.2,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Palette.violet,
onSurface: Palette.violet,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
onPressed: _isComputing || _isAutoSolving || _isSolved
? null
: () {
startAutoSolver();
},
child: Padding(
padding: const EdgeInsets.all(16.0),
child: _isComputing || _isAutoSolving
? Row(
children: [
const SizedBox(
width: 25,
height: 25,
child: CircularProgressIndicator(
color: Palette.violet,
strokeWidth: 2,
),
),
const SizedBox(width: 16),
Text(
_isComputing ? 'Computing ...' : 'Solving ...',
style: const TextStyle(fontSize: 20),
),
],
)
: const Text(
'Start Auto Solver',
style: TextStyle(fontSize: 22),
),
),
),
),
),
const SizedBox(width: 16.0),
Padding(
padding: const EdgeInsets.only(bottom: 30.0),
child: SizedBox(
width: MediaQuery.of(context).size.width * 0.2,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Palette.crimson,
onSurface: Palette.crimson,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
),
onPressed: _isComputing || _isAutoSolving
? null
: () {
scrambleBoard();
},
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Scramble',
style: TextStyle(fontSize: 22),
),
),
),
),
),
],
),
],
)
: const SizedBox(),
);
}
}

43
lib/screens/splash/screen/splash_screen.dart

@ -0,0 +1,43 @@
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';
class SplashScreen extends StatefulWidget {
const SplashScreen({Key? key}) : super(key: key);
@override
State<SplashScreen> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
@override
void initState() {
Timer(const Duration(milliseconds: 2000), () {
Navigator.push(context, MaterialPageRoute(
builder: (context) {
return const LevelListScreen();
},
));
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xff6236FF),
body: Center(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('splash_screen_image'.pngPath),
),
),
),
),
);
}
}

19
lib/utils/extensions/context_extension.dart

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
extension ContextExtentions on BuildContext {
double get height {
return MediaQuery.of(this).size.height;
}
double get width {
return MediaQuery.of(this).size.width;
}
double get horizontallyMargin {
return MediaQuery.of(this).size.width * 0.05;
}
double get verticallyMargin {
return MediaQuery.of(this).size.height * 0.025;
}
}

4
lib/utils/extensions/string_extensions.dart

@ -6,4 +6,8 @@ extension StringExtension on String {
String get rivePath {
return 'assets/rive/$this.riv';
}
String get svgPath {
return 'assets/images/svg/$this.svg';
}
}

308
lib/widgets/animated_grid.dart

@ -1,308 +0,0 @@
import 'package:flutter/material.dart';
class AnimatedGrid extends StatefulWidget {
const AnimatedGrid({
Key? key,
required this.number,
required this.offsetList,
required this.onTap,
required this.color,
required this.puzzleSize,
}) : super(key: key);
final Function onTap;
final List<int> number;
final List<FractionalOffset> offsetList;
final Color color;
final int puzzleSize;
@override
State<AnimatedGrid> createState() => _AnimatedGridState();
}
class _AnimatedGridState extends State<AnimatedGrid> {
late List<FractionalOffset> _offsetList;
@override
void initState() {
_offsetList = widget.offsetList;
super.initState();
}
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
var boardSize = screenSize.width * 0.4;
var spacing = 4;
var eachBoxSize =
(boardSize / widget.puzzleSize) - (spacing * (widget.puzzleSize - 1));
return SizedBox(
height: boardSize,
width: boardSize,
child: Stack(
children: [
for (int i = 0; i < widget.offsetList.length; i++)
widget.number[i] != 0
? AnimatedAlign(
alignment: widget.offsetList[i],
duration: const Duration(seconds: 1),
curve: Curves.easeInOut,
child: GestureDetector(
onTap: () => widget.onTap(i),
child: Card(
elevation: 4,
color: widget.color,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: SizedBox(
height: eachBoxSize,
width: eachBoxSize,
child: Center(
child: Text(
widget.number[i].toString(),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
),
),
)
: const SizedBox(),
],
),
);
// -----------------------------
// Working implementation:
// -----------------------------
// return SizedBox(
// height: screenSize.height * 0.7,
// width: screenSize.width * 0.4,
// child: GridView.builder(
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: puzzleSize,
// ),
// itemCount: number.length,
// itemBuilder: (context, index) {
// return number[index] != 0
// ? Padding(
// padding: const EdgeInsets.all(2.0),
// child: GestureDetector(
// onTap: () => onTap(index),
// child: AnimatedPositioned(
// duration: Duration(milliseconds: 600),
// child: Container(
// height: 20,
// width: 20,
// color: Colors.orange,
// ),
// ),
// ),
// )
// // ? MouseRegion(
// // child: Padding(
// // padding: const EdgeInsets.all(2.0),
// // child: GestureDetector(
// // onTap: () => onTap(index),
// // child: Card(
// // elevation: 4,
// // color: color,
// // // dark -> 0xFF14407a
// // // light -> 0xFF43b9fd
// // shape: RoundedRectangleBorder(
// // borderRadius: BorderRadius.circular(20),
// // ),
// // child: SizedBox(
// // height: 20,
// // width: 20,
// // child: Center(
// // child: Text(
// // number[index].toString(),
// // style: const TextStyle(
// // fontSize: 60,
// // fontWeight: FontWeight.bold,
// // color: Colors.white,
// // ),
// // ),
// // ),
// // ),
// // ),
// // ),
// // ),
// // )
// : const SizedBox();
// // },
// // ),
// // );
// }
}
}
// class AnimatedGrid extends StatefulWidget {
// const AnimatedGrid({
// Key? key,
// required this.number,
// required this.offsetList,
// required this.onTap,
// required this.color,
// required this.puzzleSize,
// }) : super(key: key);
// final Function onTap;
// final List<int> number;
// final List<FractionalOffset> offsetList;
// final Color color;
// final int puzzleSize;
// @override
// State<AnimatedGrid> createState() => _AnimatedGridState();
// }
// class _AnimatedGridState extends State<AnimatedGrid> {
// // FractionalOffset offset = FractionalOffset(0, 0);
// late final List<int> _numberList;
// // late final int _puzzleSize;
// @override
// void initState() {
// _numberList = widget.number;
// // _puzzleSize = widget.puzzleSize;
// // print(_numberList);
// // print(widget.offsetList);
// super.initState();
// }
// // calculateOffset() {
// // List<FractionalOffset> offsetList = [];
// // for (int i = 0; i < _puzzleSize; i++) {
// // int yMod = i % _puzzleSize;
// // double y = yMod / (_puzzleSize - 1);
// // for (int j = 0; j < _puzzleSize; j++) {
// // final xMod = _numberList[i][j] % _puzzleSize;
// // double x = xMod / (_puzzleSize - 1);
// // offsetList.add(FractionalOffset(x, y));
// // }
// // }
// // }
// @override
// Widget build(BuildContext context) {
// var screenSize = MediaQuery.of(context).size;
// var boardSize = screenSize.width * 0.4;
// var spacing = 4;
// var eachBoxSize =
// (boardSize / widget.puzzleSize) - (spacing * (widget.puzzleSize - 1));
// return SizedBox(
// height: boardSize,
// width: boardSize,
// child: Stack(
// children: [
// for (var offset in widget.offsetList)
// AnimatedAlign(
// alignment: offset,
// duration: const Duration(seconds: 1),
// curve: Curves.easeInOut,
// child: Container(
// height: eachBoxSize,
// width: eachBoxSize,
// color: Colors.black,
// ),
// ),
// // AnimatedAlign(
// // alignment: FractionalOffset(1, 0),
// // duration: Duration(seconds: 1),
// // curve: Curves.easeInOut,
// // child: Container(
// // height: eachBoxSize,
// // width: eachBoxSize,
// // color: Colors.black,
// // ),
// // ),
// // AnimatedAlign(
// // alignment: FractionalOffset(0.5, 1),
// // duration: Duration(seconds: 1),
// // curve: Curves.easeInOut,
// // child: Container(
// // height: eachBoxSize,
// // width: eachBoxSize,
// // color: Colors.black,
// // ),
// // ),
// ],
// ),
// );
// // -----------------------------
// // Working implementation:
// // -----------------------------
// // return SizedBox(
// // height: screenSize.height * 0.7,
// // width: screenSize.width * 0.4,
// // child: GridView.builder(
// // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// // crossAxisCount: puzzleSize,
// // ),
// // itemCount: number.length,
// // itemBuilder: (context, index) {
// // return number[index] != 0
// // ? Padding(
// // padding: const EdgeInsets.all(2.0),
// // child: GestureDetector(
// // onTap: () => onTap(index),
// // child: AnimatedPositioned(
// // duration: Duration(milliseconds: 600),
// // child: Container(
// // height: 20,
// // width: 20,
// // color: Colors.orange,
// // ),
// // ),
// // ),
// // )
// // // ? MouseRegion(
// // // child: Padding(
// // // padding: const EdgeInsets.all(2.0),
// // // child: GestureDetector(
// // // onTap: () => onTap(index),
// // // child: Card(
// // // elevation: 4,
// // // color: color,
// // // // dark -> 0xFF14407a
// // // // light -> 0xFF43b9fd
// // // shape: RoundedRectangleBorder(
// // // borderRadius: BorderRadius.circular(20),
// // // ),
// // // child: SizedBox(
// // // height: 20,
// // // width: 20,
// // // child: Center(
// // // child: Text(
// // // number[index].toString(),
// // // style: const TextStyle(
// // // fontSize: 60,
// // // fontWeight: FontWeight.bold,
// // // color: Colors.white,
// // // ),
// // // ),
// // // ),
// // // ),
// // // ),
// // // ),
// // // ),
// // // )
// // : const SizedBox();
// // },
// // ),
// // );
// }
// }

67
lib/widgets/grid.dart

@ -1,67 +0,0 @@
import 'package:flutter/material.dart';
class Grid extends StatelessWidget {
const Grid({
Key? key,
required this.number,
required this.onTap,
required this.color,
required this.puzzleSize,
}) : super(key: key);
final Function onTap;
final List<dynamic> number;
final Color color;
final int puzzleSize;
@override
Widget build(BuildContext context) {
var screenSize = MediaQuery.of(context).size;
return SizedBox(
height: screenSize.height * 0.7,
width: screenSize.width * 0.4,
child: GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: puzzleSize,
),
itemCount: number.length,
itemBuilder: (context, index) {
return number[index] != 0
? MouseRegion(
child: Padding(
padding: const EdgeInsets.all(2.0),
child: GestureDetector(
onTap: () => onTap(index),
child: Card(
elevation: 4,
color: color,
// dark -> 0xFF14407a
// light -> 0xFF43b9fd
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: SizedBox(
height: 20,
width: 20,
child: Center(
child: Text(
number[index].toString(),
style: const TextStyle(
fontSize: 60,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
),
),
),
),
)
: const SizedBox();
},
),
);
}
}

62
lib/widgets/login_widgets/name_field.dart

@ -1,62 +0,0 @@
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/res/palette.dart';
class NameField extends StatefulWidget {
final FocusNode focusNode;
final Function(String) onChange;
const NameField({
Key? key,
required this.focusNode,
required this.onChange,
}) : super(key: key);
@override
State<NameField> createState() => _NameFieldState();
}
class _NameFieldState extends State<NameField> {
late final TextEditingController _nameTextController;
late final FocusNode _nameFocusNode;
@override
void initState() {
super.initState();
_nameTextController = TextEditingController();
_nameFocusNode = widget.focusNode;
}
@override
Widget build(BuildContext context) {
return TextField(
controller: _nameTextController,
focusNode: _nameFocusNode,
style: const TextStyle(
fontSize: 24,
color: Palette.crimson,
),
cursorColor: Palette.violet,
decoration: InputDecoration(
border: const UnderlineInputBorder(),
focusedBorder: const UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.violet,
width: 3,
),
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(
color: Palette.violet.withOpacity(0.5),
width: 2,
),
),
hintText: 'Enter your name',
hintStyle: TextStyle(
fontSize: 22,
color: Palette.violet.withOpacity(0.2),
),
),
onChanged: (value) => widget.onChange(value),
);
}
}

72
lib/widgets/login_widgets/start_game_widget.dart

@ -1,72 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:my_flutter_puzzle/application/states/anonymous_auth_state.dart';
// import 'package:my_flutter_puzzle/providers.dart';
// import 'package:my_flutter_puzzle/res/palette.dart';
// import 'package:my_flutter_puzzle/screens/menu_screen.dart';
// import 'package:my_flutter_puzzle/screens/puzzle_screen.dart';
// import 'package:my_flutter_puzzle/widgets/login_widgets/start_game_widget/start_game_button.dart';
// class StartGameWidget extends ConsumerWidget {
// const StartGameWidget({
// Key? key,
// required String nameString,
// }) : _nameString = nameString,
// super(key: key);
// final String _nameString;
// @override
// Widget build(BuildContext context, WidgetRef ref) {
// ref.listen(anonymousAuthNotificationProvider, (previous, next) {
// if (next is StorageDone) {
// Navigator.of(context).pushAndRemoveUntil(
// MaterialPageRoute(
// builder: (context) => MenuScreen(
// userData: next.userData,
// ),
// ),
// (route) => false,
// );
// }
// });
// return Consumer(
// builder: (context, ref, child) {
// final state = ref.watch(anonymousAuthNotificationProvider);
// return state.when(
// () => StartGameButton(
// nameString: _nameString,
// ),
// processing: () => const CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet),
// ),
// done: (_) => const CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet),
// ),
// storingInfo: () => const CircularProgressIndicator(
// valueColor: AlwaysStoppedAnimation<Color>(Palette.violet),
// ),
// storageDone: (userData) => const Icon(
// Icons.check,
// size: 50,
// color: Palette.violet,
// ),
// // done: (_) => const Icon(
// // Icons.check,
// // size: 50,
// // color: Palette.violet,
// // ),
// error: (message) => Column(
// children: [
// Text('$message'),
// const SizedBox(height: 16),
// StartGameButton(nameString: _nameString),
// ],
// ),
// );
// },
// );
// }
// }

39
lib/widgets/login_widgets/start_game_widget/start_game_button.dart

@ -1,39 +0,0 @@
// import 'package:flutter/material.dart';
// import 'package:flutter_riverpod/flutter_riverpod.dart';
// import 'package:my_flutter_puzzle/providers.dart';
// import 'package:my_flutter_puzzle/res/palette.dart';
// class StartGameButton extends ConsumerWidget {
// const StartGameButton({
// Key? key,
// required String nameString,
// }) : _nameString = nameString,
// super(key: key);
// final String _nameString;
// @override
// Widget build(BuildContext context, WidgetRef ref) {
// return SizedBox(
// width: double.maxFinite,
// child: ElevatedButton(
// style: ElevatedButton.styleFrom(
// primary: Palette.violet,
// onSurface: Palette.violet,
// ),
// onPressed: _nameString.isEmpty || _nameString.length < 3
// ? null
// : () => ref
// .read(anonymousAuthNotificationProvider.notifier)
// .triggerAnonymousLogin(name: _nameString),
// child: const Padding(
// padding: EdgeInsets.all(16.0),
// child: Text(
// 'Start game',
// style: TextStyle(fontSize: 22),
// ),
// ),
// ),
// );
// }
// }

2
lib/widgets/menu_widgets/menu_widgets.dart

@ -1,2 +0,0 @@
export 'multiplayer_button.dart';
export 'solo_button.dart';

108
lib/widgets/menu_widgets/multiplayer_button.dart

@ -1,108 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:my_flutter_puzzle/models/user_info.dart';
import 'package:my_flutter_puzzle/res/palette.dart';
class MultiplayerButton extends ConsumerStatefulWidget {
const MultiplayerButton({
Key? key,
required this.myInfo,
required this.list,
}) : super(key: key);
final UserData myInfo;
final List<int> list;
@override
ConsumerState<ConsumerStatefulWidget> createState() => _MultiplayerButtonState();
}
class _MultiplayerButtonState extends ConsumerState<MultiplayerButton> {
late final List<int> numberList;
@override
void initState() {
super.initState();
numberList = widget.list;
numberList.shuffle();
}
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.maxFinite,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
primary: Palette.violet,
onSurface: Palette.violet,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
side: const BorderSide(
width: 2,
color: Palette.violet,
),
),
onPressed: () {
// ref
// .read(playerMatchingNotifierProvider.notifier)
// .triggerMatching(myInfo: widget.myInfo, numbers: numberList);
},
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Multiplayer',
style: TextStyle(fontSize: 22),
),
),
),
);
}
}
// class MultiplayerButton extends StatefulWidget {
// final UserData myInfo;
// MultiplayerButton({
// Key? key,
// required this.myInfo,
// }) : super(key: key);
// @override
// State<MultiplayerButton> createState() => _MultiplayerButtonState();
// }
// class _MultiplayerButtonState extends State<MultiplayerButton> {
// final numberList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
// @override
// Widget build(BuildContext context) {
// return SizedBox(
// width: double.maxFinite,
// child: OutlinedButton(
// style: OutlinedButton.styleFrom(
// primary: Palette.violet,
// onSurface: Palette.violet,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(50),
// ),
// side: const BorderSide(
// width: 2,
// color: Palette.violet,
// ),
// ),
// onPressed: () {
// ref.read(playerMatchingNotifierProvider.notifier).triggerMatching(
// myInfo: widget.myInfo,
// numbers: [14, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 15]);
// },
// child: const Padding(
// padding: EdgeInsets.all(16.0),
// child: Text(
// 'Multiplayer',
// style: TextStyle(fontSize: 22),
// ),
// ),
// ),
// );
// }
// }

44
lib/widgets/menu_widgets/solo_button.dart

@ -1,44 +0,0 @@
import 'package:flutter/material.dart';
import 'package:my_flutter_puzzle/res/palette.dart';
import 'package:my_flutter_puzzle/screens/puzzle_solo_screen.dart';
class SoloButton extends StatelessWidget {
const SoloButton({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.maxFinite,
child: OutlinedButton(
style: OutlinedButton.styleFrom(
primary: Palette.violet,
onSurface: Palette.violet,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
side: const BorderSide(
width: 2,
color: Palette.violet,
),
),
onPressed: () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => const PuzzleSoloScreen(),
),
(route) => false,
);
},
child: const Padding(
padding: EdgeInsets.all(16.0),
child: Text(
'Solo',
style: TextStyle(fontSize: 22),
),
),
),
);
}
}

53
lib/widgets/photo_screen/pick_image_button.dart

@ -1,53 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class PickImageButton extends ConsumerWidget {
const PickImageButton({
Key? key,
required this.text,
required this.onTap,
this.padding = const EdgeInsets.only(top: 13.0, bottom: 12.0),
this.width = 145,
}) : super(key: key);
final String text;
final Function()? onTap;
final EdgeInsets padding;
final double width;
@override
Widget build(BuildContext context, WidgetRef ref) {
return SizedBox(
width: width,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(30)),
),
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.pressed)) {
return Theme.of(context).colorScheme.primary.withOpacity(0.5);
} else if (states.contains(MaterialState.disabled)) {
return Theme.of(context).colorScheme.primary.withOpacity(0.5);
}
return Theme.of(context).colorScheme.primary;
},
),
),
onPressed: onTap,
child: Padding(
padding: padding,
child: Text(
text,
style: TextStyle(
fontSize: 16,
color: Colors.white.withOpacity(onTap == null ? 0.6 : 1),
),
),
),
),
);
}
}

28
lib/widgets/puzzle_widgets/moves_text.dart

@ -1,28 +0,0 @@
import 'package:flutter/material.dart';
class MovesText extends StatelessWidget {
const MovesText({
Key? key,
required int moves,
required this.fontSize,
}) : _moves = moves,
super(key: key);
final int _moves;
final double fontSize;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 24),
child: Text(
'$_moves Moves',
style: TextStyle(
fontSize: fontSize,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
);
}
}

26
lib/widgets/puzzle_widgets/player_text.dart

@ -1,26 +0,0 @@
import 'package:flutter/material.dart';
class PlayerText extends StatelessWidget {
final String displayName;
const PlayerText({
Key? key,
required this.displayName,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 24.0),
child: Text(
displayName,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xFF14407a),
letterSpacing: 2,
),
),
);
}
}

2
lib/widgets/puzzle_widgets/puzzle_widgets.dart

@ -1,2 +0,0 @@
export 'moves_text.dart';
export 'player_text.dart';

73
lib/widgets/puzzle_widgets/solo/timer_widget.dart

@ -1,73 +0,0 @@
import 'dart:async';
import 'package:flutter/material.dart';
class TimerWidget extends StatefulWidget {
const TimerWidget({
Key? key,
required this.fontSize,
required this.color,
}) : super(key: key);
final double fontSize;
final Color color;
@override
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
late final Timer _timer;
int _start = 0;
void startTimer() {
_timer = Timer.periodic(
const Duration(seconds: 1),
(Timer timer) => setState(() => _start++),
);
}
String printDuration() {
var duration = Duration(seconds: _start);
String twoDigits(int n) => n.toString().padLeft(2, "0");
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60));
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60));
return "${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
}
@override
void initState() {
startTimer();
super.initState();
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
printDuration(),
style: TextStyle(
fontSize: widget.fontSize,
color: widget.color,
),
),
const SizedBox(width: 8),
Icon(
Icons.timer,
color: widget.color,
size: widget.fontSize * 1.3,
)
],
),
);
}
}

6
lib/widgets/solo_screen/solo_screen_export.dart

@ -1,6 +0,0 @@
export 'animated_dash.dart';
export 'countdown_widget.dart';
export 'game_button_widget.dart';
export 'moves_tiles_widget.dart';
export 'puzzle_widget.dart';
export 'timer_widget.dart';

42
pubspec.lock

@ -278,6 +278,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: "97c5b291b4fd34ae4f55d6a4c05841d4d0ed94952e033c5a6529e1b47b4d2a29"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
flutter_test:
dependency: "direct dev"
description: flutter
@ -480,6 +488,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.2"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.dev"
source: hosted
version: "1.0.1"
path_provider:
dependency: "direct main"
description:
@ -741,6 +757,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.2.0"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: e43c38822e7d2facd790fd617ce16b10cc359a4b094d5772e3198904270918ef
url: "https://pub.dev"
source: hosted
version: "1.1.1"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: "4a85a8563405bfe223052a85d6f8bc276ba3a22e12acfa3fd9a7108c67b32076"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "9e8066d2f18e88f2fb1cf6c8ca567417bdfb0145ac28519dcca3c15d42a10b3e"
url: "https://pub.dev"
source: hosted
version: "1.1.1"
vector_math:
dependency: transitive
description:
@ -799,4 +839,4 @@ packages:
version: "3.1.1"
sdks:
dart: ">=2.19.0 <3.0.0"
flutter: ">=3.0.0"
flutter: ">=3.7.0-0"

5
pubspec.yaml

@ -12,6 +12,7 @@ dependencies:
url_strategy: ^0.2.0
flutter_riverpod: ^1.0.3
freezed_annotation: ^1.1.0
flutter_svg: ^2.0.2
collection: ^1.15.0
tuple: ^2.0.0
isolated_worker: ^0.1.0
@ -34,8 +35,8 @@ flutter:
uses-material-design: true
assets:
- assets/rive/dash.riv
- assets/images/default_image.png
- assets/images/puzzle_side_image.png
- assets/images/
- assets/images/svg/
fonts:
- family: GoogleSans
fonts:

Loading…
Cancel
Save