VeloSpot v1.0.26
VeloSpot v1.0.26
Added
- AMOLED pure-black map (a dark-mode sub-option) β a new AMOLED toggle in Settings β Appearance & map switches the dark map to a true-black style (
map_style_amoled.json, derived frommap_style_dark.jsonwith a#000000background, near-black fills and black text halos) so OLED panels can switch pixels off and save battery on night rides. It's an extension of dark mode: enabling it also turns dark mode on if it wasn't already, and it has no effect in light mode. Off by default and persisted via the DataStore-backedMapSettingsRepository(amoledEnabled,MapViewModel.amoledEnabled); the style reloads live when toggled (a newMAP_STYLE_URL_AMOLEDresolved bymapStyleUrl(isDarkTheme, amoled)). Localised across all eight supported languages (menu_amoled_mode). - Recent destinations in the search bar β focusing the (empty) address search field now initially expands its dropdown to show the last 3 destinations the rider navigated to, so a frequent place is one tap away without re-typing the address. Every navigation start (parking spot, address, saved place, custom pin) is recorded β de-duplicated by rounded coordinate and capped β in a dedicated, isolated Room store (
DestinationHistoryDatabase/recent_destinations, independent of the parking / rides / places stores), exposed reactively via a newDestinationHistoryRepositoryandMapViewModel.recentDestinations. Localised across all eight supported languages (search_recent_title,recent_destination_fallback). - Download a whole route corridor for offline use β the saved-route preview card gains a Download for offline use action that fetches the entire route corridor β the map tiles along the route (not just a 40 km box around the start) and every BRouter routing tile the route passes through β so a long tour into a dead zone works end-to-end offline. Built on a pure, JVM-testable
RouteCorridor.corridorBoxes(splitting the route polyline into overlapping, padded map-tile boxes) plusBRouterSegmentManager.downloadSegmentsForRoute/requiredSegmentNamesForPointsandOfflineMapTilesManager.downloadRouteCorridor, wired through a newOfflineRegionsController.downloadRouteCorridor(MapViewModel.downloadRouteForOffline). The corridor is registered as one offline-region pack (reusing the existing download progress overlay, listing and Wi-Fi gating);OfflineRegionPacknow carries the exactroutingTilesit needs so deleting a region only removes routing tiles no other region still depends on. Localised across all eight supported languages (offline_download_route). - First-launch welcome onboarding β the very first app start now greets the rider with a compact three-card welcome sheet instead of dropping them straight onto the bare map. The cards mirror VeloSpot's own building blocks: a short "what is VeloSpot" intro, an "offline maps & routing" card that explains navigation works without a connection and offers a direct "Set up offline routing" button (which opens the offline-regions manager), and a "ready to ride" card pointing at search, the map and the menus. It's a swipeable
HorizontalPagerbottom sheet with page-indicator dots and a Skip / Next / Get started button β deliberately not a coordinate-based coach-mark tour (the previous attempt broke against the map overlays, insets and async layout). Shown only once, gated behind a new DataStore flag (onboardingCompletedonMapSettingsRepository, exposed viaMapViewModel.onboardingCompleted/completeOnboarding/replayOnboarding) that only reveals the sheet after the launch splash and once the stored value has definitely loaded asfalse(so returning users never see a flash). It can be re-opened any time from a new App tour row on the About VeloSpot sheet. Localised across all eight supported languages (onboarding_*,about_replay_onboarding*). - Unified, multi-region offline use β map tiles and routing, downloaded together per region β the two separate Settings β Navigation & routing entries (offline routing segments and offline map tiles) are merged into a single Offline regions manager, so a region always gets both halves at once β no more "offline route on a blank grey map", and no more "map with no offline route". Each region is one combined pack: the visible vector map (a ~40 km box) plus the BRouter 5Β°Γ5Β° routing tile covering the same spot, downloaded in two clearly-labelled phases with an inline progress bar. Crucially the manager is now multi-region: a region is anchored on the rider's current position or a spot they pick on the map (a centre crosshair they pan the map under, then confirm), so a rider based in, say, Frankfurt can add a second region while on holiday in Sydney β or pre-download a destination before leaving home β and have the map + routing for both offline. The add screen shows a coverage hint (the map box is a ~40 km radius; bike routing covers a much larger surrounding area). Each downloaded region is listed with its reverse-geocoded place name (via
NominatimGeocoder) and can be deleted individually β the shared 5Β° routing tile is only removed when no other region still needs it (so a separate "disable offline routing" button is no longer needed and was removed from the routing-profile sheet). The huge "whole area (DE/FR/LU)" download is dropped in favour of these lightweight, on-the-go regions. Built on a newOfflineRegionsController+OfflineRegionsStore(a smallorg.jsonSharedPreferenceslist, the source of truth) over the existingOfflineMapTilesManager/BRouterSegmentManager(extended with a per-region name + tile helpers), a singleOfflineRegionsUiState, and a newOfflineRegionsSheet, replacing the old splitOfflineRoutingController/OfflineMapController, their UI states and setup sheets. Nothing is bundled into the APK and it adds no new dependency (F-Droid- and reproducibility-safe). Localised across all eight supported languages (offline_regions_*,menu_offline_regions_*).
Changed
- Polished "My routes" list β each saved route is now a richer card: a rounded route-icon avatar, the name, compact stat pills (distance Β· β ascent Β· waypoints), a prominent Ride button plus an outlined Reverse, and a visible secondary action row (Map Β· Ranking Β· Offline) β the offline-corridor download is now reachable straight from the list, not only the preview. Localised across all eight supported languages (
route_map_short,route_leaderboard_short,route_offline_short,common_more_options).
Security
- Hardened GitHub Actions workflows (OpenSSF Scorecard) β tightened CI token permissions to least privilege (the
ciworkflow now defaults tocontents: readat the top level and only the coverage job elevates topull-requests: write/id-token: write, dropping the unusedactions: write), addedpersist-credentials: falseto all read-onlyactions/checkoutsteps (so the repo token is never left on disk for build/lint/test/scan jobs), and enabled Renovate'shelpers:pinGitHubActionDigestspreset so every GitHub Action is pinned to a full commit SHA (with a version comment) and kept up to date automatically β satisfying Scorecard's Pinned-Dependencies and Token-Permissions checks.
π₯ APK Variants
| File | Description |
|---|---|
VeloSpot-v1.0.26.apk |
F-Droid flavor β no Google services, ready to sideload; this is the APK F-Droid reproducibly verifies |
VeloSpot-v1.0.26-googlePlay.apk |
Google Play flavor β includes Google Play Services Location |
VeloSpot-v1.0.26-sbom.cdx.json / .xml |
CycloneDX SBOM β full dependency + license inventory |
π Supply-chain verification
All release artifacts ship with signed build provenance attestations.
Verify any downloaded file with the GitHub CLI:
gh attestation verify VeloSpot-v1.0.26.apk --repo drzeeb/VeloSpotInstallation (sideload)
- Download the APK below.
- On your Android device: Settings β Apps β Install unknown apps β allow your browser or file manager.
- Open the APK and tap Install.
The F-Droid flavor is also available on F-Droid.