Added Bookshelf page for easier sorting

Renamed App
Few cosmetic tweaks for mobile so it looks nicer
Changed App Icon, Using Ophelia for placeholder. Maybe I'll just put her in a hat later.
This commit is contained in:
Azea 2025-02-25 16:13:52 -05:00
parent d8bbce38d7
commit 309304b51a
18 changed files with 151 additions and 76 deletions

View file

@ -1,42 +0,0 @@
## Recipe App Compose Multiplatform
Inspired by [Roaa Kadam](https://github.com/Roaa94) flutter [app](https://github.com/Roaa94/recipes_ui_app/), I wanted to do the same in Compose Multiplatform. There is a lot to explore in Compose Multiplatform from the aspect of this app like Heor Animation, Collapsable Toolbar, Staggered Animations, Gyroscope detection etc.
> **Note**
> It is still a work in progress
### Live
You can find it live [here](https://seabdulbasit.github.io/recipe-app/)
## Supported Platforms
- Android
- iOS
- Desktop
- Web
- Android TV
![Screenshot 2023-10-08 at 1 23 46PM](https://github.com/SEAbdulbasit/recipe-app/assets/33172684/bf0c9376-fb57-4498-80f6-4a72300cb8e9)
![Screenshot 2024-06-25 at 11 53 05AM](https://github.com/Atif-09/recipe-app/assets/55842938/16e66d0b-48de-4403-bb74-e2788c756cc3)
## Demo
### iOS Demo
https://youtu.be/MZDgPtjTiIs
### Web Demo
https://www.youtube.com/watch?v=MZDgPtjTiIs&ab_channel=AbdulBasit
### Desktop Demo
https://www.youtube.com/watch?v=6mWrp_-MxW8&ab_channel=AbdulBasit
<img width="615" alt="Screenshot 2023-06-22 at 11 49 28 AM" src="https://github.com/SEAbdulbasit/recipe-app/assets/33172684/ac19c301-8263-4d2c-8cfc-58f27d1acdb3">
## Video Demo
You can watch the video demo [here](https://www.youtube.com/watch?v=99i21nB4sI0&ab_channel=AbdulBasit)

View file

@ -15,7 +15,7 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.setDecorFitsSystemWindows(window, false)
WindowCompat.setDecorFitsSystemWindows(window, true)
setContent {
val view = LocalView.current

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@drawable/ophelia_background" />
<foreground android:drawable="@drawable/ophelia" />
</adaptive-icon>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<background android:drawable="@drawable/ophelia_background" />
<foreground android:drawable="@drawable/ophelia" />
</adaptive-icon>

View file

@ -1,3 +1,3 @@
<resources>
<string name="app_name">Recipe App</string>
<string name="app_name">Baker\'s Menagerie</string>
</resources>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#7dae7d"
android:pathData="M0,0h108v108h-108z" />
</vector>

View file

@ -1,3 +1,3 @@
<resources>
<string name="app_name">Recipe App</string>
<string name="app_name">Baker\'s Menagerie</string>
</resources>

View file

@ -2,7 +2,7 @@ import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
fun main() = application {
Window(title = "Recipe App", onCloseRequest = ::exitApplication) {
Window(title = "Baker's Menagerie", onCloseRequest = ::exitApplication) {
MainView()
}
}

View file

@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<link rel="manifest" href="manifest.json"/>
<title>Recipe App KMP</title>
<title>Baker's Menagerie KMP</title>
<script type="application/javascript" src="skiko.js"></script>
<script type="application/javascript" src="webApp.js"></script>
</head>

View file

@ -1,5 +1,5 @@
{
"name": "Recipe App",
"name": "Baker's Menagerie",
"icons": [
{
"src": "images/logo.png",

View file

@ -60,6 +60,11 @@
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
"@js-joda/core@3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273"
integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==
"@leichtgewicht/ip-codec@^2.0.1":
version "2.0.4"
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"

View file

@ -1,10 +1,21 @@
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.material.Button
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
@ -14,11 +25,15 @@ import androidx.compose.runtime.mutableStateListOf
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.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import details.RecipeDetails
import recipeslist.RecipesListScreen
import sensor.SensorManager
@ -67,6 +82,7 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
var search by remember { mutableStateOf("") }
val tags = remember { mutableStateListOf<String>() }
val recipeTags by remember { mutableStateOf(mutableListOf<String>()) }
var book by remember { mutableStateOf("") }
for (recipe in getRecipeList()) {
for (tag in recipe.tags) {
@ -83,7 +99,7 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
}
}
val filteredItems = getFilteredRecipeList(tags, search)
val filteredItems = getFilteredRecipeList(tags, search, book)
var currentRecipe = getRecipeList().first()
if (filteredItems.isNotEmpty())
@ -93,13 +109,6 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
Column {
if (searchBar) {
Row {
// Button(
// onClick = {
// onThemeToggle.invoke()
// }
// ) {
// Text(text = theme.name)
// }
Button(
onClick = {
show = true
@ -119,7 +128,6 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
}
SharedTransitionLayout {
val sharedTransitionScope = this
NavHost(
navController = navController,
startDestination = "Home",
@ -127,13 +135,30 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
) {
composable(route = "Home")
{
HomeScreen {
searchBar = true
navController.navigate(RecipeAppScreen.List.name)
}
HomeScreen(
isLarge = isLarge,
onClick = {
searchBar = false
navController.navigate("BookShelf")
}
)
}
composable(route = RecipeAppScreen.List.name) {
composable(route = "BookShelf")
{
BookShelf(
isLarge = isLarge,
tags = recipeTags,
onClick = { lockedTag ->
book = lockedTag
searchBar = true
navController.navigate(RecipeAppScreen.List.name)
}
)
}
composable(
route = RecipeAppScreen.List.name
) {
RecipesListScreen(
isLarge = isLarge,
items = filteredItems,
@ -158,4 +183,54 @@ fun App(sensorManager: SensorManager?, isLarge: Boolean = false) {
}
}
}
}
}
@Composable
fun BookShelf(
onClick: (String) -> Unit,
isLarge: Boolean,
tags: List<String>
) {
Box(
modifier = Modifier
.fillMaxSize()
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp)
.align(Alignment.Center),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text(text = "What Do You Want To Cook Today?", textAlign = TextAlign.Center)
Button(onClick = { onClick("") }) {
Text("ANYTHING!")
}
val listState = rememberLazyGridState()
LazyVerticalGrid(
columns = GridCells.Fixed(if(isLarge) 4 else 2),
state = listState
)
{
if(isLarge.not()) {
item {
Spacer(modifier = Modifier.windowInsetsPadding(WindowInsets.systemBars))
}
items(tags.size) {item ->
val tag = tags[item]
Button(onClick = {onClick(tag) }) {
Text(tag)
}
}
}
}
}
}
}

View file

@ -16,15 +16,21 @@ fun List<String>.containsPartial(text:String) : Boolean {
fun getFilteredRecipeList(
tags : List<String>,
search : String,
lockTag : String,
) : List<Recipe> {
val items = getRecipeList()
var recipes = items.filter { it.tags.containsAll(tags)}
var recipes = items.filter { it.tags.containsAll(tags) }
recipes = recipes.filter {
it.title.contains(search) || it.ingredients.containsPartial(search)
}
if (lockTag != "")
{
recipes = recipes.filter { it.tags.contains(lockTag)}
}
return recipes
}

View file

@ -11,21 +11,29 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@Composable
fun HomeScreen(
onClick: () -> Unit,
isLarge: Boolean,
) {
val text = "Recipes"
HeaderText(text, onClick)
HeaderText(text, onClick, isLarge)
}
@Composable
fun HeaderText(
text: String,
onClick: () -> Unit
onClick: () -> Unit,
isLarge: Boolean
) {
val header = if(isLarge) MaterialTheme.typography.h1 else MaterialTheme.typography.h2
val lowHead = if(isLarge) MaterialTheme.typography.h3 else MaterialTheme.typography.h4
Box(
modifier = Modifier
.fillMaxSize()
@ -41,10 +49,13 @@ fun HeaderText(
Spacer(modifier = Modifier.weight(1f))
androidx.compose.material3.Text (
text = "Baker's Menagerie",
style = MaterialTheme.typography.h1
style = header,
textAlign = TextAlign.Center
)
androidx.compose.material3.Text (
text = "An Allbright Family Cookbook"
text = "An Allbright Family Cookbook",
style = lowHead,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.weight(1f))
androidx.compose.material3.Button(

View file

@ -1,3 +1,3 @@
<resources>
<string name="app_name">Recipe App</string>
<string name="app_name">Baker\'s Menagerie</string>
</resources>

View file

@ -5,7 +5,7 @@
<link rel="manifest" href="manifest.json"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link type="text/css" rel="stylesheet" href="styles.css">
<title>Recipe App KMP</title>
<title>Baker's Menagerie KMP</title>
<script type="application/javascript" src="webApp.js"></script>
</head>
<body>

View file

@ -1,5 +1,5 @@
{
"name": "Recipe App",
"name": "Baker's Menagerie",
"icons": [
{
"src": "images/logo.png",