Skip to content

feat(ui, widget, screen, map): Added Room Search functionality prototype! + settings UI features, floorplay overlay header, and more - #126

Open
TheStaticBits wants to merge 29 commits into
navigation-hubfrom
room-search
Open

TheStaticBits wants to merge 29 commits into
navigation-hubfrom
room-search

Conversation

@TheStaticBits

@TheStaticBits TheStaticBits commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Description

Consolidated search bars sheets into one search bar, added room search functionality, recent searches, cards for nearby POI search, settings features (Sign in banner and "Help" section), along with the header bar and back button for floorplan overview mode. Also fixed search result markers not showing up. Apologies for the large pull request, MaizeBus is the only thing I have been working on for the past four days :p

Type of Change

  • New feature (feat)
  • Bug fix (fix)
  • Refactor / code improvement
  • Dependency / build update
  • Documentation
  • Other (explain)

Changed Files

  • map_screen.dart

    • Added floorplan title bar -- MaizeBus logo and settings button switches out for the title bar when zoomed in on a floor.
    • Added Android back button floorplan overlay exit zoom out
    • Loads user bathroom preference at startup
    • Awaits _loadStopsForLaunch() in _loadAllData() now, so that the code does not need to be duplicated in search_sheet_main.dart
    • _showSearchLocationMarker() takes a "showGetOnIcon" parameter, telling it whether to show a normal marker or an "enter" icon marker.
    • _searchLocationMarker is passed into CompositeMapWidget to properly display on map, as it was previously not being displayed (bug fix)
    • Added _selectedPOI state to track the currently selected room/POI for the POISheet overlay
    • Added _showPOISelection() to search around the user's location for a particular type of POI, opening the POI sheet and centering on the user after it finds them.
    • Added _showRoomSearchResult() to center onto a particular room. It switches to the floor of the room, centers it, places a marker, and opens its corresponding POISheet.
    • Added logic to move bus/floor buttons buttons around based on the device's bottom padding (should work for all devices now, including Android)
    • Added a new variable called mapCenter that tracks where the user is centered on the map (useful for distance sorting)
  • search_sheet_main.dart

    • Consolidated search sheets both into one.
    • Added helper functions such as saveRecentSearch() and getRecentSearches().
    • Added Recent Searches functionality
    • Removed duplicated code, and moved search logic out of this file and into location_sheet.dart
    • Added LocationTile to reduce duplicate code in the search UI, between Recent Searches and normal searches.
    • Implemented bathroom selection popup
    • Added isRoomSearch, onPOISelected, and roomPois parameters to SearchSheet class.
    • Probably more that I'm forgetting because GitHub stopped showing diffs for this file due to the amount of changes
    • Added an optional mapCenter to SearchSheet and LocationSearchBar, passed it from the sheet down to the search bar, and handed it to both searchLocations calls (the live results and the on-submit lookup) as center.
  • search_rooms.dart

    • Removed. This was when we were still doing separate search sheets. It's all consolidated into the main sheet now.
  • location_search.dart

    • Added a new class, RoomLocation, which extends from constants.json's Location class and stores a room POI on top of that.
    • It implements a fromJson and toJson, just like the parent Location class.
    • I moved the building search functions related to ngram search to this file for cleanliness.
    • Added searchLocations() function, which implements a new algorithm to search both buildings and rooms with a single query, and returns a List<Locations> (which can be RoomLocation objects when rooms are returned as search results)
    • The searchLocations and _ngramSearch functions also accept an optional center, and when it’s given, they take the 30 best text matches, sort them by distance to that point, and return the closest 10 (rooms in equally ranked buildings also sort nearest-first), while behaving mostly the same as when no center is passed
  • poi_sheet.dart

    • New class, POISheet, which handles the bottom modal that pops up when selecting a room or POI via search.
    • Pretty much purely UI elements, no functionality is implemented here.
    • "Get Directions" button does nothing right now.
  • settings.dart

    • Added "Sign In" sheet at the top of settings, which does nothing right now.
    • Added "Help" section with DPSS and after-hours-transit options
    • Added "Bathroom Preference" toggle, which defaults to "inclusive" when the user hasn't chosen a gender yet. This uses the BathroomProvider class.
    • Modified coloring of various elements to match the Figma
  • composite_map_widget.dart

    • Added _searchResultsMarker parameter that displays on the map (same bug fix from earlier).
  • floorplan_marker_service.dart

    • Added highlighted icon generation and cache for a yellow circle around a map icon, used for card search results. this was vibecoded a lil
  • floorplan_service.dart

    • Added LocatedFloorplanPoi class, which stores a POI along with its building, floor, etc.
    • Added a FloorplanPoiIndex class, which is used for searching. It projects all POIs onto the real world map, storing their actual latlng, and adding them all to a single List of LocatedFloorplanPois. It implements a nearest function, which returns the nearest X number of POIs of a particular type to a given LatLng.
  • floorplan_style.dart

    • Added printer and vending machine into the icons. Vending uses printer icon as a temp fix (cause UI hasn't given us vending icon yet)
  • floorplans_layer.dart

    • Added _poiIndex (using FloorplanPoiIndex) to the FloorplansLayer class
    • Added _searchMarkers list
    • Added a showNearbyPois() function as well, which uses the _poiIndex to populate the _searchMarkers list with search results for card searches (such as for nearby bathrooms or printers) to display on the map. This filters out POIs more than 600m away from the user, and returns a LatLng centered on the markers found. It does not adjust zoom level, which we might want to do.
  • floorplan_overlay_widget.dart

    • Added onRoomSearch callback for FloorplanEntryBar class
    • Made style fixes to the FloorplanEntryBar
    • Made style fixes to the FloorplanOverlay class
    • Added onClosed and onRoomSearch callbacks to FloorplanOverlay
    • Updated search bar UI in FloorplanOverlay for consistency with the map search bar UI
  • bathroom_provider.dart

    • New class which handles reading and updating the user's bathroom preference
    • Conntains an enum, BathroomPreference, with four values (not chosen, womens, mens, inclusive)
    • Has a load, save, and set function.
  • main.dart

    • Added BathroomProvider to app initialization
  • search_result_layer.dart

    • Merge changes to use icon parameter
  • dialog.dart

    • Added showDialogOptions() function, which displays a dialog to the user with as many different options on it as the function caller passes in via the options parameter.
  • constants.dart

    • Added DPSS and after-hours transit links
    • Added constant to control how many recent searches the search saves
    • Added room search colors
    • Changed default divider color
    • Added toJson() and fromJson() functions to Location class to help with saving recent search locations
  • directions_sheet.dart

    • Added parameter to SearchSheet() calls (due to the new parameter in SearchSheet widget)
  • journey_results_widget.dart

    • Added parameter to SearchSheet() calls (due to the new parameter in SearchSheet widget)
  • floorplan.dart

    • Added printer
    • Changed the bathroom strings to be accurate to the latest version of floorplan data
  • printer.png

    • Added icon for printers. Still missing vending machine icon, as UI is working on that.
  • ci.yaml

    • I know I'm technically not supposed to change these things but this was causing a build error recently from GitHub actions due to some version change in the backend of GitHub, so this just ensures that Java 17 is used for the Gradle building to make it work again.

Does your code rely on another PR

None that are still open.

Testing Done

Flutter:

  • Tested on:
    • iOS Simulator
    • Android Emulator
    • Physical device (android)

Screenshots / Demo (if UI or notification change)

Screenshot 1 Screenshot 2 Screenshot 3 Screenshot 4 Screenshot 5

Checklist

  • Commit messages follow Conventional Commits (i'm really bad at doing this)
  • PR title follows [type](scope): short description
  • PR target branch is not main and is our current working update branch (e.g. maizebus2.1)
  • No print() / debugPrint() / console.log() left in production code
  • Secrets / keys not committed

@gusrod-coder
gusrod-coder self-requested a review October 31, 2026 05:35
@gusrod-coder

Copy link
Copy Markdown

On the Android Emulator, I can't see within the Dude any more. Is this supposed to work for this PR?
image

@iswheeler

Copy link
Copy Markdown
Contributor

Great work! A couple notes:

  1. @gusrod-coder to get the Dude to show you'll need to include dudeMap.json (that fixed it for me)
  2. Search title is hard to read in dark mode--please check the colors
image 3. Hide the "Get directions" button for now since micronavigation isn't implemented yet (planned for a 3.x release) image 4. Is bathroom search working right now? If not that's ok but I noticed it couldn't find any on the grove (same for "Printing" chip, I got no results) image 5. I'm seeing a "Null check operator used on a null value" as you scroll the chips to the right image

Comment thread lib/constants.dart
ColorType.roomSearchBathroom: Color.fromARGB(255, 151, 132, 193),
ColorType.roomSearchInfoDesk: Color.fromARGB(255, 121, 176, 235),
ColorType.roomSearchDining: Color.fromARGB(255, 235, 162, 121),
ColorType.roomSearchVending: Color.fromARGB(255, 235, 121, 121),

@i-kumar i-kumar Nov 3, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dark mode crash on the Vending chip

ColorType.roomSearchVending is only defined in lightColors. It's missing from darkColors, and getColor() force-unwraps the dark map (darkColors[type]!). Vending is the last chip in the row, so it only renders once you scroll right, at which point dark mode throws "Null check operator used on a null value". I believe that's the crash from @iswheeler's earlier comment.

Fix: add a roomSearchVending entry to darkColors. It might also be worth a small test that asserts both palettes contain every ColorType value so this can't happen again.

Written by Claude, verified by Ishan.

controller: _searchController,
focusNode: _searchFocusNode,
decoration: InputDecoration(
fillColor: getColor(context, ColorType.roomSearchBg),

@i-kumar i-kumar Nov 3, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typed search text is unreadable in dark mode

The field background changed from the themed ColorType.inputBackground to ColorType.roomSearchBg, but roomSearchBg is the same light blue (223, 237, 252) in both lightColors and darkColors. The typed text style in LocationSearchBar still uses ColorType.opposite, which is white in dark mode, so you get white text on a light blue field. This is probably the dark-mode readability issue from @iswheeler's comment.

Fix: either give roomSearchBg a proper dark variant in darkColors, or use a fixed dark text colour (e.g. roomSearchText or black) for the input text so it reads against the light field in both themes.

Written by Claude, verified by Ishan.

@i-kumar

i-kumar commented Nov 3, 2026

Copy link
Copy Markdown
Member

At the top of my phone, the hidden header is still visible. Make sure you're scaling dynamically with offsets rather than a hardcoded constant. Screenshots attached:

Ex 1:
IMG_6943
Ex 2:
IMG_6942

@i-kumar

i-kumar commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Also in the future, please make much smaller PRs. 21 files changed is a lot to review. Make smaller PRs as you go rather than big summing PRs

@TheStaticBits

Copy link
Copy Markdown
Member Author

@iswheeler:
2. Changed the typing text color to make it consistent. Although, the dark mode style for the search bar along with other UI elements right now (such as the floorplan-view header) needs adjusting in general, which is something we need to ask UI/UX about.
3. Commented out the "Get Directions" button.
4. Chip search, such as finding the nearest bathrooms, only searches for matching POIs within a distance specified in the location_search.dart file. Right now, it's set to only show the nearest 5 results within 600m of the user. That's likely why you don't see anything.
5. Fixed, using Ishan's Claude's suggestion.

@i-kumar: I have changed the offset distance for the header to be based off of the globalTopPadding variable.

thank you guys!

mzjia and others added 5 commits November 4, 2026 18:31
…n the map

in map_screen.dart, added a new variable called mapCenter that tracks where the user is centered on the map.
in location_search.dart, searchLocations and _ngramSearch now accept an optional center, and when it’s given, they take the 30 best text matches, sort them by distance to that point, and return the closest 10 (rooms in equally ranked buildings also sort nearest-first), while behaving exactly as before when no center is passed
in search_sheet_main.dart, added an optional mapCenter to SearchSheet and LocationSearchBar, passed it from the sheet down to the search bar, and handed it to both searchLocations calls (the live results and the on-submit lookup) as center.
in location_search_test.dart, added 3 buildings at various locations on campus and tested results when searching with diff locations. all tests pass and this file can be removed when submitting the pr.
Calculate the slide distance from the device's bottom padding instead of using a fixed value (was 2 previously).
Nnanyere
Nnanyere previously approved these changes Nov 12, 2026
@iswheeler

iswheeler commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Claude pointed out a few extra bugs and these three seem to be the most severe. Could you take a look at these?

Retry loop with no backoff. On a failed fetch or empty result, refreshKey.value++ triggers a rebuild, then a refetch, then another increment. With the backend down, this hammers it in a tight loop with no delay or retry cap. The fetch happens on every sheet open, with no caching.

showPOISelection returns silently when location is unavailable. map_screen.dart:1411 does if (position == null) return;. The sheet is already closed and the user sees nothing. The error snackbar is commented out, so errors are swallowed by catch (). The user gets no feedback on permission denial, GPS off, or any thrown error.

Non-numeric room names are unreachable. The edge-word check (digits <= letters → skip) means rooms like "B" or "G12A" (more letters than digits) can never match as the number part. Rooms named "Lobby" or "AB" are unsearchable by room.

@Nnanyere
Nnanyere dismissed their stale review November 13, 2026 04:59

Misclick

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants