import 'package:animated_text_kit/animated_text_kit.dart'; import 'package:fhub/backend/DataManager.dart'; import 'package:fhub/backend/DebugHelper.dart'; import 'package:fhub/backend/Dialogs.dart'; import 'package:fhub/gameInfo.dart'; import 'package:fhub/src/CustomWidgets.dart'; import 'package:fhub/welcome.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'backend/helpers.dart'; class Home extends StatefulWidget { const Home({Key? key}) : super(key: key); @override State createState() => _HomeState(); } class _HomeState extends State { @override void initState() { // TODO: implement initState super.initState(); kickstartAnimations(); } void kickstartAnimations() async { await Future.delayed(const Duration(milliseconds: 500)); setState(() { op1 = 1; op2 = 1; op3 = 1; }); } int selectedPageId = 0; String TitleText = "Home"; @override Widget build(BuildContext context) { final screenHeight = MediaQuery.of(context).size.height; final screenWidth = MediaQuery.of(context).size.width; return Scaffold( backgroundColor: Colors.black, extendBody: true, body: SafeArea( child: CustomBody( context: context, onAnimEnd: () { setState(() {}); }, bottomNav: [ BottomNavBarItem( icon: Icons.home, active: selectedPageId == 0, onPressed: () { setState(() { TitleText = "Home"; selectedPageId = 0; }); }, ), BottomNavBarItem( icon: Icons.gamepad_outlined, active: selectedPageId == 3, onPressed: () { setState(() { TitleText = "Games"; selectedPageId = 3; }); }), BottomNavBarItem( icon: Icons.wallet, active: selectedPageId == 1, onPressed: () { setState(() { TitleText = "Wallet"; selectedPageId = 1; }); }), BottomNavBarItem( icon: Icons.settings, active: selectedPageId == 2, onPressed: () { setState(() { TitleText = "Settings"; selectedPageId = 2; }); }), ], child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16), child: Column(children: [ Center( child: AnimatedSwitcher( duration: Duration(milliseconds: 300), transitionBuilder: (Widget child, Animation animation) { return FadeTransition( child: child, opacity: Tween(begin: 0, end: 1).animate(animation)); }, child: GradientText( key: ValueKey(TitleText), text: TitleText, gradient: LinearGradient(colors: [ Colors.white.withOpacity(0.6), Colors.white.withOpacity(0.5), Colors.white.withOpacity(0.2) ]), style: TextStyle(fontSize: 45, fontWeight: FontWeight.bold), ), )), Padding( padding: const EdgeInsets.symmetric(vertical: 20), child: GetCurrentBody(), ) ]), ), ), )), ); } Widget GetCurrentBody() { switch (selectedPageId) { case 1: return wallet(); case 3: return games(); case 2: return settings(); default: return home(); } } double screenHeight = 0; double screenWidth = 0; Widget home() { screenHeight = MediaQuery.of(context).size.height; screenWidth = MediaQuery.of(context).size.width; return Column( children: [ InkWell( onTap: () { selectedPageId = 1; setState(() {}); }, child: TotalEarningsCard()), SizedBox( height: 30, ), GlassCard( child: Container( width: screenWidth * 0.9, padding: EdgeInsets.all(20), child: SingleChildScrollView( child: Column( children: [ Text("Challenges"), SizedBox( height: 20, ), (DataManager.Challenges.length > 0) ? ListView.builder( physics: NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: DataManager.Challenges.length, itemBuilder: (BuildContext context, int index) { dynamic gameJson = Helpers.GetGameFromCode( DataManager.Challenges[index][0]['game'] ?? 'spaceio'); return ChallengeList( gameName: gameJson['name'], coin: gameJson['coin'], challengesInfo: [ ListView.builder( physics: NeverScrollableScrollPhysics(), shrinkWrap: true, itemCount: DataManager.Challenges[index].length, itemBuilder: (BuildContext context, int index2) { return ChallengeProgress(DataManager .Challenges[index][index2]); }, ) ]); }, ) : Column( children: [ Text( "\nComplete Challenges in Games and\n EARN CRYPTO!\n\nLink a Game to receive Challenges!", textAlign: TextAlign.center, ), SizedBox(height: 20), GlassButton( color: Colors.lightBlueAccent, onTap: () { setState(() { selectedPageId = 3; }); }, child: Text( "Get Started!", style: TextStyle( fontWeight: FontWeight.w500, fontSize: 17), ), width: 200, height: 40) ], ) ], ), ), ), ) ], ); } Widget games() { return Column( children: [ Align(alignment: Alignment.topLeft, child: Text("Linked Games")), SizedBox( height: 10, ), (DataManager.LinkedGamesJson.length > 0) ? GridView.builder( shrinkWrap: true, itemCount: DataManager.LinkedGamesJson.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10.0, mainAxisSpacing: 10.0), itemBuilder: (BuildContext context, int index) { return GameCard( list: DataManager.LinkedGamesJson, index: index); }, ) : GlassCard( child: Padding( padding: const EdgeInsets.all(15.0), child: Text( "Install a game from the list below and Link it to FaucetHub(FH) to Start Earning!",style: TextStyle(color: Colors.blue.withGreen(150).withRed(100)), textAlign: TextAlign.center, ), )), SizedBox( height: 25, ), Align(alignment: Alignment.topLeft, child: Text("Non-Linked Games")), SizedBox( height: 10, ), GridView.builder( shrinkWrap: true, itemCount: DataManager.NonLinkedGamesJson.length, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10.0, mainAxisSpacing: 10.0), itemBuilder: (BuildContext context, int index) { return GameCard(list: DataManager.NonLinkedGamesJson, index: index); }, ) ], ); } Widget GameCard({required int index, required List list}) { return GlassCard( child: InkWell( onTap: () { Navigator.of(context).push(MaterialPageRoute( builder: (BuildContext context) => GameInfoPage(gameJson: list[index]))); }, child: Container( padding: EdgeInsets.all(12), child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( list[index]['name'], style: TextStyle(fontSize: 16), ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Container( width: 50, child: ClipRRect( borderRadius: BorderRadius.circular(10), child: Image.network(list[index]['icon']))), Icon(Helpers.GetIconForCrypto(list[index]['coin'])) ], ), Text(list[index]['description'], style: TextStyle(fontSize: 13)), ], ), ), )); } Widget TotalEarningsCard() { return GlassCard( child: Container( // height: screenHeight * 0.18, width: screenWidth * 0.9, padding: EdgeInsets.all(20), child: Column( children: [ Text("Total Earnings"), SizedBox( height: 10, ), Text('~ \$${DataManager.currentEarnings.toStringAsFixed(2)} ', style: TextStyle(fontSize: 50)), ], ), ), ); } ScrollController scrollController = ScrollController(); bool sortByGames = true; Widget wallet() { return Column( children: [ TotalEarningsCard(), (DataManager.currentEarnings <=0) ? Container() : Column(children: [ SizedBox( height: 30, ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text("Sort earnings by "), SizedBox( width: 20, ), GlassCard( child: Padding( padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 15), child: Row( children: [ InkWell( onTap: () { setState(() { sortByGames = true; }); }, child: GlassCard( highlighted: sortByGames, child: Padding( padding: EdgeInsets.symmetric( vertical: 8, horizontal: 20), child: Text("Games"), ))), SizedBox( width: 5, ), InkWell( onTap: () { setState(() { sortByGames = false; }); }, child: GlassCard( highlighted: !sortByGames, child: Padding( padding: EdgeInsets.symmetric( vertical: 8, horizontal: 20), child: Text("Earnings"), ))), ], ), )) ], ), SizedBox( height: 10, ), GlassCard( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( children: [ sortByGames ? ListView.builder( shrinkWrap: true, controller: scrollController, itemCount: DataManager.GamesEarnings.length, itemBuilder: (BuildContext context, int index) { String gameName = DataManager.GamesEarnings.keys.elementAt(index); dynamic GameJson = Helpers.GetGameFromCode(gameName); if (GameJson == null) { Debug.LogError( ("Error getting game json from ${gameName}. returned:\n$GameJson")); return GlassCard( child: Padding( padding: EdgeInsets.all(16), child: Text( "Error", textAlign: TextAlign.center, ), )); } double amount = Helpers.SatsToCoin(DataManager .GamesEarnings.values .elementAt(index)); return WalletGameListItem(GameJson, amount); }) : ListView.builder( shrinkWrap: true, controller: scrollController, itemCount: DataManager.CryptoEarnings.length, itemBuilder: (BuildContext context, int index) { return WalletCurrencyListItem( DataManager.CryptoEarnings.keys.elementAt(index)); }, ) ], ), )) ]) ], ); } Widget WalletGameListItem(dynamic GameJson, double amount) { return Padding( padding: const EdgeInsets.all(3.0), child: GlassCard( child: Container( padding: const EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [SizedBox(width: 100, child: Text(GameJson['name']))], ), Text( "~\$${Helpers.CryptoToDollars(amount: amount, Crypto: GameJson['coin']).toStringAsFixed(2)}"), Row( children: [ Text("${amount.toStringAsFixed(8)}"), SizedBox( width: 5, ), Icon(Helpers.GetIconForCrypto(GameJson['coin'])) ], ), ], ), )), ); } Widget WalletCurrencyListItem(String coin) { double amount = Helpers.SatsToCoin(DataManager.CryptoEarnings[coin] ?? 0); return Padding( padding: const EdgeInsets.all(3.0), child: GlassCard( child: Container( padding: const EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [SizedBox(width: 100, child: Text(coin))], ), Text( "~\$${Helpers.CryptoToDollars(amount: amount, Crypto: coin).toStringAsFixed(2)}"), Row( children: [ Text("${amount.toStringAsFixed(8)}"), SizedBox( width: 5, ), Icon(Helpers.GetIconForCrypto(coin)) ], ), ], ), )), ); } TextEditingController TxtCoinbaseAddress = TextEditingController(); Widget settings() { TxtCoinbaseAddress.text = "sewmina7@gmail.com"; return Column( children: [ GlassCard(child: Padding(padding: EdgeInsets.all(15), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Coinbase Address"), InkWell(onTap: (){Dialogs.showAlertDialog(context, "Coinbase Address", "Withdrawals will be accounted to this address");},child: Icon(Icons.help)) ], ), TextField(controller: TxtCoinbaseAddress,) ], ),)), SizedBox(height: 10,), InkWell( onTap: ()async{ final prefs = await SharedPreferences.getInstance(); prefs.clear(); Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => MyHomePage()), (Route route) => false); }, child: GlassCard(child: Padding( padding: const EdgeInsets.all(15.0), child: Row( children: [ Row( children: [ Icon(Icons.logout), SizedBox(width: 10,), Text("Signout"), ], ) ], ), )), ) ], ); } Widget ChallengeList( {required String gameName, required String coin, required List challengesInfo}) { return GlassCard( child: Container( width: screenWidth * 0.8, padding: EdgeInsets.all(15), child: Column(children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(gameName, style: TextStyle(fontSize: 16)), Row( children: [Icon(Helpers.GetIconForCrypto(coin)), Text(" $coin")], ) ], ), SizedBox( height: 20, ), Column( children: challengesInfo, ) ]), )); } Widget ChallengeProgress(dynamic ChallengeData) { int value = int.parse(ChallengeData['current'].toString()); int max = int.parse(ChallengeData['total'].toString()); String reward = ChallengeData['reward']; bool isDone = value >= max; return Padding( padding: const EdgeInsets.symmetric(horizontal: 2.0, vertical: 5), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Icon(Icons.diamond), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(ChallengeData['name'], style: TextStyle(fontSize: 13)), isDone ? SizedBox( width: 80, child: Text( "$reward Sats", style: TextStyle(fontSize: 15, color: Colors.greenAccent), textAlign: TextAlign.end, )) : GlassProgressBar( width: screenWidth * 0.4, value: value / max) ], ), SizedBox( width: 10, ), Column( children: [ !isDone ? Column( children: [ SizedBox( width: 80, child: Text( "$reward Sats", style: TextStyle( fontSize: 15, color: Colors.greenAccent), textAlign: TextAlign.end, )), SizedBox( width: 80, child: Text( "$value/$max", style: TextStyle(fontSize: 12), textAlign: TextAlign.end, )), ], ) : Container( padding: EdgeInsets.fromLTRB(10, 5, 0, 0), child: GlassButton( onTap: () async { Debug.Log("Button"); setState(() {}); showDialog( context: context!, barrierDismissible: false, routeSettings: const RouteSettings(name: "Progress"), builder: (BuildContext context) { return AlertDialog( // backgroundColor: Colors.deepPurpleAccent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30)), title: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ SpinKitDualRing( color: Colors.deepPurpleAccent), Expanded( child: Text( "Loading", textAlign: TextAlign.center, )), ], ), ); }); await DataManager.ClaimChallenge(ChallengeData); await Future.delayed(const Duration(seconds: 1)); Navigator.of(context).pop(); setState(() {}); }, child: Text("Claim"), width: 80, color: Colors.greenAccent), ), ], ) ], ), ); } }