OfflineTerrainRepository

class OfflineTerrainRepository(fileSystem: FileSystem, baseDir: Path)(source)

Owns the one downloaded offline-terrain region: its manifest, and the TerrainTileStore holding its tiles.

Not a Koin @Single. MapLibreMapViewProvider's own doc comment already states this module's rule — "free of any assumption about how the host app wires its graph" — and it turns out to bind harder than usual here: a @Module @ComponentScan in this package would only take effect once some host's Koin startup imports it, and every host that does that (androidApp/src/main's MainKoinModule) compiles into both Android flavors, so registering it there would pull a MapLibre-only type into the Google flavor's dependency graph, exactly what this module's own build.gradle.kts forbids. default is how every caller reaches the same instance instead — a plain lazily-initialized singleton, not a DI one.

Single region, not a list: see OfflineTerrainRegion's own doc comment for why. A new download therefore replaces whatever was there before — deleting the old tiles and manifest before fetching the first new one, not after. This is a known, deliberate tradeoff, not an oversight: there is nowhere to stage the new region side-by-side with the old one without doubling disk usage for the download's duration, so a download that later fails or is cancelled leaves nothing downloaded rather than restoring what was there — region reports null, the same as if nothing had ever been fetched.

Constructors

Link copied to clipboard
constructor(fileSystem: FileSystem, baseDir: Path)

Types

Link copied to clipboard
object Companion

Properties

Link copied to clipboard

The most recent state startDownload has reported, surviving a UI that goes away and comes back.

Link copied to clipboard
val region: StateFlow<OfflineTerrainRegion?>

The current region, or null if nothing has been downloaded. Populated by refresh.

Link copied to clipboard

Functions

Link copied to clipboard
suspend fun delete()

Deletes the current region's tiles and manifest, leaving nothing downloaded. A no-op if there is none.

Link copied to clipboard
fun download(bounds: GeoBounds, maxZoom: Int): Flow<TerrainDownloadState>

Replaces whatever region was downloaded before with a fresh one covering bounds up to maxZoom.

Link copied to clipboard
suspend fun refresh()

Loads the manifest from disk if this is the first call. Idempotent, and cheap after the first: everything past that point reads region's already-loaded value. Callers that only ever read region from a composable should call this once from a LaunchedEffect; see TerrainLayers.

Link copied to clipboard
fun startDownload(bounds: GeoBounds, maxZoom: Int)

Starts a download on this repository's own scope and mirrors its emissions into downloadState, so a caller observes progress instead of collecting a Flow tied to its own lifecycle — see scope's own comment for why that distinction matters here. A no-op while a download is already running, closing the double-tap window a UI-side "is it downloading" check can't close on its own (the first TerrainDownloadState.InProgress only arrives after several tiles have already been fetched).

Link copied to clipboard

The file:// URL template rememberRasterDemTileSource (hillshade) can use to reach source's downloaded tiles directly, matching TerrainTileStore's own <baseDir>/<source>/<zoom>/<x>/<y>.webp layout.