I push my tiles into my database

This commit is contained in:
Alexey 2025-08-07 16:48:06 +03:00
commit c0644b4c70
5 changed files with 81 additions and 32 deletions

13
.idea/deviceManager.xml generated Normal file
View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DeviceTable">
<option name="columnSorters">
<list>
<ColumnSorterState>
<option name="column" value="Name" />
<option name="order" value="ASCENDING" />
</ColumnSorterState>
</list>
</option>
</component>
</project>

View file

@ -3,15 +3,11 @@ package com.mirenkov.ktheightmap
import android.app.Application import android.app.Application
import android.content.Intent import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.absoluteOffset
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -24,7 +20,6 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider import androidx.compose.material3.Slider
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableFloatStateOf
@ -76,7 +71,7 @@ class MainActivity : ComponentActivity() {
@Composable @Composable
fun Main(vm: TileViewModel = viewModel()) { fun Main(vm: TileViewModel = viewModel()) {
var sliderValue = rememberSaveable { mutableFloatStateOf(1F) } val sliderValue = rememberSaveable { mutableFloatStateOf(1F) }
KtHeightMapTheme { KtHeightMapTheme {
Box(modifier = Modifier.background(color = colorScheme.background)) { Box(modifier = Modifier.background(color = colorScheme.background)) {
Scaffold( Scaffold(

View file

@ -1,22 +1,27 @@
package com.mirenkov.ktheightmap package com.mirenkov.ktheightmap
import android.graphics.BitmapFactory import android.app.Application
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.activity.result.ActivityResultLauncher
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier 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.ui.theme.KtHeightMapTheme import com.mirenkov.ktheightmap.ui.theme.KtHeightMapTheme
import com.nareshchocha.filepickerlibrary.FilePickerResultContracts import com.nareshchocha.filepickerlibrary.FilePickerResultContracts
import com.nareshchocha.filepickerlibrary.models.DocumentFilePickerConfig
import com.nareshchocha.filepickerlibrary.models.FilePickerResult import com.nareshchocha.filepickerlibrary.models.FilePickerResult
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.FileInputStream import java.io.FileInputStream
@ -25,7 +30,10 @@ import java.util.zip.ZipInputStream
class SettingsActivity : ComponentActivity() { class SettingsActivity : ComponentActivity() {
var filePath: String? = null companion object {
var filePath: String? = null
}
fun filePickerResult(result: FilePickerResult): String? { fun filePickerResult(result: FilePickerResult): String? {
if (result.errorMessage != null) { if (result.errorMessage != null) {
Log.e(TAG, result.errorMessage ?: "") Log.e(TAG, result.errorMessage ?: "")
@ -41,47 +49,72 @@ class SettingsActivity : ComponentActivity() {
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
val launcher = registerForActivityResult(FilePickerResultContracts.PickDocumentFile(), val launcher = registerForActivityResult(FilePickerResultContracts.PickDocumentFile())
{ result -> filePath = filePickerResult(result) } { result -> filePath = filePickerResult(result) }
)
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
val coroutineScope = rememberCoroutineScope() val owner = LocalViewModelStoreOwner.current
owner?.let {
KtHeightMapTheme { val viewModel: TileViewModel = viewModel(
Column(Modifier.fillMaxSize() it,
.safeDrawingPadding()) { "TileViewModel2",
Button(onClick = { TileViewModelFactory(LocalContext.current.applicationContext as Application)
launcher.launch(null) )
}) { Text(text = "Select database") } SettingsMain(viewModel, launcher)
Button(onClick = { coroutineScope.launch { processZip(filePath) } }) {
Text(text = "Load database")
}
}
} }
} }
} }
} }
suspend fun processZip(filePath: String?) = coroutineScope { @Composable
fun SettingsMain(vm: TileViewModel, launcher: ActivityResultLauncher<DocumentFilePickerConfig?>) {
val coroutineScope = rememberCoroutineScope()
KtHeightMapTheme {
Column(Modifier.fillMaxSize()
.safeDrawingPadding()) {
Button(onClick = {
launcher.launch(null)
}) { Text(text = "Select database") }
Button(onClick = { coroutineScope.launch {
processZip(SettingsActivity.filePath).forEach {
with(vm.repository) {
val t = getTile(it.x, it.y, it.level)
if (t == null) {
pushTile(it)
Log.i(TAG, "pushed to db: %d, %d, %d".format(it.level, it.x, it.y))
}
else
Log.i(TAG, "found in db: %d, %d, %d".format(t.level, t.x, t.y))
}
}
} }) { Text(text = "Load database") }
}
}
}
suspend fun processZip(filePath: String?): List<Tile> = coroutineScope {
val list: MutableList<Tile> = mutableListOf()
filePath?.let { filePath?.let {
ZipInputStream(FileInputStream(it)).use { zipInputStream -> ZipInputStream(FileInputStream(it)).use { zipInputStream ->
var entry = zipInputStream.nextEntry var entry = zipInputStream.nextEntry
while (true) { while (true) {
if (entry.name.endsWith(".jpg")) { if (entry.name.endsWith(".jpg")) {
Log.i(TAG, entry.name) Log.i(TAG, entry.name)
processEntry(zipInputStream, entry) val tile = processEntry(zipInputStream, entry)
list.add(tile)
} }
entry = zipInputStream.nextEntry entry = zipInputStream.nextEntry
if (entry == null) if (entry == null)
break break
} }
Log.i(TAG, "got list")
} }
} }
return@coroutineScope list
} }
fun processEntry(zis: ZipInputStream, entry: ZipEntry) { fun processEntry(zis: ZipInputStream, entry: ZipEntry): Tile {
val ba = ByteArray(entry.size.toInt()) val ba = ByteArray(entry.size.toInt())
var offset = 0 var offset = 0
var size = zis.read(ba, 0, ba.size) var size = zis.read(ba, 0, ba.size)
@ -93,5 +126,5 @@ fun processEntry(zis: ZipInputStream, entry: ZipEntry) {
val ( level, x, y ) = regex.findAll(entry.name).map { it.value.toInt() }.toList() val ( level, x, y ) = regex.findAll(entry.name).map { it.value.toInt() }.toList()
val base64 = ba.toBase64() val base64 = ba.toBase64()
val tile = Tile(x, y, level, base64) return Tile(x, y, level, base64)
} }

View file

@ -1,20 +1,28 @@
package com.mirenkov.ktheightmap package com.mirenkov.ktheightmap
import android.util.Log
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
class TileRepository(private val tileDao: TileDao) { class TileRepository(private val tileDao: TileDao) {
private val coroutineScope = CoroutineScope(Dispatchers.Main) private val coroutineScope = CoroutineScope(Dispatchers.Main)
fun pushTile(tile: Tile) { fun pushTile(tile: Tile) {
tileDao.pushTile(tile) coroutineScope.launch(Dispatchers.IO) { tileDao.pushTile(tile) }
} }
fun getTile(x: Int, y: Int, level: Int): Tile? { @OptIn(ExperimentalCoroutinesApi::class)
return tileDao.getTile(x, y, level) suspend fun getTile(x: Int, y: Int, level: Int): Tile? {
val tileDeferred = coroutineScope.async(Dispatchers.IO) {
tileDao.getTile(x, y, level)
}
return tileDeferred.await()
} }
fun clearTiles() { fun clearTiles() {
tileDao.clearTiles() coroutineScope.launch(Dispatchers.IO) { tileDao.clearTiles() }
} }
} }

View file

@ -5,7 +5,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
class TileViewModel(application: Application): ViewModel() { class TileViewModel(application: Application): ViewModel() {
private val repository: TileRepository val repository: TileRepository
init { init {
val tileDb = TileDB.getInstance(application) val tileDb = TileDB.getInstance(application)