724 lines
26 KiB
Dart
724 lines
26 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);
|
|
|
|
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: "Seasonal Challenges $daysLeft",
|
|
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: 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)),
|
|
);
|
|
|
|
// showLinkGameDialog(context, Brain.NonLinkedGamesJson[index]);
|
|
// try {
|
|
// ///checks if the app is installed on your mobile device
|
|
// String id = Brain.NonLinkedGamesJson[index]['link'];
|
|
// Debug.Log(id);
|
|
// bool isInstalled = await DeviceApps.isAppInstalled(id);
|
|
// if (isInstalled) {
|
|
// DeviceApps.openApp(id);
|
|
// } else {
|
|
// ///if the app is not installed it lunches google play store so you can install it from there
|
|
// // launchUrl(Uri(path: "market://details?id=" +Brain.NonLinkedGamesJson[index]['link']),mode: LaunchMode.externalApplication,);
|
|
// // try{launch("market://details?id=" +Brain.NonLinkedGamesJson[index]['link']);}catch(e){
|
|
// launch("https://play.google.com/store/apps/details?id=$id");
|
|
// // }
|
|
// }
|
|
// } catch (e) {
|
|
// print(e);
|
|
// }
|
|
},
|
|
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 : \$42.69"),
|
|
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,
|
|
),
|
|
Text(
|
|
"Sort by",
|
|
style: TextStyle(fontSize: 12),
|
|
),
|
|
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: [
|
|
CurrencyListItem("BTC", "0.0004000 = \$1.20"),
|
|
CurrencyListItem("ETH", "0.0004000 = \$0.50"),
|
|
CurrencyListItem("XRP", "0.0004000 = \$0.20"),
|
|
CurrencyListItem("DOGE", "0.0004000 = \$0.020")
|
|
],
|
|
)),
|
|
Container(
|
|
child: Column(
|
|
children: [
|
|
GameListItem(
|
|
Hoarder.GamesJson[0], "0.0004000 = \$1.20"),
|
|
GameListItem(
|
|
Hoarder.GamesJson[1], "0.0004000 = \$1.20"),
|
|
GameListItem(
|
|
Hoarder.GamesJson[2], "0.0004000 = \$1.20"),
|
|
],
|
|
)),
|
|
]),
|
|
),
|
|
],
|
|
))
|
|
],
|
|
)));
|
|
}
|
|
|
|
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, 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(currencyName)),
|
|
SizedBox(
|
|
width: 10,
|
|
),
|
|
Text(currencyName)
|
|
],
|
|
),
|
|
Text(value)
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
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();
|
|
},
|
|
)
|
|
]);
|
|
});
|
|
}
|
|
}
|