Compare commits

...

2 commits

5 changed files with 112 additions and 20 deletions

View file

@ -1,3 +1,3 @@
// lib/globals.dart
const String apiurl = "https://api.dthpp.mercurio.moe";
//const String apiurl = "http://10.0.0.10:9134";
//const String apiurl = "http://192.168.1.120:9134";

View file

@ -7,6 +7,9 @@ import 'views/joinmatch.dart';
import 'views/creatematch.dart';
import 'views/friendlist.dart';
import 'views/myprofile.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import '../globals.dart';
class HomePage extends StatefulWidget {
@override
@ -16,7 +19,6 @@ class HomePage extends StatefulWidget {
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
// Define the pages for each section
final List<Widget> _pages = [
LeaderboardPage(),
JoinMatchPage(),
@ -40,14 +42,46 @@ class _HomePageState extends State<HomePage> {
);
}
Future<Map<String, String>> fetchCommitHashes() async {
const apiUrl = '$apiurl/version';
try {
final response = await http.get(Uri.parse(apiUrl));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
String formatHash(String? hash) {
if (hash == null) return 'Unknown';
return '#${hash.substring(0, 8).toUpperCase()}';
}
return {
'backend': formatHash(data['backend']),
'frontend': formatHash(data['frontend']),
};
} else {
throw Exception('Failed to fetch commit hashes');
}
} catch (e) {
return {
'backend': 'Error fetching hash',
'frontend': 'Error fetching hash',
};
}
}
Future<void> _showOpenSourceLicenses() async {
final commitHashes = await fetchCommitHashes();
showDialog(
context: context,
builder: (BuildContext context) => AboutDialog(
applicationIcon: const Icon(Icons.code),
applicationLegalese: '© 2024 Thomas Bassi @ Defence Tech.',
applicationName: 'DTHPP',
applicationVersion: '#B22AF349A1',
applicationVersion:
'API: ${commitHashes['backend']} - UI: ${commitHashes['frontend']}',
children: [
Padding(
padding: const EdgeInsets.only(top: 16.0),

View file

@ -4,6 +4,8 @@ import 'package:http/http.dart' as http;
import 'dart:convert';
import 'home.dart';
import '../globals.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
class LoginPage extends StatefulWidget {
@override
@ -21,6 +23,17 @@ class _LoginPageState extends State<LoginPage> {
Future<void> _handleAuth() async {
final email = _emailController.text.trim();
final password = _passwordController.text.trim();
final displayName = _displayNameController.text.trim();
// Input validation
if (email.isEmpty ||
password.isEmpty ||
(!_isLogin && displayName.isEmpty)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Please fill in all required fields.')),
);
return;
}
setState(() {
_isLoading = true;
@ -36,8 +49,7 @@ class _LoginPageState extends State<LoginPage> {
context, MaterialPageRoute(builder: (context) => HomePage()));
}
} else {
final uid = await _register(
email, password, _displayNameController.text.trim());
final uid = await _register(email, password, displayName);
if (uid != null) {
setState(() {
_isLogin = true;
@ -118,21 +130,61 @@ class _LoginPageState extends State<LoginPage> {
decoration: InputDecoration(labelText: 'Display Name'),
),
const SizedBox(height: 20),
_isLoading
? CircularProgressIndicator()
: ElevatedButton(
if (_isLoading)
CircularProgressIndicator()
else
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: _handleAuth,
child: Text(_isLogin ? 'Login' : 'Register'),
),
TextButton(
ElevatedButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin
? 'Don\'t have an account? Register'
: 'Already have an account? Login'),
child: Text(_isLogin ? 'Register' : 'Back to Login'),
),
],
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
icon: Icon(FontAwesomeIcons.github),
onPressed: () async {
final url = Uri.parse(
'https://git.mercurio.moe/Mercury/dth-pingpong-mobileapp');
if (await canLaunchUrl(url)) {
await launchUrl(
url,
mode: LaunchMode
.externalApplication, // Ensures it opens in the browser
);
} else {
throw 'Could not launch $url';
}
}),
IconButton(
icon: Icon(FontAwesomeIcons.chartSimple),
onPressed: () async {
final url =
Uri.parse('https://kuma.mercurio.moe/status/dthpp');
if (await canLaunchUrl(url)) {
await launchUrl(
url,
mode: LaunchMode
.externalApplication, // Ensures it opens in the browser
);
} else {
throw 'Could not launch $url';
}
}),
],
),
],
),

View file

@ -13,10 +13,8 @@ class _CreateMatchPageState extends State<CreateMatchPage> {
String? _matchId;
bool _isLoading = false;
final String _createMatchApiUrl =
'$apiurl/creatematch'; // Replace with your API endpoint
final String _createMatchApiUrl = '$apiurl/creatematch';
// Method to create a match
Future<void> _createMatch() async {
setState(() {
_isLoading = true;
@ -90,6 +88,12 @@ class _CreateMatchPageState extends State<CreateMatchPage> {
textAlign: TextAlign.center,
),
SizedBox(height: 16),
Text(
'Due to current limitations in how we handle matchmaking, only the joining player can control the match. This is only a temporary solution to a problem we are actively fixing.',
style: TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
SizedBox(height: 16),
_isLoading
? CircularProgressIndicator() // Show loading spinner
: ElevatedButton(

View file

@ -15,6 +15,8 @@ dependencies:
http: ^1.2.2
logger: ^2.5.0
package_info: ^2.0.2
font_awesome_flutter: ^10.8.0
url_launcher: ^6.3.1
dev_dependencies:
flutter_test: