Skip to content

Commit

Permalink
Refactor reparser UI and logic into extra class
Browse files Browse the repository at this point in the history
  • Loading branch information
d4rken committed Mar 4, 2024
1 parent aa15ba5 commit 2047314
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 77 deletions.
22 changes: 22 additions & 0 deletions app/src/main/java/eu/darken/pgc/importer/core/Reparser.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package eu.darken.pgc.importer.core

import eu.darken.pgc.common.ca.CaString
import eu.darken.pgc.common.debug.logging.logTag
import javax.inject.Inject

class Reparser @Inject constructor(
private val ingester: Ingester,
) {

suspend fun reparse(onProgress: (Int, Int, CaString) -> Unit): Int {
var current = 0
val max = ingester.flightCount()
return ingester.reingest { progress ->
onProgress(current++, max, progress)
}
}

companion object {
internal val TAG = logTag("Importer", "Reparser")
}
}
74 changes: 74 additions & 0 deletions app/src/main/java/eu/darken/pgc/importer/core/UriImporter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package eu.darken.pgc.importer.core

import android.content.ContentResolver
import android.net.Uri
import android.webkit.MimeTypeMap
import eu.darken.pgc.common.ca.CaString
import eu.darken.pgc.common.ca.toCaString
import eu.darken.pgc.common.debug.logging.log
import eu.darken.pgc.common.debug.logging.logTag
import okhttp3.internal.closeQuietly
import okio.source
import java.io.InputStream
import javax.inject.Inject

class UriImporter @Inject constructor(
private val contentResolver: ContentResolver,
private val ingester: Ingester,
) {

suspend fun import(uris: Collection<Uri>, onProgress: (Int, Int, CaString) -> Unit): Result {

val success = mutableListOf<Uri>()
val skipped = mutableListOf<Uri>()
val failed = mutableListOf<Pair<Uri, Exception>>()

val validUris = uris
.filter { MimeTypeMap.getFileExtensionFromUrl(it.path!!) == "igc" }
var current = 0
validUris.forEach { uri ->
log(TAG) { "import(...): $uri" }
onProgress(current++, validUris.size, (uri.path ?: uri.toString()).toCaString())

val dangles = mutableSetOf<InputStream>()

try {
val added = ingester.ingest(
IngestIGCPayload(
sourceProvider = {
contentResolver.openInputStream(uri)!!.also { dangles.add(it) }.source()
},
originalSource = uri.toString(),
sourceType = when {
uri.authority?.contains("org.xcontest.XCTrack") == true -> IngestIGCPayload.SourceType.XCTRACK
else -> IngestIGCPayload.SourceType.UNKNOWN
},
)
)

if (added) success.add(uri) else skipped.add(uri)
} catch (e: Exception) {
failed.add(uri to e)
} finally {
dangles.forEach { it.closeQuietly() }
}
}

(uris - (success + skipped).toSet()).forEach {
failed.add(it to IllegalArgumentException("Unknown data type"))
}

return Result(success, skipped, failed)
}

data class Result(
val success: List<Uri>,
val skipped: List<Uri>,
val failed: List<Pair<Uri, Exception>>,
)


companion object {
internal val TAG = logTag("Importer", "Uri")
}
}
91 changes: 18 additions & 73 deletions app/src/main/java/eu/darken/pgc/importer/ui/ImporterFragmentVM.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package eu.darken.pgc.importer.ui

import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.net.Uri
import android.webkit.MimeTypeMap
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.pgc.R
import eu.darken.pgc.common.ca.toCaString
import eu.darken.pgc.common.coroutine.DispatcherProvider
Expand All @@ -18,8 +14,8 @@ import eu.darken.pgc.common.debug.logging.log
import eu.darken.pgc.common.debug.logging.logTag
import eu.darken.pgc.common.livedata.SingleLiveEvent
import eu.darken.pgc.common.uix.ViewModel3
import eu.darken.pgc.importer.core.IngestIGCPayload
import eu.darken.pgc.importer.core.Ingester
import eu.darken.pgc.importer.core.Reparser
import eu.darken.pgc.importer.core.UriImporter
import eu.darken.pgc.importer.core.UsbDevicesProvider
import eu.darken.pgc.importer.core.UsbImporter
import eu.darken.pgc.importer.ui.items.ManualCardVH
Expand All @@ -32,21 +28,17 @@ import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import okhttp3.internal.closeQuietly
import okio.source
import java.io.InputStream
import javax.inject.Inject

@HiltViewModel
class ImporterFragmentVM @Inject constructor(
handle: SavedStateHandle,
dispatcherProvider: DispatcherProvider,
private val ingester: Ingester,
private val contentResolver: ContentResolver,
@ApplicationContext private val context: Context,
private val usbManager: UsbManager,
private val usbDevicesProvider: UsbDevicesProvider,
private val usbImporter: UsbImporter,
private val uriImporter: UriImporter,
private val reparser: Reparser,
) : ViewModel3(dispatcherProvider = dispatcherProvider) {

val events = SingleLiveEvent<ImporterEvents>()
Expand Down Expand Up @@ -96,18 +88,12 @@ class ImporterFragmentVM @Inject constructor(

fun reparse() = launch {
log(TAG) { "reparse()" }
reparserState.value = ReparserState.Progress(
max = ingester.flightCount(),
progressMsg = R.string.general_progress_loading.toCaString()
)

val changed = ingester.reingest { progress ->
reparserState.value = (reparserState.value as ReparserState.Progress).let {
it.copy(
progressMsg = progress,
current = it.current + 1
)
}
val changed = reparser.reparse { current, max, info ->
reparserState.value = ReparserState.Progress(
current = current,
max = max,
progressMsg = info
)
}

reparserState.value = ReparserState.Result(
Expand All @@ -123,57 +109,16 @@ class ImporterFragmentVM @Inject constructor(
progressMsg = R.string.general_progress_loading.toCaString()
)

val success = mutableListOf<Uri>()
val skipped = mutableListOf<Uri>()
val failed = mutableListOf<Pair<Uri, Exception>>()

uris
.filter { MimeTypeMap.getFileExtensionFromUrl(it.path!!) == "igc" }
.forEach { uri ->
log(TAG) { "importManual(...): $uri" }
manualImportState.value =
(manualImportState.value as ManualImportState.Progress).copy(
progressMsg = (uri.lastPathSegment ?: uri.toString()).toCaString()
)

val dangles = mutableSetOf<InputStream>()

try {
val added = ingester.ingest(
IngestIGCPayload(
sourceProvider = {
contentResolver.openInputStream(uri)!!.also { dangles.add(it) }.source()
},
originalSource = uri.toString(),
sourceType = when {
uri.authority?.contains("org.xcontest.XCTrack") == true -> IngestIGCPayload.SourceType.XCTRACK
else -> IngestIGCPayload.SourceType.UNKNOWN
},
)
)

if (added) success.add(uri) else skipped.add(uri)
} catch (e: Exception) {
failed.add(uri to e)
} finally {
dangles.forEach { it.closeQuietly() }
}

manualImportState.value =
(manualImportState.value as ManualImportState.Progress).let {
it.copy(current = it.current + 1)
}
}

(uris - (success + skipped).toSet()).forEach {
failed.add(it to IllegalArgumentException("Unknown data type"))
val result = uriImporter.import(uris) { current, max, info ->
manualImportState.value = (manualImportState.value as ManualImportState.Progress).copy(
current = current,
max = max,
progressMsg = info
)
}

manualImportState.value = ManualImportState.Result(
success = success,
skipped = skipped,
failed = failed
)

manualImportState.value = ManualImportState.Result(result)
}.also { manualImportJob = it }

private var usbImportJob: Job? = null
Expand Down
14 changes: 10 additions & 4 deletions app/src/main/java/eu/darken/pgc/importer/ui/items/ManualCardVH.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import eu.darken.pgc.R
import eu.darken.pgc.common.ca.CaString
import eu.darken.pgc.common.lists.binding
import eu.darken.pgc.databinding.ImporterManualItemBinding
import eu.darken.pgc.importer.core.UriImporter
import eu.darken.pgc.importer.ui.ImporterAdapter
import kotlin.math.roundToInt

Expand Down Expand Up @@ -89,10 +90,15 @@ class ManualCardVH(parent: ViewGroup) :
) : ManualImportState

data class Result(
val success: List<Uri>,
val skipped: List<Uri>,
val failed: List<Pair<Uri, Exception>>,
) : ManualImportState
val result: UriImporter.Result
) : ManualImportState {
val success: List<Uri>
get() = result.success
val skipped: List<Uri>
get() = result.skipped
val failed: List<Pair<Uri, Exception>>
get() = result.failed
}
}
}

Expand Down

0 comments on commit 2047314

Please sign in to comment.