Compare commits
2 Commits
6e4aa55266
...
9f740e5bcc
| Author | SHA1 | Date |
|---|---|---|
|
|
9f740e5bcc | |
|
|
fcb18018d4 |
|
|
@ -21,6 +21,9 @@ class MainActivity : ComponentActivity() {
|
||||||
val recipeView: RecipesView by viewModels()
|
val recipeView: RecipesView by viewModels()
|
||||||
lateinit var db: AppDatabase
|
lateinit var db: AppDatabase
|
||||||
|
|
||||||
|
var importFinished: Boolean = false
|
||||||
|
var importError: String = ""
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
|
@ -50,10 +53,21 @@ class MainActivity : ComponentActivity() {
|
||||||
if (result.resultCode == RESULT_OK) {
|
if (result.resultCode == RESULT_OK) {
|
||||||
result.data?.data?.let { uri ->
|
result.data?.data?.let { uri ->
|
||||||
parseRecipes(this, uri)
|
parseRecipes(this, uri)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
importError = "Import cancelled"
|
||||||
|
}
|
||||||
|
|
||||||
val recipes = db.recipeWithTagsDao().getAll()
|
importFinished = true
|
||||||
recipeView.setRecipes(recipes)
|
}
|
||||||
}
|
|
||||||
|
fun getAppVersion(): String {
|
||||||
|
val info = this.packageManager.getPackageInfo(packageName, 0)
|
||||||
|
return if (info.versionName == null) {
|
||||||
|
"Unknown"
|
||||||
|
} else {
|
||||||
|
"v${info.versionName}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
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 androidx.compose.ui.Modifier
|
|
||||||
import xyz.pixelatedw.recipe.MainActivity
|
|
||||||
import xyz.pixelatedw.recipe.utils.sync
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ImportDropdownMenu(ctx: MainActivity, modifier: Modifier) {
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
|
||||||
Box(
|
|
||||||
modifier = modifier,
|
|
||||||
) {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package xyz.pixelatedw.recipe.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun LoadingIndicator(isLoading: Boolean) {
|
||||||
|
if (!isLoading) return
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier.width(128.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package xyz.pixelatedw.recipe.ui.components
|
package xyz.pixelatedw.recipe.ui.components
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
|
@ -9,19 +8,15 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material.icons.filled.Settings
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
|
@ -30,7 +25,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
|
|
@ -39,8 +33,6 @@ import xyz.pixelatedw.recipe.MainActivity
|
||||||
import xyz.pixelatedw.recipe.R
|
import xyz.pixelatedw.recipe.R
|
||||||
import xyz.pixelatedw.recipe.data.RecipeWithTags
|
import xyz.pixelatedw.recipe.data.RecipeWithTags
|
||||||
import xyz.pixelatedw.recipe.data.RecipesView
|
import xyz.pixelatedw.recipe.data.RecipesView
|
||||||
import xyz.pixelatedw.recipe.utils.DEFAULT_SYNC_SERVER_IP
|
|
||||||
import xyz.pixelatedw.recipe.utils.DEFAULT_SYNC_SERVER_PORT
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -51,11 +43,6 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
val search = view.search.collectAsState()
|
val search = view.search.collectAsState()
|
||||||
val filters = view.tagFilters.collectAsState()
|
val filters = view.tagFilters.collectAsState()
|
||||||
|
|
||||||
val prefs = ctx.getPreferences(Context.MODE_PRIVATE)
|
|
||||||
|
|
||||||
var syncIp by remember { mutableStateOf(prefs.getString("syncServerIp", DEFAULT_SYNC_SERVER_IP)!!) }
|
|
||||||
var syncPort by remember { mutableIntStateOf(prefs.getInt("syncServerPort", DEFAULT_SYNC_SERVER_PORT)) }
|
|
||||||
|
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
|
|
||||||
var openDeletionDialog by remember { mutableStateOf(false) }
|
var openDeletionDialog by remember { mutableStateOf(false) }
|
||||||
|
|
@ -118,17 +105,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
value = search.value.orEmpty(),
|
value = search.value.orEmpty(),
|
||||||
onValueChange = { search -> view.setSearch(search) },
|
onValueChange = { search -> view.setSearch(search) },
|
||||||
)
|
)
|
||||||
// Tags
|
// Tags / Delete
|
||||||
IconButton(
|
|
||||||
modifier = Modifier.weight(0.1f),
|
|
||||||
onClick = { openTagFilterDialog = true },
|
|
||||||
) {
|
|
||||||
Icon(
|
|
||||||
imageVector = ImageVector.vectorResource(R.drawable.filter_24),
|
|
||||||
contentDescription = "Toggle tags filtering menu"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Import / Delete
|
|
||||||
if (selectedEntries.isNotEmpty()) {
|
if (selectedEntries.isNotEmpty()) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.weight(0.1f),
|
modifier = Modifier.weight(0.1f),
|
||||||
|
|
@ -143,12 +120,23 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImportDropdownMenu(ctx, Modifier.weight(0.1f))
|
IconButton(
|
||||||
|
modifier = Modifier.weight(0.1f),
|
||||||
|
onClick = { openTagFilterDialog = true },
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = ImageVector.vectorResource(R.drawable.filter_24),
|
||||||
|
contentDescription = "Toggle tags filtering menu"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Options
|
// Options
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.weight(0.1f),
|
modifier = Modifier.weight(0.1f),
|
||||||
onClick = { navController.navigate("settings") },
|
onClick = {
|
||||||
|
ctx.importError = ""
|
||||||
|
navController.navigate("settings")
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Settings,
|
imageVector = Icons.Default.Settings,
|
||||||
|
|
@ -217,42 +205,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
RecipeInfo(ctx, view, navController, padding, active.value!!)
|
RecipeInfo(ctx, view, navController, padding, active.value!!)
|
||||||
}
|
}
|
||||||
composable("settings") {
|
composable("settings") {
|
||||||
Column(modifier = Modifier.padding(start = 12.dp, top = 48.dp)) {
|
SettingsScreen(ctx, navController)
|
||||||
OutlinedTextField(
|
|
||||||
label = { Text("Sync Server IP") },
|
|
||||||
singleLine = true,
|
|
||||||
value = syncIp,
|
|
||||||
onValueChange = { syncIp = it },
|
|
||||||
)
|
|
||||||
|
|
||||||
OutlinedTextField(
|
|
||||||
modifier = Modifier.padding(top = 8.dp),
|
|
||||||
label = { Text("Sync Server IP") },
|
|
||||||
singleLine = true,
|
|
||||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
|
||||||
value = syncPort.toString(),
|
|
||||||
onValueChange = {
|
|
||||||
syncPort = when (it.toIntOrNull()) {
|
|
||||||
null -> syncPort
|
|
||||||
else -> it.toInt()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
Button(
|
|
||||||
modifier = Modifier.padding(top = 8.dp),
|
|
||||||
onClick = {
|
|
||||||
with (prefs.edit()) {
|
|
||||||
putString("syncServerIp", syncIp)
|
|
||||||
putInt("syncServerPort", syncPort)
|
|
||||||
apply()
|
|
||||||
}
|
|
||||||
navController.navigate("list")
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text("Save")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
package xyz.pixelatedw.recipe.ui.components
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import xyz.pixelatedw.recipe.MainActivity
|
||||||
|
import xyz.pixelatedw.recipe.utils.DEFAULT_SYNC_SERVER_IP
|
||||||
|
import xyz.pixelatedw.recipe.utils.DEFAULT_SYNC_SERVER_PORT
|
||||||
|
import xyz.pixelatedw.recipe.utils.import
|
||||||
|
import xyz.pixelatedw.recipe.utils.sync
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SettingsScreen(ctx: MainActivity, nav: NavHostController) {
|
||||||
|
val prefs = ctx.getPreferences(Context.MODE_PRIVATE)
|
||||||
|
|
||||||
|
var syncIp by remember {
|
||||||
|
mutableStateOf(
|
||||||
|
prefs.getString(
|
||||||
|
"syncServerIp",
|
||||||
|
DEFAULT_SYNC_SERVER_IP
|
||||||
|
)!!
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var syncPort by remember {
|
||||||
|
mutableIntStateOf(
|
||||||
|
prefs.getInt(
|
||||||
|
"syncServerPort",
|
||||||
|
DEFAULT_SYNC_SERVER_PORT
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
val (isLoading, setLoading) = remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
LoadingIndicator(isLoading)
|
||||||
|
|
||||||
|
// Error text field
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(bottom = 128.dp),
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
ctx.importError,
|
||||||
|
color = Color.Red,
|
||||||
|
fontSize = 32.sp,
|
||||||
|
softWrap = true,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
lineHeight = 32.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(start = 12.dp, top = 48.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
label = { Text("Sync Server IP") },
|
||||||
|
singleLine = true,
|
||||||
|
value = syncIp,
|
||||||
|
onValueChange = { syncIp = it },
|
||||||
|
)
|
||||||
|
|
||||||
|
OutlinedTextField(
|
||||||
|
label = { Text("Sync Server Port") },
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
|
||||||
|
value = syncPort.toString(),
|
||||||
|
onValueChange = {
|
||||||
|
syncPort = when (it.toIntOrNull()) {
|
||||||
|
null -> syncPort
|
||||||
|
else -> it.toInt()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
Button(onClick = {
|
||||||
|
import(ctx, nav, setLoading)
|
||||||
|
}) {
|
||||||
|
Text("Import")
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(onClick = {
|
||||||
|
sync(ctx, nav, setLoading)
|
||||||
|
}) {
|
||||||
|
Text("Sync")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
with(prefs.edit()) {
|
||||||
|
putString("syncServerIp", syncIp)
|
||||||
|
putInt("syncServerPort", syncPort)
|
||||||
|
apply()
|
||||||
|
}
|
||||||
|
nav.navigate("list")
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text("Save")
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(bottom = 64.dp),
|
||||||
|
horizontalArrangement = Arrangement.Center,
|
||||||
|
verticalAlignment = Alignment.Bottom
|
||||||
|
) {
|
||||||
|
Text(ctx.getAppVersion())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package xyz.pixelatedw.recipe.utils
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import xyz.pixelatedw.recipe.MainActivity
|
||||||
|
import java.util.concurrent.Executors
|
||||||
|
|
||||||
|
fun import(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> Unit) {
|
||||||
|
val executor = Executors.newSingleThreadExecutor()
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
|
executor.execute {
|
||||||
|
setLoading(true)
|
||||||
|
ctx.importError = ""
|
||||||
|
ctx.importFinished = false
|
||||||
|
|
||||||
|
try {
|
||||||
|
ctx.sourceChooser.launch(Intent(Intent.ACTION_OPEN_DOCUMENT_TREE))
|
||||||
|
// Keep the thread busy until the import is done
|
||||||
|
// TODO This feels dirty but it doesn't block the main thread and I can't figure out a better way
|
||||||
|
while(!ctx.importFinished) {}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ctx.importError = when (e) {
|
||||||
|
else -> "Exception occurred: ${e.javaClass.canonicalName}"
|
||||||
|
}
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.post {
|
||||||
|
if (ctx.importError.isEmpty()) {
|
||||||
|
val recipes = ctx.db.recipeWithTagsDao().getAll()
|
||||||
|
ctx.recipeView.setRecipes(recipes)
|
||||||
|
nav.navigate("list")
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,29 +4,37 @@ import android.content.Context
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import androidx.documentfile.provider.DocumentFile
|
import androidx.documentfile.provider.DocumentFile
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
import xyz.pixelatedw.recipe.MainActivity
|
import xyz.pixelatedw.recipe.MainActivity
|
||||||
import java.io.DataInputStream
|
import java.io.DataInputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
|
import java.net.InetSocketAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
import java.nio.ByteBuffer
|
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_IP = "192.168.0.100"
|
||||||
const val DEFAULT_SYNC_SERVER_PORT = 9696
|
const val DEFAULT_SYNC_SERVER_PORT = 9696
|
||||||
|
const val CONNECTION_TIMEOUT = 1_000 // 1 seconds
|
||||||
|
|
||||||
fun sync(ctx: MainActivity) {
|
fun sync(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> Unit) {
|
||||||
val executor = Executors.newSingleThreadExecutor()
|
val executor = Executors.newSingleThreadExecutor()
|
||||||
val handler = Handler(Looper.getMainLooper())
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
executor.execute {
|
executor.execute {
|
||||||
|
setLoading(true)
|
||||||
|
ctx.importError = ""
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val prefs = ctx.getPreferences(Context.MODE_PRIVATE)
|
val prefs = ctx.getPreferences(Context.MODE_PRIVATE)
|
||||||
val syncServerIp = prefs.getString("syncServerIp", DEFAULT_SYNC_SERVER_IP)
|
val syncServerIp = prefs.getString("syncServerIp", DEFAULT_SYNC_SERVER_IP)
|
||||||
val syncServerPort = prefs.getInt("syncServerPort", DEFAULT_SYNC_SERVER_PORT)
|
val syncServerPort = prefs.getInt("syncServerPort", DEFAULT_SYNC_SERVER_PORT)
|
||||||
|
|
||||||
val conn = Socket(syncServerIp, syncServerPort)
|
val conn = Socket()
|
||||||
|
conn.connect(InetSocketAddress(syncServerIp, syncServerPort), CONNECTION_TIMEOUT)
|
||||||
val stream = conn.getInputStream()
|
val stream = conn.getInputStream()
|
||||||
|
|
||||||
val inputStream = DataInputStream(stream)
|
val inputStream = DataInputStream(stream)
|
||||||
|
|
@ -80,19 +88,28 @@ fun sync(ctx: MainActivity) {
|
||||||
|
|
||||||
// println("new file: ${newFile.absolutePath} | $contentBufLen | ${newFile.length()}")
|
// println("new file: ${newFile.absolutePath} | $contentBufLen | ${newFile.length()}")
|
||||||
}
|
}
|
||||||
|
inputStream.close()
|
||||||
|
|
||||||
val docDir = DocumentFile.fromFile(ctx.filesDir)
|
val docDir = DocumentFile.fromFile(ctx.filesDir)
|
||||||
parseDir(ctx, docDir, "")
|
parseDir(ctx, docDir, "")
|
||||||
parseRecipeFiles(ctx)
|
parseRecipeFiles(ctx)
|
||||||
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
ctx.importError = when (e) {
|
||||||
|
is SocketTimeoutException -> "Connection timed out"
|
||||||
|
else -> "Exception occurred: ${e.javaClass.canonicalName}"
|
||||||
|
}
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.post {
|
handler.post {
|
||||||
|
if (ctx.importError.isEmpty()) {
|
||||||
val recipes = ctx.db.recipeWithTagsDao().getAll()
|
val recipes = ctx.db.recipeWithTagsDao().getAll()
|
||||||
ctx.recipeView.setRecipes(recipes)
|
ctx.recipeView.setRecipes(recipes)
|
||||||
// println("syncing complete")
|
nav.navigate("list")
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue