Refactored

This commit is contained in:
2024-10-28 17:34:48 +05:30
parent fc1f6189e6
commit 2714797fcc
220 changed files with 1996 additions and 776 deletions

View File

@@ -1,5 +1,6 @@
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'package:http/http.dart' as http;
import 'package:mhunt_launcher/Backend/Structures.dart';
@@ -7,63 +8,68 @@ import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'DebugHelper.dart';
class Backend{
class Backend {
static const String API_ENDPOINT = "https://vps.playpoolstudios.com/metahunt/api/launcher/";
static const String SOLOGIN_ENDPOINT = "http://vps.playpoolstudios.com:20017/";
static List<GameData> Games = [
GameData(0,"mhunt","Metahunt", "High-Stake Battle Royale game with Play to earn abilities", "images/mhunt_thumbnail.png", true,"METAHUNT.exe"),
GameData(1,"pop3d","Pop3D", "a game I dont know much about xD", "images/pop3d_thumbnail.png", false, "pop3d.exe"),
GameData(0, "mhunt", "Metahunt", "High-Stake Battle Royale game with Play to earn abilities", "images/mhunt_thumbnail.png", true, "METAHUNT.exe"),
GameData(1, "pop3d", "Pop3D", "a game I dont know much about xD", "images/pop3d_thumbnail.png", false, "pop3d.exe"),
];
static SharedPreferences? prefs;
static Directory? docPath;
static String Username="";
static String Username = "";
static String displayName = "";
static String walletAddress = "";
static String pubKey = "";
static Map<String,dynamic> UserJson = {'username':'test', 'passwd':'test123'};
static Map<String, dynamic> UserJson = {'username': 'test', 'passwd': 'test123'};
static Future<bool> Login(String username, String password) async{
static Future<bool> Login(String username, String password) async {
var loginResponse = null;
init();
try {
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}login.php'),
body: <String, String>{"username": username, "password": password}));
Debug.LogResponse(loginResponse.body.toString(),src: '${API_ENDPOINT}login.php');
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}login.php'), body: <String, String>{"username": username, "password": password}));
Debug.LogResponse(loginResponse.body.toString(), src: '${API_ENDPOINT}login.php');
if(loginResponse.body.toString().contains("no user")){
return false;
}
try {
Username=username;
Username = username;
SetUsernamePassword(username, password);
return true;
} catch (e) {
}
} catch (e) {}
} catch (e) {
Debug.LogError("Error while login $e");
return false;
}
return false;
}
static void init()async{
static void init() async {
prefs = await SharedPreferences.getInstance();
docPath = await getDownloadsDirectory();
}
static Future<bool> Register(String username, String password, String displayname) async{
static Future<bool> Register(String username, String password, String displayname) async {
var loginResponse = null;
init();
try {
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}register.php'),
body: <String, String>{"username": username, "password": password, "display_name": displayname}));
Debug.LogResponse(loginResponse.body.toString(),src: '${API_ENDPOINT}register.php');
loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}register.php'), body: <String, String>{"username": username, "password": password, "display_name": displayname}));
Debug.LogResponse(loginResponse.body.toString(), src: '${API_ENDPOINT}register.php');
try {
SetUsernamePassword(username, password);
Username = username;
displayName=displayname;
Debug.Log("User is " + username);
displayName = displayname;
return true;
} catch (e) {
}
} catch (e) {}
} catch (e) {
Debug.LogError("Error while login $e");
}
@@ -71,44 +77,49 @@ class Backend{
return false;
}
static void SetUsernamePassword(String username, String passwd){
UserJson = {'username':username, 'passwd':passwd};
static Future<String> GetPubkey() async{
var response = await http.get(Uri.parse('${SOLOGIN_ENDPOINT}getPubkey?email=${Username}'));
pubKey = jsonDecode(response.body.toString())["pub_key"];
return pubKey;
}
static Future<List<LeaderboardEntry>> GetLeaderboard(String gameCode) async{
static void SetUsernamePassword(String username, String passwd) {
UserJson = {'username': username, 'passwd': passwd};
}
static Future<List<LeaderboardEntry>> GetLeaderboard(String gameCode) async {
String url = '${API_ENDPOINT}/${gameCode}/get_leaderboard.php';
var leaderboardResponse = await http.get(Uri.parse(url));
return LeaderboardEntry.listFromJson(leaderboardResponse.body);
}
static Future<List<Map<String,dynamic>>> GetNewsForGame(int gameId)async{
static Future<List<Map<String, dynamic>>> GetNewsForGame(int gameId) async {
String url = '${API_ENDPOINT}${Games[gameId].code}/get_news.php';
try{
try {
var res = await http.get(Uri.parse(url));
List<dynamic> jsonList = jsonDecode(res.body);
List<Map<String,dynamic>> output = [];
List<Map<String, dynamic>> output = [];
jsonList.forEach((element) {
output.add(element as Map<String,dynamic>);
output.add(element as Map<String, dynamic>);
});
return output;
}catch(e){
} catch (e) {
Debug.LogError(e);
}
return [{}];
}
static Future<Map<String,dynamic>> GetUserStatsForGame(int gameId) async{
static Future<Map<String, dynamic>> GetUserStatsForGame(int gameId) async {
var loginResponse = null;
init();
try {
String url = '${API_ENDPOINT}${Games[gameId].code}/get_user_stats.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"username": prefs!.getString("username") ?? "test"}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"username": Username ?? "test"}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
return jsonDecode(loginResponse.body);
} catch (e) {
@@ -118,13 +129,13 @@ class Backend{
return {};
}
static Future<String> CreateRequest() async{
static Future<String> CreateRequest() async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}create_request.php';
loginResponse = await http.get(Uri.parse(url));
Debug.LogResponse(loginResponse.body.toString(),src: url);
Debug.LogResponse(loginResponse.body.toString(), src: url);
return loginResponse.body.toString();
} catch (e) {
@@ -134,14 +145,13 @@ class Backend{
return "-1";
}
static Future<String> GetRequestResponse(String id) async{
static Future<String> GetRequestResponse(String id) async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}get_request_response.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"id":id.toString()}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"id": id.toString()}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
return loginResponse.body;
} catch (e) {
@@ -151,14 +161,13 @@ class Backend{
return "-1";
}
static Future<String> GetDisplayName(String id) async{
static Future<String> GetDisplayName(String id) async {
var response = null;
try {
String url = '${API_ENDPOINT}get_display_name.php';
response = (await http.post(Uri.parse(url),
body: <String, String>{"id":id.toString()}));
Debug.LogResponse(response.body.toString(),src: url);
response = (await http.post(Uri.parse(url), body: <String, String>{"id": id.toString()}));
Debug.LogResponse(response.body.toString(), src: url);
return response.body;
} catch (e) {
@@ -168,18 +177,17 @@ class Backend{
return "-1";
}
static Future<bool> GetUsernameValidation(String username) async{
static Future<bool> GetUsernameValidation(String username) async {
var loginResponse = null;
try {
String url = '${API_ENDPOINT}validate_username.php';
loginResponse = (await http.post(Uri.parse(url),
body: <String, String>{"username":username}));
Debug.LogResponse(loginResponse.body.toString(),src: url);
loginResponse = (await http.post(Uri.parse(url), body: <String, String>{"username": username}));
Debug.LogResponse(loginResponse.body.toString(), src: url);
if(loginResponse.body == "0"){
if (loginResponse.body == "0") {
return true;
}else{
} else {
return false;
}
} catch (e) {
@@ -188,10 +196,39 @@ class Backend{
return false;
}
static Future<String> GetNextGuestUsername() async{
try{
String url = '${API_ENDPOINT}get_next_guest_username.php';
var response = await http.get(Uri.parse(url));
return response.body.toString();
}catch(e){
}
Random random = new Random();
return 'guest ${random.nextInt(10000000)}';
}
static VaultData vault = VaultData('0x0', 0, 0);
static Future<VaultData> RefreshVaultData() async{
var response = null;
try{
String url = '${API_ENDPOINT}get_vault_data.php';
response = (await http.post(Uri.parse(url), body: <String,String>{"id": Username}));
Debug.LogResponse(response.body.toString(), src:url);
vault = jsonDecode(response.body.toString());
}catch(e){
}
return vault;
}
}
class GameData{
class GameData {
int id;
String code;
String name;
@@ -200,5 +237,13 @@ class GameData{
bool isAvailable;
String exeName;
GameData(this.id,this.code,this.name,this.description,this.imagePath,this.isAvailable,this.exeName);
}
GameData(this.id, this.code, this.name, this.description, this.imagePath, this.isAvailable, this.exeName);
}
class VaultData{
String address;
int vc;
int php;
VaultData(this.address, this.vc, this.php);
}

View File

@@ -35,14 +35,16 @@ class InstallHelper{
localFiles = await getHashtable(pathDir);
}
//Get local hashtable
// Debug.Log(localFilesJson);
Debug.LogResponse(jsonEncode(localFiles), src:"local files");
//Write to file
if(!usedLocalSave){
String localFilesJson = FileHashEntry.listToJson(localFiles);
Backend.prefs!.setString(GetValidationSaveKey(gameId),localFilesJson);
if(kDebugMode) {
File writeJsonFile = File(Path.join(pathDir.parent.path, "hashes.txt"));
String hashFilePath = Path.join(pathDir.parent.path, "hashes.txt");
File writeJsonFile = File(hashFilePath);
writeJsonFile.writeAsString(localFilesJson);
Debug.Log("Wrote hash into ${hashFilePath}");
}
}

39
lib/Shared/Dialogs.dart Normal file
View File

@@ -0,0 +1,39 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../main.dart';
class Dialogs{
static showAlertDialog(BuildContext context, String title, String message) {
// set up the button
Widget okButton = TextButton(
child: Text("OK"),
onPressed: () {
Navigator.of(context).pop();
},
);
// set up the AlertDialog
AlertDialog alert = AlertDialog(
backgroundColor: Color(0xFF1F1F1F),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
title: Text(title),
content: Text(message),
actions: [
okButton,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}

View File

@@ -0,0 +1,75 @@
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher_string.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
Widget AccountPage(){
return Padding(
padding: const EdgeInsets.all(25.0),
child: Column(
children: [
Row(
children: [
Text("Hello, ${Backend.displayName}", style: TextStyle(fontSize: 30)),
],
),
SizedBox(height: 100,),
Text(Backend.pubKey),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Column(
children: [
Text("Vault Credits",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 15),),
Row(
children: [
Image.asset('images/vault.png',width: 40,height: 40,),
Text(Backend.vault.php.toString(),style: TextStyle(fontSize: 50),),
],
)
],
),
SizedBox(width: 60,),
Column(
children: [
Text("Pre-hunt Points",style: TextStyle(fontWeight: FontWeight.bold,fontSize: 15),),
Row(
children: [
Image.asset('images/token.png',width: 40,height: 40,),
Text(Backend.vault.vc.toString(),style: TextStyle(fontSize: 50),),
],
)
],
),
],
),
// Text("Your wallet address is "),
// Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(Backend.walletAddress, style: TextStyle(fontSize: 25),),
// InkWell(child: Padding(
// padding: const EdgeInsets.all(16.0),
// child: Icon(Icons.copy),
// ), onTap: (){
// //Copy wallet
// },)
// ],
// ),
SizedBox(height: 50,),
GlassButton(onTap: (){
launchUrlString('https://auth.playpoolstudios.com');
}, child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Open Dashboard"),
SizedBox(width: 10,),
Icon(Icons.open_in_new, color: Colors.grey)
],
), width: 250, height: 50)
],
),
);
}

View File

@@ -0,0 +1,342 @@
import 'dart:io';
import 'package:filepicker_windows/filepicker_windows.dart';
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../../Backend/FileHashEntry.dart';
import '../../Backend/InstallHelper.dart';
import '../../Backend/Structures.dart';
import '../CustomWidgets.dart';
Widget Dashboard({
required BuildContext context,
required Map<int, List<FileHashEntry>> downloadQueue,
required int dashboardSelectedGameIndex,
required List<FileHashEntry> missingFilesForSelectedGame,
required bool calculatingFiles,
required bool isUninstalling,
required bool isRunning,
required Map<String, dynamic> myStatsForSelectedGame,
required List<LeaderboardEntry> leaderboardForSelectedGame,
required List<Map<String, dynamic>> newsForSelectedGame,
required Function(int) onSelectedGameChanged,
required Function onUpdate,
required Function(int) onUninstallClicked,
required dynamic OnGameActionButtonClicked,
}) {
GameData selectedGameData = Backend.Games[dashboardSelectedGameIndex];
String filePath = InstallHelper.GetFilePath(dashboardSelectedGameIndex);
bool folderExists = Directory(filePath).existsSync();
String ActionBtnTxt = "Install";
if (missingFilesForSelectedGame.length <= 0) {
ActionBtnTxt = "Play";
} else {
ActionBtnTxt =
("Download ${FileHashEntry.getTotalSizeInMbytes(missingFilesForSelectedGame).toStringAsFixed(0)} MB");
}
if (calculatingFiles) {
ActionBtnTxt = "Validating";
}
if (downloadQueue.containsKey(dashboardSelectedGameIndex)) {
ActionBtnTxt = "Downloading";
}
if (isUninstalling) {
ActionBtnTxt = "Uninstalling";
}
if(isRunning){
ActionBtnTxt = "Running";
}
Widget ActionButton = GlassButton(
onTap: OnGameActionButtonClicked,
child: Text(ActionBtnTxt),
width: 200,
color: Colors.blue,
opacity: 0.5,
height: 50);
final screenHeight = MediaQuery.of(context).size.height;
List<DataRow> leaderboardList = [];
// leaderboardList.add(TableRow(children: [Text("username"),Text("kills"), Text("deaths")]));
// leaderboardList.add(TableRow());
leaderboardList
.addAll(List.generate(leaderboardForSelectedGame.length, (i) {
return DataRow(cells: <DataCell>[
DataCell(Text(leaderboardForSelectedGame[i].place.toString())),
DataCell(Text(leaderboardForSelectedGame[i].username)),
DataCell(Text(leaderboardForSelectedGame[i].kills.toString())),
DataCell(Text(leaderboardForSelectedGame[i].deaths.toString())),
DataCell(Text(leaderboardForSelectedGame[i].xp.toString())),
]);
}));
return Theme(
data: ThemeData(splashColor: Colors.transparent),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: screenHeight * 0.18,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
selectedGameData.name,
style: TextStyle(fontSize: 25),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(Backend.Games.length, (index) {
bool isSelected = index == dashboardSelectedGameIndex;
return InkWell(
onTap: (){
onSelectedGameChanged(index);
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 100),
margin: EdgeInsets.all(9),
height: 80 * (isSelected ? 1.5 : 1),
width: 130 * (isSelected ? 1.5 : 1),
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[index].imagePath),
fit: BoxFit.fill),
borderRadius: BorderRadius.circular(20)),
),
);
}),
),
],
),
),
!Backend.Games[dashboardSelectedGameIndex].isAvailable
? Center(
child: Text("Coming Soon", style: TextStyle(fontSize: 40)))
: Container(
height: screenHeight * 0.72,
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
ActionButton,
PopupMenuButton<String>(
iconColor: Colors.blueGrey,
onSelected: (val) {
if (val.toLowerCase().contains("uninstall")) {
onUninstallClicked(dashboardSelectedGameIndex);
}
},
itemBuilder: (BuildContext context) {
return {'Uninstall'}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
),
GlassCard(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text("My Stats",
style:
TextStyle(color: Colors.blueGrey)),
SizedBox(
width: 50,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Kills : ${(myStatsForSelectedGame['kills'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Deaths : ${(myStatsForSelectedGame['deaths'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Assist : ${(myStatsForSelectedGame['assists'] ?? "0")}"),
),
],
),
),
),
Container()
],
),
),
Container(
height: screenHeight * 0.6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: GlassCard(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
width: 350,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 12.0, horizontal: 20),
child: Text(
"News",
style: TextStyle(fontSize: 20),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
newsForSelectedGame.length,
(index) {
return NewsCard(
newsForSelectedGame[index]
['title'],
newsForSelectedGame[index]
['message']);
}),
),
),
)
],
),
)),
),
SizedBox(
width: 50,
),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
0, 20, 0, 0),
child: Text(
"Leaderboard",
style: TextStyle(fontSize: 20),
),
),
DataTable(
dataTextStyle:
TextStyle(color: Colors.white),
headingTextStyle:
TextStyle(color: Colors.white),
dividerThickness: 0,
columns: [
DataColumn(
label:
Expanded(child: Text("Place"))),
DataColumn(
label: Expanded(
child: Text("Username"))),
DataColumn(
label:
Expanded(child: Text("Kills"))),
DataColumn(
label: Expanded(
child: Text("Deaths"))),
DataColumn(
label: Expanded(child: Text("XP"))),
],
rows: leaderboardList,
),
],
),
),
],
))
],
),
),
Container(
//Install path footer
padding: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.bottomCenter,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [Text("Install path "), Text(filePath)]),
GlassButton(
onTap: () {
DirectoryPicker file = DirectoryPicker();
final dir = file.getDirectory();
Backend.prefs!.setString(
'${selectedGameData.name}_path', dir!.path);
onUpdate();
},
child: Text("Change Install Location"),
width: 250)
],
),
SizedBox(
height: 10,
)
],
),
)
],
),
);
}
Widget NewsCard(String title, String message) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: GlassCard(
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Icon(
Icons.newspaper,
color: Colors.blueGrey,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18),
textAlign: TextAlign.left,
),
Text(
message,
overflow: TextOverflow.clip,
)
],
)
],
)),
);
}

View File

@@ -0,0 +1,129 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../../Backend/FileHashEntry.dart';
import '../CustomWidgets.dart';
Widget DownloadCard({
required int gameId,
required Map<int, Map<FileHashEntry, num>> downloadProgress,
required Map<int, double> totalDownloadSize,
required Map<int, List<FileHashEntry>> downloadQueue,
required bool downloadRunning,
required Function(int) onChanged
}) {
int doneSize = 0;
if (downloadProgress.containsKey(gameId)) {
Map<FileHashEntry, num> _progress = downloadProgress[gameId]!;
_progress.forEach((key, value) {
doneSize += value.toInt();
});
}
double totalSize = totalDownloadSize[gameId]! / 1024 / 1024;
double doneSizeMb = doneSize / 1024 / 1024;
double progress = doneSizeMb / totalSize;
return Padding(
padding: const EdgeInsets.all(8.0),
child: GlassCard(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[gameId].imagePath)),
borderRadius: BorderRadius.circular(50)),
width: 160,
height: 80,
),
Column(
children: [
Text(
Backend.Games[gameId].name,
style: TextStyle(fontSize: 20),
),
Text((doneSizeMb).toStringAsFixed(2) +
" MB" +
" / " +
totalSize.toStringAsFixed(2) +
" MB")
],
)
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black.withOpacity(0.2),
color: Colors.blue,
),
),
),
InkWell(
child: Icon(Icons.cancel,
size: 40, color: Colors.red.withOpacity(0.6)),
onTap: () {
downloadQueue.remove(gameId);
downloadProgress.remove(gameId);
downloadRunning = false;
onChanged(gameId);
},
)
// Icon(Icons.download,size: 40,color: Colors.green.withOpacity(0.4),)
],
)
],
),
)),
);
}
Widget Downloads({
required Map<int, List<FileHashEntry>> downloadQueue,
required Map<int, Map<FileHashEntry, num>> downloadProgress,
required Map<int, double> totalDownloadSize,
required bool downloadRunning,
required Function(int) onChanged
}) {
if (downloadQueue.length <= 0) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.download_done_sharp,
size: 100,
color: Colors.white.withOpacity(0.5),
),
Text(
"No ongoing Downloads",
style:
TextStyle(fontSize: 40, color: Colors.white.withOpacity(0.4)),
),
],
),
);
}
return Container(
child: Container(
padding: EdgeInsets.all(100),
child: GlassCard(
child: Column(
children: List.generate(downloadQueue.keys.length, (index) {
int gameId = downloadQueue.keys.toList()[index];
return DownloadCard(gameId: gameId, downloadQueue:downloadQueue, downloadProgress: downloadProgress, downloadRunning: downloadRunning, totalDownloadSize: totalDownloadSize, onChanged: onChanged );
}),
))));
}

View File

@@ -0,0 +1,98 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
String hoveringGameCard = "";
Widget Library({
required int selectedSidebarIndex,
required Function(int) onGameChanged,
required Function onUpdate,
}) {
return Center(
child: Wrap(
spacing: 20,
children: List.generate(Backend.Games.length, (index) {
GameData gameData = Backend.Games[index];
return LibGameCard(
gameData: gameData,
selectedSidebarIndex: selectedSidebarIndex,
onUpdate: onUpdate,
onGameChanged: onGameChanged
);
}),
),
);
}
Widget LibGameCard({
required GameData gameData,
required int selectedSidebarIndex,
required Function(int) onGameChanged,
required Function onUpdate,
}) {
return InkWell(
onTap: () {
selectedSidebarIndex = 1;
onGameChanged(gameData.id);
},
onHover: (val) {
if (val) {
hoveringGameCard = gameData.name;
} else if (hoveringGameCard == gameData.name) {
hoveringGameCard = "";
}
onUpdate();
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.black,
image: DecorationImage(
image: AssetImage(gameData.imagePath), fit: BoxFit.fill)),
height: 200,
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
hoveringGameCard != gameData.name
? Container()
: Expanded(
child: GlassContainer(
child: Center(
child: Text(
gameData.description,
textAlign: TextAlign.center,
),
),
opacity: 0.5,
color: Colors.black)),
GlassContainer(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: true? Container():Row(
children: [
Text(gameData.name),
gameData.isAvailable
? GlassButton(
onTap: () {},
child: Text("Install"),
width: 100,
color: Colors.blue,
opacity: 0.8)
: Text("Coming soon")
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
),
opacity: 0.9,
color: Colors.black),
],
),
),
);
}

View File

@@ -0,0 +1,127 @@
import 'package:flutter/material.dart';
import '../../Backend/Backend.dart';
import '../CustomWidgets.dart';
int selectedSidebarIndex = 0;
Widget SideBar(
{required double width, required double height,required Function(int) onChanged, int selectedIndex = 0}) {
return GlassContainer(
child: Container(
width: width,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
SizedBox(
height: 100,
),
SidebarTitle("Library", Icons.laptop_chromebook_outlined, onChanged,
index: 0),
SidebarTitle("Dashboard", Icons.dashboard,onChanged, index: 1),
SidebarTitle("Downloads", Icons.download,onChanged, index: 2),
],
),
InkWell(
onTap:(){
selectedSidebarIndex=3;
onChanged(3);
},
child: GlassContainer(child: Padding(
padding: const EdgeInsets.fromLTRB(10,0,10,10),
child: Row(
children: [
Icon(Icons.supervised_user_circle_rounded, size: 50),
SizedBox(width: 15,),
Column(crossAxisAlignment:CrossAxisAlignment.start,children: [
Text(Backend.displayName,style: TextStyle(fontSize: 24),),
// Text("Vault credits : 50")
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 2),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.black.withAlpha(100)),
child: Row(
children: [
Container(
height: 30,
width: 30,
child: Image.asset('images/vault.png'),
),
SizedBox(width: 5,),
Text(Backend.vault.vc.toString())
],
),
),
SizedBox(width: 5,),
Container(
padding: EdgeInsets.symmetric(horizontal: 10,vertical: 2),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.black.withAlpha(100)),
child: Row(
children: [
Container(
height: 30,
width: 30,
child: Image.asset('images/token.png'),
),
SizedBox(width: 5,),
Text(Backend.vault.php.toString())
],
),
),
],
)
],
),
],)
],
),
)),
)
],
),
),
opacity: 0.15,
color: Colors.blueGrey);
}
Widget SidebarTitle(String title, IconData iconData, Function(int) onChanged, {int index = 0}) {
return InkWell(
onTap: () {
selectedSidebarIndex = index;
onChanged(index);
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 0),
child: GlassContainer(
opacity: selectedSidebarIndex == index ? 0.1 : 0,
color:
selectedSidebarIndex == index ? Colors.white : Colors.transparent,
child: Container(
height: 75,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(iconData),
SizedBox(
width: 20,
),
Text(
title,
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}

View File

@@ -1,10 +1,11 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:http/http.dart' as http;
import 'package:mhunt_launcher/home.dart';
import 'package:process_run/shell.dart';
import 'package:mhunt_launcher/login.dart';
class UpdateCheckScreen extends StatefulWidget {
const UpdateCheckScreen({super.key});
@@ -15,8 +16,8 @@ class UpdateCheckScreen extends StatefulWidget {
class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
int localVersion = 0;
String otaPath = Directory.current.path + "\\ota_wrapper_v2.exe";
int localVersion = 4;
String otaPath = Directory.current.path + "\\ota_wrapper_silent.vbs";
@override
void initState() {
@@ -25,31 +26,35 @@ class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
CheckForUpdates();
}
Future<List<ProcessResult>> runExecutable(String executable) async {
return await run(executable);
}
void CheckForUpdates() async{
// http.Response remoteVersionResponse = await http.get(Uri.parse("https://vps.playpoolstudios.com/metahunt/api/launcher/get_version.php"));
// int remoteVersion = int.parse(remoteVersionResponse.body);
if(!await File(otaPath).exists()){
print("otapath not existing");
setState(() {
updateStatus=2;
});
return;
}
try {
final result = await runExecutable(otaPath + " noupdate");
if (result[0].stdout.trim() == '0') {
updateStatus = 2;
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> HomePage()));
}else{
updateStatus = 1;
}
} catch (e) {
print('Error running the executable: $e');
}
http.Response remoteVersionResponse = await http.get(Uri.parse("https://vps.playpoolstudios.com/metahunt/data/bin/launcher_win/get_version_code.php"));
int remoteVersion = int.parse(remoteVersionResponse.body);
print("local version:${localVersion}, remote version:${remoteVersion}");
if(remoteVersion>localVersion){
updateStatus = 1;
}else{
updateStatus=2;
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> LoginPage()));
}
// if(!await File(otaPath).exists()){
// print("otapath not existing");
// setState(() {
// updateStatus=2;
// });
// return;
// }
// try {
//
// final result = await runExecutable(otaPath + " noupdate");
// if (result[0].stdout.trim() == '0') {
// updateStatus = 2;
// Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context)=> LoginPage()));
// }else{
// updateStatus = 1;
// }
// } catch (e) {
// print('Error running the executable: $e');
// }
setState(() {
@@ -57,10 +62,16 @@ class _UpdateCheckScreenState extends State<UpdateCheckScreen> {
});
}
void update() async{
await Process.start(otaPath,[], runInShell: true);
// await Future.delayed(const Duration(seconds: 5));
// await Process.start(otaPath,[], runInShell: true);
//
final process = await Process.start('wscript',[otaPath], runInShell: true);
updateStatus = 2;
process.stdout.transform(utf8.decoder).listen((data) {
});
process.stderr.transform(utf8.decoder).listen((data) {
print(data);
});
await Future.delayed(const Duration(seconds: 1));
exit(0);
setState(() {

View File

@@ -14,11 +14,17 @@ import 'package:mhunt_launcher/sidebar.dart';
import 'package:process_run/process_run.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:path/path.dart' as Path;
import 'package:url_launcher/url_launcher_string.dart';
import 'Backend/DebugHelper.dart';
import 'package:http/http.dart' as http;
import 'Backend/FileHashEntry.dart';
import 'Backend/Structures.dart';
import 'Widgets/Home/AccountsPage.dart';
import 'Widgets/Home/Dashboard.dart';
import 'Widgets/Home/Downloads.dart';
import 'Widgets/Home/Library.dart';
import 'Widgets/Home/Sidebar.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@@ -39,14 +45,38 @@ class _HomePageState extends State<HomePage> {
bool downloadRunning = false;
int unwaitingFiles = 0;
int dashboardSelectedGameIndex = 0;
String userPubKey = "loading";
@override
void initState() {
// TODO: implement initState
super.initState();
kickstartAnimations();
initData();
SetSelectedDashboardGame(0);
SetVaultUpdateLoop();
}
void SetVaultUpdateLoop() async{
while(true){
await Backend.RefreshVaultData();
setState(() {
});
await Future.delayed(const Duration(seconds: 30));
}
}
void initData()async{
userPubKey= await Backend.GetPubkey();
setState(() {
});
}
void kickstartAnimations() async {
@@ -63,11 +93,50 @@ class _HomePageState extends State<HomePage> {
Widget build(BuildContext context) {
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
Widget content = Library();
Widget content = Library(
selectedSidebarIndex: selectedSidebarIndex,
onGameChanged: SetSelectedDashboardGame,
onUpdate: (){
setState(() {
});
}
);
if (selectedSidebarIndex == 1) {
content = Dashboard();
content = Dashboard(
context: context,
downloadQueue: downloadQueue,
dashboardSelectedGameIndex: dashboardSelectedGameIndex,
missingFilesForSelectedGame: missingFilesForSelectedGame,
calculatingFiles: calculatingFiles,
isRunning: runningProcs.containsKey(dashboardSelectedGameIndex),
isUninstalling: isUninstalling,
myStatsForSelectedGame: myStatsForSelectedGame,
leaderboardForSelectedGame: leaderboardForSelectedGame,
newsForSelectedGame: newsForSelectedGame,
onSelectedGameChanged: SetSelectedDashboardGame,
onUninstallClicked: UninstallGame,
OnGameActionButtonClicked: OnGameActionButtonClicked,
onUpdate: (){
setState(() {
});
}
);
} else if (selectedSidebarIndex == 2) {
content = Downloads();
content = Downloads(
downloadQueue: downloadQueue,
downloadRunning: downloadRunning,
downloadProgress: downloadProgress,
totalDownloadSize: totalDownloadSize,
onChanged: (val){
setState(() {
SetSelectedDashboardGame(val);
});
}
);
}else if(selectedSidebarIndex == 3){
content = AccountPage();
}
@@ -83,7 +152,11 @@ class _HomePageState extends State<HomePage> {
children: [
SideBar(
width: screenWidth * 0.2,
height: screenHeight,
height: screenHeight, onChanged: (val){
setState(() {
selectedSidebarIndex = val;
});
},
),
SizedBox(
width: screenWidth * 0.8,
@@ -96,301 +169,7 @@ class _HomePageState extends State<HomePage> {
);
}
Widget Library() {
return Center(
child: Wrap(
spacing: 20,
children: List.generate(Backend.Games.length, (index) {
GameData gameData = Backend.Games[index];
return LibGameCard(gameData);
}),
),
);
}
Widget AccountPage(){
return Padding(
padding: const EdgeInsets.all(25.0),
child: Column(
children: [
Row(
children: [
Text("Hello, ${Backend.displayName}", style: TextStyle(fontSize: 30)),
],
),
],
),
);
}
Widget Downloads() {
if (downloadQueue.length <= 0) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.download_done_sharp,
size: 100,
color: Colors.white.withOpacity(0.5),
),
Text(
"No ongoing Downloads",
style:
TextStyle(fontSize: 40, color: Colors.white.withOpacity(0.4)),
),
],
),
);
}
return Container(
child: Container(
padding: EdgeInsets.all(100),
child: GlassCard(
child: Column(
children: List.generate(downloadQueue.keys.length, (index) {
int gameId = downloadQueue.keys.toList()[index];
return DownloadCard(gameId, downloadQueue[gameId]!);
}),
))));
}
Widget DownloadCard(int gameId, List<FileHashEntry> files) {
int doneSize = 0;
if (downloadProgress.containsKey(gameId)) {
Map<FileHashEntry, num> _progress = downloadProgress[gameId]!;
_progress.forEach((key, value) {
doneSize += value.toInt();
});
}
double totalSize = totalDownloadSize[gameId]! / 1024 / 1024;
double doneSizeMb = doneSize / 1024 / 1024;
double progress = doneSizeMb / totalSize;
return Padding(
padding: const EdgeInsets.all(8.0),
child: GlassCard(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[gameId].imagePath)),
borderRadius: BorderRadius.circular(50)),
width: 160,
height: 80,
),
Column(
children: [
Text(
Backend.Games[gameId].name,
style: TextStyle(fontSize: 20),
),
Text((doneSizeMb).toStringAsFixed(2) +
" MB" +
" / " +
totalSize.toStringAsFixed(2) +
" MB")
],
)
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(20, 50, 20, 20),
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.black.withOpacity(0.2),
color: Colors.blue,
),
),
),
InkWell(
child: Icon(Icons.cancel,
size: 40, color: Colors.red.withOpacity(0.6)),
onTap: () {
downloadQueue.remove(gameId);
downloadProgress.remove(gameId);
downloadRunning = false;
SetSelectedDashboardGame(gameId);
setState(() {});
},
)
// Icon(Icons.download,size: 40,color: Colors.green.withOpacity(0.4),)
],
)
],
),
)),
);
}
Widget SideBar(
{required double width, required double height, int selectedIndex = 0}) {
return GlassContainer(
child: Container(
width: width,
height: height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: [
// Padding(
// padding: const EdgeInsets.all(8.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// SizedBox(width: 10,),
// Text("10")
// ],
// ),
// ),
SizedBox(
height: 100,
),
SidebarTitle("Library", Icons.laptop_chromebook_outlined,
index: 0),
SidebarTitle("Dashboard", Icons.dashboard, index: 1),
SidebarTitle("Downloads", Icons.download, index: 2),
],
),
InkWell(
onTap:(){
setState(() {
selectedSidebarIndex=3;
});
},
child: GlassContainer(child: Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
children: [
Icon(Icons.supervised_user_circle_rounded, size: 50),
SizedBox(width: 15,),
Column(crossAxisAlignment:CrossAxisAlignment.start,children: [
Text(Backend.displayName,style: TextStyle(fontSize: 24),),
// Text("Vault credits : 50")
],)
],
),
)),
)
],
),
),
opacity: 0.15,
color: Colors.blueGrey);
}
Widget SidebarTitle(String title, IconData iconData, {int index = 0}) {
return InkWell(
onTap: () {
setState(() {
selectedSidebarIndex = index;
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 0),
child: GlassContainer(
opacity: selectedSidebarIndex == index ? 0.1 : 0,
color:
selectedSidebarIndex == index ? Colors.white : Colors.transparent,
child: Container(
height: 75,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(iconData),
SizedBox(
width: 20,
),
Text(
title,
style: TextStyle(fontSize: 20),
),
],
),
),
),
),
);
}
String hoveringGameCard = "";
Widget LibGameCard(GameData gameData) {
return InkWell(
onTap: () {
selectedSidebarIndex = 1;
SetSelectedDashboardGame(gameData.id);
},
onHover: (val) {
if (val) {
hoveringGameCard = gameData.name;
} else if (hoveringGameCard == gameData.name) {
hoveringGameCard = "";
}
setState(() {});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.black,
image: DecorationImage(
image: AssetImage(gameData.imagePath), fit: BoxFit.fill)),
height: 200,
width: 300,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
hoveringGameCard != gameData.name
? Container()
: Expanded(
child: GlassContainer(
child: Center(
child: Text(
gameData.description,
textAlign: TextAlign.center,
),
),
opacity: 0.5,
color: Colors.black)),
GlassContainer(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: true? Container():Row(
children: [
Text(gameData.name),
gameData.isAvailable
? GlassButton(
onTap: () {},
child: Text("Install"),
width: 100,
color: Colors.blue,
opacity: 0.8)
: Text("Coming soon")
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
),
opacity: 0.9,
color: Colors.black),
],
),
),
);
}
void SetSelectedDashboardGame(int i) async {
calculatingFiles = true;
@@ -448,7 +227,7 @@ class _HomePageState extends State<HomePage> {
if(runningProcs.containsKey(id)){return;}
String exePath = InstallHelper.GetExeFilePath(dashboardSelectedGameIndex);
// Process proc = await run(exePath,);
runningProcs.putIfAbsent(id, ()=> run(exePath + " username ${Backend.UserJson['username']} password ${Backend.UserJson['passwd']}"));
runningProcs.putIfAbsent(id, ()=> run(exePath + " username ${Backend.Username} password ${Backend.UserJson['passwd']}"));
setState(() {
});
@@ -475,11 +254,6 @@ class _HomePageState extends State<HomePage> {
bool isUninstalling = false;
void UninstallGame(int id) async {
if(runningProcs.containsKey(id)){return;}
// String exeFilePath = InstallHelper.GetExeFilePath(id);
// if(!File(exeFilePath).existsSync()){
// Debug.LogError("No game installed to uninstall");
// return;
// }
isUninstalling = true;
setState(() {});
@@ -592,322 +366,4 @@ class _HomePageState extends State<HomePage> {
});
});
}
Widget Dashboard() {
GameData selectedGameData = Backend.Games[dashboardSelectedGameIndex];
String filePath = InstallHelper.GetFilePath(dashboardSelectedGameIndex);
bool folderExists = Directory(filePath).existsSync();
String ActionBtnTxt = "Install";
if (missingFilesForSelectedGame.length <= 0) {
ActionBtnTxt = "Play";
} else {
ActionBtnTxt =
("Download ${FileHashEntry.getTotalSizeInMbytes(missingFilesForSelectedGame).toStringAsFixed(0)} MB");
}
if (calculatingFiles) {
ActionBtnTxt = "Validating";
}
if (downloadQueue.containsKey(dashboardSelectedGameIndex)) {
ActionBtnTxt = "Downloading";
}
if (isUninstalling) {
ActionBtnTxt = "Uninstalling";
}
if(runningProcs.containsKey(dashboardSelectedGameIndex)){
ActionBtnTxt = "Running";
}
Widget ActionButton = GlassButton(
onTap: OnGameActionButtonClicked,
child: Text(ActionBtnTxt),
width: 200,
color: Colors.blue,
opacity: 0.5,
height: 50);
final screenHeight = MediaQuery.of(context).size.height;
List<DataRow> leaderboardList = [];
// leaderboardList.add(TableRow(children: [Text("username"),Text("kills"), Text("deaths")]));
// leaderboardList.add(TableRow());
leaderboardList
.addAll(List.generate(leaderboardForSelectedGame.length, (i) {
return DataRow(cells: <DataCell>[
DataCell(Text(leaderboardForSelectedGame[i].place.toString())),
DataCell(Text(leaderboardForSelectedGame[i].username)),
DataCell(Text(leaderboardForSelectedGame[i].kills.toString())),
DataCell(Text(leaderboardForSelectedGame[i].deaths.toString())),
DataCell(Text(leaderboardForSelectedGame[i].xp.toString())),
]);
}));
return Theme(
data: ThemeData(splashColor: Colors.transparent),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
height: screenHeight * 0.18,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(
selectedGameData.name,
style: TextStyle(fontSize: 25),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate(Backend.Games.length, (index) {
bool isSelected = index == dashboardSelectedGameIndex;
return InkWell(
onTap: () {
SetSelectedDashboardGame(index);
setState(() {});
},
child: AnimatedContainer(
duration: const Duration(milliseconds: 100),
margin: EdgeInsets.all(9),
height: 80 * (isSelected ? 1.5 : 1),
width: 130 * (isSelected ? 1.5 : 1),
decoration: BoxDecoration(
image: DecorationImage(
image:
AssetImage(Backend.Games[index].imagePath),
fit: BoxFit.fill),
borderRadius: BorderRadius.circular(20)),
),
);
}),
),
],
),
),
!Backend.Games[dashboardSelectedGameIndex].isAvailable
? Center(
child: Text("Coming Soon", style: TextStyle(fontSize: 40)))
: Container(
height: screenHeight * 0.72,
child: Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
ActionButton,
PopupMenuButton<String>(
iconColor: Colors.blueGrey,
onSelected: (val) {
if (val
.toLowerCase()
.contains("uninstall")) {
UninstallGame(dashboardSelectedGameIndex);
}
},
itemBuilder: (BuildContext context) {
return {'Uninstall'}.map((String choice) {
return PopupMenuItem<String>(
value: choice,
child: Text(choice),
);
}).toList();
},
),
],
),
GlassCard(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Text("My Stats",
style:
TextStyle(color: Colors.blueGrey)),
SizedBox(
width: 50,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Kills : ${(myStatsForSelectedGame['kills'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Deaths : ${(myStatsForSelectedGame['deaths'] ?? "0")}"),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"Assist : ${(myStatsForSelectedGame['assists'] ?? "0")}"),
),
],
),
),
),
],
),
),
Container(
height: screenHeight * 0.6,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: GlassCard(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 10),
width: 350,
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(
vertical: 12.0, horizontal: 20),
child: Text(
"News",
style: TextStyle(fontSize: 20),
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: List.generate(
newsForSelectedGame.length,
(index) {
return NewsCard(
newsForSelectedGame[index]
['title'],
newsForSelectedGame[index]
['message']);
}),
),
),
)
],
),
)),
),
SizedBox(
width: 50,
),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Padding(
padding: const EdgeInsets.fromLTRB(
0, 20, 0, 0),
child: Text(
"Leaderboard",
style: TextStyle(fontSize: 20),
),
),
DataTable(
dataTextStyle:
TextStyle(color: Colors.white),
headingTextStyle:
TextStyle(color: Colors.white),
dividerThickness: 0,
columns: [
DataColumn(
label:
Expanded(child: Text("Place"))),
DataColumn(
label: Expanded(
child: Text("Username"))),
DataColumn(
label:
Expanded(child: Text("Kills"))),
DataColumn(
label: Expanded(
child: Text("Deaths"))),
DataColumn(
label: Expanded(child: Text("XP"))),
],
rows: leaderboardList,
),
],
),
),
],
))
],
),
),
Container(
//Install path footer
padding: EdgeInsets.symmetric(horizontal: 10),
alignment: Alignment.bottomCenter,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(children: [Text("Install path "), Text(filePath)]),
GlassButton(
onTap: () {
DirectoryPicker file = DirectoryPicker();
final dir = file.getDirectory();
Backend.prefs!.setString(
'${selectedGameData.name}_path', dir!.path);
setState(() {});
},
child: Text("Change Install Location"),
width: 250)
],
),
SizedBox(
height: 10,
)
],
),
)
],
),
);
}
Widget NewsCard(String title, String message) {
return Padding(
padding: const EdgeInsets.all(5.0),
child: GlassCard(
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(18.0),
child: Icon(
Icons.newspaper,
color: Colors.blueGrey,
),
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18),
textAlign: TextAlign.left,
),
Text(
message,
overflow: TextOverflow.clip,
)
],
)
],
)),
);
}
}

View File

@@ -1,12 +1,17 @@
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:mhunt_launcher/Backend/Backend.dart';
import 'package:mhunt_launcher/Backend/DebugHelper.dart';
import 'package:mhunt_launcher/Widgets/CustomWidgets.dart';
import 'package:mhunt_launcher/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_launcher/url_launcher.dart';
import 'Shared/Dialogs.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@@ -32,7 +37,6 @@ class _LoginPageState extends State<LoginPage> {
if (prefs.containsKey("username") && prefs.containsKey("password")) {
usernameController.text = prefs.getString("username") ?? '';
passwordController.text = prefs.getString("password") ?? '';
LoginOrReg();
}
}
@@ -48,6 +52,7 @@ class _LoginPageState extends State<LoginPage> {
}
TextEditingController usernameController = TextEditingController();
TextEditingController gamertagController = TextEditingController();
TextEditingController passwordController = TextEditingController();
@override
@@ -64,7 +69,7 @@ class _LoginPageState extends State<LoginPage> {
setState(() {});
},
child: Center(
child: web3LoginCard()
child: TraditionalLoginCard()
))
);
}
@@ -145,7 +150,7 @@ class _LoginPageState extends State<LoginPage> {
setState(() {
web3loginState = 1;
});
launchUrl(Uri.parse('https://auth.playpoolstudios.com/?request_id=${requestId}'));
launchUrl(Uri.parse('https://auth.playpoolstudios.com/auth/?request_id=${requestId}'));
String requestResponse = "-1";
while(requestResponse == "-1"){
await Future.delayed(const Duration(seconds: 1));
@@ -190,72 +195,120 @@ class _LoginPageState extends State<LoginPage> {
}
await Backend.Register(web3id,web3id,usernameEditingController.text);
await Backend.Login(usernameEditingController.text, web3id);
await Backend.Login(web3id, web3id);
OnLoginSuccess();
}
bool isGuest = false;
Widget TraditionalLoginCard(){
return GlassCard(
child: Container(
padding: EdgeInsets.all(25),
width: 600,
height: 400,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Text("Username "),
SizedBox(
width: 300,
child: TextField(
controller: usernameController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
Row(children: [
Text("Password "),
SizedBox(
width: 300,
child: TextField(
controller: passwordController,
))
], mainAxisAlignment: MainAxisAlignment.center),
SizedBox(
height: 30,
),
GlassButton(onTap: LoginOrReg, child: Text(isReg ? "Register" : "Login"), width: 150, height: 40),
],
),
Row(children: [
Text(isReg ? "Already have an Account? " : "Don't have an Account? "),
InkWell(
child: Text(
isReg ? "Login Here" : "Register Here",
style: TextStyle(color: Colors.blue),
),
onTap: () {
setState(() {
isReg = !isReg;
});
},
)
], mainAxisAlignment: MainAxisAlignment.center)
],
),
child: isGuest? TraditionalLoginGuest() :TraditionalLoginMain()
));
}
Widget TraditionalLoginMain(){
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
children: [
Text("Username "),
SizedBox(
width: 300,
child: TextField(
controller: usernameController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
Row(children: [
Text("Password "),
SizedBox(
width: 300,
child: TextField(
controller: passwordController,
))
], mainAxisAlignment: MainAxisAlignment.center),
SizedBox(
height: 30,
),
GlassButton(onTap: LoginOrReg, child: Text(isReg ? "Register" : "Login"), width: 150, height: 40),
],
),
Row(children: [
Text(isReg ? "Already have an Account? " : "Don't have an Account? "),
InkWell(
child: Text(
isReg ? "Login Here" : "Register Here",
style: TextStyle(color: Colors.blue),
),
onTap: () {
setState(() {
isReg = !isReg;
});
},
)
], mainAxisAlignment: MainAxisAlignment.center),
GlassButton(onTap: (){setState(() {
isGuest=true;
});}, child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.person),
SizedBox(width: 10,),
Text("Guest Mode"),
],
), width: 130, height: 30)
],
);
}
Widget TraditionalLoginGuest(){
return Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Welcome to W3B Launcher - Guest Mode",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
Column(
children: [
Row(
children: [
Text("Gamer Tag "),
SizedBox(
width: 300,
child: TextField(
controller: gamertagController,
))
],
mainAxisAlignment: MainAxisAlignment.center,
),
SizedBox(height: 15,),
SizedBox(width: 250,child:usernameExists ? Text("Username is taken",style: TextStyle(color: Colors.red),) : Container()),
GlassButton(onTap:GuestModeComplete , child: Text("Complete Login"), width: 250,height: 40,color: Colors.green)
],
),
GlassButton(onTap: (){setState(() {
isGuest=false;
});}, child: Text("Back"), width: 200, color: Colors.blueGrey)
],
);
}
void LoginOrReg() async {
// if(kDebugMode){
// Navigator.of(context).push(MaterialPageRoute(builder: (context)=>HomePage()));
@@ -268,8 +321,35 @@ class _LoginPageState extends State<LoginPage> {
success = await Backend.Login(usernameController.text, passwordController.text);
}
Debug.Log('${isReg ? "Register": "Login"} was ${success ? "success" : "faild"}');
if (success) {
OnLoginSuccess();
}else{
if(isReg){
Dialogs.showAlertDialog(context, 'Failed Register', "Username already exists");
}else{
Dialogs.showAlertDialog(context, 'Failed Login', "Username or Password is incorrect");
}
}
}
void GuestModeComplete()async{
bool usernameValidated = await Backend.GetUsernameValidation(gamertagController.text);
if(!usernameValidated){
setState(() {
usernameExists=true;
});
}
String username = await Backend.GetNextGuestUsername();
bool success= await Backend.Register(username, username, gamertagController.text);
if(success){
usernameController.text = username;
passwordController.text = username;
OnLoginSuccess();
}
}
@@ -277,7 +357,7 @@ class _LoginPageState extends State<LoginPage> {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('username', usernameController.text);
prefs.setString('password', passwordController.text);
prefs.setString('displayname', Backend.displayName);
Navigator.of(context).push(MaterialPageRoute(builder: (context) => HomePage()));
}
}