From 33be6d022125066fe9c5c0042095bbd32987315d Mon Sep 17 00:00:00 2001 From: Sewmina Date: Sat, 25 Jan 2025 12:01:14 +0530 Subject: [PATCH] sync --- android/app/build.gradle | 3 + android/app/google-services.json | 39 +++ android/settings.gradle | 3 + firebase.json | 1 + lib/Backend/Backend.dart | 75 ++++- lib/Backend/InstallHelper.dart | 2 +- lib/Shared/Helpers.dart | 4 + .../Home/AccountsPage/AccountsPage.dart | 305 ++++++++++-------- lib/Widgets/Home/AccountsPage/BuyDialog.dart | 216 +++++++++---- lib/firebase_options.dart | 83 +++++ lib/home.dart | 17 +- lib/login.dart | 84 ++++- lib/main.dart | 8 +- macos/Flutter/GeneratedPluginRegistrant.swift | 4 + pubspec.lock | 76 ++++- pubspec.yaml | 2 + .../flutter/generated_plugin_registrant.cc | 6 + windows/flutter/generated_plugins.cmake | 2 + 18 files changed, 710 insertions(+), 220 deletions(-) create mode 100644 android/app/google-services.json create mode 100644 firebase.json create mode 100644 lib/firebase_options.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 66ad64e..d30e0fe 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,5 +1,8 @@ plugins { id "com.android.application" + // START: FlutterFire Configuration + id 'com.google.gms.google-services' + // END: FlutterFire Configuration id "kotlin-android" id "dev.flutter.flutter-gradle-plugin" } diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..8c569d9 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,39 @@ +{ + "project_info": { + "project_number": "652710461284", + "project_id": "sologin-55bbd", + "storage_bucket": "sologin-55bbd.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:652710461284:android:44b78de76f4d6f88f54471", + "android_client_info": { + "package_name": "com.xperience_mhunt_launcher.mhunt_launcher" + } + }, + "oauth_client": [ + { + "client_id": "652710461284-7e2909o0bmsqqo17l4fhtkm33emh35vj.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDyWHadwDE-CAtMbKfZ7Llq18zGMDPyRpY" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "652710461284-7e2909o0bmsqqo17l4fhtkm33emh35vj.apps.googleusercontent.com", + "client_type": 3 + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 1d6d19b..816dbe0 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -20,6 +20,9 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "com.android.application" version "7.3.0" apply false + // START: FlutterFire Configuration + id "com.google.gms.google-services" version "4.3.15" apply false + // END: FlutterFire Configuration id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..2b02518 --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"sologin-55bbd","appId":"1:652710461284:android:44b78de76f4d6f88f54471","fileOutput":"android/app/google-services.json"}},"dart":{"lib/firebase_options.dart":{"projectId":"sologin-55bbd","configurations":{"android":"1:652710461284:android:44b78de76f4d6f88f54471","ios":"1:652710461284:ios:6eee89e45d69a3d1f54471","macos":"1:652710461284:ios:bae7c085a1ba8dfbf54471","windows":"1:652710461284:web:4d52a8a41d1f3ae2f54471"}}}}}} \ No newline at end of file diff --git a/lib/Backend/Backend.dart b/lib/Backend/Backend.dart index 61937a6..c81db0c 100644 --- a/lib/Backend/Backend.dart +++ b/lib/Backend/Backend.dart @@ -11,6 +11,7 @@ import 'DebugHelper.dart'; class Backend { static const String API_ENDPOINT = Helpers.WEB2_ENDPOINT; + static const String GUEST_PREFIX = "slguest"; static List Games = [ GameData(0, "mhunt", "Metahunt", "High-Stake Battle Royale game with Play to earn abilities", "images/mhunt_thumbnail.png", true, "METAHUNT.exe"), @@ -23,6 +24,7 @@ class Backend { static String displayName = ""; static String walletAddress = ""; static String pubKey = ""; + static String ticketsATA = ""; static int SolBalance =0; static int TicketsBalance = 0; @@ -32,16 +34,16 @@ class Backend { var loginResponse = null; init(); try { - loginResponse = (await http.post(Uri.parse('${API_ENDPOINT}login.php'), body: {"username": username, "password": password})); - Debug.LogResponse(loginResponse.body.toString(), src: '${API_ENDPOINT}login.php'); - + String url = '${API_ENDPOINT}login.php'; + loginResponse = (await http.post(Uri.parse(url), body: {"username": username, "password": password})); + Debug.LogResponse(loginResponse.body.toString(), src: url); if(loginResponse.body.toString().contains("no user")){ return false; } try { Username = username; - displayName = username; - + dynamic responseJson = jsonDecode(loginResponse.body.toString()); + displayName = responseJson['display_name']; SetUsernamePassword(username, password); return true; @@ -86,6 +88,8 @@ class Backend { var response = await http.get(Uri.parse(url)); Debug.LogResponse(response.body.toString(), src: url); pubKey = jsonDecode(response.body.toString())["pub_key"]; + + ticketsATA = await GetTicketsAccount(); return pubKey; } @@ -95,17 +99,51 @@ class Backend { } static Future GetSolBalance() async{ - String url ='${API_ENDPOINT}get_wallet_balance.php?wallet=${pubKey}'; - var response = await http.get(Uri.parse(url)); - Debug.LogResponse(response.body.toString(), src: url); - return jsonDecode(response.body.toString())["balance"]; + try { + String url = '${API_ENDPOINT}get_wallet_balance.php?wallet=${pubKey}'; + var response = await http.get(Uri.parse(url)); + Debug.LogResponse(response.body.toString(), src: url); + return jsonDecode(response.body.toString())["balance"]; + }catch(e){ + return 0; + } } static Future GetTicketsBalance() async{ - String url ='${API_ENDPOINT}get_tickets_balance.php?wallet=${pubKey}'; + try { + String url = '${API_ENDPOINT}get_tickets_balance.php?wallet=${pubKey}'; + var response = await http.get(Uri.parse(url)); + Debug.LogResponse(response.body.toString(), src: url); + String balanceString = jsonDecode(response.body.toString())["balance"]; + return int.parse(balanceString); + }catch(e){ + return 0; + } + } + + static Future GetTicketsAccount() async{ + try { + String url = '${Helpers.SOBRIDGE_ENDPOINT}getTicketsATA?wallet=${pubKey}'; + var response = await http.get(Uri.parse(url)); + Debug.LogResponse(response.body.toString(), src: url); + return jsonDecode(response.body.toString())["ATA"]; + }catch(e){ + return ""; + } + } + + static Future PurchaseTickets(int amount) async{ + String email = UserJson['username']; + String password = UserJson['passwd']; + String url ='${Helpers.SOBRIDGE_ENDPOINT}purchaseTickets?email=$email&password=$password&amount=$amount'; + Debug.Log("Requesting ticket purchase"); var response = await http.get(Uri.parse(url)); + Debug.LogResponse(response.body.toString(), src: url); - return jsonDecode(response.body.toString())["balance"]; + + + dynamic resJson = jsonDecode(response.body.toString()); + return resJson; } static void SetUsernamePassword(String username, String passwd) { @@ -192,7 +230,7 @@ class Backend { try { String url = '${API_ENDPOINT}get_display_name.php'; response = (await http.post(Uri.parse(url), body: {"id": id.toString()})); - Debug.LogResponse(response.body.toString(), src: url); + Debug.LogResponse(response.body.toString()+":id=${id}", src: url); return response.body; } catch (e) { @@ -235,6 +273,19 @@ class Backend { return 'guest ${random.nextInt(10000000)}'; } + static Future CreateNewRequest() async{ + try{ + String url = '${API_ENDPOINT}create_new_request.php'; + var response = await http.get(Uri.parse(url)); + Debug.LogResponse(response.body.toString(), src:url); + + return response.body.toString(); + }catch(e){ + + } + return ""; + } + static VaultData vault = VaultData('0x0', 0, 0); static Future RefreshVaultData() async{ diff --git a/lib/Backend/InstallHelper.dart b/lib/Backend/InstallHelper.dart index d7a5841..cf2c6fe 100644 --- a/lib/Backend/InstallHelper.dart +++ b/lib/Backend/InstallHelper.dart @@ -51,7 +51,7 @@ class InstallHelper{ //Get remote hashtable String link ='${Backend.API_ENDPOINT}${Backend.Games[gameId].code}/get_hashes.php'; var remoteHashResponse = (await http.post(Uri.parse(link))); - Debug.LogResponse(remoteHashResponse.body.toString(),src: link); + // Debug.LogResponse(remoteHashResponse.body.toString(),src: link); List remoteList = FileHashEntry.listFromJson(remoteHashResponse.body.toString()); //Comapreeee diff --git a/lib/Shared/Helpers.dart b/lib/Shared/Helpers.dart index 524ad92..793a7d1 100644 --- a/lib/Shared/Helpers.dart +++ b/lib/Shared/Helpers.dart @@ -1,7 +1,11 @@ class Helpers{ static const int LAMPORTS_PER_SOL = 1000000000; + static const int TICKET_PRICE = 300000000; static const String DASHBOARD_URL = 'https://auth.playpoolstudios.com'; static const String WEB2_ENDPOINT = "https://vps.playpoolstudios.com/metahunt/api/launcher/"; + static const String SOBRIDGE_ENDPOINT = "http://vps.playpoolstudios.com:20117/"; + + static const String MOONPAY_URL = 'http://vps.playpoolstudios.com:3640'; static String trimTrailingZeros(double number) { diff --git a/lib/Widgets/Home/AccountsPage/AccountsPage.dart b/lib/Widgets/Home/AccountsPage/AccountsPage.dart index b7fbbac..9bd55aa 100644 --- a/lib/Widgets/Home/AccountsPage/AccountsPage.dart +++ b/lib/Widgets/Home/AccountsPage/AccountsPage.dart @@ -2,10 +2,13 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mhunt_launcher/Shared/Helpers.dart'; import 'package:mhunt_launcher/Shared/TextStyles.dart'; +import 'package:mhunt_launcher/login.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:toastification/toastification.dart'; import 'package:url_launcher/url_launcher_string.dart'; import '../../../Backend/Backend.dart'; +import '../../../Shared/Dialogs.dart'; import '../../CustomWidgets.dart'; import 'BuyDialog.dart'; @@ -13,155 +16,201 @@ Widget AccountPage(BuildContext context, Function onUpdate) { return Padding( padding: const EdgeInsets.all(25.0), child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( + Column( children: [ - Text("Hello, ${Backend.displayName}", - style: TextStyle(fontSize: 30)), - ], - ), - SizedBox( - height: 100, - ), - GlassCard( - child: Container( - padding: const EdgeInsets.all(12.0), - margin: const EdgeInsets.symmetric(horizontal: 50), - child: Row( - mainAxisSize: MainAxisSize.min, + Row( children: [ - Column( - children: [ - Text("Solana Wallet Address", style: TextStyles.title2BTextStyle,), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text(Backend.pubKey), - InkWell( - onTap: ()async { - await Clipboard.setData(ClipboardData(text: Backend.pubKey)); - toastification.show( - context: context, // optional if you use ToastificationWrapper - title: Text('Wallet address copied to clipboard'), - autoCloseDuration: const Duration(seconds: 2), - style: ToastificationStyle.simple, - ); - }, - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: Icon(Icons.copy), - ), - ) - ], - ), - ], - ), - SizedBox(width: 50,), - Row( - children: [ - Column( - children: [ - Text("SOL Balance", style: TextStyles.title2BTextStyle,), - - Text('${Helpers.trimTrailingZeros(Backend.SolBalance / Helpers.LAMPORTS_PER_SOL).toString()} SOL') - ], - ), - InkWell( - onTap: ()async{ - await Backend.GetWalletBalance(); - onUpdate(); - }, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Icon(Icons.refresh), - ), - ) - ], - ) - ], - ), - ), - ), - SizedBox( - height: 20, - ), - 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), - ), - ], - ) + Text("Hello, ${Backend.displayName}", + style: TextStyle(fontSize: 30)), ], ), SizedBox( - width: 60, + height: 100, ), - Column( - children: [ - Text( - "Tickets", - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), - ), - Row( + GlassCard( + child: Container( + padding: const EdgeInsets.all(12.0), + margin: const EdgeInsets.symmetric(horizontal: 50), + child: Row( + mainAxisSize: MainAxisSize.min, children: [ - Icon( - Icons.airplane_ticket_rounded, - color: Colors.amber, - size: 35, - ), - Text( - Backend.TicketsBalance.toString(), - style: TextStyle(fontSize: 50), + InkWell( + onTap: (){ + launchUrlString('https://explorer.solana.com/address/${Backend.pubKey}?cluster=devnet'); + }, + child: Column( + children: [ + Text("Solana Wallet Address", style: TextStyles.title2BTextStyle,), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(Backend.pubKey), + InkWell( + onTap: ()async { + await Clipboard.setData(ClipboardData(text: Backend.pubKey)); + toastification.show( + context: context, // optional if you use ToastificationWrapper + title: Text('Wallet address copied to clipboard'), + autoCloseDuration: const Duration(seconds: 2), + style: ToastificationStyle.simple, + ); + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Icon(Icons.copy), + ), + ) + ], + ), + ], + ), ), + SizedBox(width: 50,), + Row( + children: [ + Column( + children: [ + Text("SOL Balance", style: TextStyles.title2BTextStyle,), + + Text('${Helpers.trimTrailingZeros(Backend.SolBalance / Helpers.LAMPORTS_PER_SOL).toString()} SOL') + ], + ), + InkWell( + onTap: ()async{ + await Backend.GetWalletBalance(); + onUpdate(); + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(Icons.refresh), + ), + ) + ], + ) ], ), - GlassButton( - onTap: () { - Navigator.of(context).restorablePush(buyTicketsDialogBuilder); - }, child: Text("Buy Tickets"), width: 100) - ], + ), ), - ], - ), - SizedBox( - height: 50, - ), - GlassButton( - onTap: () { - launchUrlString(Helpers.DASHBOARD_URL); - }, - child: Row( + SizedBox( + height: 20, + ), + Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("Open Dashboard"), - SizedBox( - width: 10, + 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( + "Tickets", + style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15), + ), + InkWell( + onTap: (){ + launchUrlString('https://explorer.solana.com/address/${Backend.ticketsATA}?cluster=devnet'); + }, + child: Row( + children: [ + Icon( + Icons.airplane_ticket_rounded, + color: Colors.amber, + size: 35, + ), + Text( + Backend.TicketsBalance.toString(), + style: TextStyle(fontSize: 50), + ), + ], + ), + ), + GlassButton( + onTap: (){OnPurchaseClicked(context);}, child: Text("Buy Tickets"), width: 100) + ], ), - Icon(Icons.open_in_new, color: Colors.grey) ], ), - width: 250, - height: 50) + SizedBox( + height: 50, + ), + GlassButton( + onTap: () { + launchUrlString(Helpers.DASHBOARD_URL); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Open Dashboard"), + SizedBox( + width: 10, + ), + Icon(Icons.open_in_new, color: Colors.grey) + ], + ), + width: 250, + height: 50), + + ], + + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Container(), + GlassButton( + color: Colors.red, + onTap: ()async { + var prefs = await SharedPreferences.getInstance(); + prefs.clear(); + + Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => LoginPage())); + }, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Logout"), + SizedBox( + width: 10, + ), + Icon(Icons.logout, color: Colors.grey) + ], + ), + width: 150, + height: 50), + ], + ) ], ), ); } +void OnPurchaseClicked(BuildContext context){ + Navigator.of(context).restorablePush(buyTicketsDialogBuilder); +} + + diff --git a/lib/Widgets/Home/AccountsPage/BuyDialog.dart b/lib/Widgets/Home/AccountsPage/BuyDialog.dart index dabd3b8..229b128 100644 --- a/lib/Widgets/Home/AccountsPage/BuyDialog.dart +++ b/lib/Widgets/Home/AccountsPage/BuyDialog.dart @@ -1,85 +1,183 @@ import 'package:flutter/material.dart'; +import 'package:mhunt_launcher/Widgets/CustomWidgets.dart'; +import 'package:toastification/toastification.dart'; +import 'package:url_launcher/url_launcher_string.dart'; -Route buyTicketsDialogBuilder(BuildContext context, Object? arguments) { +import '../../../Backend/Backend.dart'; +import '../../../Backend/DebugHelper.dart'; +import '../../../Shared/Dialogs.dart'; +import '../../../Shared/Helpers.dart'; +import '../../../Shared/TextStyles.dart'; + +Route buyTicketsDialogBuilder( + BuildContext context, Object? arguments) { return DialogRoute( context: context, builder: (BuildContext context) { return AlertDialog( - title: const Text('How many Tickets?'), content: PurchaseTicketsContent(), - actions: [ - TextButton( - style: TextButton.styleFrom( - textStyle: Theme.of(context).textTheme.labelLarge, - ), - child: const Text('Purchase',style: TextStyle(color: Colors.green),), - onPressed: () { - // Handle the purchase with the selected ticketCount - Navigator.of(context).pop(); - }, - ), - TextButton( - style: TextButton.styleFrom( - textStyle: Theme.of(context).textTheme.labelLarge, - ), - child: const Text('Cancel'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ], ); }, ); } - class PurchaseTicketsContent extends StatefulWidget { const PurchaseTicketsContent({super.key}); @override State createState() => _PurchaseTicketsContentState(); } + int ticketCount = 1; +bool isLoading = false; class _PurchaseTicketsContentState extends State { + + @override + void initState() { + // TODO: implement initState + super.initState(); + + isLoading=false; + setState(() { + + }); + } + @override Widget build(BuildContext context) { - return Column( - mainAxisSize: MainAxisSize.min, + return isLoading ? Row( + mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - 'Select an amount of Tickets you want to purchase', - ), - SizedBox(height: 20,), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - InkWell( - onTap: () { - setState(() { - if (ticketCount > 1) ticketCount--; - }); - }, - child: Icon(Icons.remove_circle), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - '$ticketCount', - style: TextStyle(fontSize: 40), - ), - ), - InkWell( - onTap: () { - setState(() { - ticketCount++; - }); - }, - child: Icon(Icons.add_circle_rounded), - ), - ], - ) + Text("Loading... Please wait"), ], + ) :BuyWindow( + context: context, + onTicketDecrease: () => { + setState(() { + if (ticketCount > 1) ticketCount--; + }) + }, + onTicketIncrease: () => { + setState(() { + ticketCount++; + }) + }, + onPurchase: ()async{ + setState(() { + isLoading=true; + }); + + dynamic result =await Backend.PurchaseTickets(ticketCount); + + if(result['status'] == "Success"){ + toastification.show( + context: context, // optional if you use ToastificationWrapper + title: Text('$ticketCount Tickets purchased successfully, Click to show Transaction'), + callbacks: ToastificationCallbacks( + onTap: (toastItem){ + launchUrlString('https://explorer.solana.com/tx/${result['tx']}?cluster=devnet'); + } + ), + autoCloseDuration: const Duration(seconds: 10), + style: ToastificationStyle.simple, + ); + } + + Navigator.of(context).pop(); + + } ); } -} \ No newline at end of file +} + +Widget BuyWindow( + {required BuildContext context, + required Function() onTicketDecrease, + required Function() onTicketIncrease, + required Function() onPurchase + }) { + int totalCostLamports = Helpers.TICKET_PRICE * ticketCount; + double totalCostSol = totalCostLamports / Helpers.LAMPORTS_PER_SOL; + bool hasEnoughSol = Backend.SolBalance > totalCostLamports; + Debug.Log( + 'I have ${Backend.SolBalance} LAMPORTS, Ticket price is ${totalCostLamports}, do I have enough? :${hasEnoughSol}'); + return Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Select an amount of Tickets you want to purchase', + ), + SizedBox( + height: 20, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InkWell( + onTap: onTicketDecrease, + child: Icon(Icons.remove_circle), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + '$ticketCount', + style: TextStyle(fontSize: 40), + ), + ), + InkWell( + onTap: onTicketIncrease, + child: Icon(Icons.add_circle_rounded), + ), + ], + ), + Column( + children: [ + Text( + '${Helpers.trimTrailingZeros(totalCostSol)} SOL', + style: TextStyles.titleTextStyle, + ), + (!hasEnoughSol + ? Text( + "Insufficient balance", + style: TextStyle(color: Colors.red), + ) + : Container()) + ], + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + (hasEnoughSol + ? GlassButton( + onTap: onPurchase, + child: Text("Purchase"), + width: 250, + color: Colors.green) + : GlassButton( + onTap: () { + launchUrlString( + '${Helpers.MOONPAY_URL}/?wallet=${Backend.pubKey}'); + }, + child: Text("Recharge"), + width: 250, + color: Colors.blue)), + ], + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: GlassButton( + onTap: () { + Navigator.of(context).pop(); + }, + child: Text("Cancel"), + width: 150, + color: Colors.red), + ) + ], + ); +} diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..69fa439 --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,83 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + return macos; + case TargetPlatform.windows: + return windows; + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyDyWHadwDE-CAtMbKfZ7Llq18zGMDPyRpY', + appId: '1:652710461284:android:44b78de76f4d6f88f54471', + messagingSenderId: '652710461284', + projectId: 'sologin-55bbd', + storageBucket: 'sologin-55bbd.firebasestorage.app', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyC9CtRWl698ntfegoGzdhjQjmpYNNMkTgI', + appId: '1:652710461284:ios:6eee89e45d69a3d1f54471', + messagingSenderId: '652710461284', + projectId: 'sologin-55bbd', + storageBucket: 'sologin-55bbd.firebasestorage.app', + iosClientId: '652710461284-edt1dp5nd7v5k6u0hov8hrq2fkk46bal.apps.googleusercontent.com', + iosBundleId: 'com.xperiencemhuntlauncher.mhuntLauncher', + ); + + static const FirebaseOptions macos = FirebaseOptions( + apiKey: 'AIzaSyC9CtRWl698ntfegoGzdhjQjmpYNNMkTgI', + appId: '1:652710461284:ios:bae7c085a1ba8dfbf54471', + messagingSenderId: '652710461284', + projectId: 'sologin-55bbd', + storageBucket: 'sologin-55bbd.firebasestorage.app', + iosClientId: '652710461284-7c8o89arbs7aebma2gljgi8iq06f07k6.apps.googleusercontent.com', + iosBundleId: 'com.xperiencemhuntlauncher.mhuntla', + ); + + static const FirebaseOptions windows = FirebaseOptions( + apiKey: 'AIzaSyCpATgMXv9Pu3coBwljh0uv9I9ciFkBJIA', + appId: '1:652710461284:web:4d52a8a41d1f3ae2f54471', + messagingSenderId: '652710461284', + projectId: 'sologin-55bbd', + authDomain: 'sologin-55bbd.firebaseapp.com', + storageBucket: 'sologin-55bbd.firebasestorage.app', + measurementId: 'G-8NTXQZGV4P', + ); +} diff --git a/lib/home.dart b/lib/home.dart index 499f763..06ef930 100644 --- a/lib/home.dart +++ b/lib/home.dart @@ -14,6 +14,7 @@ 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:toastification/toastification.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'Backend/DebugHelper.dart'; import 'package:http/http.dart' as http; @@ -47,7 +48,6 @@ class _HomePageState extends State { int dashboardSelectedGameIndex = 0; String userPubKey = "loading"; - @override void initState() { // TODO: implement initState @@ -74,9 +74,24 @@ class _HomePageState extends State { void initData()async{ userPubKey= await Backend.GetPubkey(); + await Backend.GetWalletBalance(); setState(() { }); + + Debug.Log("Logged in as " + Backend.Username); + if(Backend.Username.contains(Backend.GUEST_PREFIX)){ + Debug.Log("Guest mode on"); + toastification.show( + context: context, // optional if you use ToastificationWrapper + title: Text('You are in guest Mode\n Link a social account to secure your login'), + autoCloseDuration: const Duration(seconds: 10), + showIcon: true, + backgroundColor: Colors.amber, + foregroundColor: Colors.red, + icon: Icon(Icons.warning,color: Colors.red,) + ); + } } void kickstartAnimations() async { diff --git a/lib/login.dart b/lib/login.dart index f03093c..5ec0d51 100644 --- a/lib/login.dart +++ b/lib/login.dart @@ -1,5 +1,7 @@ +import 'dart:convert'; import 'dart:math'; +import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; @@ -29,7 +31,7 @@ class _LoginPageState extends State { kickstartAnimations(); - //autoLogin(); + autoLogin(); } void autoLogin() async { @@ -145,6 +147,7 @@ class _LoginPageState extends State { } int web3loginState = 0; String web3id = ""; + void loginWeb3() async{ String requestId = await Backend.CreateRequest(); setState(() { @@ -156,8 +159,11 @@ class _LoginPageState extends State { await Future.delayed(const Duration(seconds: 1)); requestResponse = await Backend.GetRequestResponse(requestId); } + Debug.Log("Signing with firebase auth"); - web3id = requestResponse; + UserCredential user = await FirebaseAuth.instance.signInWithCustomToken(requestResponse); + Debug.Log(jsonEncode(user.user)); + web3id = user.user?.displayName ?? "null"; String dispName = await Backend.GetDisplayName(web3id); if(dispName == "-1"){ setState(() { @@ -221,10 +227,11 @@ class _LoginPageState extends State { ), Column( mainAxisAlignment: MainAxisAlignment.center, + children: [ Row( children: [ - Text("Username "), + Text("Email address"), SizedBox( width: 300, child: TextField( @@ -261,6 +268,35 @@ class _LoginPageState extends State { }, ) ], mainAxisAlignment: MainAxisAlignment.center), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + GlassButton(onTap: ()=>{ + HandleExternalLogin("google") + }, color: Colors.green, child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Icon(Icons.g_mobiledata,size: 25,), + Text("Sign in with Google"), + SizedBox() + ], + ), + ), width: 200, height: 40), + GlassButton(onTap: (){}, color: Colors.grey, child: Container( + padding: EdgeInsets.symmetric(horizontal: 10), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Icon(Icons.g_mobiledata,size: 25,), + Text("Sign in with Github"), + SizedBox() + ], + ), + ), width: 200, height: 40) + ], + ), GlassButton(onTap: (){setState(() { isGuest=true; });}, child: Row( @@ -275,6 +311,31 @@ class _LoginPageState extends State { ); } + Future HandleExternalLogin(String provider) async { + String newId = await Backend.CreateNewRequest(); + + String url = 'https://sologin.playpoolstudios.com/external_auth?provider=${provider}&id=${newId}'; + + launchUrl(Uri.parse(url)); + + String requestResponse = ""; + while(requestResponse == ""){ + await Future.delayed(const Duration(seconds: 1)); + requestResponse = (await Backend.GetRequestResponse(newId)).replaceAll(" ", ""); + } + UserCredential user = await FirebaseAuth.instance.signInWithCustomToken(requestResponse); + web3id = user.user?.uid ?? ""; + String dispName = await Backend.GetDisplayName(web3id); + if(dispName == "-1"){ + setState(() { + web3loginState = 2; + }); + }else{ + usernameEditingController.text = dispName; + completeweb3(); + } + } + Widget TraditionalLoginGuest(){ return Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -351,21 +412,28 @@ class _LoginPageState extends State { return; } - String username = await Backend.GetNextGuestUsername(); - bool success= await Backend.Register(username, username, gamertagController.text); - - if(success){ + // String username = Backend.GUEST_PREFIX + await Backend.GetNextGuestUsername(); + String username = ""; + try { + final userCredential = await FirebaseAuth.instance.signInAnonymously(); + username = userCredential.user?.uid ?? ""; + }catch(e){ + Dialogs.showAlertDialog(context, "Error", e.toString()); + } + if(username.length > 2){ + bool success= await Backend.Register(username, username, gamertagController.text); usernameController.text = username; passwordController.text = username; OnLoginSuccess(); } } + void OnLoginSuccess() async{ 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())); + Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => HomePage())); } } diff --git a/lib/main.dart b/lib/main.dart index a10644d..5a77c4a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,8 +1,14 @@ +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:mhunt_launcher/checking_update.dart'; import 'package:mhunt_launcher/login.dart'; +import 'firebase_options.dart'; -void main() { +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); runApp(const MyApp()); } diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b19945c..1ed9bba 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,11 +5,15 @@ import FlutterMacOS import Foundation +import firebase_auth +import firebase_core import path_provider_foundation import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) diff --git a/pubspec.lock b/pubspec.lock index ecaf8b8..d6acbd4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "71c01c1998c40b3af1944ad0a5f374b4e6fef7f3d2df487f3970dbeadaeb25a1" + url: "https://pub.dev" + source: hosted + version: "1.3.46" args: dependency: transitive description: @@ -113,6 +121,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "49c356bac95ed234805e3bb928a86d5b21a4d3745d77be53ecf2d61409ddb802" + url: "https://pub.dev" + source: hosted + version: "5.3.3" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "9bc336ce673ea90a9dbdb04f0e9a3e52a32321898dc869cdefe6cc0f0db369ed" + url: "https://pub.dev" + source: hosted + version: "7.4.9" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: "56dcce4293e2a2c648c33ab72c09e888bd0e64cbb1681a32575ec9dc9c2f67f3" + url: "https://pub.dev" + source: hosted + version: "5.13.4" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "2438a75ad803e818ad3bd5df49137ee619c46b6fc7101f4dbc23da07305ce553" + url: "https://pub.dev" + source: hosted + version: "3.8.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 + url: "https://pub.dev" + source: hosted + version: "5.3.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 + url: "https://pub.dev" + source: hosted + version: "2.18.1" fixnum: dependency: transitive description: @@ -156,10 +212,10 @@ packages: dependency: "direct main" description: name: http - sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" http_parser: dependency: transitive description: @@ -388,10 +444,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" + sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "2.2.1" shared_preferences_windows: dependency: transitive description: @@ -537,10 +593,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.3" url_launcher_windows: dependency: transitive description: @@ -577,10 +633,10 @@ packages: dependency: transitive description: name: web - sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "1.1.0" win32: dependency: transitive description: @@ -606,5 +662,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.3.1 <4.0.0" - flutter: ">=3.19.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index a152fc5..61f0204 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,6 +45,8 @@ dependencies: url_launcher: ^6.2.6 flutter_spinkit: ^5.2.1 toastification: ^2.3.0 + firebase_core: ^3.8.0 + firebase_auth: ^5.3.3 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 4f78848..869eeca 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,9 +6,15 @@ #include "generated_plugin_registrant.h" +#include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseAuthPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseAuthPluginCApi")); + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 88b22e5..7ba8383 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,8 @@ # list(APPEND FLUTTER_PLUGIN_LIST + firebase_auth + firebase_core url_launcher_windows )