diff --git a/lib/backend/DataManager.dart b/lib/backend/DataManager.dart index fdeb80e..5c04962 100644 --- a/lib/backend/DataManager.dart +++ b/lib/backend/DataManager.dart @@ -41,13 +41,17 @@ class DataManager{ while(true){ await Future.delayed(const Duration(minutes: 1)); - await GetSettings(); - await GetGames(); - await GetChallenges(); - CalculateEarnings(); + await GrabOnce(); } } + static Future GrabOnce() async{ + await GetSettings(); + await GetGames(); + await GetChallenges(); + CalculateEarnings(); + } + static Future GetGamesProgress() async{ FilterLinkedGames(); await GetChallenges(); @@ -103,6 +107,20 @@ class DataManager{ return false; } } + + static double MinWdAmount(){ + return double.parse(GetSettingById("min_wd_amount")); + } + + static String GetSettingById(String id){ + String val = ""; + Settings.forEach((key, value) { + if(key == id){ + val = value; + } + }); + return val; + } static FutureGetGames() async{ try { @@ -229,5 +247,19 @@ class DataManager{ } } + static Future SetWdAddress(String newAddress) async{ + String prevAddress = UserJson['wd_address'] ?? ""; + Map body = { + "id": UserJson['id'], + "newAddress" : newAddress + }; + var response = (await http.post( + Uri.parse('${API_ENDPOINT}set_wd_address.php'), + body: body)); + Debug.Log("Set WD Address response: " +response.body.toString()); + UserJson['wd_address'] =(response.body.toString() == newAddress) ? newAddress : prevAddress; + + return (response.body.toString()); + } } \ No newline at end of file diff --git a/lib/backend/Dialogs.dart b/lib/backend/Dialogs.dart index 500fe12..b2729ab 100644 --- a/lib/backend/Dialogs.dart +++ b/lib/backend/Dialogs.dart @@ -20,9 +20,9 @@ class Dialogs{ // set up the AlertDialog AlertDialog alert = AlertDialog( backgroundColor: Color(0xFF1F1F1F), - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)), - title: Text(title), - content: Text(message), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)), + title: Text(title,textAlign: TextAlign.center,), + content: Text(message,textAlign: TextAlign.center,), actions: [ okButton, ], diff --git a/lib/gameInfo.dart b/lib/gameInfo.dart index 2ec0681..db1c929 100644 --- a/lib/gameInfo.dart +++ b/lib/gameInfo.dart @@ -11,13 +11,41 @@ class GameInfoPage extends StatefulWidget { State createState() => _GameInfoPageState(); } -class _GameInfoPageState extends State { +class _GameInfoPageState extends State with WidgetsBindingObserver { @override void initState() { // TODO: implement initState super.initState(); kickstartAnimations(); + + WidgetsBinding.instance.addObserver(this); + } + + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + + WidgetsBinding.instance.removeObserver(this); + } + + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // TODO: implement didChangeAppLifecycleState + super.didChangeAppLifecycleState(state); + + if(state == AppLifecycleState.resumed){ + Refresh(); + } + } + + void Refresh() async{ + await DataManager.GrabOnce(); + setState(() { + + }); } void kickstartAnimations() async { diff --git a/lib/home.dart b/lib/home.dart index 1894f9e..eee2b8e 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -4,6 +4,7 @@ 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/wd_portal.dart'; import 'package:fhub/welcome.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; @@ -19,14 +20,46 @@ class Home extends StatefulWidget { State createState() => _HomeState(); } -class _HomeState extends State { +class _HomeState extends State with WidgetsBindingObserver { @override void initState() { // TODO: implement initState super.initState(); kickstartAnimations(); + + TxtCoinbaseAddress.text = DataManager.UserJson['wd_address'] ?? ""; + + WidgetsBinding.instance.addObserver(this); } + @override + void dispose() { + // TODO: implement dispose + super.dispose(); + + WidgetsBinding.instance.removeObserver(this); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + // TODO: implement didChangeAppLifecycleState + super.didChangeAppLifecycleState(state); + // Debug.Log(state); + + if(state == AppLifecycleState.resumed){ + Refresh(); + } + } + + void Refresh()async{ + await DataManager.GrabOnce(); + + setState(() { + + }); + } + + void kickstartAnimations() async { await Future.delayed(const Duration(milliseconds: 500)); @@ -338,7 +371,46 @@ class _HomeState extends State { Widget wallet() { return Column( children: [ - TotalEarningsCard(), + GlassCard( + child: Container( + // height: screenHeight * 0.18, + width: screenWidth * 0.9, + padding: EdgeInsets.all(20), + child: Column( + children: [ + Text("Earnings"), + SizedBox( + height: 10, + ), + Text('~ \$${DataManager.currentEarnings.toStringAsFixed(2)} ', + style: TextStyle(fontSize: 50)), + + SizedBox(height: 20,), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + GlassButton(onTap: (){ + if(DataManager.currentEarnings <= 1){ + Dialogs.showAlertDialog(context, "Not Enough To Withdraw", "You need atleast \$1 to initiate a withdraw."); + return; + } + + if(!DataManager.UserJson['wd_address'].toString().contains("@")){ + Dialogs.showAlertDialog(context, "Invalid Withdrawal Address", "Please enter a valid email address for coinbase address. Your earnings will be sent to that address via coinbase"); + return; + } + + Navigator.of(context).push(MaterialPageRoute( + builder: (BuildContext context) => + WithdrawalPortal())); + }, child: Text("Withdraw"),height: 40, width: 200, color: Colors.greenAccent), + GlassButton(onTap: (){}, child: Icon(Icons.history), width: 60, height: 40) + ], + ) + ], + ), + ), + ), (DataManager.currentEarnings <=0) ? Container() : Column(children: [ SizedBox( height: 30, @@ -367,7 +439,7 @@ class _HomeState extends State { child: Padding( padding: EdgeInsets.symmetric( vertical: 8, horizontal: 20), - child: Text("Games"), + child: Text("Game"), ))), SizedBox( width: 5, @@ -383,7 +455,7 @@ class _HomeState extends State { child: Padding( padding: EdgeInsets.symmetric( vertical: 8, horizontal: 20), - child: Text("Earnings"), + child: Text("Crypto"), ))), ], ), @@ -502,21 +574,36 @@ class _HomeState extends State { } 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,) - ], - ),)), + GlassCard(child: AnimatedSize( + duration: const Duration(milliseconds: 200), + 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, onChanged: (e){setState(() { + + });},), + (TxtCoinbaseAddress.text != (DataManager.UserJson['wd_address'] ?? "") )? Container(padding: EdgeInsets.all(10), child: GlassButton(onTap: () async{ + String response = await DataManager.SetWdAddress(TxtCoinbaseAddress.text); + bool success = response == TxtCoinbaseAddress.text; + // DataManager.UserJson['wd_address'] = TxtCoinbaseAddress.text; + if(!success){ + Dialogs.showAlertDialog(context, "Error saving Coinbase Address", response); + } + setState(() { + + }); + }, child: Text("Save"), width: 250),) : Container() + ], + ),), + )), SizedBox(height: 10,), InkWell( onTap: ()async{ diff --git a/lib/src/CustomWidgets.dart b/lib/src/CustomWidgets.dart index 4c2d042..3a78098 100644 --- a/lib/src/CustomWidgets.dart +++ b/lib/src/CustomWidgets.dart @@ -221,7 +221,7 @@ Widget GlassButton({Color color = Colors.white,double height = 30,required Funct ); } -Widget GlassCard({bool highlighted = false,required Widget child}) { +Widget GlassCard({bool highlighted = false,Color color = Colors.white,required Widget child}) { return Container( // padding: EdgeInsets.all(30), decoration: BoxDecoration( @@ -229,8 +229,8 @@ Widget GlassCard({bool highlighted = false,required Widget child}) { begin: Alignment.topLeft, end: Alignment.bottomCenter, colors: [ - Colors.white.withOpacity(highlighted ? 0.4 : 0.12), - Colors.white.withOpacity(highlighted? 0.15:0.05), + color.withOpacity(highlighted ? 0.4 : 0.12), + color.withOpacity(highlighted? 0.15:0.05), ]), borderRadius: BorderRadius.circular(20), diff --git a/lib/wd_portal.dart b/lib/wd_portal.dart new file mode 100644 index 0000000..dfd098e --- /dev/null +++ b/lib/wd_portal.dart @@ -0,0 +1,167 @@ +import 'package:fhub/backend/DataManager.dart'; +import 'package:fhub/backend/DebugHelper.dart'; +import 'package:fhub/backend/Dialogs.dart'; +import 'package:fhub/backend/helpers.dart'; +import 'package:fhub/src/CustomWidgets.dart'; +import 'package:flutter/material.dart'; + +class WithdrawalPortal extends StatefulWidget { + const WithdrawalPortal({Key? key}) : super(key: key); + + @override + State createState() => _WithdrawalPortalState(); +} +ScrollController scrollController = ScrollController(); +class _WithdrawalPortalState extends State { + @override + void initState() { + // TODO: implement initState + super.initState(); + + kickstartAnimations(); + } + + void kickstartAnimations() async { + await Future.delayed(const Duration(milliseconds: 500)); + + setState(() { + op1 = 0.5; + op2 = 0.5; + op3 = 0.5; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: CustomBody( + child: SafeArea( + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + InkWell( + child: Container( + margin: EdgeInsets.all(10), + child: Icon(Icons.keyboard_arrow_left, size: 50)), + onTap: () { + Navigator.of(context).pop(); + }, + ), + GradientText( + text: "Withdrawal Portal", + gradient: LinearGradient(colors: [ + Colors.white.withOpacity(0.6), + Colors.white.withOpacity(0.5), + Colors.white.withOpacity(0.2) + ]), + style: TextStyle( + fontSize: 29, fontWeight: FontWeight.bold), + ), + Container( + width: 40, + ) + ], + ), + SizedBox( + height: 50, + ), + GlassCard( + child: Padding( + padding: const EdgeInsets.all(12.0), + child: AnimatedSize( + duration: const Duration(milliseconds: 100), + child: Column( + children: [ + Text("Select Cryptos to Withdraw"), + SizedBox(height: 20,), + ListView.builder( + shrinkWrap: true, + controller: scrollController, + itemCount: DataManager.CryptoEarnings.length, + itemBuilder: (BuildContext context, int index) { + return WalletCurrencyListItem( + DataManager.CryptoEarnings.keys.elementAt(index)); + }, + ), + SizedBox(height: 10,), + (selectedCurrencies.length > 0) ? Text("Selected ${selectedCurrencies.length} currencies to withdraw") : Container() + ], + ), + ), + ), + ) + ]), + GlassButton(onTap: (){ + + }, child: Text("Withdraw"), width: 300,height: 50,color: selectedCurrencies.length > 0 ? Colors.greenAccent: Colors.blueGrey) + ], + ))), + context: context, + onAnimEnd: () { + kickstartAnimations(); + }), + ); + } + + List selectedCurrencies = []; + + Widget WalletCurrencyListItem(String coin) { + double amount = Helpers.SatsToCoin(DataManager.CryptoEarnings[coin] ?? 0); + double amountDollars = Helpers.CryptoToDollars(amount: amount, Crypto: coin); + return InkWell( + onTap: (){ + if(amountDollars < 1){ + Dialogs.showAlertDialog(context, "Not Enough to Withdraw", "You need to reach the minimum withdrawal amount of\n\$1\nto Withdraw"); + return; + } + if(selectedCurrencies.contains(coin)){ + selectedCurrencies.remove(coin); + }else{ + selectedCurrencies.add(coin); + } + Debug.Log(selectedCurrencies); + setState(() { + + }); + }, + child: Padding( + padding: const EdgeInsets.all(3.0), + child: GlassCard( + color: selectedCurrencies.contains(coin) ? Colors.blue : Colors.white, + child: Container( + padding: const EdgeInsets.all(10.0), + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [SizedBox(width: 100, child: Text(coin))], + ), + Text( + "~\$${amountDollars.toStringAsFixed(2)}"), + Row( + children: [ + Text("${amount.toStringAsFixed(8)}"), + SizedBox( + width: 5, + ), + Icon(Helpers.GetIconForCrypto(coin)) + ], + ), + ], + ), + ), + )), + ), + ); + } +}