Import menu composable for both kinds of imports

master
Wynd 2026-02-22 17:57:55 +02:00
parent a6105c9ced
commit ef1353e82b
3 changed files with 72 additions and 26 deletions

View File

@ -0,0 +1,53 @@
package xyz.pixelatedw.recipe.ui.components
import android.content.Intent
import androidx.compose.foundation.layout.Box
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import xyz.pixelatedw.recipe.MainActivity
import xyz.pixelatedw.recipe.utils.sync
@Composable
fun ImportDropdownMenu(ctx: MainActivity) {
var expanded by remember { mutableStateOf(false) }
Box(
) {
IconButton(
onClick = { expanded = !expanded }
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Import recipes"
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text("Import") },
onClick = {
ctx.sourceChooser.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE))
expanded = false
}
)
DropdownMenuItem(
text = { Text("Sync") },
onClick = {
sync(ctx)
expanded = false
}
)
}
}
}

View File

@ -115,7 +115,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
contentDescription = "Toggle tags filtering menu" contentDescription = "Toggle tags filtering menu"
) )
} }
// Load / Delete // Import / Delete
if (selectedEntries.isNotEmpty()) { if (selectedEntries.isNotEmpty()) {
IconButton( IconButton(
modifier = Modifier.weight(0.15f), modifier = Modifier.weight(0.15f),
@ -130,16 +130,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
) )
} }
} else { } else {
IconButton( ImportDropdownMenu(ctx)
modifier = Modifier.weight(0.15f),
onClick = { sync(ctx) },
// onClick = { ctx.sourceChooser.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)) },
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Load recipes from filesystem"
)
}
} }
} }
LazyColumn { LazyColumn {

View File

@ -1,13 +1,10 @@
package xyz.pixelatedw.recipe.utils package xyz.pixelatedw.recipe.utils
import android.os.Build import android.content.Context
import android.os.FileUtils
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import androidx.annotation.RequiresApi
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import xyz.pixelatedw.recipe.MainActivity import xyz.pixelatedw.recipe.MainActivity
import java.io.BufferedOutputStream
import java.io.DataInputStream import java.io.DataInputStream
import java.io.File import java.io.File
import java.io.FileOutputStream import java.io.FileOutputStream
@ -16,14 +13,20 @@ import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.util.concurrent.Executors import java.util.concurrent.Executors
const val DEFAULT_SYNC_SERVER_IP = "192.168.0.100"
const val DEFAULT_SYNC_SERVER_PORT = 9696
fun sync(ctx: MainActivity) { fun sync(ctx: MainActivity) {
val executor = Executors.newSingleThreadExecutor() val executor = Executors.newSingleThreadExecutor()
val handler = Handler(Looper.getMainLooper()) val handler = Handler(Looper.getMainLooper())
executor.execute(Runnable() { executor.execute {
try { try {
val conn = Socket("192.168.0.100", 9696) val prefs = ctx.getPreferences(Context.MODE_PRIVATE)
val syncServerIp = prefs.getString("syncServerIp", DEFAULT_SYNC_SERVER_IP)
val syncServerPort = prefs.getInt("syncServerPort", DEFAULT_SYNC_SERVER_PORT)
val conn = Socket(syncServerIp, syncServerPort)
val stream = conn.getInputStream() val stream = conn.getInputStream()
val inputStream = DataInputStream(stream) val inputStream = DataInputStream(stream)
@ -31,16 +34,16 @@ fun sync(ctx: MainActivity) {
var buffer = ByteArray(8) var buffer = ByteArray(8)
inputStream.read(buffer) inputStream.read(buffer)
val filesSent = ByteBuffer.wrap(buffer).getLong().toInt() val filesSent = ByteBuffer.wrap(buffer).getLong().toInt()
// println("files sent: $filesSent")
for(f in 0..<filesSent) { for (f in 0..<filesSent) {
buffer = ByteArray(8) buffer = ByteArray(8)
inputStream.read(buffer) inputStream.read(buffer)
val nameBufLen = ByteBuffer.wrap(buffer).getLong().toInt() val nameBufLen = ByteBuffer.wrap(buffer).getLong().toInt()
buffer = ByteArray(nameBufLen) buffer = ByteArray(nameBufLen)
inputStream.read(buffer) inputStream.read(buffer)
val fileFullPath = StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer)).toString(); val fileFullPath =
StandardCharsets.UTF_8.decode(ByteBuffer.wrap(buffer)).toString();
val fileName = fileFullPath.split("/").last() val fileName = fileFullPath.split("/").last()
val filePath = fileFullPath.replace(fileName, "") val filePath = fileFullPath.replace(fileName, "")
@ -62,8 +65,7 @@ fun sync(ctx: MainActivity) {
while (usedBytes != contentBufLen) { while (usedBytes != contentBufLen) {
if (usedBytes + blockSize > contentBufLen) { if (usedBytes + blockSize > contentBufLen) {
blockSize = contentBufLen - usedBytes blockSize = contentBufLen - usedBytes
} } else if (blockSize > contentBufLen) {
else if (blockSize > contentBufLen) {
blockSize = contentBufLen blockSize = contentBufLen
} }
@ -87,10 +89,10 @@ fun sync(ctx: MainActivity) {
e.printStackTrace() e.printStackTrace()
} }
handler.post(Runnable { handler.post {
val recipes = ctx.db.recipeWithTagsDao().getAll() val recipes = ctx.db.recipeWithTagsDao().getAll()
ctx.recipeView.setRecipes(recipes) ctx.recipeView.setRecipes(recipes)
println("syncing complete") // println("syncing complete")
}) }
}) }
} }