From 57e50aec217c0e42a0f889dfd2b8cc8ec9f4c9ba Mon Sep 17 00:00:00 2001 From: Kyle Corry Date: Sat, 9 Sep 2023 13:47:04 -0400 Subject: [PATCH] Add internal support for path group export --- .../persistence/WaypointRepo.kt | 5 +- .../paths/ui/commands/ExportPathCommand.kt | 61 +++++++++++++------ .../grouping/persistence/GroupLoader.kt | 7 ++- 3 files changed, 48 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/infrastructure/persistence/WaypointRepo.kt b/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/infrastructure/persistence/WaypointRepo.kt index 3c2e824c2..adb7eba4d 100644 --- a/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/infrastructure/persistence/WaypointRepo.kt +++ b/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/infrastructure/persistence/WaypointRepo.kt @@ -3,6 +3,7 @@ package com.kylecorry.trail_sense.navigation.paths.infrastructure.persistence import android.content.Context import androidx.lifecycle.LiveData import androidx.lifecycle.map +import com.kylecorry.andromeda.core.coroutines.onIO import com.kylecorry.trail_sense.navigation.paths.domain.PathPoint import com.kylecorry.trail_sense.navigation.paths.domain.WaypointEntity import com.kylecorry.trail_sense.shared.database.AppDatabase @@ -71,12 +72,12 @@ class WaypointRepo private constructor(context: Context) : IWaypointRepo { } } - override suspend fun getAllInPaths(pathIds: List): List { + override suspend fun getAllInPaths(pathIds: List): List = onIO { val points = mutableListOf() for (pathId in pathIds) { points.addAll(waypointDao.getAllInPathSync(pathId)) } - return points.map { it.toPathPoint() } + points.map { it.toPathPoint() } } override fun getAllInPathLive(pathId: Long): LiveData> { diff --git a/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/ui/commands/ExportPathCommand.kt b/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/ui/commands/ExportPathCommand.kt index 73b6fc09f..6ec862be7 100644 --- a/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/ui/commands/ExportPathCommand.kt +++ b/app/src/main/java/com/kylecorry/trail_sense/navigation/paths/ui/commands/ExportPathCommand.kt @@ -4,13 +4,18 @@ import android.content.Context import androidx.lifecycle.LifecycleOwner import com.kylecorry.andromeda.alerts.Alerts import com.kylecorry.andromeda.core.coroutines.BackgroundMinimumState +import com.kylecorry.andromeda.core.coroutines.onIO +import com.kylecorry.andromeda.core.coroutines.onMain import com.kylecorry.andromeda.fragments.inBackground import com.kylecorry.andromeda.gpx.GPXData import com.kylecorry.trail_sense.R import com.kylecorry.trail_sense.navigation.paths.domain.FullPath +import com.kylecorry.trail_sense.navigation.paths.domain.IPath import com.kylecorry.trail_sense.navigation.paths.domain.IPathService import com.kylecorry.trail_sense.navigation.paths.domain.Path import com.kylecorry.trail_sense.navigation.paths.domain.PathGPXConverter +import com.kylecorry.trail_sense.navigation.paths.domain.PathGroup +import com.kylecorry.trail_sense.navigation.paths.infrastructure.PathGroupLoader import com.kylecorry.trail_sense.navigation.paths.infrastructure.persistence.PathService import com.kylecorry.trail_sense.shared.io.IOService import kotlinx.coroutines.Dispatchers @@ -23,34 +28,50 @@ class ExportPathCommand( private val lifecycleOwner: LifecycleOwner, private val gpxService: IOService, private val pathService: IPathService = PathService.getInstance(context) -) : IPathCommand { +) { - // TODO: Take in an IPath - override fun execute(path: Path) { + fun execute(path: IPath) { lifecycleOwner.inBackground(BackgroundMinimumState.Created) { - // TODO: Load all children of the path (if any) - // TODO: Ask the user what paths to export (if the path is a Path, don't ask) - // TODO: Load all waypoints for the paths - // TODO: Assign parent groups and convert to FullPath - val waypoints = pathService.getWaypoints(path.id) - val parent = pathService.getGroup(path.parentId) - val full = FullPath(path, waypoints, parent) - val gpx = PathGPXConverter().toGPX(full) + + val all = getPaths(path) + val paths = all.filterIsInstance() + val groups = all.filterIsInstance().associateBy { it.id } + + // TODO: Ask the user what paths to export, unless the path is a Path + val chosenIds = paths.map { it.id } + + // Load the waypoints and associate them with the paths + val waypoints = pathService.getWaypoints(chosenIds) + val pathsToExport = paths + .filter { chosenIds.contains(it.id) } + .map { + val parent = it.parentId?.let { id -> groups[id] } + FullPath(it, waypoints[it.id] ?: emptyList(), parent) + } + + // Export to a GPX file + val gpx = PathGPXConverter().toGPX(pathsToExport) val exportFile = "trail-sense-${Instant.now().epochSecond}.gpx" val success = gpxService.export(gpx, exportFile) - withContext(Dispatchers.Main) { + + // Notify the user + onMain { if (success) { - Alerts.toast( - context, - context.getString(R.string.path_exported) - ) + Alerts.toast(context, context.getString(R.string.path_exported)) } else { - Alerts.toast( - context, - context.getString(R.string.export_path_error) - ) + Alerts.toast(context, context.getString(R.string.export_path_error)) } } } } + + private suspend fun getPaths(path: IPath): List = onIO { + if (path is Path) { + listOf(path) + } else { + listOf(path) + pathService.loader().getChildren(path.id) + } + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/kylecorry/trail_sense/shared/grouping/persistence/GroupLoader.kt b/app/src/main/java/com/kylecorry/trail_sense/shared/grouping/persistence/GroupLoader.kt index 6a2785591..5067c960c 100644 --- a/app/src/main/java/com/kylecorry/trail_sense/shared/grouping/persistence/GroupLoader.kt +++ b/app/src/main/java/com/kylecorry/trail_sense/shared/grouping/persistence/GroupLoader.kt @@ -1,5 +1,6 @@ package com.kylecorry.trail_sense.shared.grouping.persistence +import com.kylecorry.andromeda.core.coroutines.onIO import com.kylecorry.trail_sense.shared.grouping.Groupable class GroupLoader( @@ -15,9 +16,9 @@ class GroupLoader( return groupLoader.invoke(id) } - private suspend fun loadChildren(id: Long?, maxDepth: Int?): List { + private suspend fun loadChildren(id: Long?, maxDepth: Int?): List = onIO { if (maxDepth != null && maxDepth <= 0) { - return emptyList() + return@onIO emptyList() } val children = childLoader.invoke(id) @@ -27,6 +28,6 @@ class GroupLoader( maxDepth - 1 } val subchildren = children.filter { it.isGroup }.flatMap { loadChildren(it.id, newDepth) } - return children + subchildren + children + subchildren } } \ No newline at end of file