Refactored
This commit is contained in:
parent
fc1f6189e6
commit
2714797fcc
BIN
images/token.png
Normal file
BIN
images/token.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
images/vault.png
Normal file
BIN
images/vault.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
39
lib/Shared/Dialogs.dart
Normal 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;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
75
lib/Widgets/Home/AccountsPage.dart
Normal file
75
lib/Widgets/Home/AccountsPage.dart
Normal 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)
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
342
lib/Widgets/Home/Dashboard.dart
Normal file
342
lib/Widgets/Home/Dashboard.dart
Normal 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,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
129
lib/Widgets/Home/Downloads.dart
Normal file
129
lib/Widgets/Home/Downloads.dart
Normal 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 );
|
||||
}),
|
||||
))));
|
||||
}
|
||||
98
lib/Widgets/Home/Library.dart
Normal file
98
lib/Widgets/Home/Library.dart
Normal 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),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
127
lib/Widgets/Home/Sidebar.dart
Normal file
127
lib/Widgets/Home/Sidebar.dart
Normal 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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -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(() {
|
||||
|
||||
|
|
|
|||
700
lib/home.dart
700
lib/home.dart
|
|
@ -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,
|
||||
)
|
||||
],
|
||||
)
|
||||
],
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
194
lib/login.dart
194
lib/login.dart
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
BIN
ota/Microsoft.CSharp.dll
Normal file
BIN
ota/Microsoft.CSharp.dll
Normal file
Binary file not shown.
BIN
ota/Microsoft.DiaSymReader.Native.amd64.dll
Normal file
BIN
ota/Microsoft.DiaSymReader.Native.amd64.dll
Normal file
Binary file not shown.
BIN
ota/Microsoft.VisualBasic.Core.dll
Normal file
BIN
ota/Microsoft.VisualBasic.Core.dll
Normal file
Binary file not shown.
BIN
ota/Microsoft.VisualBasic.dll
Normal file
BIN
ota/Microsoft.VisualBasic.dll
Normal file
Binary file not shown.
BIN
ota/Microsoft.Win32.Primitives.dll
Normal file
BIN
ota/Microsoft.Win32.Primitives.dll
Normal file
Binary file not shown.
BIN
ota/Microsoft.Win32.Registry.dll
Normal file
BIN
ota/Microsoft.Win32.Registry.dll
Normal file
Binary file not shown.
BIN
ota/Newtonsoft.Json.dll
Normal file
BIN
ota/Newtonsoft.Json.dll
Normal file
Binary file not shown.
BIN
ota/System.AppContext.dll
Normal file
BIN
ota/System.AppContext.dll
Normal file
Binary file not shown.
BIN
ota/System.Buffers.dll
Normal file
BIN
ota/System.Buffers.dll
Normal file
Binary file not shown.
BIN
ota/System.Collections.Concurrent.dll
Normal file
BIN
ota/System.Collections.Concurrent.dll
Normal file
Binary file not shown.
BIN
ota/System.Collections.Immutable.dll
Normal file
BIN
ota/System.Collections.Immutable.dll
Normal file
Binary file not shown.
BIN
ota/System.Collections.NonGeneric.dll
Normal file
BIN
ota/System.Collections.NonGeneric.dll
Normal file
Binary file not shown.
BIN
ota/System.Collections.Specialized.dll
Normal file
BIN
ota/System.Collections.Specialized.dll
Normal file
Binary file not shown.
BIN
ota/System.Collections.dll
Normal file
BIN
ota/System.Collections.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.Annotations.dll
Normal file
BIN
ota/System.ComponentModel.Annotations.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.DataAnnotations.dll
Normal file
BIN
ota/System.ComponentModel.DataAnnotations.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.EventBasedAsync.dll
Normal file
BIN
ota/System.ComponentModel.EventBasedAsync.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.Primitives.dll
Normal file
BIN
ota/System.ComponentModel.Primitives.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.TypeConverter.dll
Normal file
BIN
ota/System.ComponentModel.TypeConverter.dll
Normal file
Binary file not shown.
BIN
ota/System.ComponentModel.dll
Normal file
BIN
ota/System.ComponentModel.dll
Normal file
Binary file not shown.
BIN
ota/System.Configuration.dll
Normal file
BIN
ota/System.Configuration.dll
Normal file
Binary file not shown.
BIN
ota/System.Console.dll
Normal file
BIN
ota/System.Console.dll
Normal file
Binary file not shown.
BIN
ota/System.Core.dll
Normal file
BIN
ota/System.Core.dll
Normal file
Binary file not shown.
BIN
ota/System.Data.Common.dll
Normal file
BIN
ota/System.Data.Common.dll
Normal file
Binary file not shown.
BIN
ota/System.Data.DataSetExtensions.dll
Normal file
BIN
ota/System.Data.DataSetExtensions.dll
Normal file
Binary file not shown.
BIN
ota/System.Data.dll
Normal file
BIN
ota/System.Data.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.Contracts.dll
Normal file
BIN
ota/System.Diagnostics.Contracts.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.Debug.dll
Normal file
BIN
ota/System.Diagnostics.Debug.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.DiagnosticSource.dll
Normal file
BIN
ota/System.Diagnostics.DiagnosticSource.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.FileVersionInfo.dll
Normal file
BIN
ota/System.Diagnostics.FileVersionInfo.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.Process.dll
Normal file
BIN
ota/System.Diagnostics.Process.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.StackTrace.dll
Normal file
BIN
ota/System.Diagnostics.StackTrace.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.TextWriterTraceListener.dll
Normal file
BIN
ota/System.Diagnostics.TextWriterTraceListener.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.Tools.dll
Normal file
BIN
ota/System.Diagnostics.Tools.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.TraceSource.dll
Normal file
BIN
ota/System.Diagnostics.TraceSource.dll
Normal file
Binary file not shown.
BIN
ota/System.Diagnostics.Tracing.dll
Normal file
BIN
ota/System.Diagnostics.Tracing.dll
Normal file
Binary file not shown.
BIN
ota/System.Drawing.Primitives.dll
Normal file
BIN
ota/System.Drawing.Primitives.dll
Normal file
Binary file not shown.
BIN
ota/System.Drawing.dll
Normal file
BIN
ota/System.Drawing.dll
Normal file
Binary file not shown.
BIN
ota/System.Dynamic.Runtime.dll
Normal file
BIN
ota/System.Dynamic.Runtime.dll
Normal file
Binary file not shown.
BIN
ota/System.Formats.Asn1.dll
Normal file
BIN
ota/System.Formats.Asn1.dll
Normal file
Binary file not shown.
BIN
ota/System.Formats.Tar.dll
Normal file
BIN
ota/System.Formats.Tar.dll
Normal file
Binary file not shown.
BIN
ota/System.Globalization.Calendars.dll
Normal file
BIN
ota/System.Globalization.Calendars.dll
Normal file
Binary file not shown.
BIN
ota/System.Globalization.Extensions.dll
Normal file
BIN
ota/System.Globalization.Extensions.dll
Normal file
Binary file not shown.
BIN
ota/System.Globalization.dll
Normal file
BIN
ota/System.Globalization.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Compression.Brotli.dll
Normal file
BIN
ota/System.IO.Compression.Brotli.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Compression.FileSystem.dll
Normal file
BIN
ota/System.IO.Compression.FileSystem.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Compression.Native.dll
Normal file
BIN
ota/System.IO.Compression.Native.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Compression.ZipFile.dll
Normal file
BIN
ota/System.IO.Compression.ZipFile.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Compression.dll
Normal file
BIN
ota/System.IO.Compression.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.FileSystem.AccessControl.dll
Normal file
BIN
ota/System.IO.FileSystem.AccessControl.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.FileSystem.DriveInfo.dll
Normal file
BIN
ota/System.IO.FileSystem.DriveInfo.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.FileSystem.Primitives.dll
Normal file
BIN
ota/System.IO.FileSystem.Primitives.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.FileSystem.Watcher.dll
Normal file
BIN
ota/System.IO.FileSystem.Watcher.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.FileSystem.dll
Normal file
BIN
ota/System.IO.FileSystem.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.IsolatedStorage.dll
Normal file
BIN
ota/System.IO.IsolatedStorage.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.MemoryMappedFiles.dll
Normal file
BIN
ota/System.IO.MemoryMappedFiles.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Pipes.AccessControl.dll
Normal file
BIN
ota/System.IO.Pipes.AccessControl.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.Pipes.dll
Normal file
BIN
ota/System.IO.Pipes.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.UnmanagedMemoryStream.dll
Normal file
BIN
ota/System.IO.UnmanagedMemoryStream.dll
Normal file
Binary file not shown.
BIN
ota/System.IO.dll
Normal file
BIN
ota/System.IO.dll
Normal file
Binary file not shown.
BIN
ota/System.Linq.Expressions.dll
Normal file
BIN
ota/System.Linq.Expressions.dll
Normal file
Binary file not shown.
BIN
ota/System.Linq.Parallel.dll
Normal file
BIN
ota/System.Linq.Parallel.dll
Normal file
Binary file not shown.
BIN
ota/System.Linq.Queryable.dll
Normal file
BIN
ota/System.Linq.Queryable.dll
Normal file
Binary file not shown.
BIN
ota/System.Linq.dll
Normal file
BIN
ota/System.Linq.dll
Normal file
Binary file not shown.
BIN
ota/System.Memory.dll
Normal file
BIN
ota/System.Memory.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Http.Json.dll
Normal file
BIN
ota/System.Net.Http.Json.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Http.dll
Normal file
BIN
ota/System.Net.Http.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.HttpListener.dll
Normal file
BIN
ota/System.Net.HttpListener.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Mail.dll
Normal file
BIN
ota/System.Net.Mail.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.NameResolution.dll
Normal file
BIN
ota/System.Net.NameResolution.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.NetworkInformation.dll
Normal file
BIN
ota/System.Net.NetworkInformation.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Ping.dll
Normal file
BIN
ota/System.Net.Ping.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Primitives.dll
Normal file
BIN
ota/System.Net.Primitives.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Quic.dll
Normal file
BIN
ota/System.Net.Quic.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Requests.dll
Normal file
BIN
ota/System.Net.Requests.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Security.dll
Normal file
BIN
ota/System.Net.Security.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.ServicePoint.dll
Normal file
BIN
ota/System.Net.ServicePoint.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.Sockets.dll
Normal file
BIN
ota/System.Net.Sockets.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.WebClient.dll
Normal file
BIN
ota/System.Net.WebClient.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.WebHeaderCollection.dll
Normal file
BIN
ota/System.Net.WebHeaderCollection.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.WebProxy.dll
Normal file
BIN
ota/System.Net.WebProxy.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.WebSockets.Client.dll
Normal file
BIN
ota/System.Net.WebSockets.Client.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.WebSockets.dll
Normal file
BIN
ota/System.Net.WebSockets.dll
Normal file
Binary file not shown.
BIN
ota/System.Net.dll
Normal file
BIN
ota/System.Net.dll
Normal file
Binary file not shown.
BIN
ota/System.Numerics.Vectors.dll
Normal file
BIN
ota/System.Numerics.Vectors.dll
Normal file
Binary file not shown.
BIN
ota/System.Numerics.dll
Normal file
BIN
ota/System.Numerics.dll
Normal file
Binary file not shown.
BIN
ota/System.ObjectModel.dll
Normal file
BIN
ota/System.ObjectModel.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user