Skip to content

Commit

Permalink
Merge branch 'master' into es999/fa24-name-update
Browse files Browse the repository at this point in the history
  • Loading branch information
shah-esha authored Jan 23, 2025
2 parents 0084de6 + f3156f1 commit 39eb31c
Show file tree
Hide file tree
Showing 20 changed files with 386 additions and 142 deletions.
2 changes: 1 addition & 1 deletion game/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ apply from: project(':flutter_config').projectDir.getPath() + "/dotenv.gradle"


android {
compileSdkVersion 33
compileSdkVersion 34

sourceSets {
main.java.srcDirs += 'src/main/kotlin'
Expand Down
2 changes: 1 addition & 1 deletion game/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Firebase
import GoogleMaps
import flutter_config

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
33 changes: 27 additions & 6 deletions game/lib/api/game_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,14 @@ class ApiClient extends ChangeNotifier {
_createSocket(false);
return loginResponse;
} else {
print(loginResponse.body);
}
authenticated = false;
notifyListeners();
print("LoginResponse:" + loginResponse.body);

print("Failed to connect to server!");
return null;
authenticated = false;
notifyListeners();

print("Failed to connect to server!");
return null;
}
/*
}
print("Failed to get location data!");
Expand All @@ -243,4 +244,24 @@ class ApiClient extends ChangeNotifier {
authenticated = false;
notifyListeners();
}

Future<bool> checkUserExists(String idToken) async {
try {
final uri = _googleLoginUrl.replace(
path: '${_googleLoginUrl.path}/check-user',
queryParameters: {'idToken': idToken},
);
final response = await http.get(uri);

if (response.statusCode == 200) {
final responseData = jsonDecode(response.body);
return responseData['exists'];
}
print('Failed to check user. Status code: ${response.statusCode}');
return false;
} catch (e) {
print('Error occurred while checking user: $e');
return false;
}
}
}
16 changes: 10 additions & 6 deletions game/lib/api/game_server_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,21 @@ class GameServerApi {

Future<dynamic> _invokeWithRefresh(String ev, Map<String, dynamic> data) {
Completer<dynamic> completer = Completer();
bool isCompleted = false;

final completionFunc = (arg) {
if (completer.isCompleted) {
return;
if (!isCompleted) {
isCompleted = true;
completer.complete(arg);
}

completer.complete(arg);
};

Future.delayed(Duration(seconds: 5))
.then((value) => completer.complete(null));
Future.delayed(Duration(seconds: 5)).then((_) {
if (!isCompleted) {
isCompleted = true;
completer.completeError(TimeoutException('Operation timed out'));
}
});

_refreshEv = ev;
_refreshDat = data;
Expand Down
4 changes: 3 additions & 1 deletion game/lib/api/geopoint.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,16 @@ class GeoPoint {
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
print("Getting location");
final pos = await Geolocator.getCurrentPosition(
// Ideally we would use best accuracy, but it doesn't work for some reason
// desiredAccuracy: LocationAccuracy.best
desiredAccuracy: LocationAccuracy.medium);
print("Got location: ${pos.latitude}, ${pos.longitude}");
return GeoPoint(pos.latitude, pos.longitude, pos.heading);
} catch (e) {
print(e);
return Future.error(e.toString());
return Future.error("Error:" + e.toString());
}
}

Expand Down
81 changes: 58 additions & 23 deletions game/lib/challenges/challenge_cell.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,26 @@ import 'package:flutter/material.dart';
import 'package:game/preview/preview.dart';
import 'package:flutter_svg/flutter_svg.dart';

/**
* `ChallengeCell` Widget - Individual challenge display component.
*
* @remarks
* This widget represents a single challenge card in the challenges list.
* It displays key information about a challenge and handles tap interactions
* to show more details.
*
* @param props - Contains:
* - `location`: Challenge location
* - `challengeName`: Name of the challenge
* - `challengeLat`: Latitude coordinate
* - `challengeLong`: Longitude coordinate
* - `imgUrl`: Challenge image URL
* - `isCompleted`: Completion status
* - `description`: Challenge description
* - `difficulty`: Challenge difficulty level
* - `points`: Points awarded for completion
* - `eventId`: Unique identifier for the challenge
*/
class ChallengeCell extends StatefulWidget {
final String location;
final String challengeName;
Expand Down Expand Up @@ -73,6 +93,9 @@ class _ChallengeCellState extends State<ChallengeCell> {

@override
Widget build(BuildContext context) {
double deviceWidth = MediaQuery.sizeOf(context).width;
double deviceHeight = MediaQuery.sizeOf(context).height;

return GestureDetector(
onTap: () async {
await showModalBottomSheet(
Expand Down Expand Up @@ -105,8 +128,8 @@ class _ChallengeCellState extends State<ChallengeCell> {
),
],
),
height: MediaQuery.sizeOf(context).height * 0.15,
width: MediaQuery.sizeOf(context).width * 0.85,
height: deviceHeight * 0.15,
width: deviceWidth * 0.85,
child: Padding(
padding: EdgeInsets.all(16),
child: Row(
Expand All @@ -117,8 +140,8 @@ class _ChallengeCellState extends State<ChallengeCell> {
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(4.6)),
child: Image.network(imgUrl,
width: MediaQuery.sizeOf(context).height * 0.1,
height: MediaQuery.sizeOf(context).height * 0.1,
width: deviceHeight * 0.1,
height: deviceHeight * 0.1,
fit: BoxFit.cover),
),
),
Expand All @@ -128,19 +151,25 @@ class _ChallengeCellState extends State<ChallengeCell> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
padding: EdgeInsets.symmetric(
vertical: MediaQuery.sizeOf(context).height * 0.005,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(Icons.location_on,
size: 20,
size: MediaQuery.sizeOf(context).height * 0.025,
color: Color.fromARGB(255, 131, 90, 124)),
Text(
location,
style: TextStyle(
color: Color.fromARGB(255, 131, 90, 124),
fontSize: 14,
fontFamily: 'Poppins',
Expanded(
child: Text(
location,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Color.fromARGB(255, 131, 90, 124),
fontSize:
MediaQuery.sizeOf(context).height * 0.016,
fontFamily: 'Poppins',
),
),
),
],
Expand All @@ -149,9 +178,10 @@ class _ChallengeCellState extends State<ChallengeCell> {
Spacer(),
Text(
challengeName,
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: Color.fromARGB(204, 0, 0, 0),
fontSize: 16.5,
fontSize: deviceHeight * 0.02,
fontFamily: 'Poppins',
fontWeight: FontWeight.w600,
),
Expand All @@ -161,8 +191,10 @@ class _ChallengeCellState extends State<ChallengeCell> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 2),
padding: EdgeInsets.symmetric(
horizontal: deviceWidth * 0.02,
vertical: deviceHeight * 0.003,
),
decoration: BoxDecoration(
color: Color.fromARGB(255, 249, 237, 218),
borderRadius: BorderRadius.circular(20),
Expand All @@ -171,23 +203,26 @@ class _ChallengeCellState extends State<ChallengeCell> {
difficulty,
style: TextStyle(
color: Color.fromARGB(204, 0, 0, 0),
fontSize: 14,
fontSize: deviceHeight * 0.016,
fontFamily: 'Poppins',
fontWeight: FontWeight.w300,
),
),
),
SizedBox(width: 10),
SizedBox(width: deviceWidth * 0.02),
Row(children: [
SvgPicture.asset(
"assets/icons/bearcoins.svg",
width: 25,
width: deviceWidth * 0.06,
),
Text(
' ' + points.toString() + " PTS",
style: TextStyle(
fontSize: deviceHeight * 0.018,
fontWeight: FontWeight.w500,
color: Color(0xFFC17E19),
),
),
Text(' ' + points.toString() + " PTS",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Color(0xFFC17E19)))
]),
],
),
Expand Down
51 changes: 42 additions & 9 deletions game/lib/gameplay/gameplay_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@ import 'package:game/model/group_model.dart';
import 'package:game/model/event_model.dart';
import 'package:game/model/challenge_model.dart';

/// GameplayMap Widget
///
/// Displays an interactive map for gameplay, showing the user's location,
/// hint circles, and challenge-related information.
///
/// @remarks
/// This widget is responsible for handling user location updates, displaying
/// hints, and managing the challenge completion process. It uses Google Maps
/// for rendering the map and integrates with various game-related models and
/// APIs to provide a seamless gameplay experience.
///
/// @param challengeId - The unique identifier for the current challenge.
/// @param targetLocation - The GeoPoint representing the target location for the challenge.
/// @param awardingRadius - The radius (in meters) within which the challenge is considered complete.
/// @param points - The number of points awarded for completing this challenge.
/// @param startingHintsUsed - The number of hints already used for this challenge.
///
/// @returns A StatefulWidget that renders the gameplay map and associated UI elements
class GameplayMap extends StatefulWidget {
final String challengeId;
final GeoPoint targetLocation;
Expand Down Expand Up @@ -70,6 +89,9 @@ class _GameplayMapState extends State<GameplayMap> {
// whether the picture is expanded over the map
bool isExpanded = false;

// Add this to your state variables (After isExapnded)
bool isArrivedButtonEnabled = true;

@override
void initState() {
setCustomMarkerIcon();
Expand Down Expand Up @@ -400,18 +422,25 @@ class _GameplayMapState extends State<GameplayMap> {
padding:
EdgeInsets.only(right: 15, left: 15, top: 10, bottom: 10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10), // button's shape
borderRadius: BorderRadius.circular(10),
),
),
child: Text(
"I've Arrived!",
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 21,
fontWeight: FontWeight.w400,
color: Color(0xFFFFFFFF)),
fontFamily: 'Poppins',
fontSize: 21,
fontWeight: FontWeight.w400,
color: Color(0xFFFFFFFF),
),
),
onPressed: () async {
if (!isArrivedButtonEnabled) return;

setState(() {
isArrivedButtonEnabled = false;
});

bool hasArrived = checkArrived();
String? chalName;
if (hasArrived) {
Expand All @@ -431,17 +460,21 @@ class _GameplayMapState extends State<GameplayMap> {
return Container(
margin: EdgeInsetsDirectional.only(start: 10, end: 10),
child: Dialog(
elevation: 16, //arbitrary large number
elevation: 16,
child: ClipRRect(
borderRadius: BorderRadius.circular(
10), // Same as the Dialog's shape
borderRadius: BorderRadius.circular(10),
child: displayDialog(
context, hasArrived, chalId, chalName),
),
),
);
},
);
).then((_) {
// Re-enable the button after the dialog is closed
setState(() {
isArrivedButtonEnabled = true;
});
});
},
),
),
Expand Down
1 change: 1 addition & 0 deletions game/lib/global_leaderboard/global_leaderboard_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ class _GlobalLeaderboardWidgetState extends State<GlobalLeaderboardWidget> {
topRight: Radius.circular(10.0),
),
),
// Ranking List
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
Expand Down
2 changes: 2 additions & 0 deletions game/lib/interests/interests_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import 'package:google_sign_in/google_sign_in.dart';
import 'package:game/utils/utility_functions.dart';
import 'package:flutter_svg/flutter_svg.dart';

/// This page allows the user to select their interests. Connection to backend
/// (creating the user) happens here.
class InterestsPageWidget extends StatefulWidget {
InterestsPageWidget(
{Key? key,
Expand Down
Loading

0 comments on commit 39eb31c

Please sign in to comment.