recipe-kt/app/src/main/java/xyz/pixelatedw/recipe/utils/RecipeParser.kt

129 lines
2.9 KiB
Kotlin
Raw Normal View History

2025-08-08 23:21:33 +03:00
package xyz.pixelatedw.recipe.utils
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
2025-08-08 23:21:33 +03:00
import android.net.Uri
import androidx.core.text.trimmedLength
import androidx.documentfile.provider.DocumentFile
import io.github.wasabithumb.jtoml.JToml
import xyz.pixelatedw.recipe.data.Recipe
import xyz.pixelatedw.recipe.data.RecipesView
import java.io.BufferedReader
import java.io.InputStreamReader
private val previews = HashMap<String, Bitmap>()
private val recipeFiles = mutableListOf<DocumentFile>()
2025-08-08 23:21:33 +03:00
fun getRecipes(ctx: Context, view: RecipesView, uri: Uri?) {
if (uri == null) {
return
}
val dir = DocumentFile.fromTreeUri(ctx, uri)
if (dir != null) {
parseDir(ctx, dir)
for (file in recipeFiles) {
val recipe = parseRecipe(ctx, file)
if (recipe != null) {
view.addRecipe(recipe)
}
}
}
}
fun parseDir(ctx: Context, dir: DocumentFile) {
val fileList: Array<DocumentFile> = dir.listFiles()
for (file in fileList) {
if(file.isDirectory) {
parseDir(ctx, file)
continue;
}
if (file.isFile && file.name?.endsWith(".jpg") == true) {
val inStream = ctx.contentResolver.openInputStream(file.uri)
var bitmap: Bitmap? = null
if (file.exists()) {
try {
bitmap = BitmapFactory.decodeStream(inStream)
2025-08-08 23:21:33 +03:00
}
finally {
inStream?.close()
}
}
if (bitmap != null) {
previews[file.name!!] = bitmap
2025-08-08 23:21:33 +03:00
}
}
if (file.isFile && file.name?.endsWith(".md") == true) {
recipeFiles.add(file)
}
2025-08-08 23:21:33 +03:00
}
}
private fun parseRecipe(ctx: Context, file: DocumentFile): Recipe? {
val lastModified = file.lastModified()
val inputStream = ctx.contentResolver.openInputStream(file.uri)
val reader = BufferedReader(InputStreamReader(inputStream))
val text = reader.readText()
val lines = text.lines()
val sb = StringBuilder()
var hasToml = false
var frontMatterSize = 0
// TODO This could use some improvements as it always assumes frontmatter is the very first thing in the file
for (i in 0..lines.size) {
val line = lines[i]
frontMatterSize += line.trimmedLength() + 1
if (line == "+++") {
if (hasToml) {
break
}
hasToml = true
continue
}
sb.appendLine(line)
}
val toml = JToml.jToml()
val doc = toml.readFromString(sb.toString())
val tags = arrayListOf<String>()
for (tomlElem in doc["tags"]!!.asArray()) {
tags.add(tomlElem!!.asPrimitive().asString())
}
val pics = arrayListOf<String>()
for (tomlElem in doc["pics"]!!.asArray()) {
pics.add(tomlElem!!.asPrimitive().asString())
}
val recipePreviews = mutableListOf<Bitmap>()
for (pic in pics) {
val bitmap = previews[pic]
if (bitmap != null) {
recipePreviews.add(bitmap)
}
}
2025-08-08 23:21:33 +03:00
val content = text.substring(frontMatterSize..<text.length)
val recipe = Recipe(
title = doc["title"]!!.asPrimitive().asString(),
tags = tags,
previews = recipePreviews,
2025-08-08 23:21:33 +03:00
lastModified = lastModified,
content = content
)
reader.close()
2025-08-08 23:21:33 +03:00
return recipe
}