Skip to content

Commit

Permalink
Add recipe download screen
Browse files Browse the repository at this point in the history
  • Loading branch information
lneugebauer committed Jul 19, 2024
1 parent ff538ad commit 9ce3f73
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fun DefaultButton(

@Preview
@Composable
fun DefaultButtonPreview() {
private fun DefaultButtonPreview() {
DefaultButton(onClick = { }) {
Text("Button")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package de.lukasneugebauer.nextcloudcookbook.recipe.domain.state

import de.lukasneugebauer.nextcloudcookbook.core.util.UiText

data class DownloadRecipeScreenState(
val url: String = "",
val error: UiText? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package de.lukasneugebauer.nextcloudcookbook.recipe.presentation.download

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.hilt.navigation.compose.hiltViewModel
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import de.lukasneugebauer.nextcloudcookbook.R
import de.lukasneugebauer.nextcloudcookbook.core.presentation.components.DefaultOutlinedTextField
import de.lukasneugebauer.nextcloudcookbook.core.presentation.components.HideBottomNavigation
import de.lukasneugebauer.nextcloudcookbook.core.presentation.ui.theme.NextcloudCookbookTheme
import de.lukasneugebauer.nextcloudcookbook.core.util.UiText

@Destination
@Composable
fun DownloadRecipeScreen(
navigator: DestinationsNavigator,
viewModel: DownloadRecipeViewModel = hiltViewModel(),
) {
val uiState by viewModel.uiState.collectAsState()
HideBottomNavigation()

Scaffold(
topBar = {
RecipeDownloadTopBar {
navigator.navigateUp()
}
},
) { innerPadding ->
DownloadRecipeScreen(
url = uiState.url,
onUrlChange = { viewModel.updateUrl(it) },
modifier =
Modifier
.padding(innerPadding)
.padding(top = dimensionResource(id = R.dimen.padding_m)),
error = uiState.error,
)
}
}

@Composable
private fun DownloadRecipeScreen(
url: String,
onUrlChange: (String) -> Unit,
modifier: Modifier = Modifier,
error: UiText? = null,
) {
Column(
modifier = modifier,
) {
DefaultOutlinedTextField(
value = url,
onValueChange = onUrlChange,
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = dimensionResource(id = R.dimen.padding_m))
.padding(bottom = dimensionResource(id = R.dimen.padding_xs)),
label = { Text(text = "Recipe URL") },
errorText = error?.asString(),
keyboardOptions =
KeyboardOptions.Default.copy(
imeAction = ImeAction.Done,
),
keyboardActions =
KeyboardActions(
onDone = { },
),
singleLine = true,
colors =
TextFieldDefaults.outlinedTextFieldColors(
textColor = MaterialTheme.colors.onBackground,
cursorColor = MaterialTheme.colors.onBackground,
focusedBorderColor = MaterialTheme.colors.primary,
unfocusedBorderColor = MaterialTheme.colors.primary,
),
)
Button(
onClick = { /*TODO*/ },
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = dimensionResource(id = R.dimen.padding_m)),
) {
Text(text = "Download")
}
}
}

@Composable
private fun RecipeDownloadTopBar(onNavIconClick: () -> Unit) {
TopAppBar(
title = {
Text(
text = "Download recipe",
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
},
navigationIcon = {
IconButton(onClick = onNavIconClick) {
Icon(
Icons.AutoMirrored.Default.ArrowBack,
contentDescription = stringResource(id = R.string.common_back),
)
}
},
backgroundColor = MaterialTheme.colors.primary,
contentColor = MaterialTheme.colors.onPrimary,
)
}

@Preview
@Composable
private fun DownloadRecipeScreenPreview(modifier: Modifier = Modifier) {
NextcloudCookbookTheme {
DownloadRecipeScreen(
url = "https://example.com/recipe",
onUrlChange = {},
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package de.lukasneugebauer.nextcloudcookbook.recipe.presentation.download

import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import de.lukasneugebauer.nextcloudcookbook.recipe.domain.state.DownloadRecipeScreenState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import javax.inject.Inject

@HiltViewModel
class DownloadRecipeViewModel
@Inject
constructor() : ViewModel() {
private val _uiState = MutableStateFlow(DownloadRecipeScreenState())
val uiState = _uiState.asStateFlow()

fun updateUrl(newUrl: String) {
_uiState.update {
it.copy(url = newUrl)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.CloudDownload
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
Expand Down Expand Up @@ -73,6 +71,7 @@ import de.lukasneugebauer.nextcloudcookbook.core.presentation.error.AbstractErro
import de.lukasneugebauer.nextcloudcookbook.core.presentation.error.NotFoundScreen
import de.lukasneugebauer.nextcloudcookbook.core.presentation.ui.theme.NcBlue700
import de.lukasneugebauer.nextcloudcookbook.core.presentation.ui.theme.NextcloudCookbookTheme
import de.lukasneugebauer.nextcloudcookbook.destinations.DownloadRecipeScreenDestination
import de.lukasneugebauer.nextcloudcookbook.destinations.RecipeCreateScreenDestination
import de.lukasneugebauer.nextcloudcookbook.destinations.RecipeDetailScreenDestination
import de.lukasneugebauer.nextcloudcookbook.recipe.domain.model.RecipePreview
Expand Down Expand Up @@ -115,7 +114,7 @@ fun RecipeListScreen(
categoryName
},
onBackClick = { navigator.navigateUp() },
onImportClick = { TODO("add action") },
onImportClick = { navigator.navigate(DownloadRecipeScreenDestination) },
onSearchClick = { viewModel.toggleSearchAppBarVisibility() },
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ class RecipeListViewModel
private val _selectedKeywordsState = MutableStateFlow(emptyList<String>())
val selectedKeywordsState = _selectedKeywordsState.asStateFlow()

private val categoryName: String?
private val categoryName: String? = savedStateHandle["categoryName"]

init {
categoryName = savedStateHandle["categoryName"]
val keyword: String? = savedStateHandle["keyword"]
if (!keyword.isNullOrBlank()) {
_selectedKeywordsState.update { listOf(keyword) }
Expand Down

0 comments on commit 9ce3f73

Please sign in to comment.