You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Offline search (Menu → Search, / or F): places, streets, addresses ("street number" in either order), points of
interest and categories, with diacritics and Greek/Cyrillic in Latin letters not mattering
Results nearest first with type, distance, direction and the town or city district they are in, nearby by
category
House numbers in the map data have no street: each gets the nearest named street, or the nearest village in
regions where addresses are "village + number", estimated results are marked
The search index is built on the device in idle time, per downloaded region, large regions are split into blocks
Off-route detection follows the GPS precision (0.4.1)
Tiles on screen get their POIs and house numbers during a download
Letters missing from the UI font are drawn as
their base letter
Summary by CodeRabbit
New Features
Added offline search for downloaded maps, including place, street, and address queries, nearby categories, and recent searches.
Search results can recenter the map and open a place details sheet.
Added background search-index building and progress reporting.
Map labels now handle more unsupported characters through text fallback.
Improvements
Route deviation detection now accounts for GPS accuracy, direction, nearby roads, and weak GPS signals.
Map downloads better handle urgent tile preparation and tiles that move between regions.
Replay testing now supports configurable GPS accuracy and position noise.
Documentation
Updated Maps version information and documented offline search and navigation behavior.
- Search places, streets, addresses and points of interest in the downloaded maps, offline
- Results nearest first, with type, town, distance and direction; nearby by category; recent searches
- House numbers matched to the nearest street, or to the village where addresses have no street
- Search index built on the device in idle time
- Off-route detection follows the GPS precision
- Tiles on screen get their labels during downloads, letters missing from the UI font drawn as base letters
This change adds offline search for downloaded map data in Maps. It introduces text folding, tile extraction, region assembly, index writing and reading, background index building, and a search UI with recents, categories, pagination, and map result opening. It also changes route following to use accuracy-aware off-route rules, nearby side-road data, weak-GPS handling, and tunable recalculation timing. Related updates add debug commands, replay noise controls, urgent tile-conversion handling during downloads, font fallback for unsupported characters, version bumps, and documentation updates.
Severity of issue fixed: Medium
Pre-merge checks: 4
Check name
Status
Explanation
Description Check
Check skipped - CodeRabbit’s high-level summary is enabled.
Title check
The title "Updates Maps to 0.5.0" names the release that this PR prepares. The version bump is part of the changeset: README, CHANGELOG, manifest.properties, and APP_VERSION all move to 0.5.0. However…
Linked Issues check
Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check
Check skipped because no linked issues were found for this pull request.
Full details: Title check
Explanation
The title "Updates Maps to 0.5.0" names the release that this PR prepares. The version bump is part of the changeset: README, CHANGELOG, manifest.properties, and APP_VERSION all move to 0.5.0. However, the title does not name the main functional changes, which are offline search, the search index build, and off-route detection tuning. The title is partially related: it states a real part of the change but not its main substance.
Finishing Touches
Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
Review coverage is incomplete: 1 file could not be fully reviewed. Findings from completed review steps are included; see review info for details.
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 20
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
⚠️ Outside diff range comments (2)
Minor · Long press while the search sheet is open opens a waypoint sheet for the… · MapInput.cpp:690-705
Apps/Maps/main/Source/app/MapInput.cpp:690-705 Minor · Functional Correctness · Quick win
Long press while the search sheet is open opens a waypoint sheet for the map behind it
handleLongPress has no searchSheet.isOpen() guard. On Screen::Map, a long press on a search row reaches the controls.hit(...) == Control::None && !sheet.contains(...) branch, because openSearch hid the controls. That branch calls openNewWaypoint for the hidden map point.
The waypoint sheet stays hidden behind the search sheet, because key and tap routing check searchSheet first. After the user closes search, the waypoint sheet appears for an unrelated point.
Return early when the search sheet is open.
Proposed fix
- if (screen == Screen::Map && !dialog.isOpen()) {+ if (screen == Screen::Map && !dialog.isOpen() && !searchSheet.isOpen()) {
Minor · Handle the search sheet in goBack(). · MapScreens.cpp:103-109
Apps/Maps/main/Source/app/MapScreens.cpp:103-109 Minor · Functional Correctness · Quick win
Handle the search sheet in goBack().
With Search open, handleGesture() sends a right swipe to goBack(). However, menuOpen is false, screen is Screen::Map, and activeList() returns null. The swipe therefore leaves Search open. Add a search-sheet branch that applies its back action and closes Search when appropriate. Keep menu handling first. (raw.githubusercontent.com)
Have SearchRegionBuilder use houseNumberStyle and houseVoteNumber
The comment on Line 118 says that SearchRegionBuilder uses the same grammar. In fact, SearchRegion.cpp defines its own NumberKind, classifyNumber, leadingNumber and streetNumberOf copies. The two builders must produce the same .sidx file byte for byte. With two copies, a later change to one copy can make the indexes differ. Call these shared functions from SearchRegion.cpp and delete the local copies.
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: d7642a6e-3627-4e72-bafa-2f3985d1558d
Commits
Reviewing files that changed from the base of the PR and between 54fd48c and 99b2d3d.
Files selected for processing: 58
Apps/Maps/CHANGELOG.md
Apps/Maps/README.md
Apps/Maps/main/CMakeLists.txt
Apps/Maps/main/Source/app/BinFontText.cpp
Apps/Maps/main/Source/app/BinFontText.h
Apps/Maps/main/Source/app/Debug.cpp
Apps/Maps/main/Source/app/Debug.h
Apps/Maps/main/Source/app/MapInput.cpp
Apps/Maps/main/Source/app/MapNavigation.cpp
Apps/Maps/main/Source/app/MapScreens.cpp
Apps/Maps/main/Source/app/MapSearch.cpp
Apps/Maps/main/Source/app/MapView.cpp
Apps/Maps/main/Source/app/MapView.h
Apps/Maps/main/Source/app/Navigator.cpp
Apps/Maps/main/Source/app/Navigator.h
Apps/Maps/main/Source/app/SearchIndexJob.cpp
Apps/Maps/main/Source/app/SearchIndexJob.h
Apps/Maps/main/Source/app/SearchTask.cpp
Apps/Maps/main/Source/app/SearchTask.h
Apps/Maps/main/Source/app/TileWorker.cpp
Apps/Maps/main/Source/app/TileWorker.h
Apps/Maps/main/Source/mvt/MvtDecoder.cpp
Apps/Maps/main/Source/mvt/MvtDecoder.h
Apps/Maps/main/Source/mvt/Schema.h
Apps/Maps/main/Source/route/GrowArray.h
Apps/Maps/main/Source/route/RouteFollower.cpp
Apps/Maps/main/Source/route/RouteFollower.h
Apps/Maps/main/Source/route/RouteSearch.cpp
Apps/Maps/main/Source/route/RouteSearch.h
Apps/Maps/main/Source/route/RouteSides.cpp
Apps/Maps/main/Source/search/AddressMatch.cpp
Apps/Maps/main/Source/search/AddressMatch.h
Apps/Maps/main/Source/search/ExternalSort.cpp
Apps/Maps/main/Source/search/ExternalSort.h
Apps/Maps/main/Source/search/FoldTable.h
Apps/Maps/main/Source/search/QueryParse.cpp
Apps/Maps/main/Source/search/QueryParse.h
Apps/Maps/main/Source/search/ScratchFiles.h
Apps/Maps/main/Source/search/SearchEngine.cpp
Apps/Maps/main/Source/search/SearchEngine.h
Apps/Maps/main/Source/search/SearchExtract.cpp
Apps/Maps/main/Source/search/SearchExtract.h
Apps/Maps/main/Source/search/SearchIndex.cpp
Apps/Maps/main/Source/search/SearchIndex.h
Apps/Maps/main/Source/search/SearchRegion.cpp
Apps/Maps/main/Source/search/SearchRegion.h
Apps/Maps/main/Source/search/SearchStream.cpp
Apps/Maps/main/Source/search/SearchStream.h
Apps/Maps/main/Source/search/TextFold.cpp
Apps/Maps/main/Source/search/TextFold.h
Apps/Maps/main/Source/ui/BackgroundWork.cpp
Apps/Maps/main/Source/ui/BackgroundWork.h
Apps/Maps/main/Source/ui/SearchSheet.cpp
Apps/Maps/main/Source/ui/SearchSheet.h
Apps/Maps/main/Source/ui/WaypointSheet.h
Apps/Maps/manifest.properties
Apps/Maps/tools/fold.py
Apps/Maps/tools/make_fold_table.py
Files not fully reviewed because they exceed a per-file size limit: 2
Apps/Maps/main/Source/search/FoldTable.h
Apps/Maps/main/Source/search/SearchStream.cpp
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Major · Functional Correctness · Quick win
Do not count a cached position as another GPS fix.
After settling, suppose one erroneous position is 20 m from the route with 5 m accuracy. If GPS updates stop, this timer submits the same position every two seconds. The 500 ms guard permits each call. RouteFollower::update increments awayFixes on every call, so the cached position satisfies the three-fix threshold and triggers recalculation without another GPS measurement. See Apps/Maps/main/Source/route/RouteFollower.cpp, Line 348–367, and RouteFollower.h, Line 33–43. (raw.githubusercontent.com)
Track the fix timestamp or generation before advancing the off-route counters. Keep stale-position display updates separate from new-fix evaluation.
The reason will be displayed to describe this comment to others. Learn more.
Major · Stability & Availability · Quick win
internName copies a settlement name out of text while it appends to text
Line 1110 passes &text[points[i].name] to internName. A settlement name is usually not also a street name, so it is usually new. For a new name, copyText calls text.push(s[i]) in a loop while s still points into text. If a push grows text and moves its buffer, s points to freed memory. The rest of the name then comes from freed memory, and the strcmp checks in later hash lookups can fail. This can corrupt settlement names and pseudo-street names. It also breaks the byte-for-byte match with the streaming builder.
Copy the name before you intern it, or reserve space in copyText before it reads s.
Proposed fix
uint32_t SearchRegionBuilder::copyText(const char* s) {
if (s == nullptr) {
return EXTRACT_NONE;
}
const auto offset = static_cast<uint32_t>(text.size());
const size_t length = strlen(s);
+ // s can point into text: copy it before text can move+ GrowArray<char> copy;+ for (size_t i = 0; i <= length; i++) {+ copy.push(s[i]);+ }
for (size_t i = 0; i <= length; i++) {
- text.push(s[i]);+ text.push(copy[i]);
}
return offset;
}
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to GitHub limitations.
⚠️ Outside diff range comments (2)
Major · Return an error when lineHash fails inside addLines. · SearchStream.cpp:841
Apps/Maps/main/Source/search/SearchStream.cpp:841 Major · Stability & Availability · Quick win
Return an error when lineHash fails inside addLines.
takeFeature checks the tables only once per feature. addLines then processes every line in that feature. Lines 873-875 push to lineName and lineHash separately. If the lineHash growth fails while lineName succeeds, lineName gets one more entry than lineHash. The duplicate check on the next line of the same feature then reads lineHash[k] at the new index. That read is past the end of the lineHash allocation. It is undefined behavior and can crash during index building. Under the same condition, the unwritten slot can also hold a stale hash that drops a valid line.
The build already fails on the next feature, so returning the error here does not change the result. It only stops the bad read.
Suggested fix
const uint32_t nameId = names.intern(name);
lineName.push(nameId);
lineHash.push(hash);
+ if (lineName.failed() || lineHash.failed()) {+ return fail("no memory for the tile tables");+ }
rec.clear();
Minor · Process pending buffer cleanup before the download memory check. · TileWorker.cpp:724
Apps/Maps/main/Source/app/TileWorker.cpp:724 Minor · Functional Correctness · Quick win
Process pending buffer cleanup before the download memory check.
If cache slots are already at their minimum, this return prevents lane.trimBuffers.exchange(false) from releasing retained buffers. For example, 1,200 KiB free fails the 1,300 KiB threshold even when pending cleanup could release another 256 KiB. Each retry reaches the same return, so urgent tiles can remain unprepared until the download ends. Move pending buffer cleanup before this check. (raw.githubusercontent.com)
Review info
Run configuration
Source mode: Auto
Repository: Unavailable
Branch: Unavailable
File: No configuration file from this repository applied
Commit: Unavailable
Layers: Organization UI
Review profile: CHILL
Plan: Advanced
Run ID: ae6aa04a-4023-4a1a-abf2-89c75971e8e3
Commits
Reviewing files that changed from the base of the PR and between 99b2d3d and 3acba76.
Files selected for processing: 27
Apps/Maps/main/Source/app/BinFontText.cpp
Apps/Maps/main/Source/app/MapInput.cpp
Apps/Maps/main/Source/app/MapNavigation.cpp
Apps/Maps/main/Source/app/MapScreens.cpp
Apps/Maps/main/Source/app/MapView.cpp
Apps/Maps/main/Source/app/MapView.h
Apps/Maps/main/Source/app/Navigator.cpp
Apps/Maps/main/Source/app/SearchIndexJob.cpp
Apps/Maps/main/Source/app/SearchIndexJob.h
Apps/Maps/main/Source/app/TileWorker.cpp
Apps/Maps/main/Source/mvt/MvtDecoder.cpp
Apps/Maps/main/Source/mvt/MvtDecoder.h
Apps/Maps/main/Source/mvt/Schema.h
Apps/Maps/main/Source/route/RouteFollower.cpp
Apps/Maps/main/Source/route/RouteFollower.h
Apps/Maps/main/Source/route/RouteSearch.h
Apps/Maps/main/Source/route/RouteSides.cpp
Apps/Maps/main/Source/search/ExternalSort.cpp
Apps/Maps/main/Source/search/QueryParse.cpp
Apps/Maps/main/Source/search/SearchEngine.cpp
Apps/Maps/main/Source/search/SearchExtract.cpp
Apps/Maps/main/Source/search/SearchExtract.h
Apps/Maps/main/Source/search/SearchRegion.cpp
Apps/Maps/main/Source/search/SearchRegion.h
Apps/Maps/main/Source/search/SearchStream.cpp
Apps/Maps/main/Source/search/SearchStream.h
Apps/Maps/main/Source/ui/SearchSheet.cpp
Files with no reviewable changes: 1
Apps/Maps/main/Source/search/SearchStream.h
Files not fully reviewed because they exceed a per-file size limit: 1
Apps/Maps/main/Source/search/SearchStream.cpp
Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.
The reason will be displayed to describe this comment to others. Learn more.
Major · Functional Correctness · Quick win
Clear the off-route state when weak GPS suppresses detection.
If current.state is OffRoute, a weak fix beyond matchLimit sets rule to None but leaves the state as OffRoute. For example, median accuracy of 80 m and route distance of 150 m take this path.
MapNavigation.cpp, Line 500–510, still treats that state as a recalculation request. After a failed recalculation, it can request another route during weak GPS instead of showing “Weak GPS”.
When weak GPS prevents a valid match, retain progress but set a non-triggering state. Do not leave OffRoute active.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Updates Maps to 0.5.0 (includes 0.4.1).
interest and categories, with diacritics and Greek/Cyrillic in Latin letters not mattering
category
regions where addresses are "village + number", estimated results are marked
their base letter
Summary by CodeRabbit