From a224acc670019ccba1dc9d7aa6a5851f4fdcd044 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Mon, 2 Oct 2023 00:29:37 -0500 Subject: [PATCH 1/8] feat: improve set up password, login, dashboard, minigames and up game views following new UI --- lib/main.dart | 2 +- lib/pages/comingSoon.dart | 31 ++++ lib/pages/generatePhrase.dart | 10 +- lib/pages/home.dart | 215 +++++++++++++++-------- lib/pages/inputPhrase.dart | 11 +- lib/pages/login.dart | 127 ++++++------- lib/pages/mini-games/mini_games.dart | 42 +++-- lib/pages/mini-games/up/up.dart | 2 +- lib/pages/setupPassword.dart | 90 ++++++---- lib/ui/widgets/GameCard/game_card.dart | 52 ++++++ lib/ui/widgets/IntroLogo/intro_logo.dart | 2 +- lib/ui/widgets/widgets.dart | 1 + 12 files changed, 394 insertions(+), 191 deletions(-) create mode 100644 lib/pages/comingSoon.dart create mode 100644 lib/ui/widgets/GameCard/game_card.dart diff --git a/lib/main.dart b/lib/main.dart index ab9a795..9bc9db9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -79,4 +79,4 @@ class MyApp extends StatelessWidget { routerConfig: _router, ); } -} \ No newline at end of file +} diff --git a/lib/pages/comingSoon.dart b/lib/pages/comingSoon.dart new file mode 100644 index 0000000..fbb6c13 --- /dev/null +++ b/lib/pages/comingSoon.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; + +import '../ui/widgets/widgets.dart'; + +class ComingSoonScreen extends StatelessWidget { + const ComingSoonScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, + ), + ), + child: const Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + IntroLogoWidget(), + SizedBox(height: 30), + TextBoxWidget(text: 'Coming soon ^-^'), + ]), + ), + ), + ); + } +} diff --git a/lib/pages/generatePhrase.dart b/lib/pages/generatePhrase.dart index f4ee5ef..498e060 100644 --- a/lib/pages/generatePhrase.dart +++ b/lib/pages/generatePhrase.dart @@ -3,6 +3,7 @@ import 'package:flutter/services.dart'; import 'package:bip39/bip39.dart' as bip39; import 'package:go_router/go_router.dart'; +import 'package:dinogrow/pages/setupPassword.dart'; import '../ui/widgets/widgets.dart'; class GeneratePhraseScreen extends StatefulWidget { @@ -81,7 +82,14 @@ class _GeneratePhraseScreenState extends State { text: _copied ? 'Continue' : 'Go Back', onPressed: _copied ? () { - GoRouter.of(context).push("/passwordSetup/$_mnemonic"); + // GoRouter.of(context).push("/passwordSetup/$_mnemonic"); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return SetupPasswordScreen(mnemonic: _mnemonic); + }, + ); } : () { GoRouter.of(context).push("/"); diff --git a/lib/pages/home.dart b/lib/pages/home.dart index d3d856d..38451d6 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -4,6 +4,9 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:solana/solana.dart'; +import 'package:dinogrow/pages/mini-games/mini_games.dart'; +import 'package:dinogrow/pages/comingSoon.dart'; + class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @@ -24,86 +27,152 @@ class _HomeScreenState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('DINOGROW'), - ), - body: Padding( - padding: const EdgeInsets.all(16), - child: ListView( - children: [ - // User card - Card( - child: Padding( - padding: const EdgeInsets.all(8), - child: Column( - children: [ - const Text('User'), - Text(_publicKey == null - ? 'Loading...' - : '${_publicKey!.substring(0, 4)}...${_publicKey!.substring(_publicKey!.length - 3, _publicKey!.length)}'), - Text(_balance ?? 'Loading...'), - ], + return DefaultTabController( + length: 4, + child: Scaffold( + appBar: AppBar( + toolbarHeight: 108, + flexibleSpace: Column( + children: [ + const SizedBox(height: 38), + Card( + child: Padding( + padding: const EdgeInsets.all(6), + child: Row( + children: [ + const Text( + 'Wallet: ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(width: 3), + Expanded( + child: Text(_publicKey == null + ? 'Loading...' + : '${_publicKey!.substring(0, 4)}...${_publicKey!.substring(_publicKey!.length - 3, _publicKey!.length)}')), + const SizedBox(width: 12), + const Text( + 'Balance: ', + style: TextStyle(fontWeight: FontWeight.bold), + ), + const SizedBox(width: 3), + Text(_balance ?? 'Loading...'), + const SizedBox(width: 3), + const Text('SOL'), + ], + ), ), ), - ), - - // menu card - Card( - child: Padding( - padding: EdgeInsets.all(8), - child: Column( - children: [ - TextButton( - child: Text('My Dinogrow'), - onPressed: () { - // My Dinos button - }, - ), - TextButton( - child: Text('Mini Games'), - onPressed: () { - GoRouter.of(context).push("/mini_games"); - }, - ), - TextButton( - child: Text('Wallet'), - onPressed: () { - // wallet button - }, - ), - TextButton( - child: Text('Ranking'), - onPressed: () { - // Ranking button - }, - ) - ], - ), + const TabBar( + tabs: [ + Tab( + icon: Icon(Icons.pets), + text: 'My Dino', + ), + Tab( + icon: Icon(Icons.videogame_asset), + text: 'Games', + ), + Tab( + icon: Icon(Icons.wallet), + text: 'Wallet', + ), + Tab( + icon: Icon(Icons.emoji_events), + text: 'Ranking', + ), + ], ), - ), - - // logout card - Card( - child: Padding( - padding: EdgeInsets.all(8), - child: Row( - children: [ - Text('Log Out'), - IconButton( - icon: Icon(Icons.logout), - onPressed: () { - GoRouter.of(context).push("/"); - }, - ) - ], - ), - ), - ), + ], + ), + ), + body: const TabBarView( + children: [ + ComingSoonScreen(), + MiniGamesScreen(), + ComingSoonScreen(), + ComingSoonScreen(), ], ), ), ); + + // Scaffold( + // body: Padding( + // padding: const EdgeInsets.all(16), + // child: ListView( + // children: [ + // // User card + // Card( + // child: Padding( + // padding: const EdgeInsets.all(8), + // child: Column( + // children: [ + // const Text('User'), + // Text(_publicKey == null + // ? 'Loading...' + // : '${_publicKey!.substring(0, 4)}...${_publicKey!.substring(_publicKey!.length - 3, _publicKey!.length)}'), + // Text(_balance ?? 'Loading...'), + // ], + // ), + // ), + // ), + + // // menu card + // Card( + // child: Padding( + // padding: EdgeInsets.all(8), + // child: Column( + // children: [ + // TextButton( + // child: Text('My Dinogrow'), + // onPressed: () { + // // My Dinos button + // }, + // ), + // TextButton( + // child: Text('Mini Games'), + // onPressed: () { + // GoRouter.of(context).push("/mini_games"); + // }, + // ), + // TextButton( + // child: Text('Wallet'), + // onPressed: () { + // // wallet button + // }, + // ), + // TextButton( + // child: Text('Ranking'), + // onPressed: () { + // // Ranking button + // }, + // ) + // ], + // ), + // ), + // ), + + // // logout card + // Card( + // child: Padding( + // padding: EdgeInsets.all(8), + // child: Row( + // children: [ + // Text('Log Out'), + // IconButton( + // icon: Icon(Icons.logout), + // onPressed: () { + // GoRouter.of(context).push("/"); + // }, + // ) + // ], + // ), + // ), + // ), + // ], + // ), + // ), + // ); } void _readPk() async { diff --git a/lib/pages/inputPhrase.dart b/lib/pages/inputPhrase.dart index 02c0757..71d8970 100644 --- a/lib/pages/inputPhrase.dart +++ b/lib/pages/inputPhrase.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; import 'package:bip39/bip39.dart' as bip39; +import 'package:dinogrow/pages/setupPassword.dart'; import '../ui/widgets/widgets.dart'; class InputPhraseScreen extends StatefulWidget { @@ -126,7 +126,14 @@ class _InputPhraseScreenState extends State { String wordsString = _words.join(' '); final t = bip39.validateMnemonic(wordsString); if (t) { - GoRouter.of(context).push("/passwordSetup/$wordsString"); + // GoRouter.of(context).push("/passwordSetup/$wordsString"); + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) { + return SetupPasswordScreen(mnemonic: wordsString); + }, + ); } else { setState(() { validationFailed = true; diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 10573c5..48b3e4a 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; +import '../ui/widgets/widgets.dart'; + class LoginScreen extends StatefulWidget { const LoginScreen({super.key}); @@ -41,73 +43,78 @@ class _LoginScreenState extends State { } return Scaffold( body: SingleChildScrollView( - child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - const SizedBox(height: 40), - Center( - child: Image.asset( - 'assets/images/logo.jpeg', - width: 200, + child: Container( + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, ), ), - const SizedBox(height: 16), - const Padding( - padding: EdgeInsets.only(left: 16), - child: Text( - 'Login', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.bold, - ), - ), - ), - const SizedBox(height: 16), - Form( - key: _formKey, - child: Padding( - padding: const EdgeInsets.all(16.0), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Center( child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - TextFormField( - controller: passwordController, - obscureText: true, - decoration: const InputDecoration( - labelText: 'Password', - border: OutlineInputBorder(), + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 60), + const IntroLogoWidget(), + const SizedBox(height: 30), + const TextBoxWidget( + text: + 'To continue, please enter your current password'), + const SizedBox(height: 16), + Form( + key: _formKey, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextFormField( + controller: passwordController, + obscureText: true, + decoration: InputDecoration( + labelText: 'Password', + filled: true, + fillColor: Colors.black, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + validator: (value) { + if (value != password) { + setState(() { + validationFailed = true; + }); + return; + } + GoRouter.of(context).pushReplacement("/home"); + return null; + // Validation + }), + const SizedBox(height: 8), + Text(validationFailed ? 'Invalid Password' : '', + style: const TextStyle(color: Colors.red)), + const SizedBox(height: 8), + IntroButtonWidget( + text: 'Login', + onPressed: _onSubmit, + ), + const SizedBox(height: 32), + IntroButtonWidget( + text: 'Use different Account', + onPressed: () { + onDifferentAccountPressed(context); + }, + ), + ], ), - validator: (value) { - if (value != password) { - setState(() { - validationFailed = true; - }); - return; - } - GoRouter.of(context).push("/home"); - return null; - // Validation - }), - const SizedBox(height: 8), - Text(validationFailed ? 'Invalid Password' : '', - style: const TextStyle(color: Colors.red)), - const SizedBox(height: 8), - ElevatedButton( - onPressed: _onSubmit, - child: const Text('Login'), - ), - const SizedBox(height: 32), - Center( - child: ElevatedButton( - onPressed: () { - onDifferentAccountPressed(context); - }, - child: const Text('Use different Account'), ), - ), - ], - ), + const SizedBox(height: 60), + ]), ), ), - ]), + ), ), ); } diff --git a/lib/pages/mini-games/mini_games.dart b/lib/pages/mini-games/mini_games.dart index a2641dc..04bb4b4 100644 --- a/lib/pages/mini-games/mini_games.dart +++ b/lib/pages/mini-games/mini_games.dart @@ -1,5 +1,7 @@ +import 'package:dinogrow/ui/widgets/GameCard/game_card.dart'; import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; + +import '../../ui/widgets/widgets.dart'; class MiniGamesScreen extends StatefulWidget { const MiniGamesScreen({Key? key}) : super(key: key); @@ -12,18 +14,32 @@ class _MiniGamesPageState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Mini Games'), + body: Container( + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, + ), + ), + child: const Center( + child: Padding( + padding: EdgeInsets.all(12), + child: Wrap( + spacing: 12, + runSpacing: 12, + alignment: WrapAlignment.center, + children: [ + GameCardWidget( + text: 'UP', + route: "/mini_games/up", + ), + GameCardWidget(text: 'COMING SOON'), + GameCardWidget(text: 'COMING SOON'), + ], + )), ), - body: Center( - child: Column(children: [ - TextButton( - child: const Text('UP GAME'), - onPressed: () { - GoRouter.of(context).push("/mini_games/up"); - }, - ), - ]), - )); + ), + ); } } diff --git a/lib/pages/mini-games/up/up.dart b/lib/pages/mini-games/up/up.dart index 6f8c6e7..288c6b7 100644 --- a/lib/pages/mini-games/up/up.dart +++ b/lib/pages/mini-games/up/up.dart @@ -190,7 +190,7 @@ class GameWidgetUp extends StatelessWidget { leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () { - GoRouter.of(context).push("/mini_games"); + GoRouter.of(context).pop(); }, ), ), diff --git a/lib/pages/setupPassword.dart b/lib/pages/setupPassword.dart index a3f509e..eab971f 100644 --- a/lib/pages/setupPassword.dart +++ b/lib/pages/setupPassword.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; +import '../ui/widgets/widgets.dart'; + class SetupPasswordScreen extends StatefulWidget { final String? mnemonic; SetupPasswordScreen({super.key, required this.mnemonic}); @@ -17,45 +19,55 @@ class _SetupPasswordScreenState extends State { final storage = FlutterSecureStorage(); @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: Text('Set Up Password')), - body: Padding( - padding: EdgeInsets.all(16), - child: Form( - key: formKey, - child: Column( - children: [ - TextFormField( - controller: passwordController, - obscureText: true, - decoration: InputDecoration(labelText: 'Password'), - validator: (value) { - if (value!.isEmpty) { - return 'Password is required'; - } - return null; - }), - const SizedBox(height: 16), - TextFormField( - controller: confirmPasswordController, - obscureText: true, - decoration: - const InputDecoration(labelText: 'Confirm Password'), - validator: (value) { - if (value!.isEmpty) { - return 'Confirm password is required'; - } - if (value != passwordController.text) { - return 'Passwords do not match'; - } - return null; - }), - const SizedBox(height: 16), - ElevatedButton( - onPressed: _submit, - child: Text('Submit'), - ) - ], + return Container( + height: MediaQuery.of(context).size.height * 0.75, + child: Scaffold( + appBar: AppBar( + iconTheme: const IconThemeData(color: Color.fromRGBO(34, 38, 59, 1)), + title: const Text( + 'Set Up Password', + style: TextStyle(color: Color.fromRGBO(34, 38, 59, 1)), + ), + backgroundColor: const Color.fromRGBO(241, 189, 57, 1), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16), + child: Form( + key: formKey, + child: Column(children: [ + TextFormField( + controller: passwordController, + obscureText: true, + decoration: const InputDecoration(labelText: 'Password'), + validator: (value) { + if (value!.isEmpty) { + return 'Password is required'; + } + return null; + }), + const SizedBox(height: 16), + TextFormField( + controller: confirmPasswordController, + obscureText: true, + decoration: + const InputDecoration(labelText: 'Confirm Password'), + validator: (value) { + if (value!.isEmpty) { + return 'Confirm password is required'; + } + if (value != passwordController.text) { + return 'Passwords do not match'; + } + return null; + }), + const SizedBox(height: 42), + IntroButtonWidget( + text: 'Submit', + onPressed: _submit, + ), + ]), + ), ), ), ), diff --git a/lib/ui/widgets/GameCard/game_card.dart b/lib/ui/widgets/GameCard/game_card.dart new file mode 100644 index 0000000..567b5ac --- /dev/null +++ b/lib/ui/widgets/GameCard/game_card.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; + +class GameCardWidget extends StatelessWidget { + final String text; + final String? route; + + const GameCardWidget({ + super.key, + required this.text, + this.route, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + if (route != null) { + GoRouter.of(context).push(route!); + } + }, + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(24), + border: Border.all( + color: const Color.fromRGBO(241, 189, 57, 1), width: 6), + ), + child: Column( + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Image.asset( + 'assets/images/logo.jpeg', + width: 120, + ), + ), + const SizedBox(height: 16), + Text( + text, + style: const TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + fontSize: 18), + ), + ], + ), + ), + ); + } +} diff --git a/lib/ui/widgets/IntroLogo/intro_logo.dart b/lib/ui/widgets/IntroLogo/intro_logo.dart index 0e1993c..422aec8 100644 --- a/lib/ui/widgets/IntroLogo/intro_logo.dart +++ b/lib/ui/widgets/IntroLogo/intro_logo.dart @@ -63,7 +63,7 @@ class _IntroLogoWidgetState extends State borderRadius: BorderRadius.circular(120), child: Image.asset( 'assets/images/logo.jpeg', - width: 240, + width: 210, ), ), ), diff --git a/lib/ui/widgets/widgets.dart b/lib/ui/widgets/widgets.dart index c29a91a..99efd15 100644 --- a/lib/ui/widgets/widgets.dart +++ b/lib/ui/widgets/widgets.dart @@ -2,3 +2,4 @@ export './IntroLogo/intro_logo.dart'; export './IntroButton/intro_button.dart'; export './TextBox/text_box.dart'; export './AppBar/app_bar.dart'; +export './GameCard/game_card.dart'; From ccbdb8e3d3b75bb7906e75087b6632f3a09e9c0f Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Mon, 2 Oct 2023 00:39:51 -0500 Subject: [PATCH 2/8] feat: add log out button and improve gorouter flow --- lib/pages/comingSoon.dart | 19 +++++++++++++++---- lib/pages/login.dart | 4 ++++ lib/pages/mini-games/mini_games.dart | 2 +- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/pages/comingSoon.dart b/lib/pages/comingSoon.dart index fbb6c13..1df9d0a 100644 --- a/lib/pages/comingSoon.dart +++ b/lib/pages/comingSoon.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import '../ui/widgets/widgets.dart'; @@ -15,14 +16,24 @@ class ComingSoonScreen extends StatelessWidget { fit: BoxFit.cover, ), ), - child: const Center( + child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - IntroLogoWidget(), - SizedBox(height: 30), - TextBoxWidget(text: 'Coming soon ^-^'), + const IntroLogoWidget(), + const SizedBox(height: 30), + const TextBoxWidget(text: 'Coming soon ^-^'), + const SizedBox(height: 30), + IntroButtonWidget( + text: 'Log out', + onPressed: () { + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } + GoRouter.of(context).pushReplacement("/"); + }, + ) ]), ), ), diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 48b3e4a..1c9cb0f 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -88,6 +88,10 @@ class _LoginScreenState extends State { }); return; } + + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } GoRouter.of(context).pushReplacement("/home"); return null; // Validation diff --git a/lib/pages/mini-games/mini_games.dart b/lib/pages/mini-games/mini_games.dart index 04bb4b4..fbe7d48 100644 --- a/lib/pages/mini-games/mini_games.dart +++ b/lib/pages/mini-games/mini_games.dart @@ -18,7 +18,7 @@ class _MiniGamesPageState extends State { height: MediaQuery.of(context).size.height, decoration: const BoxDecoration( image: DecorationImage( - image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + image: AssetImage("assets/images/ui/config_jungle_bg.jpg"), fit: BoxFit.cover, ), ), From d63c29548ecb345c8fe9fd2cb4b748e2eda4b616 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 11:16:55 -0500 Subject: [PATCH 3/8] refactor: change styles of tabs in home view --- lib/pages/home.dart | 51 ++++++++++++++++++++++++++++--------------- lib/pages/login.dart | 52 ++++++++++++++++++++++---------------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 38451d6..e933229 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:go_router/go_router.dart'; import 'package:solana/solana.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; @@ -31,54 +30,72 @@ class _HomeScreenState extends State { length: 4, child: Scaffold( appBar: AppBar( - toolbarHeight: 108, + backgroundColor: const Color.fromRGBO(241, 189, 57, 1), + elevation: 6, + toolbarHeight: 120, flexibleSpace: Column( children: [ const SizedBox(height: 38), Card( + color: Colors.white, + shadowColor: Colors.white, + elevation: 9, child: Padding( - padding: const EdgeInsets.all(6), + padding: const EdgeInsets.all(12), child: Row( children: [ const Text( 'Wallet: ', - style: TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, color: Colors.black), ), const SizedBox(width: 3), Expanded( - child: Text(_publicKey == null - ? 'Loading...' - : '${_publicKey!.substring(0, 4)}...${_publicKey!.substring(_publicKey!.length - 3, _publicKey!.length)}')), + child: Text( + _publicKey == null + ? 'Loading...' + : '${_publicKey!.substring(0, 6)}...${_publicKey!.substring(_publicKey!.length - 6, _publicKey!.length)}', + style: const TextStyle(color: Colors.black), + )), const SizedBox(width: 12), const Text( 'Balance: ', - style: TextStyle(fontWeight: FontWeight.bold), + style: TextStyle( + fontWeight: FontWeight.bold, color: Colors.black), ), const SizedBox(width: 3), - Text(_balance ?? 'Loading...'), + Text(_balance ?? 'Loading...', + style: const TextStyle(color: Colors.black)), const SizedBox(width: 3), - const Text('SOL'), + const Text('SOL', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black)), ], ), ), ), const TabBar( + unselectedLabelColor: Color.fromRGBO(34, 38, 59, 1), + labelColor: Colors.white, + indicatorColor: Colors.white, + indicatorSize: TabBarIndicatorSize.tab, tabs: [ - Tab( - icon: Icon(Icons.pets), - text: 'My Dino', - ), Tab( icon: Icon(Icons.videogame_asset), text: 'Games', ), + Tab( + icon: Icon(Icons.emoji_events), + text: 'Ranking', + ), Tab( icon: Icon(Icons.wallet), text: 'Wallet', ), Tab( - icon: Icon(Icons.emoji_events), - text: 'Ranking', + icon: Icon(Icons.pets), + text: 'My Dino', ), ], ), @@ -87,10 +104,10 @@ class _HomeScreenState extends State { ), body: const TabBarView( children: [ - ComingSoonScreen(), MiniGamesScreen(), ComingSoonScreen(), ComingSoonScreen(), + ComingSoonScreen(), ], ), ), diff --git a/lib/pages/login.dart b/lib/pages/login.dart index 1c9cb0f..7ef5a88 100644 --- a/lib/pages/login.dart +++ b/lib/pages/login.dart @@ -71,31 +71,17 @@ class _LoginScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ TextFormField( - controller: passwordController, - obscureText: true, - decoration: InputDecoration( - labelText: 'Password', - filled: true, - fillColor: Colors.black, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), + controller: passwordController, + obscureText: true, + decoration: InputDecoration( + labelText: 'Password', + filled: true, + fillColor: Colors.black, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), ), - validator: (value) { - if (value != password) { - setState(() { - validationFailed = true; - }); - return; - } - - while (GoRouter.of(context).canPop() == true) { - GoRouter.of(context).pop(); - } - GoRouter.of(context).pushReplacement("/home"); - return null; - // Validation - }), + ), + ), const SizedBox(height: 8), Text(validationFailed ? 'Invalid Password' : '', style: const TextStyle(color: Colors.red)), @@ -160,8 +146,22 @@ class _LoginScreenState extends State { } void _onSubmit() async { - if (_formKey.currentState!.validate()) { - _formKey.currentState!.save(); + setState(() { + _loading = true; + }); + if (passwordController.text == password) { + await Future.delayed(const Duration(seconds: 1)); + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } + GoRouter.of(context).pushReplacement("/home"); + } else { + setState(() { + validationFailed = true; + }); + setState(() { + _loading = false; + }); } } } From 9f4881ee3b31c8aaf0061a266416bc71e6519f53 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 12:08:58 -0500 Subject: [PATCH 4/8] feat: create ranking view --- lib/pages/comingSoon.dart | 41 +++---- lib/pages/home.dart | 11 +- lib/pages/ranking/ranking.dart | 102 ++++++++++++++++++ lib/ui/widgets/IntroButton/intro_button.dart | 1 + linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 66 +++++++++++- pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 11 files changed, 208 insertions(+), 25 deletions(-) diff --git a/lib/pages/comingSoon.dart b/lib/pages/comingSoon.dart index 1df9d0a..a625c46 100644 --- a/lib/pages/comingSoon.dart +++ b/lib/pages/comingSoon.dart @@ -16,25 +16,28 @@ class ComingSoonScreen extends StatelessWidget { fit: BoxFit.cover, ), ), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const IntroLogoWidget(), - const SizedBox(height: 30), - const TextBoxWidget(text: 'Coming soon ^-^'), - const SizedBox(height: 30), - IntroButtonWidget( - text: 'Log out', - onPressed: () { - while (GoRouter.of(context).canPop() == true) { - GoRouter.of(context).pop(); - } - GoRouter.of(context).pushReplacement("/"); - }, - ) - ]), + child: Padding( + padding: EdgeInsets.all(12), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const IntroLogoWidget(), + const SizedBox(height: 30), + const TextBoxWidget(text: 'Coming soon ^-^'), + const SizedBox(height: 30), + IntroButtonWidget( + text: 'Log out', + onPressed: () { + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } + GoRouter.of(context).pushReplacement("/"); + }, + ), + ]), + ), ), ), ); diff --git a/lib/pages/home.dart b/lib/pages/home.dart index e933229..12a84dc 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -4,6 +4,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:solana/solana.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; +import 'package:dinogrow/pages/ranking/ranking.dart'; import 'package:dinogrow/pages/comingSoon.dart'; class HomeScreen extends StatefulWidget { @@ -102,12 +103,12 @@ class _HomeScreenState extends State { ], ), ), - body: const TabBarView( + body: TabBarView( children: [ - MiniGamesScreen(), - ComingSoonScreen(), - ComingSoonScreen(), - ComingSoonScreen(), + const MiniGamesScreen(), + RankingScreen(), + const ComingSoonScreen(), + const ComingSoonScreen(), ], ), ), diff --git a/lib/pages/ranking/ranking.dart b/lib/pages/ranking/ranking.dart index e69de29..8777b83 100644 --- a/lib/pages/ranking/ranking.dart +++ b/lib/pages/ranking/ranking.dart @@ -0,0 +1,102 @@ +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../ui/widgets/widgets.dart'; + +class RankingScreen extends StatelessWidget { + RankingScreen({super.key}); + + final List items = List.generate( + 20, + (i) => ItemsProps(wallet: 'User $i', score: (i * 100).toString()), + ); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, + ), + ), + child: Padding( + padding: const EdgeInsets.all(12), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const SizedBox(height: 12), + const TextBoxWidget( + text: + "We'll announce the prizes to each winner on our social networks, please stay connected."), + const SizedBox(height: 12), + const IntroButtonWidget( + text: 'Visit us', + onPressed: _launchUrl, + ), + const SizedBox(height: 12), + Expanded( + child: Container( + padding: const EdgeInsets.only(left: 12, right: 12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(24), + border: Border.all( + color: const Color.fromRGBO(241, 189, 57, 1), + width: 6), + ), + child: ListView.builder( + shrinkWrap: true, + itemCount: items.length, + itemBuilder: (context, index) { + final item = items[index]; + + return ListTile( + leading: index < 3 + ? Icon( + Icons.emoji_events, + color: prizeColors[index], + ) + : null, + title: Text(item.wallet, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black)), + trailing: Text(item.score, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: Colors.black)), + ); + }, + ), + ), + ), + ]), + ), + ), + ), + ); + } +} + +List prizeColors = List.generate( + 3, + (index) => + index == 0 ? Colors.orange : (index == 1 ? Colors.grey : Colors.brown)); + +class ItemsProps { + String wallet; + String score; + + ItemsProps({required this.wallet, required this.score}); +} + +Future _launchUrl() async { + Uri url = Uri(scheme: 'https', host: 'x.com', path: '/din0gr0w'); + if (!await launchUrl(url)) { + throw Exception('Could not launch $url'); + } +} diff --git a/lib/ui/widgets/IntroButton/intro_button.dart b/lib/ui/widgets/IntroButton/intro_button.dart index ecd89b7..52016aa 100644 --- a/lib/ui/widgets/IntroButton/intro_button.dart +++ b/lib/ui/widgets/IntroButton/intro_button.dart @@ -15,6 +15,7 @@ class IntroButtonWidget extends StatelessWidget { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( + minimumSize: const Size.fromHeight(50), backgroundColor: const Color.fromRGBO(241, 189, 57, 1), padding: const EdgeInsets.all(18), shadowColor: Colors.purple, diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index d0e7f79..38dd0bc 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index b29e9ba..65240e9 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_secure_storage_linux + url_launcher_linux ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index e84ed5a..e58cc93 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,7 +6,9 @@ import FlutterMacOS import Foundation import flutter_secure_storage_macos +import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 59d948e..03a6aa8 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -437,6 +437,70 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "47e208a6711459d813ba18af120d9663c20bdf6985d6ad39fe165d2538378d27" + url: "https://pub.dev" + source: hosted + version: "6.1.14" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: b04af59516ab45762b2ca6da40fa830d72d0f6045cd97744450b73493fa76330 + url: "https://pub.dev" + source: hosted + version: "6.1.0" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7c65021d5dee51813d652357bc65b8dd4a6177082a9966bc8ba6ee477baa795f" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: b651aad005e0cb06a01dbd84b428a301916dc75f0e7ea6165f80057fee2d8e8e + url: "https://pub.dev" + source: hosted + version: "3.0.6" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: b55486791f666e62e0e8ff825e58a023fd6b1f71c49926483f1128d3bbd8fe88 + url: "https://pub.dev" + source: hosted + version: "3.0.7" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "95465b39f83bfe95fcb9d174829d6476216f2d548b79c38ab2506e0458787618" + url: "https://pub.dev" + source: hosted + version: "2.1.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: ba140138558fcc3eead51a1c42e92a9fb074a1b1149ed3c73e66035b2ccd94f2 + url: "https://pub.dev" + source: hosted + version: "2.0.19" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: "95fef3129dc7cfaba2bc3d5ba2e16063bb561fc6d78e63eee16162bc70029069" + url: "https://pub.dev" + source: hosted + version: "3.0.8" vector_math: dependency: transitive description: @@ -455,4 +519,4 @@ packages: version: "2.4.0" sdks: dart: ">=3.0.2 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index 1f04663..4157b9b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: flame: ^1.8.2 flame_forge2d: ^0.14.1+1 flutter_joystick: ^0.0.3 + url_launcher: ^6.1.14 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 0c50753..2048c45 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -7,8 +7,11 @@ #include "generated_plugin_registrant.h" #include +#include void RegisterPlugins(flutter::PluginRegistry* registry) { FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 4fc759c..de626cc 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_secure_storage_windows + url_launcher_windows ) list(APPEND FLUTTER_FFI_PLUGIN_LIST From 0a2ff016094e6366231dc269ad28b1c378ea0a55 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 12:33:48 -0500 Subject: [PATCH 5/8] feat: create wallet view --- .../{comingSoon.dart => coming_soon.dart} | 11 ++-- ...neratePhrase.dart => generate_phrase.dart} | 2 +- lib/pages/home.dart | 23 ++++--- .../{inputPhrase.dart => input_phrase.dart} | 0 lib/pages/mini-games/mini_games.dart | 8 +-- lib/pages/ranking/ranking.dart | 9 +-- .../{setupAccount.dart => setup_account.dart} | 0 ...setupPassword.dart => setup_password.dart} | 0 lib/pages/wallet/wallet.dart | 61 +++++++++++++++++++ lib/ui/widgets/IntroButton/intro_button.dart | 4 +- 10 files changed, 90 insertions(+), 28 deletions(-) rename lib/pages/{comingSoon.dart => coming_soon.dart} (80%) rename lib/pages/{generatePhrase.dart => generate_phrase.dart} (95%) rename lib/pages/{inputPhrase.dart => input_phrase.dart} (100%) rename lib/pages/{setupAccount.dart => setup_account.dart} (100%) rename lib/pages/{setupPassword.dart => setup_password.dart} (100%) diff --git a/lib/pages/comingSoon.dart b/lib/pages/coming_soon.dart similarity index 80% rename from lib/pages/comingSoon.dart rename to lib/pages/coming_soon.dart index a625c46..8506437 100644 --- a/lib/pages/comingSoon.dart +++ b/lib/pages/coming_soon.dart @@ -9,15 +9,12 @@ class ComingSoonScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: Colors.transparent, body: Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/ui/intro_jungle_bg.png"), - fit: BoxFit.cover, - ), - ), + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration(color: Colors.transparent), child: Padding( - padding: EdgeInsets.all(12), + padding: const EdgeInsets.all(12), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, diff --git a/lib/pages/generatePhrase.dart b/lib/pages/generate_phrase.dart similarity index 95% rename from lib/pages/generatePhrase.dart rename to lib/pages/generate_phrase.dart index 498e060..604fa7d 100644 --- a/lib/pages/generatePhrase.dart +++ b/lib/pages/generate_phrase.dart @@ -3,7 +3,7 @@ import 'package:flutter/services.dart'; import 'package:bip39/bip39.dart' as bip39; import 'package:go_router/go_router.dart'; -import 'package:dinogrow/pages/setupPassword.dart'; +import 'package:dinogrow/pages/setup_password.dart'; import '../ui/widgets/widgets.dart'; class GeneratePhraseScreen extends StatefulWidget { diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 12a84dc..1ecac8f 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -5,6 +5,7 @@ import 'package:solana/solana.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; import 'package:dinogrow/pages/ranking/ranking.dart'; +import 'package:dinogrow/pages/wallet/wallet.dart'; import 'package:dinogrow/pages/comingSoon.dart'; class HomeScreen extends StatefulWidget { @@ -103,13 +104,21 @@ class _HomeScreenState extends State { ], ), ), - body: TabBarView( - children: [ - const MiniGamesScreen(), - RankingScreen(), - const ComingSoonScreen(), - const ComingSoonScreen(), - ], + body: Container( + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, + ), + ), + child: TabBarView( + children: [ + const MiniGamesScreen(), + RankingScreen(), + WalletScreen(address: _publicKey, balance: _balance), + const ComingSoonScreen(), + ], + ), ), ), ); diff --git a/lib/pages/inputPhrase.dart b/lib/pages/input_phrase.dart similarity index 100% rename from lib/pages/inputPhrase.dart rename to lib/pages/input_phrase.dart diff --git a/lib/pages/mini-games/mini_games.dart b/lib/pages/mini-games/mini_games.dart index fbe7d48..c56073e 100644 --- a/lib/pages/mini-games/mini_games.dart +++ b/lib/pages/mini-games/mini_games.dart @@ -14,14 +14,10 @@ class _MiniGamesPageState extends State { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: Colors.transparent, body: Container( height: MediaQuery.of(context).size.height, - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/ui/config_jungle_bg.jpg"), - fit: BoxFit.cover, - ), - ), + decoration: const BoxDecoration(color: Colors.transparent), child: const Center( child: Padding( padding: EdgeInsets.all(12), diff --git a/lib/pages/ranking/ranking.dart b/lib/pages/ranking/ranking.dart index 8777b83..53c3fd4 100644 --- a/lib/pages/ranking/ranking.dart +++ b/lib/pages/ranking/ranking.dart @@ -14,13 +14,10 @@ class RankingScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + backgroundColor: Colors.transparent, body: Container( - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/images/ui/intro_jungle_bg.png"), - fit: BoxFit.cover, - ), - ), + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration(color: Colors.transparent), child: Padding( padding: const EdgeInsets.all(12), child: Center( diff --git a/lib/pages/setupAccount.dart b/lib/pages/setup_account.dart similarity index 100% rename from lib/pages/setupAccount.dart rename to lib/pages/setup_account.dart diff --git a/lib/pages/setupPassword.dart b/lib/pages/setup_password.dart similarity index 100% rename from lib/pages/setupPassword.dart rename to lib/pages/setup_password.dart diff --git a/lib/pages/wallet/wallet.dart b/lib/pages/wallet/wallet.dart index e69de29..44faef3 100644 --- a/lib/pages/wallet/wallet.dart +++ b/lib/pages/wallet/wallet.dart @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../ui/widgets/widgets.dart'; + +class WalletScreen extends StatelessWidget { + final String? address; + final String? balance; + + const WalletScreen({super.key, this.address, this.balance}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.transparent, + body: Container( + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration(color: Colors.transparent), + child: Padding( + padding: const EdgeInsets.all(12), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Row(children: [ + Expanded( + child: TextBoxWidget(text: 'Your address: $address')), + const SizedBox(width: 12), + IntroButtonWidget( + text: 'Copy', + onPressed: () { + Clipboard.setData(ClipboardData(text: address ?? '')); + const snackBar = SnackBar( + content: Text('Copied!'), + ); + + ScaffoldMessenger.of(context).showSnackBar(snackBar); + }, + size: 'fit', + ) + ]), + const SizedBox(height: 30), + Row(children: [ + Expanded( + child: TextBoxWidget(text: 'Balace: $balance SOL')), + const SizedBox(width: 12), + IntroButtonWidget( + text: 'Send', + onPressed: () {}, + size: 'fit', + ) + ]), + const SizedBox(height: 30), + ]), + ), + ), + ), + ); + } +} diff --git a/lib/ui/widgets/IntroButton/intro_button.dart b/lib/ui/widgets/IntroButton/intro_button.dart index 52016aa..55655c4 100644 --- a/lib/ui/widgets/IntroButton/intro_button.dart +++ b/lib/ui/widgets/IntroButton/intro_button.dart @@ -3,11 +3,13 @@ import 'package:flutter/material.dart'; class IntroButtonWidget extends StatelessWidget { final VoidCallback? onPressed; final String text; + final String? size; const IntroButtonWidget({ super.key, this.onPressed, required this.text, + this.size, }); @override @@ -15,7 +17,7 @@ class IntroButtonWidget extends StatelessWidget { return ElevatedButton( onPressed: onPressed, style: ElevatedButton.styleFrom( - minimumSize: const Size.fromHeight(50), + minimumSize: size == 'fit' ? null : const Size.fromHeight(50), backgroundColor: const Color.fromRGBO(241, 189, 57, 1), padding: const EdgeInsets.all(18), shadowColor: Colors.purple, From 3dc5a1fa40a95240ca68053d6453ca0060773109 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 13:23:29 -0500 Subject: [PATCH 6/8] feat: create my dino view --- lib/main.dart | 8 +-- lib/pages/coming_soon.dart | 12 +++- lib/pages/home.dart | 5 +- lib/pages/my-dinogrow/my_dinogrow.dart | 92 ++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 7 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 9bc9db9..4366e97 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,12 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; -import 'package:dinogrow/pages/generatePhrase.dart'; +import 'package:dinogrow/pages/generate_phrase.dart'; import 'package:dinogrow/pages/home.dart'; -import 'package:dinogrow/pages/inputPhrase.dart'; +import 'package:dinogrow/pages/input_phrase.dart'; import 'package:dinogrow/pages/login.dart'; -import 'package:dinogrow/pages/setupAccount.dart'; -import 'package:dinogrow/pages/setupPassword.dart'; +import 'package:dinogrow/pages/setup_account.dart'; +import 'package:dinogrow/pages/setup_password.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; import 'package:dinogrow/pages/mini-games/up/up.dart'; diff --git a/lib/pages/coming_soon.dart b/lib/pages/coming_soon.dart index 8506437..3794cff 100644 --- a/lib/pages/coming_soon.dart +++ b/lib/pages/coming_soon.dart @@ -1,9 +1,11 @@ -import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; +import 'package:flutter/material.dart'; import '../ui/widgets/widgets.dart'; class ComingSoonScreen extends StatelessWidget { + final storage = const FlutterSecureStorage(); const ComingSoonScreen({super.key}); @override @@ -39,4 +41,12 @@ class ComingSoonScreen extends StatelessWidget { ), ); } + + void logout(BuildContext context) async { + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } + GoRouter.of(context).pushReplacement("/"); + // await storage.delete(key: 'mnemonic'); + } } diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 1ecac8f..2a43c6f 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -3,10 +3,11 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:solana/solana.dart'; +import 'package:dinogrow/pages/my-dinogrow/my_dinogrow.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; import 'package:dinogrow/pages/ranking/ranking.dart'; import 'package:dinogrow/pages/wallet/wallet.dart'; -import 'package:dinogrow/pages/comingSoon.dart'; +// import 'package:dinogrow/pages/coming_soon.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @@ -116,7 +117,7 @@ class _HomeScreenState extends State { const MiniGamesScreen(), RankingScreen(), WalletScreen(address: _publicKey, balance: _balance), - const ComingSoonScreen(), + const MydinogrowScreen(), ], ), ), diff --git a/lib/pages/my-dinogrow/my_dinogrow.dart b/lib/pages/my-dinogrow/my_dinogrow.dart index e69de29..cec22f6 100644 --- a/lib/pages/my-dinogrow/my_dinogrow.dart +++ b/lib/pages/my-dinogrow/my_dinogrow.dart @@ -0,0 +1,92 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:go_router/go_router.dart'; +import 'package:flutter/material.dart'; + +import '../../ui/widgets/widgets.dart'; + +class MydinogrowScreen extends StatefulWidget { + const MydinogrowScreen({super.key}); + + @override + State createState() => _MydinogrowScreenState(); +} + +class _MydinogrowScreenState extends State { + final storage = const FlutterSecureStorage(); + final mintContent = (_onClaim) => [ + const IntroLogoWidget(), + const SizedBox(height: 30), + IntroButtonWidget( + text: 'Claim your Dino', + onPressed: _onClaim, + ), + const SizedBox(height: 30), + Container( + color: Colors.orange[700], + padding: const EdgeInsets.all(8), + child: const Text( + 'Wait ... you must to have a Dino to start play our games, so "Claim your Dino" is our last step to auto-generate your first NFT free!', + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), + textAlign: TextAlign.center, + ), + ) + ]; + + final myDinosContent = [ + const GameCardWidget( + text: 'Mini Dino', + route: "/mini_games/up", + ), + const SizedBox(height: 30), + const TextBoxWidget(text: "Hi ^.^ I'm Mini Dino"), + ]; + + bool showDinos = false; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.transparent, + body: Container( + height: MediaQuery.of(context).size.height, + decoration: const BoxDecoration(color: Colors.transparent), + child: Padding( + padding: const EdgeInsets.all(12), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ...(showDinos ? myDinosContent : mintContent(onClaim)), + const SizedBox(height: 30), + IntroButtonWidget( + text: 'Log out', + onPressed: () => logout(context), + size: 'fit', + ) + ]), + ), + ), + ), + ); + } + + void logout(BuildContext context) async { + while (GoRouter.of(context).canPop() == true) { + GoRouter.of(context).pop(); + } + GoRouter.of(context).pushReplacement("/"); + // await storage.delete(key: 'mnemonic'); + } + + void onClaim() { + setState(() { + showDinos = true; + }); + } +} From 8c7732c72d1a2906c9da38dbf321e934082d1543 Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 14:03:46 -0500 Subject: [PATCH 7/8] feat: generate random image colors in my dino --- lib/main.dart | 6 ++ lib/pages/home.dart | 1 - lib/pages/{ => mini-games}/coming_soon.dart | 18 +++--- lib/pages/mini-games/mini_games.dart | 10 ++- lib/pages/my-dinogrow/my_dinogrow.dart | 71 ++++++++++++++++++--- lib/pages/ranking/ranking.dart | 3 + 6 files changed, 88 insertions(+), 21 deletions(-) rename lib/pages/{ => mini-games}/coming_soon.dart (74%) diff --git a/lib/main.dart b/lib/main.dart index 4366e97..313925f 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,6 +9,7 @@ import 'package:dinogrow/pages/setup_account.dart'; import 'package:dinogrow/pages/setup_password.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; import 'package:dinogrow/pages/mini-games/up/up.dart'; +import 'package:dinogrow/pages/mini-games/coming_soon.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); @@ -59,6 +60,11 @@ final GoRouter _router = GoRouter(routes: [ builder: (context, state) { return GameWidgetUp(game: UpGame()); }), + GoRoute( + path: '/mini_games/comming_soon', + builder: (context, state) { + return const ComingSoonScreen(); + }), ]); class MyApp extends StatelessWidget { diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 2a43c6f..46facfd 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -7,7 +7,6 @@ import 'package:dinogrow/pages/my-dinogrow/my_dinogrow.dart'; import 'package:dinogrow/pages/mini-games/mini_games.dart'; import 'package:dinogrow/pages/ranking/ranking.dart'; import 'package:dinogrow/pages/wallet/wallet.dart'; -// import 'package:dinogrow/pages/coming_soon.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); diff --git a/lib/pages/coming_soon.dart b/lib/pages/mini-games/coming_soon.dart similarity index 74% rename from lib/pages/coming_soon.dart rename to lib/pages/mini-games/coming_soon.dart index 3794cff..8a4b493 100644 --- a/lib/pages/coming_soon.dart +++ b/lib/pages/mini-games/coming_soon.dart @@ -2,7 +2,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:flutter/material.dart'; -import '../ui/widgets/widgets.dart'; +import '../../ui/widgets/widgets.dart'; class ComingSoonScreen extends StatelessWidget { final storage = const FlutterSecureStorage(); @@ -11,10 +11,14 @@ class ComingSoonScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: Colors.transparent, body: Container( height: MediaQuery.of(context).size.height, - decoration: const BoxDecoration(color: Colors.transparent), + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage("assets/images/ui/intro_jungle_bg.png"), + fit: BoxFit.cover, + ), + ), child: Padding( padding: const EdgeInsets.all(12), child: Center( @@ -27,13 +31,11 @@ class ComingSoonScreen extends StatelessWidget { const TextBoxWidget(text: 'Coming soon ^-^'), const SizedBox(height: 30), IntroButtonWidget( - text: 'Log out', + text: 'Return', onPressed: () { - while (GoRouter.of(context).canPop() == true) { - GoRouter.of(context).pop(); - } - GoRouter.of(context).pushReplacement("/"); + GoRouter.of(context).pop(); }, + size: 'fit', ), ]), ), diff --git a/lib/pages/mini-games/mini_games.dart b/lib/pages/mini-games/mini_games.dart index c56073e..005af61 100644 --- a/lib/pages/mini-games/mini_games.dart +++ b/lib/pages/mini-games/mini_games.dart @@ -30,8 +30,14 @@ class _MiniGamesPageState extends State { text: 'UP', route: "/mini_games/up", ), - GameCardWidget(text: 'COMING SOON'), - GameCardWidget(text: 'COMING SOON'), + GameCardWidget( + text: 'COMING SOON', + route: "/mini_games/comming_soon", + ), + GameCardWidget( + text: 'COMING SOON', + route: "/mini_games/comming_soon", + ), ], )), ), diff --git a/lib/pages/my-dinogrow/my_dinogrow.dart b/lib/pages/my-dinogrow/my_dinogrow.dart index cec22f6..e19e8b4 100644 --- a/lib/pages/my-dinogrow/my_dinogrow.dart +++ b/lib/pages/my-dinogrow/my_dinogrow.dart @@ -13,7 +13,15 @@ class MydinogrowScreen extends StatefulWidget { class _MydinogrowScreenState extends State { final storage = const FlutterSecureStorage(); - final mintContent = (_onClaim) => [ + final filters = [ + Colors.white, + ...List.generate( + Colors.primaries.length, + (index) => Colors.primaries[(index * 4) % Colors.primaries.length], + ) + ]; + + List mintContent(_onClaim) => [ const IntroLogoWidget(), const SizedBox(height: 30), IntroButtonWidget( @@ -32,14 +40,34 @@ class _MydinogrowScreenState extends State { ) ]; - final myDinosContent = [ - const GameCardWidget( - text: 'Mini Dino', - route: "/mini_games/up", - ), - const SizedBox(height: 30), - const TextBoxWidget(text: "Hi ^.^ I'm Mini Dino"), - ]; + List myDinosContent(returnImageColorFc) => [ + SizedBox( + height: 90, + child: ListView.builder( + scrollDirection: Axis.horizontal, + shrinkWrap: true, + itemCount: 12, + itemBuilder: (context, index) { + // final item = items[index]; + + return Container( + margin: const EdgeInsets.only(right: 12), + child: ClipRRect( + borderRadius: BorderRadius.circular(45), + child: returnImageColorFc(index), + ), + ); + }, + ), + ), + const SizedBox(height: 30), + const GameCardWidget( + text: 'Mini Dino', + route: "/mini_games/up", + ), + const SizedBox(height: 30), + const TextBoxWidget(text: "Hi ^.^ I'm Mini Dino"), + ]; bool showDinos = false; @@ -62,7 +90,9 @@ class _MydinogrowScreenState extends State { mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - ...(showDinos ? myDinosContent : mintContent(onClaim)), + ...(showDinos + ? myDinosContent(returnImageColor) + : mintContent(onClaim)), const SizedBox(height: 30), IntroButtonWidget( text: 'Log out', @@ -89,4 +119,25 @@ class _MydinogrowScreenState extends State { showDinos = true; }); } + + Image returnImageColor(int index) { + if (index == 0) { + return Image.asset( + 'assets/images/logo.jpeg', + width: 90, + height: 90, + fit: BoxFit.cover, + colorBlendMode: BlendMode.color, + ); + } + + return Image.asset( + 'assets/images/logo.jpeg', + width: 90, + height: 90, + fit: BoxFit.cover, + colorBlendMode: BlendMode.color, + color: filters[index], + ); + } } diff --git a/lib/pages/ranking/ranking.dart b/lib/pages/ranking/ranking.dart index 53c3fd4..18def6c 100644 --- a/lib/pages/ranking/ranking.dart +++ b/lib/pages/ranking/ranking.dart @@ -49,6 +49,9 @@ class RankingScreen extends StatelessWidget { shrinkWrap: true, itemCount: items.length, itemBuilder: (context, index) { + items.sort((a, b) => double.parse(b.score) + .compareTo(double.parse(a.score))); + final item = items[index]; return ListTile( From 23af61c1d0b25a2529e785e2e2af1d6e93355e2f Mon Sep 17 00:00:00 2001 From: Dan Lopez Date: Thu, 5 Oct 2023 15:20:38 -0500 Subject: [PATCH 8/8] refactor: change readme and some texts in home and my dino screens --- README.md | 82 ++++++++++++++++++++--- lib/pages/home.dart | 90 ++------------------------ lib/pages/input_phrase.dart | 2 +- lib/pages/my-dinogrow/my_dinogrow.dart | 2 +- 4 files changed, 81 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 855dae8..0a018da 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,80 @@ -# dinogrow +# DINOGROW -A new Flutter project. +![DINOGROW Logo](https://github.com/sistemaseltigre/dinogrow/raw/master/assets/images/logo.jpeg) + +DINOGROW is an exciting mobile game developed in Flutter that combines the fun of dinosaur games with the power of the Solana blockchain. In this game, players can create a new wallet on the Solana blockchain as their in-game identity, allowing them to interact with the blockchain quickly and transparently. + +## Key Features + +- Solana Login: Players can log in to the game and generate a new wallet on the Solana blockchain, which acts as their avatar in the game. +- NFTs and Paid Games: Players who own NFTs can participate in paid matches and compete for rewards. Rewards are divided among the top 3 players on the leaderboard every 24 hours. +- Offline Mode: DINOGROW allows players to enjoy the game without an internet connection. You can play anywhere and decide when to synchronize blockchain transactions later. +- Dinosaur Games: The project focuses on creating a series of dinosaur mini-games that interact with the Solana blockchain, providing a unique gaming experience. + +## Objectives + +- Hackathon Participation: Our main goal is to develop at least one dinosaur mini-game before the end of the Solana Hyperdrive Hackathon. + +- Open Source: This project is entirely open source. Anyone can download and use it as a foundation for creating their own mobile blockchain game. We are using Flutter and Flutter Flame, along with the Solana and Solana Web3 libraries to ensure functionality and stability. + +## Quicknode Integration + +In this project, we utilize Quicknode and its NFT API to seamlessly access Solana NFTs. Quicknode provides a fast and easy way to interact with the Solana blockchain, enhancing the user experience. + +## Set up .env + +Create a .env File: You need to create a .env file at the root of your project directory. This file should contain the following two environment variables: +QUICKNODE_RPC_URL and QUICKNODE_RPC_WSS with the appropriate RPC URL and WebSocket URL that you want to use. + +```bash +QUICKNODE_RPC_URL=https://your-quicknode-rpc-url.com +QUICKNODE_RPC_WSS=wss://your-quicknode-websocket-url.com +``` + +Note: These settings will enable your application to connect to Quicknode's Solana API for NFT functionality. If you use other RPCs, obtaining data from the nft may not work the same way. + +Example .env content: ## Getting Started -This project is a starting point for a Flutter application. +If you want to try DINOGROW or contribute to the project, follow these steps: + +- Clone the Repository: Clone this repository to your local machine using the following command: + +```bash + git clone https://github.com/YourUsername/DINOGROW.git +``` + +- Install Dependencies: Make sure you have Flutter and the Solana and Solana Web3 libraries installed. Then, install the project's dependencies: + +```bash + flutter pub get +``` + +- Run the Game: Start the game on your device or emulator with the following command: + +```bash + flutter run +``` + +## Contributions + +We welcome contributions from the community! If you'd like to collaborate on the project, please follow these guidelines: + +Fork the repository. +Make your changes in a new branch. +Submit a pull request (PR) describing your changes concisely. + +## License + +This project is licensed under the MIT License. See the LICENSE file for more details. + +## Contact + +If you have any questions or suggestions, feel free to contact us: -A few resources to get you started if this is your first Flutter project: +Email: dinogrow@​yahoo.com -- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) +Twitter: @DIN0GR0W -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. +We hope you enjoy DINOGROW, and we hope this project inspires others to create mobile SOLANA blockchain games. Have fun playing and developing! diff --git a/lib/pages/home.dart b/lib/pages/home.dart index 46facfd..c49f1c5 100644 --- a/lib/pages/home.dart +++ b/lib/pages/home.dart @@ -47,7 +47,7 @@ class _HomeScreenState extends State { child: Row( children: [ const Text( - 'Wallet: ', + 'User: ', style: TextStyle( fontWeight: FontWeight.bold, color: Colors.black), ), @@ -91,14 +91,14 @@ class _HomeScreenState extends State { icon: Icon(Icons.emoji_events), text: 'Ranking', ), - Tab( - icon: Icon(Icons.wallet), - text: 'Wallet', - ), Tab( icon: Icon(Icons.pets), text: 'My Dino', ), + Tab( + icon: Icon(Icons.wallet), + text: 'Wallet', + ), ], ), ], @@ -115,91 +115,13 @@ class _HomeScreenState extends State { children: [ const MiniGamesScreen(), RankingScreen(), - WalletScreen(address: _publicKey, balance: _balance), const MydinogrowScreen(), + WalletScreen(address: _publicKey, balance: _balance), ], ), ), ), ); - - // Scaffold( - // body: Padding( - // padding: const EdgeInsets.all(16), - // child: ListView( - // children: [ - // // User card - // Card( - // child: Padding( - // padding: const EdgeInsets.all(8), - // child: Column( - // children: [ - // const Text('User'), - // Text(_publicKey == null - // ? 'Loading...' - // : '${_publicKey!.substring(0, 4)}...${_publicKey!.substring(_publicKey!.length - 3, _publicKey!.length)}'), - // Text(_balance ?? 'Loading...'), - // ], - // ), - // ), - // ), - - // // menu card - // Card( - // child: Padding( - // padding: EdgeInsets.all(8), - // child: Column( - // children: [ - // TextButton( - // child: Text('My Dinogrow'), - // onPressed: () { - // // My Dinos button - // }, - // ), - // TextButton( - // child: Text('Mini Games'), - // onPressed: () { - // GoRouter.of(context).push("/mini_games"); - // }, - // ), - // TextButton( - // child: Text('Wallet'), - // onPressed: () { - // // wallet button - // }, - // ), - // TextButton( - // child: Text('Ranking'), - // onPressed: () { - // // Ranking button - // }, - // ) - // ], - // ), - // ), - // ), - - // // logout card - // Card( - // child: Padding( - // padding: EdgeInsets.all(8), - // child: Row( - // children: [ - // Text('Log Out'), - // IconButton( - // icon: Icon(Icons.logout), - // onPressed: () { - // GoRouter.of(context).push("/"); - // }, - // ) - // ], - // ), - // ), - // ), - // ], - // ), - // ), - // ); } void _readPk() async { diff --git a/lib/pages/input_phrase.dart b/lib/pages/input_phrase.dart index 71d8970..0c1e543 100644 --- a/lib/pages/input_phrase.dart +++ b/lib/pages/input_phrase.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:bip39/bip39.dart' as bip39; -import 'package:dinogrow/pages/setupPassword.dart'; +import 'package:dinogrow/pages/setup_password.dart'; import '../ui/widgets/widgets.dart'; class InputPhraseScreen extends StatefulWidget { diff --git a/lib/pages/my-dinogrow/my_dinogrow.dart b/lib/pages/my-dinogrow/my_dinogrow.dart index e19e8b4..61e7f68 100644 --- a/lib/pages/my-dinogrow/my_dinogrow.dart +++ b/lib/pages/my-dinogrow/my_dinogrow.dart @@ -33,7 +33,7 @@ class _MydinogrowScreenState extends State { color: Colors.orange[700], padding: const EdgeInsets.all(8), child: const Text( - 'Wait ... you must to have a Dino to start play our games, so "Claim your Dino" is our last step to auto-generate your first NFT free!', + 'Wait ... you must to have a Dino to start play our games, so "Claim your Dino" is our last step to auto-generate your first NFT!', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), textAlign: TextAlign.center, ),