Replaced the preview pic with an actual list of images that are also displayed in the recipe's info page

master
Wynd 2025-09-27 01:46:38 +03:00
parent 7e04c31ae3
commit 69bf00ee7b
6 changed files with 64 additions and 10 deletions

View File

@ -56,6 +56,7 @@ dependencies {
implementation(libs.androidx.room) implementation(libs.androidx.room)
implementation(libs.jtoml) implementation(libs.jtoml)
implementation(libs.commonmark) implementation(libs.commonmark)
implementation(libs.gson)
ksp(libs.androidx.room.compiler) ksp(libs.androidx.room.compiler)

View File

@ -2,11 +2,13 @@ package xyz.pixelatedw.recipe.data
import androidx.room.Database import androidx.room.Database
import androidx.room.RoomDatabase import androidx.room.RoomDatabase
import androidx.room.TypeConverters
@Database( @Database(
version = 1, version = 1,
entities = [Recipe::class, Tag::class, RecipeTag::class], entities = [Recipe::class, Tag::class, RecipeTag::class],
) )
@TypeConverters(PicsTypeConvertor::class)
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
abstract fun recipeWithTagsDao(): RecipeWithTagsDao abstract fun recipeWithTagsDao(): RecipeWithTagsDao

View File

@ -11,20 +11,28 @@ 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.Query
import androidx.room.TypeConverter
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.io.File import java.io.File
@Entity @Entity
data class Recipe( data class Recipe(
@PrimaryKey @PrimaryKey
val title: String, val title: String,
val preview: String?, val pics: ArrayList<String>,
val lastModified: Long, val lastModified: Long,
val content: String, val content: String,
val hash: Int val hash: Int
) { ) {
fun previewImage(ctx: Context): Bitmap? { fun previewImage(ctx: Context): Bitmap? {
if (this.preview != null) { return showImage(ctx, 0)
val file = File(ctx.filesDir, this.preview) }
fun showImage(ctx: Context, idx: Int): Bitmap? {
val img = this.pics.getOrNull(idx)
if (img != null) {
val file = File(ctx.filesDir, img)
if (file.exists()) { if (file.exists()) {
ctx.contentResolver.openInputStream(file.toUri()).use { ctx.contentResolver.openInputStream(file.toUri()).use {
return BitmapFactory.decodeStream(it) return BitmapFactory.decodeStream(it)
@ -36,6 +44,20 @@ data class Recipe(
} }
} }
inline fun <reified T> Gson.fromJson(json: String?): T = fromJson<T>(json, object: TypeToken<T>() {}.type)
class PicsTypeConvertor {
@TypeConverter
fun fromString(value: String?): ArrayList<String> {
return Gson().fromJson<ArrayList<String>>(value)
}
@TypeConverter
fun fromArrayList(value: ArrayList<String>?): String {
return Gson().toJson(value)
}
}
@Dao @Dao
interface RecipeDao { interface RecipeDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)

View File

@ -1,6 +1,8 @@
package xyz.pixelatedw.recipe.ui.components package xyz.pixelatedw.recipe.ui.components
import android.util.DisplayMetrics
import android.view.WindowManager import android.view.WindowManager
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -8,7 +10,12 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.grid.GridCells
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.Button
@ -20,8 +27,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
@ -50,7 +60,7 @@ fun RecipeInfo(
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.Center,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 24.dp, bottom = 24.dp) .padding(top = 24.dp, bottom = 12.dp)
) { ) {
Text( Text(
text = active.recipe.title, text = active.recipe.title,
@ -59,6 +69,28 @@ fun RecipeInfo(
) )
} }
LazyHorizontalGrid(
rows = GridCells.Fixed(1),
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.height(256.dp)
.padding(bottom = 16.dp),
contentPadding = PaddingValues(horizontal = 16.dp)
) {
items(active.recipe.pics.size) { idx ->
val pic = active.recipe.showImage(ctx, idx)
if (pic != null) {
Image(
bitmap = pic.asImageBitmap(),
contentDescription = "Recipe image",
contentScale = ContentScale.Crop,
modifier = Modifier.size(256.dp),
)
}
}
}
Row(modifier = Modifier.fillMaxWidth()) { Row(modifier = Modifier.fillMaxWidth()) {
Box( Box(
modifier = Modifier modifier = Modifier

View File

@ -128,16 +128,11 @@ private fun parseRecipe(ctx: Context, db: AppDatabase, file: DocumentFile) {
} }
} }
var recipePreview: String? = null
for (pic in pics) {
recipePreview = pic
}
val content = text.substring(frontMatterSize..<text.length) val content = text.substring(frontMatterSize..<text.length)
val recipe = Recipe( val recipe = Recipe(
title = recipeTitle, title = recipeTitle,
preview = recipePreview, pics = pics,
lastModified = lastModified, lastModified = lastModified,
content = content, content = content,
hash = hash hash = hash

View File

@ -15,6 +15,7 @@ navVersion = "2.9.3"
room = "2.7.2" room = "2.7.2"
roomCompiler = "2.7.2" roomCompiler = "2.7.2"
ksp = "2.0.21-1.0.27" ksp = "2.0.21-1.0.27"
gson = "2.13.2"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -39,6 +40,7 @@ androidx-navigation-fragment = { group = "androidx.navigation", name = "navigati
androidx-navigation-navigation-ui = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navVersion"} androidx-navigation-navigation-ui = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navVersion"}
androidx-navigation-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navVersion"} androidx-navigation-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navVersion"}
androidx-room = { group = "androidx.room", name = "room-runtime", version.ref = "room"} androidx-room = { group = "androidx.room", name = "room-runtime", version.ref = "room"}
gson = { group = "com.google.code.gson", name = "gson", version.ref = "gson" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }