SettingsActivity refactor
This commit is contained in:
parent
516455209e
commit
2b821d8204
6 changed files with 117 additions and 96 deletions
4
TODO
4
TODO
|
|
@ -1,8 +1,8 @@
|
|||
functionality:
|
||||
(done) sasplanet zipped sqlitedbs parser
|
||||
refactor:
|
||||
extract file opener from settings activity
|
||||
extract zip parser from settings activity
|
||||
(done) extract file opener from settings activity
|
||||
(done) extract zip parser from settings activity
|
||||
make use of Config.kt (maybe move consts here?)
|
||||
fix:
|
||||
app rotation with placed point
|
||||
|
|
|
|||
31
app/src/main/java/com/mirenkov/ktheightmap/FileLoader.kt
Normal file
31
app/src/main/java/com/mirenkov/ktheightmap/FileLoader.kt
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import android.util.Log
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.mirenkov.ktheightmap.FileLoader.Companion.filePickerResult
|
||||
import com.nareshchocha.filepickerlibrary.FilePickerResultContracts
|
||||
import com.nareshchocha.filepickerlibrary.models.DocumentFilePickerConfig
|
||||
import com.nareshchocha.filepickerlibrary.models.FilePickerResult
|
||||
|
||||
class FileLoader {
|
||||
companion object {
|
||||
var filePath: MutableState<String?> = mutableStateOf(null)
|
||||
fun filePickerResult(result: FilePickerResult): String? {
|
||||
if (result.errorMessage != null) {
|
||||
Log.e(TAG, result.errorMessage!!)
|
||||
return null
|
||||
} else {
|
||||
val filePath = result.selectedFilePath
|
||||
return filePath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ComponentActivity.registerFileLoader(): ActivityResultLauncher<DocumentFilePickerConfig?> {
|
||||
return registerForActivityResult(FilePickerResultContracts.PickDocumentFile())
|
||||
{ result -> FileLoader.filePath.value = filePickerResult(result) }
|
||||
}
|
||||
|
|
@ -27,6 +27,7 @@ import androidx.compose.ui.text.drawText
|
|||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import com.mirenkov.ktheightmap.parser.KhmParser
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.pow
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package com.mirenkov.ktheightmap
|
|||
|
||||
import android.app.Application
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
|
|
@ -14,50 +13,26 @@ import androidx.compose.foundation.layout.safeDrawingPadding
|
|||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.mirenkov.ktheightmap.parser.KhmParser
|
||||
import com.mirenkov.ktheightmap.parser.SasJPEGParser
|
||||
import com.mirenkov.ktheightmap.parser.SasSQLiteParser
|
||||
import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme
|
||||
import com.nareshchocha.filepickerlibrary.FilePickerResultContracts
|
||||
import com.nareshchocha.filepickerlibrary.models.DocumentFilePickerConfig
|
||||
import com.nareshchocha.filepickerlibrary.models.FilePickerResult
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.FileInputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
class SettingsActivity : ComponentActivity() {
|
||||
|
||||
companion object {
|
||||
var filePath: MutableState<String?> = mutableStateOf(null)
|
||||
}
|
||||
|
||||
fun filePickerResult(result: FilePickerResult): String? {
|
||||
if (result.errorMessage != null) {
|
||||
Log.e(TAG, result.errorMessage ?: "")
|
||||
return null
|
||||
} else {
|
||||
val filePath = result.selectedFilePath
|
||||
filePath?.let {
|
||||
if (it.endsWith(".zip") || it.endsWith(".khm"))
|
||||
return filePath
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val launcher = registerForActivityResult(FilePickerResultContracts.PickDocumentFile())
|
||||
{ result -> filePath.value = filePickerResult(result) }
|
||||
|
||||
val launcher = registerFileLoader()
|
||||
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
|
|
@ -77,79 +52,38 @@ class SettingsActivity : ComponentActivity() {
|
|||
@Composable
|
||||
fun SettingsMain(vm: TileViewModel, launcher: ActivityResultLauncher<DocumentFilePickerConfig?>) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val filePath by remember { SettingsActivity.filePath }
|
||||
val filePath by remember { FileLoader.filePath }
|
||||
val ctx = LocalContext.current
|
||||
val toast = Toast.makeText(ctx, "File parsed.", Toast.LENGTH_LONG)
|
||||
KtHeightMapTheme {
|
||||
Column(Modifier.fillMaxSize()
|
||||
.safeDrawingPadding()) {
|
||||
Button(
|
||||
onClick = { launcher.launch(null) }
|
||||
) { Text(text = "Select database") }
|
||||
Button(
|
||||
onClick = { coroutineScope.launch {
|
||||
processZip(filePath).forEach {
|
||||
with(vm.repository) {
|
||||
val t = getTile(it.x, it.y, it.level)
|
||||
if (t == null) {
|
||||
pushTile(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
} },
|
||||
) { Text(text = "Load .zip") }
|
||||
Button(
|
||||
onClick = { coroutineScope.launch { vm.repository.clearTiles() } },
|
||||
) { Text(text = "Clear database") }
|
||||
Button(
|
||||
onClick = { filePath?.let {
|
||||
KhmParser.load(it, ctx)
|
||||
} },
|
||||
) { Text(text = "Load .khm") }
|
||||
Button(
|
||||
onClick = {
|
||||
Button({ launcher.launch(null) }) { Text("Select file") }
|
||||
Button({
|
||||
filePath?.let {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
SasSQLiteParser.processZip(it, vm.repository, ctx)
|
||||
coroutineScope.launch(Dispatchers.Main) { Toast.makeText(ctx, "File parsed.", Toast.LENGTH_LONG).show() }
|
||||
coroutineScope.launch(Dispatchers.Main) { toast.show() }
|
||||
}
|
||||
} }
|
||||
) { Text("Load SQLite") }
|
||||
Button({
|
||||
filePath?.let {
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
SasJPEGParser.processZip(it, vm.repository)
|
||||
coroutineScope.launch(Dispatchers.Main) { toast.show() }
|
||||
}
|
||||
}
|
||||
}
|
||||
) { Text("Load SAS") }
|
||||
},
|
||||
) { Text("Load JPEG") }
|
||||
Button({
|
||||
filePath?.let {
|
||||
KhmParser.load(it, ctx)
|
||||
toast.show()
|
||||
} },
|
||||
) { Text("Load KHM") }
|
||||
Button({ coroutineScope.launch { vm.repository.clearTiles() } }) { Text("Clear tiles") }
|
||||
Button({ KhmParser.clear(ctx) }) { Text("Clear KHM") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun processZip(filePath: String?): List<Tile> = coroutineScope {
|
||||
val list: MutableList<Tile> = mutableListOf()
|
||||
filePath?.let {
|
||||
ZipInputStream(FileInputStream(it)).use { zipInputStream ->
|
||||
var entry = zipInputStream.nextEntry
|
||||
while (true) {
|
||||
if (entry.name.endsWith(".jpg")) {
|
||||
Log.i(TAG, entry.name)
|
||||
val tile = processEntry(zipInputStream, entry)
|
||||
list.add(tile)
|
||||
}
|
||||
entry = zipInputStream.nextEntry
|
||||
if (entry == null)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return@coroutineScope list
|
||||
}
|
||||
|
||||
fun processEntry(zis: ZipInputStream, entry: ZipEntry): Tile {
|
||||
val ba = ByteArray(entry.size.toInt())
|
||||
var offset = 0
|
||||
var size = zis.read(ba)
|
||||
while (size > 0) {
|
||||
offset += size
|
||||
size = zis.read(ba, offset, ba.size - offset)
|
||||
}
|
||||
val regex = Regex("(?<=z)(\\d+)|(?<=x)(\\d+)|(?<=y)(\\d+)")
|
||||
|
||||
val ( level, x, y ) = regex.findAll(entry.name).map { it.value.toInt() }.toList()
|
||||
val base64 = ba.toBase64()
|
||||
return Tile(x, y, level, base64)
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
package com.mirenkov.ktheightmap.parser
|
||||
|
||||
import android.content.Context
|
||||
import java.io.DataInputStream
|
||||
|
|
@ -32,6 +32,12 @@ class KhmParser {
|
|||
inp.close()
|
||||
}
|
||||
|
||||
fun clear(ctx: Context) {
|
||||
if (ctx.getFileStreamPath(HEIGHT_FILE).exists()) {
|
||||
assert(ctx.deleteFile(HEIGHT_FILE))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOffset(header: HeightInfo, x: Int, y: Int): Int {
|
||||
return (x * header.width + y) * 2
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package com.mirenkov.ktheightmap.parser
|
||||
|
||||
import android.util.Log
|
||||
import com.mirenkov.ktheightmap.TAG
|
||||
import com.mirenkov.ktheightmap.Tile
|
||||
import com.mirenkov.ktheightmap.TileRepository
|
||||
import com.mirenkov.ktheightmap.toBase64
|
||||
import java.io.FileInputStream
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipInputStream
|
||||
|
||||
class SasJPEGParser {
|
||||
companion object {
|
||||
fun processZip(filePath: String?, repo: TileRepository) {
|
||||
filePath?.let {
|
||||
ZipInputStream(FileInputStream(it)).use { zipInputStream ->
|
||||
var entry = zipInputStream.nextEntry
|
||||
while (true) {
|
||||
if (entry.name.endsWith(".jpg")) {
|
||||
Log.i(TAG, entry.name)
|
||||
processEntry(zipInputStream, entry, repo)
|
||||
}
|
||||
entry = zipInputStream.nextEntry
|
||||
if (entry == null)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun processEntry(zis: ZipInputStream, entry: ZipEntry, repo: TileRepository) {
|
||||
val ba = ByteArray(entry.size.toInt())
|
||||
var offset = 0
|
||||
var size = zis.read(ba)
|
||||
while (size > 0) {
|
||||
offset += size
|
||||
size = zis.read(ba, offset, ba.size - offset)
|
||||
}
|
||||
val regex = Regex("(?<=z)(\\d+)|(?<=x)(\\d+)|(?<=y)(\\d+)")
|
||||
|
||||
val ( level, x, y ) = regex.findAll(entry.name).map { it.value.toInt() }.toList()
|
||||
val base64 = ba.toBase64()
|
||||
val tile = Tile(x, y, level, base64)
|
||||
val checkedTile = repo.getTile(tile.x, tile.y, tile.level)
|
||||
if (checkedTile == null)
|
||||
repo.pushTile(tile)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue