Compare commits
No commits in common. "143555c22e59cad79685d38d234d7ae3c28dafbb" and "d60cbe4678c809893cd1fe549a88b58daa015910" have entirely different histories.
143555c22e
...
d60cbe4678
|
|
@ -1,2 +1 @@
|
||||||
/build
|
/build
|
||||||
/release
|
|
||||||
|
|
@ -1,63 +1,55 @@
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application)
|
alias(libs.plugins.android.application)
|
||||||
alias(libs.plugins.kotlin.android)
|
alias(libs.plugins.kotlin.android)
|
||||||
alias(libs.plugins.kotlin.compose)
|
alias(libs.plugins.kotlin.compose)
|
||||||
alias(libs.plugins.devtools.ksp)
|
alias(libs.plugins.devtools.ksp)
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "xyz.pixelatedw.recipe"
|
namespace = "xyz.pixelatedw.recipe"
|
||||||
compileSdk = 35
|
compileSdk = 35
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "xyz.pixelatedw.recipe"
|
applicationId = "xyz.pixelatedw.recipe"
|
||||||
minSdk = 24
|
minSdk = 24
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 2
|
versionCode = 1
|
||||||
versionName = "1.1"
|
versionName = "1.0"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
proguardFiles(
|
proguardFiles(
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
compileOptions {
|
||||||
compileOptions {
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
}
|
||||||
}
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
kotlinOptions {
|
}
|
||||||
jvmTarget = "11"
|
buildFeatures {
|
||||||
}
|
compose = true
|
||||||
|
}
|
||||||
buildFeatures {
|
|
||||||
compose = true
|
|
||||||
}
|
|
||||||
|
|
||||||
lint {
|
|
||||||
checkReleaseBuilds = false
|
|
||||||
abortOnError = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.androidx.core.ktx)
|
implementation(libs.androidx.core.ktx)
|
||||||
implementation(libs.androidx.lifecycle.runtime.ktx)
|
implementation(libs.androidx.lifecycle.runtime.ktx)
|
||||||
implementation(libs.androidx.activity.compose)
|
implementation(libs.androidx.activity.compose)
|
||||||
implementation(platform(libs.androidx.compose.bom))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
implementation(libs.androidx.ui)
|
implementation(libs.androidx.ui)
|
||||||
implementation(libs.androidx.ui.graphics)
|
implementation(libs.androidx.ui.graphics)
|
||||||
implementation(libs.androidx.ui.tooling.preview)
|
implementation(libs.androidx.ui.tooling.preview)
|
||||||
implementation(libs.androidx.material3)
|
implementation(libs.androidx.material3)
|
||||||
implementation(libs.androidx.documentfile)
|
implementation(libs.androidx.documentfile)
|
||||||
implementation(libs.androidx.navigation.fragment)
|
implementation(libs.androidx.navigation.fragment)
|
||||||
implementation(libs.androidx.navigation.navigation.ui)
|
implementation(libs.androidx.navigation.navigation.ui)
|
||||||
implementation(libs.androidx.navigation.navigation.compose)
|
implementation(libs.androidx.navigation.navigation.compose)
|
||||||
|
|
@ -70,11 +62,11 @@ dependencies {
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
|
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
androidTestImplementation(platform(libs.androidx.compose.bom))
|
androidTestImplementation(platform(libs.androidx.compose.bom))
|
||||||
androidTestImplementation(libs.androidx.ui.test.junit4)
|
androidTestImplementation(libs.androidx.ui.test.junit4)
|
||||||
|
|
||||||
debugImplementation(libs.androidx.ui.tooling)
|
debugImplementation(libs.androidx.ui.tooling)
|
||||||
debugImplementation(libs.androidx.ui.test.manifest)
|
debugImplementation(libs.androidx.ui.test.manifest)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,10 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.room.Room
|
import androidx.room.Room
|
||||||
|
import xyz.pixelatedw.recipe.ui.theme.RecipeTheme
|
||||||
import xyz.pixelatedw.recipe.data.AppDatabase
|
import xyz.pixelatedw.recipe.data.AppDatabase
|
||||||
import xyz.pixelatedw.recipe.data.RecipesView
|
import xyz.pixelatedw.recipe.data.RecipesView
|
||||||
import xyz.pixelatedw.recipe.ui.components.MainScreen
|
import xyz.pixelatedw.recipe.ui.components.MainScreen
|
||||||
import xyz.pixelatedw.recipe.ui.theme.RecipeTheme
|
|
||||||
import xyz.pixelatedw.recipe.utils.parseRecipes
|
import xyz.pixelatedw.recipe.utils.parseRecipes
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
@ -54,7 +54,8 @@ class MainActivity : ComponentActivity() {
|
||||||
result.data?.data?.let { uri ->
|
result.data?.data?.let { uri ->
|
||||||
parseRecipes(this, uri)
|
parseRecipes(this, uri)
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
importError = "Import cancelled"
|
importError = "Import cancelled"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package xyz.pixelatedw.recipe.data
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
|
import android.widget.ImageView
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Delete
|
import androidx.room.Delete
|
||||||
|
|
@ -17,7 +18,6 @@ import com.google.gson.reflect.TypeToken
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
private val thumbnailsCache: HashMap<String, Bitmap> = hashMapOf()
|
|
||||||
private val imagesCache: HashMap<String, Bitmap> = hashMapOf()
|
private val imagesCache: HashMap<String, Bitmap> = hashMapOf()
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
|
@ -29,29 +29,11 @@ data class Recipe(
|
||||||
val content: String,
|
val content: String,
|
||||||
val hash: Int
|
val hash: Int
|
||||||
) {
|
) {
|
||||||
fun getThumbnail(ctx: Context, idx: Int): Bitmap? {
|
fun previewImage(ctx: Context, idx: Int): Bitmap? {
|
||||||
val img = this.pics.getOrNull(idx)
|
return showImage(ctx, idx)
|
||||||
if (img != null) {
|
|
||||||
val cachedImage = thumbnailsCache[img]
|
|
||||||
if (cachedImage != null) {
|
|
||||||
return cachedImage
|
|
||||||
}
|
|
||||||
|
|
||||||
val originalFile = File(ctx.filesDir, img)
|
|
||||||
val thumbnail = File(originalFile.parentFile, "thumb-${originalFile.name}")
|
|
||||||
if (thumbnail.exists()) {
|
|
||||||
ctx.contentResolver.openInputStream(thumbnail.toUri()).use {
|
|
||||||
val bitmapData = BitmapFactory.decodeStream(it)
|
|
||||||
thumbnailsCache[img] = bitmapData
|
|
||||||
return bitmapData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFullImage(ctx: Context, idx: Int): Bitmap? {
|
fun showImage(ctx: Context, idx: Int): Bitmap? {
|
||||||
val img = this.pics.getOrNull(idx)
|
val img = this.pics.getOrNull(idx)
|
||||||
if (img != null) {
|
if (img != null) {
|
||||||
val cachedImage = imagesCache[img]
|
val cachedImage = imagesCache[img]
|
||||||
|
|
@ -71,36 +53,6 @@ data class Recipe(
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateThumbnails(ctx: Context) {
|
|
||||||
for (img in this.pics) {
|
|
||||||
val file = File(ctx.filesDir, img)
|
|
||||||
ctx.contentResolver.openInputStream(file.toUri()).use {
|
|
||||||
var bitmapData = BitmapFactory.decodeStream(it)
|
|
||||||
val aspectRatio: Float = bitmapData.getWidth() / bitmapData.getHeight().toFloat()
|
|
||||||
val width = 256
|
|
||||||
val height = Math.round(width / aspectRatio)
|
|
||||||
bitmapData = Bitmap.createScaledBitmap(bitmapData, width, height, true);
|
|
||||||
|
|
||||||
val thumbnailName = "thumb-${file.name}"
|
|
||||||
val thumbnailFile = File(file.parentFile, thumbnailName)
|
|
||||||
if (!thumbnailFile.exists()) {
|
|
||||||
thumbnailFile.createNewFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.contentResolver.openOutputStream(thumbnailFile.toUri()).use { out ->
|
|
||||||
bitmapData.compress(Bitmap.CompressFormat.PNG, 100, out!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun clearCache() {
|
|
||||||
thumbnailsCache.clear()
|
|
||||||
imagesCache.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun <reified T> Gson.fromJson(json: String?): T = fromJson<T>(json, object: TypeToken<T>() {}.type)
|
inline fun <reified T> Gson.fromJson(json: String?): T = fromJson<T>(json, object: TypeToken<T>() {}.type)
|
||||||
|
|
@ -119,9 +71,6 @@ class PicsTypeConvertor {
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface RecipeDao {
|
interface RecipeDao {
|
||||||
@Query("SELECT * FROM recipe")
|
|
||||||
fun getAll(): List<Recipe>
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(recipe: Recipe)
|
fun insert(recipe: Recipe)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ data class RecipeWithTags(
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface RecipeWithTagsDao {
|
interface RecipeWithTagsDao {
|
||||||
|
@Transaction
|
||||||
@Query("SELECT * FROM recipe")
|
@Query("SELECT * FROM recipe")
|
||||||
fun getAll(): List<RecipeWithTags>
|
fun getAll(): List<RecipeWithTags>
|
||||||
|
|
||||||
|
|
@ -46,7 +47,6 @@ interface RecipeWithTagsDao {
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(recipe: RecipeTag)
|
fun insert(recipe: RecipeTag)
|
||||||
|
|
||||||
@Transaction
|
|
||||||
@Query("DELETE FROM recipetag WHERE recipetag.title = :recipe")
|
@Query("DELETE FROM recipetag WHERE recipetag.title = :recipe")
|
||||||
fun delete(recipe: String)
|
fun delete(recipe: String)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ import androidx.room.Entity
|
||||||
import androidx.room.Insert
|
import androidx.room.Insert
|
||||||
import androidx.room.OnConflictStrategy
|
import androidx.room.OnConflictStrategy
|
||||||
import androidx.room.PrimaryKey
|
import androidx.room.PrimaryKey
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Transaction
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
data class Tag(
|
data class Tag(
|
||||||
|
|
@ -16,16 +14,6 @@ data class Tag(
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface TagDao {
|
interface TagDao {
|
||||||
@Query("SELECT * FROM tag")
|
|
||||||
fun getAll(): List<Tag>
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
fun insert(tag: Tag)
|
fun insert(tag: Tag)
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) FROM tag")
|
|
||||||
fun count(): Int
|
|
||||||
|
|
||||||
@Transaction
|
|
||||||
@Query("DELETE FROM tag WHERE tag.name = :name")
|
|
||||||
fun delete(name: String)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
val search by view.search.collectAsState()
|
val search by view.search.collectAsState()
|
||||||
val filters by view.tagFilters.collectAsState()
|
val filters by view.tagFilters.collectAsState()
|
||||||
|
|
||||||
|
var activeRecipes by remember { mutableStateOf(recipes) }
|
||||||
var activeTags = 0
|
var activeTags = 0
|
||||||
|
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
|
|
@ -79,9 +80,8 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
value = search.orEmpty(),
|
value = search.orEmpty(),
|
||||||
onValueChange = { search ->
|
onValueChange = { search ->
|
||||||
view.setSearch(search)
|
view.setSearch(search)
|
||||||
val newRecipes =
|
activeRecipes =
|
||||||
recipes.filter { filterRecipe(it, search, filters) }
|
recipes.filter { filterRecipe(it, search, filters) }
|
||||||
view.setRecipes(newRecipes)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
// Tags / Delete
|
// Tags / Delete
|
||||||
|
|
@ -141,10 +141,10 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
state = gridState,
|
state = gridState,
|
||||||
) {
|
) {
|
||||||
items(
|
items(
|
||||||
count = recipes.size,
|
count = activeRecipes.size,
|
||||||
key = { recipes[it].recipe.title },
|
key = { activeRecipes[it].recipe.title },
|
||||||
itemContent = { entryId ->
|
itemContent = { entryId ->
|
||||||
val entry = recipes[entryId]
|
val entry = activeRecipes[entryId]
|
||||||
val isSelected = selectedEntries.contains(entry)
|
val isSelected = selectedEntries.contains(entry)
|
||||||
RecipePreview(entry, isSelected, onClick = {
|
RecipePreview(entry, isSelected, onClick = {
|
||||||
view.setActive(entry)
|
view.setActive(entry)
|
||||||
|
|
@ -194,14 +194,13 @@ fun MainScreen(ctx: MainActivity, padding: PaddingValues, view: RecipesView) {
|
||||||
openTagFilterDialog = false
|
openTagFilterDialog = false
|
||||||
view.reloadTagFilterState()
|
view.reloadTagFilterState()
|
||||||
activeTags = filters.count { f -> f.checked }
|
activeTags = filters.count { f -> f.checked }
|
||||||
val newRecipes = recipes.filter {
|
activeRecipes = recipes.filter {
|
||||||
filterRecipe(
|
filterRecipe(
|
||||||
it,
|
it,
|
||||||
search,
|
search,
|
||||||
filters
|
filters
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ctx.recipeView.setRecipes(newRecipes)
|
|
||||||
},
|
},
|
||||||
view,
|
view,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,17 @@ import androidx.compose.foundation.lazy.grid.GridCells
|
||||||
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
|
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.ButtonDefaults
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Switch
|
import androidx.compose.material3.Switch
|
||||||
import androidx.compose.material3.Text
|
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.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.asImageBitmap
|
import androidx.compose.ui.graphics.asImageBitmap
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
|
@ -80,7 +84,7 @@ fun RecipeInfo(
|
||||||
contentPadding = PaddingValues(horizontal = 64.dp)
|
contentPadding = PaddingValues(horizontal = 64.dp)
|
||||||
) {
|
) {
|
||||||
items(picsCounts) { idx ->
|
items(picsCounts) { idx ->
|
||||||
val pic = active.recipe.getFullImage(ctx, idx)
|
val pic = active.recipe.showImage(ctx, idx)
|
||||||
if (pic != null) {
|
if (pic != null) {
|
||||||
Image(
|
Image(
|
||||||
bitmap = pic.asImageBitmap(),
|
bitmap = pic.asImageBitmap(),
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
|
@ -76,7 +78,7 @@ fun RecipePreview(
|
||||||
.togetherWith(fadeOut(animationSpec = tween(500)))
|
.togetherWith(fadeOut(animationSpec = tween(500)))
|
||||||
}
|
}
|
||||||
) { targetImage ->
|
) { targetImage ->
|
||||||
val displayImage = entry.recipe.getThumbnail(LocalContext.current, targetImage)
|
val displayImage = entry.recipe.previewImage(LocalContext.current, targetImage)
|
||||||
if (displayImage != null) {
|
if (displayImage != null) {
|
||||||
Image(
|
Image(
|
||||||
bitmap = displayImage.asImageBitmap(),
|
bitmap = displayImage.asImageBitmap(),
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@ import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.InputStreamReader
|
import java.io.InputStreamReader
|
||||||
import kotlin.io.path.Path
|
|
||||||
import kotlin.io.path.absolutePathString
|
|
||||||
import kotlin.io.path.fileSize
|
|
||||||
|
|
||||||
private val recipeFiles = mutableListOf<DocumentFile>()
|
private val recipeFiles = mutableListOf<DocumentFile>()
|
||||||
|
|
||||||
|
|
@ -45,41 +42,6 @@ fun parseRecipeFiles(ctx: MainActivity) {
|
||||||
|
|
||||||
reader.close()
|
reader.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clearing unused tags after an import/sync
|
|
||||||
val usedTags = ctx.recipeView.tagFilters.value.map { t -> t.tag }
|
|
||||||
for (tag in ctx.db.tagDao().getAll()) {
|
|
||||||
if (!usedTags.contains(tag.name)) {
|
|
||||||
ctx.db.tagDao().delete(tag.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a list with all the pics used by all the registered recipes
|
|
||||||
val usedPics = ctx.db.recipeDao().getAll()
|
|
||||||
.asSequence()
|
|
||||||
.flatMap { it.pics }
|
|
||||||
.map { File(it) }
|
|
||||||
.map { p ->
|
|
||||||
val list = mutableListOf<String>()
|
|
||||||
|
|
||||||
list.add(p.name)
|
|
||||||
list.add("thumb-${p.name}")
|
|
||||||
|
|
||||||
list
|
|
||||||
}
|
|
||||||
.flatten()
|
|
||||||
.toList()
|
|
||||||
|
|
||||||
// Clear unused images
|
|
||||||
ctx.filesDir.walkTopDown().forEach {
|
|
||||||
if (it.name.endsWith(".jpg") && !usedPics.contains(it.name)) {
|
|
||||||
it.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Recipe.clearCache()
|
|
||||||
|
|
||||||
// ctx.filesDir.walkTopDown().forEach { println(it.absolutePath + " | " + Path(it.absolutePath).fileSize()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseDir(ctx: Context, dir: DocumentFile, path: String) {
|
fun parseDir(ctx: Context, dir: DocumentFile, path: String) {
|
||||||
|
|
@ -100,6 +62,7 @@ fun handleFile(ctx: Context, file: DocumentFile, path: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
val fileName = file.name ?: return
|
val fileName = file.name ?: return
|
||||||
|
// println("file: ${file.name} | ${file.uri.path} | ${file.length()}")
|
||||||
|
|
||||||
if (fileName.endsWith(".jpg")) {
|
if (fileName.endsWith(".jpg")) {
|
||||||
val picsDir = File(ctx.filesDir, path)
|
val picsDir = File(ctx.filesDir, path)
|
||||||
|
|
@ -192,7 +155,5 @@ fun parseRecipe(ctx: MainActivity, lastModified: Long, text: String) {
|
||||||
hash = hash
|
hash = hash
|
||||||
)
|
)
|
||||||
|
|
||||||
recipe.generateThumbnails(ctx)
|
|
||||||
|
|
||||||
ctx.db.recipeDao().insert(recipe)
|
ctx.db.recipeDao().insert(recipe)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,11 @@ fun sync(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> Uni
|
||||||
inputStream.read(buffer)
|
inputStream.read(buffer)
|
||||||
val contentBufLen = ByteBuffer.wrap(buffer).getLong().toInt()
|
val contentBufLen = ByteBuffer.wrap(buffer).getLong().toInt()
|
||||||
|
|
||||||
var parentDir = File(ctx.filesDir, ".sync")
|
var parentDir = ctx.filesDir
|
||||||
if (filePath.isNotEmpty()) {
|
if (filePath.isNotEmpty()) {
|
||||||
parentDir = File(ctx.filesDir, filePath)
|
parentDir = File(ctx.filesDir, filePath)
|
||||||
|
parentDir.mkdirs()
|
||||||
}
|
}
|
||||||
parentDir.mkdirs()
|
|
||||||
|
|
||||||
val newFile = File(parentDir, fileName)
|
val newFile = File(parentDir, fileName)
|
||||||
|
|
||||||
|
|
@ -94,10 +94,6 @@ fun sync(ctx: MainActivity, nav: NavHostController, setLoading: (Boolean) -> Uni
|
||||||
parseDir(ctx, docDir, "")
|
parseDir(ctx, docDir, "")
|
||||||
parseRecipeFiles(ctx)
|
parseRecipeFiles(ctx)
|
||||||
|
|
||||||
val syncFolder = File(ctx.filesDir, ".sync")
|
|
||||||
if (syncFolder.exists()) {
|
|
||||||
syncFolder.deleteRecursively()
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ctx.importError = when (e) {
|
ctx.importError = when (e) {
|
||||||
is SocketTimeoutException -> "Connection timed out"
|
is SocketTimeoutException -> "Connection timed out"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue