Show ecosystem type cards in favorites section and make filtering functional#122
Show ecosystem type cards in favorites section and make filtering functional#122RyanCheung555 merged 16 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the Home ecosystem bottom sheet favorites experience so that favorited ecosystem places (eateries, gyms, libraries, printers) can appear with their appropriate card types and be filtered using the existing favorites filter UI.
Changes:
- Added new
PlaceTypevalues and updated ecosystem model →Placemappings so favorites can retain the originating ecosystem type. - Implemented favorites filtering + type-specific rendering in
EcosystemBottomSheetContent(including gym/printer favorite toggling). - Updated shared UI components (place cards/images, bottom-sheet cards, search
MenuItem) to support the new place types and card behaviors.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/main/java/com/cornellappdev/transit/util/ecosystem/PlaceUtils.kt | Maps ecosystem entities to Place using the new ecosystem PlaceTypes (incl. gym). |
| app/src/main/java/com/cornellappdev/transit/models/Place.kt | Extends PlaceType with EATERY/LIBRARY/GYM/PRINTER and impacts labeling. |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt | Implements favorites filtering and renders ecosystem-type cards in favorites; updates gym/printer lists and adds previews. |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/RoundedImagePlaceCard.kt | Makes the placeholder drawable optional to support cards without images. |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/PlaceCardImage.kt | Makes placeholder optional and adjusts image rendering logic. |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/DetailedPlaceSheetContent.kt | Adds a temporary gym details header + directions navigation. |
| app/src/main/java/com/cornellappdev/transit/ui/components/home/BottomSheetLocationCard.kt | Updates bottom-sheet card layout to include favorite star state/callback. |
| app/src/main/java/com/cornellappdev/transit/ui/components/MenuItem.kt | Adds TODO for ecosystem icons and additional previews; impacts icons for new types. |
Comments suppressed due to low confidence (2)
app/src/main/java/com/cornellappdev/transit/ui/components/home/PlaceCardImage.kt:53
PlaceCardImagecurrently renders nothing whenplaceholderResis null, even ifimageUrlis non-blank, because theAsyncImagebranch is gated onplaceholderRes != null. This prevents remote images from showing in cases where you intentionally have no placeholder. Consider always renderingAsyncImagewhenimageUrlis present, and only usingplaceholderResfor error/placeholder handling (and/or render an empty Box withimageModifierwhen both are null to preserve layout if needed).
// Images with no placeholders will simply not show
if (imageUrl.isNullOrBlank() && placeholderRes != null) {
Image(
painter = painterResource(id = placeholderRes),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = imageModifier
)
} else if (!imageUrl.isNullOrBlank() && placeholderRes != null) {
AsyncImage(
model = imageUrl,
contentDescription = null,
error = painterResource(id = placeholderRes),
contentScale = ContentScale.Crop,
modifier = imageModifier
)
}
app/src/main/java/com/cornellappdev/transit/ui/components/MenuItem.kt:52
MenuItemcurrently treats everyPlaceTypeother thanAPPLE_PLACEas a bus stop for icon purposes. Now thatPlaceTypeincludesEATERY/LIBRARY/GYM/PRINTER, those items (e.g., favorites/recents shown viaMenuItem) will incorrectly render the bus stop icon. Consider switching to awhen(type)that explicitly maps eachPlaceTypeto the correct icon (or at least a generic place icon for non-bus-stop types).
//TODO: Add icons for each ecosystem type
if (type == PlaceType.APPLE_PLACE) {
Image(
painterResource(R.drawable.location_pin_gray),
contentDescription = "Place",
modifier = Modifier.padding(end = 20.dp),
)
} else {
Image(
painterResource(R.drawable.bus_stop_pin),
contentDescription = "Stop",
modifier = Modifier.padding(end = 20.dp),
)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
app/src/main/java/com/cornellappdev/transit/ui/components/home/BottomSheetLocationCard.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (2)
app/src/main/java/com/cornellappdev/transit/ui/components/MenuItem.kt:52
MenuItemnow treats every non-APPLE_PLACEtype as a bus stop (bus icon + contentDescription "Stop"). With the newly addedPlaceTypevalues (EATERY/LIBRARY/GYM/PRINTER), favorites/recents shown in search suggestions and routing will display the wrong icon and accessibility label. Update this conditional to distinguishBUS_STOPfrom other place types (and provide a sensible default icon/contentDescription for ecosystem places until specific icons are added).
//TODO: Add icons for each ecosystem type
if (type == PlaceType.APPLE_PLACE) {
Image(
painterResource(R.drawable.location_pin_gray),
contentDescription = "Place",
modifier = Modifier.padding(end = 20.dp),
)
} else {
Image(
painterResource(R.drawable.bus_stop_pin),
contentDescription = "Stop",
modifier = Modifier.padding(end = 20.dp),
)
}
app/src/main/java/com/cornellappdev/transit/ui/components/home/PlaceCardImage.kt:53
PlaceCardImagecurrently only renders anAsyncImagewhenplaceholderRes != null. IfimageUrlis non-blank but the caller intentionally omits a placeholder (now allowed by the nullable/default param), nothing is rendered at all. Consider renderingAsyncImagewheneverimageUrlis present, and only passing theerror/fallback painter when a placeholder is provided (and optionally render just the gray background when both are null).
// Images with no placeholders will simply not show
if (imageUrl.isNullOrBlank() && placeholderRes != null) {
Image(
painter = painterResource(id = placeholderRes),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = imageModifier
)
} else if (!imageUrl.isNullOrBlank() && placeholderRes != null) {
AsyncImage(
model = imageUrl,
contentDescription = null,
error = painterResource(id = placeholderRes),
contentScale = ContentScale.Crop,
modifier = imageModifier
)
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/util/ecosystem/PlaceUtils.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/BottomSheetLocationCard.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/BottomSheetLocationCard.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/BottomSheetLocationCard.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/PlaceCardImage.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
| onAddFavoritesClick | ||
| ) | ||
| } | ||
| key(currentFilter, appliedFilters) { |
There was a problem hiding this comment.
Do we need this key or will compose just handle it based on those states being used inside?
There was a problem hiding this comment.
Not exactly sure what your question is, but the key is used so that the scrollstate is set to be at the very top when switching between tabs. If there is an unintended sideeffect or an easier way to do this, I can implement that
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Show resolved
Hide resolved
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
app/src/main/java/com/cornellappdev/transit/ui/components/home/PlaceCardImage.kt:49
AsyncImageis currently gated byplaceholderRes != null, so providing a validimageUrlwith no placeholder results in no image being rendered at all. Consider always renderingAsyncImagewhenimageUrlis non-blank, and only usingplaceholderResforplaceholder/errordrawables (or render a fixed-size gray box when both are null to keep layout stable).
} else if (!imageUrl.isNullOrBlank() && placeholderRes != null) {
AsyncImage(
model = imageUrl,
contentDescription = null,
error = painterResource(id = placeholderRes),
app/src/main/java/com/cornellappdev/transit/ui/components/MenuItem.kt:43
- With the new
PlaceTypes (EATERY/LIBRARY/GYM/PRINTER), this logic will show the bus-stop icon for every non-APPLE_PLACEitem (including ecosystem favorites/recents), which is misleading. Update the icon selection to distinguish at leastBUS_STOPvs “place-like” types, and optionally add distinct icons per ecosystem type.
//TODO: Add icons for each ecosystem type
if (type == PlaceType.APPLE_PLACE) {
Image(
painterResource(R.drawable.location_pin_gray),
contentDescription = "Place",
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| .sortedWith(compareBy<Place>({ it.type.ordinal }, { it.name })) | ||
| .toList() |
There was a problem hiding this comment.
Future implementation will be to sort by distance (and by open/closed if possible)
app/src/main/java/com/cornellappdev/transit/ui/components/home/EcosystemBottomSheetContent.kt
Outdated
Show resolved
Hide resolved
| val filteredSortedFavorites = favorites.asSequence() | ||
| .filter { allowedTypes.isEmpty() || it.type in allowedTypes } | ||
| .sortedWith(compareBy<Place>({ it.type.ordinal }, { it.name })) | ||
| .toList() | ||
|
|
||
| val eateries = (staticPlaces.eateries as? ApiResponse.Success)?.data.orEmpty() | ||
| val libraries = (staticPlaces.libraries as? ApiResponse.Success)?.data.orEmpty() | ||
| val gyms = (staticPlaces.gyms as? ApiResponse.Success)?.data.orEmpty() | ||
| val printers = (staticPlaces.printers as? ApiResponse.Success)?.data.orEmpty() | ||
|
|
There was a problem hiding this comment.
Old favorites are not a huge concern right now
Overview
Changes Made
Test Coverage
Next Steps (delete if not applicable)
Screenshots (delete if not applicable)
Favoriting each type of place
favoriting_functionality.webm
Filtering functionality
filter_functionality.webm