mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
feat(search): implement back navigation in SearchScreen and SearchViewModel
This commit is contained in:
@@ -4,10 +4,8 @@ import androidx.compose.animation.ExperimentalSharedTransitionApi
|
|||||||
import androidx.compose.animation.SharedTransitionScope
|
import androidx.compose.animation.SharedTransitionScope
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.foundation.BorderStroke
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
import androidx.compose.foundation.layout.FlowRow
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
@@ -20,15 +18,13 @@ import androidx.compose.foundation.layout.padding
|
|||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.ArrowBack
|
||||||
import androidx.compose.material.icons.outlined.Close
|
import androidx.compose.material.icons.outlined.Close
|
||||||
import androidx.compose.material.icons.outlined.Menu
|
|
||||||
import androidx.compose.material.icons.outlined.Person
|
|
||||||
import androidx.compose.material.icons.outlined.Search
|
import androidx.compose.material.icons.outlined.Search
|
||||||
import androidx.compose.material.icons.outlined.Tune
|
import androidx.compose.material.icons.outlined.Tune
|
||||||
import androidx.compose.material3.FilterChip
|
import androidx.compose.material3.FilterChip
|
||||||
@@ -36,7 +32,6 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextField
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.material3.TextFieldDefaults
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
@@ -49,13 +44,11 @@ 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.platform.LocalSoftwareKeyboardController
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import hu.bbara.purefin.feature.search.SearchResult
|
import hu.bbara.purefin.feature.search.SearchResult
|
||||||
@@ -65,8 +58,8 @@ import hu.bbara.purefin.model.MediaKind
|
|||||||
import hu.bbara.purefin.navigation.HOME_SEARCH_SHARED_BOUNDS_KEY
|
import hu.bbara.purefin.navigation.HOME_SEARCH_SHARED_BOUNDS_KEY
|
||||||
import hu.bbara.purefin.navigation.LocalNavSharedAnimatedVisibilityScope
|
import hu.bbara.purefin.navigation.LocalNavSharedAnimatedVisibilityScope
|
||||||
import hu.bbara.purefin.navigation.LocalSharedTransitionScope
|
import hu.bbara.purefin.navigation.LocalSharedTransitionScope
|
||||||
import hu.bbara.purefin.ui.common.image.PurefinLogo
|
|
||||||
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
|
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
|
||||||
|
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBarIconButton
|
||||||
import hu.bbara.purefin.ui.theme.AppTheme
|
import hu.bbara.purefin.ui.theme.AppTheme
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@@ -116,6 +109,7 @@ fun SearchScreen(
|
|||||||
selectedGenreName = genre.name.takeIf { it != selectedGenreName }
|
selectedGenreName = genre.name.takeIf { it != selectedGenreName }
|
||||||
viewModel.setSelectedGenre(selectedGenreName)
|
viewModel.setSelectedGenre(selectedGenreName)
|
||||||
},
|
},
|
||||||
|
onBack = viewModel::onBack,
|
||||||
modifier = modifier.then(sharedBoundsModifier)
|
modifier = modifier.then(sharedBoundsModifier)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -131,36 +125,50 @@ private fun SearchFullScreenContent(
|
|||||||
onSearch: () -> Unit,
|
onSearch: () -> Unit,
|
||||||
onResultClick: (SearchResult) -> Unit,
|
onResultClick: (SearchResult) -> Unit,
|
||||||
onGenreSelected: (Genre) -> Unit,
|
onGenreSelected: (Genre) -> Unit,
|
||||||
|
onBack: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { SearchHeader() },
|
topBar = { SearchHeader(
|
||||||
|
onBack = onBack
|
||||||
|
) },
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(scheme.background)
|
.background(scheme.background)
|
||||||
.statusBarsPadding()
|
.statusBarsPadding()
|
||||||
.verticalScroll(rememberScrollState())
|
|
||||||
.padding(horizontal = 20.dp)
|
|
||||||
.padding(bottom = 28.dp)
|
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
SearchField(
|
Column(
|
||||||
query = query,
|
modifier = Modifier
|
||||||
onQueryChange = onQueryChange,
|
.padding(innerPadding)
|
||||||
onSearch = onSearch
|
.verticalScroll(rememberScrollState())
|
||||||
)
|
.padding(horizontal = 20.dp)
|
||||||
Spacer(modifier = Modifier.height(30.dp))
|
.padding(bottom = 28.dp)
|
||||||
if (query.isBlank()) {
|
) {
|
||||||
SectionTitle(text = "Browse Genres")
|
SearchField(
|
||||||
Spacer(modifier = Modifier.height(18.dp))
|
query = query,
|
||||||
GenreChips(
|
onQueryChange = onQueryChange,
|
||||||
genres = genres,
|
onSearch = onSearch
|
||||||
selectedGenreName = selectedGenreName,
|
|
||||||
onGenreSelected = onGenreSelected
|
|
||||||
)
|
)
|
||||||
if (selectedGenreName != null) {
|
Spacer(modifier = Modifier.height(30.dp))
|
||||||
Spacer(modifier = Modifier.height(30.dp))
|
if (query.isBlank()) {
|
||||||
|
SectionTitle(text = "Browse Genres")
|
||||||
|
Spacer(modifier = Modifier.height(18.dp))
|
||||||
|
GenreChips(
|
||||||
|
genres = genres,
|
||||||
|
selectedGenreName = selectedGenreName,
|
||||||
|
onGenreSelected = onGenreSelected
|
||||||
|
)
|
||||||
|
if (selectedGenreName != null) {
|
||||||
|
Spacer(modifier = Modifier.height(30.dp))
|
||||||
|
SectionTitle(text = "Search Results")
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
SearchResults(
|
||||||
|
searchResults = searchResults,
|
||||||
|
onResultClick = onResultClick
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
SectionTitle(text = "Search Results")
|
SectionTitle(text = "Search Results")
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
SearchResults(
|
SearchResults(
|
||||||
@@ -168,13 +176,6 @@ private fun SearchFullScreenContent(
|
|||||||
onResultClick = onResultClick
|
onResultClick = onResultClick
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
SectionTitle(text = "Search Results")
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
SearchResults(
|
|
||||||
searchResults = searchResults,
|
|
||||||
onResultClick = onResultClick
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,13 +203,18 @@ private fun SearchResults(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchHeader(
|
private fun SearchHeader(
|
||||||
|
onBack: () -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
DefaultTopBar(
|
DefaultTopBar(
|
||||||
leftActions = {
|
leftActions = {
|
||||||
|
DefaultTopBarIconButton(
|
||||||
|
imageVector = Icons.Outlined.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
|
onClick = onBack
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -379,6 +385,7 @@ private fun SearchFullScreenPreview() {
|
|||||||
onSearch = {},
|
onSearch = {},
|
||||||
onResultClick = {},
|
onResultClick = {},
|
||||||
onGenreSelected = {},
|
onGenreSelected = {},
|
||||||
|
onBack = {},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ class SearchViewModel @Inject constructor(
|
|||||||
searchManager.setGenres(genreName?.let { setOf(it) } ?: emptySet())
|
searchManager.setGenres(genreName?.let { setOf(it) } ?: emptySet())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onBack() {
|
||||||
|
navigationManager.pop()
|
||||||
|
}
|
||||||
|
|
||||||
fun onSearchResultSelected(searchResult: SearchResult) {
|
fun onSearchResultSelected(searchResult: SearchResult) {
|
||||||
when (searchResult.type) {
|
when (searchResult.type) {
|
||||||
MediaKind.MOVIE -> onMovieSelected(searchResult.id)
|
MediaKind.MOVIE -> onMovieSelected(searchResult.id)
|
||||||
|
|||||||
Reference in New Issue
Block a user