-
Notifications
You must be signed in to change notification settings - Fork 2
Feature: Implement Map for Locating Events #102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
These changes simply introduce the usage of Google maps to display the events that are fetched through the event view model. No color yet.
- Added an init function in the EventRepository interface
- Implemented the init function in the event repository 'EventRepositoryFirestore'
- Modified the init { } block in EventListViewModel to also into account the initialization of its repository
- Added the map composable under the home route in the NavGraph. - Added initialization of the event repository and view model in the main activity (might not be useful later) - Added the right callback for the onClick field of the floating action button in the home screen.
This addition was needed because the EventRepository interface now has an init function.
This addition in the requestAll function of FirestoreReferenceList.kt fixes the crash that occurs every time the app is launched.
This is the API key required to use google maps. It should be defined in local.properties.
…ions Updated the FloatingActionButton icon in Home.kt to use Icons.Filled.Place instead of Icons.Filled.Add. This corresponds better the to the map screen.
A callback parameter was used to test the HomeScreen. This has been factored out and the tests have been corrected.
|
Since I need @Aurelien9Code's changes that implement the favorite event mechanism, e.g. "save event", I will work with an arbitrary saved event for all users, and refactor this when his PR makes it into our main branch successfully. |
- Added a custom pin point that refers to a "favorited" event - Added a mock list of an arbitrary saved event list. This will simply be replaced by the list of the saved events by the user when it is available (waiting for another PR) - Changed the color of the pin points that correspond to all the events to blue. This will later on be refactored to only take events that are in the very near future.
- Added the "timeUntilEvent" function to calculate time remaining time until an event occurs, displayed in days and hours. - Updated marker snippet to show countdown information in front of the event description. - Added condition check to display only future events. This provides users with a clear indication of how much time remains until each event, improving the usability of the map.
Additional changes:
|
This improves code readability.
- Added a test that checks that the main components of the MapScreen composable are displayed. - Added a test that checks that the "go back" button successfully triggers the navigation back.
Added tests to validate the init function. The choice of making these tests separate has been made, as, if successful according to SonarCloud standards, they will serve as models for the other repositories' tests.
|
@oskar-codes Good news, after quite a bit of research for testing, I have figured out how to cover the init functions of our repositories! Have a look at this commit. This required me to combine the usage of First, you define the captor like this: private lateinit var authStateListenerCaptor: ArgumentCaptor<FirebaseAuth.AuthStateListener>Then you use verify(auth).addAuthStateListener(authStateListenerCaptor.capture())And the state listener can then be fetched through the captor with a simple authStateListenerCaptor.value.onAuthStateChanged(auth)I have tested the two conditions, e.g. if the user is authenticated and if the user isn't authenticated. And indeed, SonarCloud is happy about this and shows that the init function is fully covered! |
- Added a check that verifies that the button is displayed and clickable - Added a check that verifies that the icon is displayed and clickable
This prevents initializing an actual event view model and repository in BottomNavigationTest.
|
|
More tests will come tomorrow. Will open this PR for review for more detailed opinions. |
AlexeiThornber
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, very nice additions to Unio @Zafouche, great work 💪 !
Some domains are still lacking, especially e2e testing, but that is something that should be done for the entire projetct for milestone 2 :/.
Try to separate the funtionality elements with the UI elements of your code, typically helper funtions can go in the ViewModel instead of the View.
I tried testing your PR on my device but google maps was not loading. I believe that is because I do not have the API keys and I forgot how to retrieve it 😓 .
Anyhow I'll trust you on this one and approve your PR even though there are some minor issues that can be worked on. Very solid work 🚀 .
| @Composable | ||
| fun EventMap(pd: PaddingValues, eventListViewModel: EventListViewModel) { | ||
| val cameraPositionState = rememberCameraPositionState { | ||
| position = CameraPosition.fromLatLngZoom(LatLng(46.518831258, 6.559331096), 10f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could possibly put this hardcoded location into a constant. @Aurelien9Code provided a new manager for all backend strings, we could possibly use this for hardcoded values too, but this is very minor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are Doubles but yes, they can at least be put in constants. In the future we should replace this with the user's current position.
| val events = eventListViewModel.events.collectAsState() | ||
|
|
||
| /** Mock arbitrary saved event for all users. */ | ||
| val arbitrarySavedEvents: List<Event> = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid mocking in the main code. But then again because this feature is still in devellopement, it is normal to do so. Especially as you explained in your PR, the saved events feature is not yet implemented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, still waiting on the feature to make it into the main branch.
| cameraPositionState = cameraPositionState) { | ||
| // Display saved events | ||
| arbitrarySavedEvents.forEach { event -> | ||
| if (event.date.toDate() > Calendar.getInstance().time) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's best practise to have all the functionality of the code in the viewModel, the UI (or View) should only be for displaying elements. Consider adding a checkEventHasPassed() function in the viewModel, this will improve readability. But I am nit picking here as I am the first one guilty of adding functionality in the View 😓.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, but that would mean deleting old events. I think it will be necessary to keep old events in the database up to some "expiration date" and remove them when that "expiration date", as we potentially wanted to add some social features for past events, e.g. pictures or simple comments and whatnot.
Deleting old events is caching duty, so I think it's fair to say this is just display logic, don't you agree?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes absolutely. As I said i was nit picking and this is completly fine as it's done right now.
| * @param eventTimestamp the timestamp of the event | ||
| * @return a string giving information about the time until the event occurs | ||
| */ | ||
| fun timeUntilEvent(eventTimestamp: Timestamp): String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This too I believe could be defined in the viewModel instead of the View for the reasons mentioned above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the time counter is (at least for now) solely for informational purpose, I'd argue we keep it here.
| Firebase.auth.addAuthStateListener { | ||
| if (it.currentUser != null) { | ||
| onSuccess() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding some error handling if the user is null. Typically an onFailure() callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue error handling shouldn't be done in this initializing function, as the repository shouldn't work if there is no user, as to not make unnecessary queries.
However I agree that we should at least Log it, e.g. have some failure functionality
Also I don't see what the onFailure function would do, except logging. In that case we can simply add an else Log.e:
If there is a user, we can loadEvents(), e.g. onSuccess call.
And if there is no user, we don't make any queries.
Do you have something additional in mind?
Thank you for your review @AlouchLaBouche ! All good points
I agree! I plan on writing e2e testing today, however I don't really see what could be done here, except clicking on markers.
Totally! As you can see in my responses to your review comments, some are still ambiguous and depends on what comes next, so I appreciate more opinions and discussions.
Yes, you should set up your API key in |
|
@AlouchLaBouche Are we happy to merge this? |
|
Yup, all seems to be in order 👍. E2E tests will be worked on next sprint I believe as they are essential to be done before milestone 2. |



Description:
This PR introduces a map feature within the app, allowing users to view event locations. The changes include implementing a map interface, adding navigation to the map screen, setting up proper initialization for the event repository and view model, and configuring the API key injection process. The map currently displays all events, as I am waiting for the integration of event-saving logic.
Motivation and context:
This feature enhances the app's usability by providing a visual representation of events' locations, making it possible for users to locate the events of interest. Initially, the map displays all events; however, what still needs to be done is to show the saved events and those relevant to the user (e.g., nearby events), and further define the logic of color gradients and specific views.
The Google Maps API key setup is necessary for the functionality of the map.
The implementation of a proper event repository and view model initialization is needed for consistency and good behavior.
Changes:
Edit 1:
Edit 2:
Edit 3:
What's left:
How has this been tested?
Other tests: Tested the init function I had to add to the Event repository.
Still left