FaucetHub/lib/home.dart

714 lines
27 KiB
Dart

// import 'package:crypto_font_icons/crypto_font_icons.dart';
import 'package:crypto_font_icons/crypto_font_icons.dart';
import 'package:external_app_launcher/external_app_launcher.dart';
import 'package:faucethub/Backend/DebugHelper.dart';
import 'package:faucethub/Backend/Dialogs.dart';
import 'package:faucethub/Backend/Encryptor.dart';
import 'package:faucethub/Backend/brains.dart';
import 'package:faucethub/Backend/hoarder.dart';
import 'package:faucethub/Backend/login_mgr.dart';
import 'package:faucethub/game_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'Backend/helpers.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
int selectedBotNavIndex = 0;
String daysLeft = "";
class _HomePageState extends State<HomePage> {
bool looping = false;
@override
void initState() {
// TODO: implement initState
super.initState();
loop();
}
void loop() async {
looping = true;
while (looping) {
await Hoarder.FetchChallenges();
DateTime now = DateTime.now();
DateTime nextMonth = DateTime(now.year, (now.month < 12) ? now.month +1 : 1);
daysLeft = "${nextMonth.difference(now).inDays} Days Remaining";
setState(() {});
await Future.delayed(const Duration(seconds: 30));
}
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
looping = false;
}
Widget HomeWidget() {
final ScrollController _firstController = ScrollController();
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
padding: EdgeInsets.all(20),
child: Text("Welcome ${Brain.DisplayName},",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
),
Card(
margin: EdgeInsets.all(12),
child: Container(
padding: EdgeInsets.all(10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text("Earnings",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
InkWell(child: Icon(Icons.arrow_forward_outlined,size:25), onTap: (){
selectedBotNavIndex=2;
setState(() {
});
},)
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
SizedBox(height: 20,),
Text("Previously Earned",
style: TextStyle(
fontSize: 25, fontWeight: FontWeight.bold)),
Text('\$0', style: TextStyle(fontSize: 20)),
SizedBox(height: 20,),
Text("This Seasons",
style: TextStyle(
fontSize: 25, fontWeight: FontWeight.bold)),
Text('~ \$${Hoarder.currentEarnings.toStringAsFixed(2)}', style: TextStyle(fontSize: 18))
],
),
),
],
),
),
),
// HomeCard(
// child: Container(
// padding: EdgeInsets.symmetric(vertical: 50),
// child: Column(
// mainAxisSize: MainAxisSize.max,
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: [
// Text("Previously earned", style:TextStyle(fontSize: 25, fontWeight: FontWeight.bold)),
// Text('\$6.9'),
// Text("This Seasons'",style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold)),
// Text('\$2.3')
// ],
// )
// // child: Text(
// // "\$6.90",
// // style: TextStyle(fontSize: 50),
// // ),
// ),
// title: "Earnings"),
HomeCard(
title: "Ongoing Challenges",
child: Container(
child: Column(
children: [
(Hoarder.Challenges.length > 0)
? ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: Hoarder.Challenges.length,
itemBuilder: (BuildContext context, int index) {
dynamic gameJson = Helpers.GetGameFromCode(
Hoarder.Challenges[index][0]['game'] ??
'spaceio');
return ChallengesList(
gameName: gameJson['name'],
coin: gameJson['coin'],
challengesInfo: [
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount:
Hoarder.Challenges[index].length,
itemBuilder:
(BuildContext context, int index2) {
return ChallengeProgress(
Hoarder.Challenges[index][index2]
['name'],
int.parse(
Hoarder.Challenges[index]
[index2]['total']),
int.parse(
Hoarder.Challenges[index]
[index2]['current']),
int.parse(
Hoarder.Challenges[index]
[index2]['reward']));
})
]);
})
: Container(
padding: EdgeInsets.all(30),
child: Text("Not linked to any games"))
],
),
)),
// HomeCard(
// title: "Featured Games",
// child: SizedBox(
// height: 110,
// child: Scrollbar(
// thumbVisibility: true,
// controller: _firstController,
// child: ListView.builder(
// scrollDirection: Axis.horizontal,
// controller: _firstController,
// itemCount: Hoarder.FeaturedGames.length,
// itemBuilder: (BuildContext context, int index) {
// Debug.Log(Hoarder.FeaturedGames[index]);
// return InkWell(
// onTap: () {},
// child: Card(
// child: ClipRRect(
// borderRadius: BorderRadius.circular(12),
// child: Image.network(
// Hoarder.FeaturedGames[index]['icon'],
// width: 100,
// height: 100),
// ),
// ),
// );
// }),
// ),
// ),
// ),
// HomeCard(
// child: SizedBox(
// height: 250,
// ),
// title: "Top Players"),
],
),
);
}
Widget ChallengesList(
{required String gameName,
required String coin,
required List<Widget> challengesInfo}) {
return Card(
color: Colors.black12,
child: Container(
padding: EdgeInsets.all(10),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text(gameName,
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
Row(
children: [
FaIcon(Helpers.GetIconForCrypto(coin)),
Text(" $coin"),
],
)
]),
SizedBox(
height: 10,
),
Container(
padding: const EdgeInsets.all(8.0),
child: Column(
children: challengesInfo,
),
),
],
),
),
);
}
Widget ChallengeProgress(String title, int total, int current, int reward,
{String prefix = ""}) {
return Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.max,
children: [
Text(
title,
textAlign: TextAlign.left,
),
Text("$reward Sats",
style: TextStyle(
fontWeight: FontWeight.bold,
color: (total <= current) ? Colors.green : Colors.grey,
fontSize: 15))
],
),
const SizedBox(
height: 5,
),
Row(
children: [
Expanded(
child: LinearProgressIndicator(
value: current / total,
color: Colors.green,
)),
SizedBox(width: 15,),
(total <= current) ? SizedBox(height: 30,width: 70 ,child: MaterialButton(onPressed: (){}, child: Text("Claim"),color: Colors.green,)): SizedBox(
width: 60,
child: Text("$current / $total $prefix",
textAlign: TextAlign.end,
style: TextStyle(
fontSize: 12,
color: (total <= current)
? Colors.green
: Colors.white)))
],
),
const SizedBox(
height: 12,
),
]),
);
}
Widget GamesWidget() {
final ScrollController scrollController = ScrollController();
return Container(
padding: EdgeInsets.fromLTRB(20, 20, 0, 20),
child: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
alignment: Alignment.center,
padding: EdgeInsets.fromLTRB(0, 0, 0, 20),
child: Text("FH ID : ${Brain.UserJson['id']}"),
),
Text(
"Linked",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(
height: 5,
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
controller: scrollController,
itemCount: Brain.LinkedGamesJson.length,
itemBuilder: (BuildContext context, int index) {
// Debug.Log(Hoarder.LinkedGamesJson[index]);
return InkWell(
onTap: () async {
// showLinkGameDialog(context, Brain.LinkedGamesJson[index]);
// await LaunchApp.openApp(
// androidPackageName: Brain.LinkedGamesJson[index]['link'],
// // openStore: false
// );
String code = Brain.LinkedGamesJson[index]['code'];
Navigator.push(
context,
MaterialPageRoute(builder: (context) => GamePage(code)),
);
},
child: ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
Brain.LinkedGamesJson[index]['icon'],
width: 50,
height: 50),
),
title: Text(Brain.LinkedGamesJson[index]['name']),
subtitle:
Text(Brain.LinkedGamesJson[index]['description']),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(
Helpers.GetIconForCrypto(
Brain.LinkedGamesJson[index]['coin']),
size: 17,
),
SizedBox(
width: 2,
),
// Text("0.00004000"),
],
),
),
);
}),
SizedBox(
height: 20,
),
Text(
"Not Linked",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(
height: 5,
),
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
controller: scrollController,
itemCount: Brain.NonLinkedGamesJson.length,
itemBuilder: (BuildContext context, int index) {
// Debug.Log(Hoarder.NonLinkedGamesJson[index]);
String code = Brain.NonLinkedGamesJson[index]['code'];
return InkWell(
onTap: () async {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => GamePage(code)),
);
},
child: ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
Brain.NonLinkedGamesJson[index]['icon'],
width: 50,
height: 50),
),
title: Text(Brain.NonLinkedGamesJson[index]['name']),
subtitle:
Text(Brain.NonLinkedGamesJson[index]['description']),
trailing: Icon(
Helpers.GetIconForCrypto(
Brain.NonLinkedGamesJson[index]['coin']),
size: 17,
),
),
);
})
],
),
),
);
}
Widget WalletWidget() {
final ScrollController scrollController = ScrollController();
return Container(
padding: EdgeInsets.all(10),
child: Container(
child: Column(
children: [
HomeCard(
child: Container(
child: ListTile(
leading: FaIcon(
FontAwesomeIcons.solidCircleUser,
size: 60,
),
title: Text(Brain.Username),
subtitle: Text("Total Earnings : \$${(Hoarder.previousEarnings + Hoarder.currentEarnings).toStringAsFixed(2)}"),
trailing: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
selectedBotNavIndex = 3;
setState(() {});
},
),
)),
title: "Your Account",
showMore: false),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Expanded(
child: MaterialButton(
onPressed: () {},
child: Text("Withdraw"),
color: Colors.green,
))
],
),
SizedBox(
height: 30,
),
DefaultTabController(
length: 2,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TabBar(tabs: [
Tab(
text: "Currency",
),
Tab(
text: "Games",
)
]),
Container(
padding: EdgeInsets.all(10),
//Add this to give height
constraints: BoxConstraints.expand(height: 250),
child: TabBarView(children: [
Container(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
controller: scrollController,
itemCount: Hoarder.ThisSeasonCryptoEarnings.length,
itemBuilder: (BuildContext context, int index) {
return CurrencyListItem(Hoarder.ThisSeasonCryptoEarnings.keys.elementAt(index));
})
],
)),
Container(
child: Column(
children: [
ListView.builder(
shrinkWrap: true,
controller: scrollController,
itemCount: Hoarder.ThisSeasonGamesEarnings.length,
itemBuilder: (BuildContext context, int index) {
String gameName= Hoarder.ThisSeasonGamesEarnings.keys.elementAt(index);
dynamic GameJson = Helpers.GetGameFromCode(gameName);
if(GameJson == null){
Debug.LogError("Error receiving game json from ${gameName}. returned:\n$GameJson");
return Text("Error");
}
double amount = Helpers.SatsToCoin(Hoarder.ThisSeasonGamesEarnings.values.elementAt(index));
return GameListItem(
GameJson, "$amount ~ \$${Helpers.CryptoToDollars(amount: amount, Crypto: GameJson['coin']).toStringAsFixed(2)}");
})
],
)),
]),
),
],
))
],
)));
}
Widget SettingsWidget() {
final ScrollController scrollController = ScrollController();
return Container(
padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
child: SingleChildScrollView(
physics: ScrollPhysics(),
child: Column(
children: [
Text(
"Settings",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
ListTile()
],
)));
}
@override
Widget build(BuildContext context) {
List<Widget> bodyOptions = [
HomeWidget(),
GamesWidget(),
WalletWidget(),
SettingsWidget()
];
return SafeArea(
child: Scaffold(
// appBar: AppBar(title: Text('Faucet Hub'),),
body: bodyOptions.elementAt(selectedBotNavIndex),
bottomNavigationBar: BottomNavigationBar(
enableFeedback: true,
selectedItemColor: Colors.green,
unselectedItemColor: Colors.grey,
elevation: 20,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.home), label: "Home"),
BottomNavigationBarItem(
icon: Icon(Icons.videogame_asset), label: "Games"),
BottomNavigationBarItem(
icon: Icon(Icons.account_balance_wallet), label: "Wallet"),
BottomNavigationBarItem(
icon: Icon(Icons.settings), label: "Settings"),
],
currentIndex: selectedBotNavIndex,
onTap: onBotNavTapped,
)),
);
}
static Widget HomeCard(
{bool showMore = false, required Widget child, required String title}) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 5, vertical: 10),
child: Column(children: [
Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 8, 8),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: TextStyle(
fontSize: 17, fontWeight: FontWeight.bold),
),
(showMore)
? InkWell(
child: Icon(Icons.arrow_right_alt),
onTap: () {},
)
: Container()
],
),
),
child
]))));
}
Widget CurrencyListItem(String currencyName) {
double val = (Hoarder.ThisSeasonCryptoEarnings[currencyName] ?? 0).toDouble() * (0.00000001);
return Container(
padding: EdgeInsets.all(5),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Helpers.GetIconForCrypto(currencyName)),
SizedBox(
width: 10,
),
Text(currencyName)
],
),
Text('${val.toStringAsFixed(8)} ~ \$${Helpers.CryptoToDollars(amount: val, Crypto: currencyName).toStringAsFixed(2)}' )
],
),
);
}
Widget GameListItem(dynamic Game, String value) {
return Container(
padding: EdgeInsets.all(5),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Helpers.GetIconForCrypto(Game['coin'])),
SizedBox(
width: 10,
),
Text(Game['name'])
],
),
Text(value)
],
),
);
}
void onBotNavTapped(int value) {
selectedBotNavIndex = value;
setState(() {});
}
TextEditingController manualLinkInput = TextEditingController();
void showLinkGameDialog(BuildContext context, dynamic Game) {
Debug.Log("Showing custom dialog");
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Link game - ${Game['name']}"),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Enter user id in-game to Link this game to the Faucet Hub"),
TextField(
controller: manualLinkInput,
decoration: InputDecoration(hintText: 'User ID'))
],
),
actions: [
TextButton(
child: Text("Link"),
onPressed: () {
String input = manualLinkInput.text;
manualLinkInput.clear();
if (input.length < 2) {
Dialogs.showAlertDialog(
context, "Failed", "Invalid User ID");
return;
}
int userId = Encryptor.stringToInt(input);
if (userId < 0) {
return;
}
print("Init link to id $userId");
},
),
TextButton(
child: Text("Cancel"),
onPressed: () {
manualLinkInput.clear();
Navigator.of(context).pop();
},
)
]);
});
}
}