Skip to content

Commit

Permalink
feat(phone): move search bar to own component and add to media screen
Browse files Browse the repository at this point in the history
  • Loading branch information
jarnedemeulemeester committed Dec 27, 2024
1 parent cf5f3e3 commit c20c460
Show file tree
Hide file tree
Showing 3 changed files with 219 additions and 112 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.jdtech.jellyfin.presentation.film

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand All @@ -17,11 +16,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
Expand All @@ -34,7 +29,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
Expand All @@ -51,6 +45,7 @@ import dev.jdtech.jellyfin.film.presentation.home.HomeViewModel
import dev.jdtech.jellyfin.presentation.components.ErrorDialog
import dev.jdtech.jellyfin.presentation.film.components.Direction
import dev.jdtech.jellyfin.presentation.film.components.ErrorCard
import dev.jdtech.jellyfin.presentation.film.components.FilmSearchBar
import dev.jdtech.jellyfin.presentation.film.components.ItemCard
import dev.jdtech.jellyfin.presentation.theme.FindroidTheme
import dev.jdtech.jellyfin.presentation.theme.spacings
Expand Down Expand Up @@ -84,28 +79,18 @@ private fun HomeScreenLayout(
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current

val startPadding = with(density) { WindowInsets.safeDrawing.getLeft(this, layoutDirection).toDp() + MaterialTheme.spacings.default }
val endPadding = with(density) { WindowInsets.safeDrawing.getRight(this, layoutDirection).toDp() + MaterialTheme.spacings.default }
val safePaddingStart = with(density) { WindowInsets.safeDrawing.getLeft(this, layoutDirection).toDp() }
val safePaddingEnd = with(density) { WindowInsets.safeDrawing.getRight(this, layoutDirection).toDp() }

val itemsPadding = PaddingValues(
start = startPadding,
end = endPadding,
)
val paddingStart = safePaddingStart + MaterialTheme.spacings.default
val paddingEnd = safePaddingEnd + MaterialTheme.spacings.default

var searchQuery by rememberSaveable { mutableStateOf("") }
var expanded by rememberSaveable { mutableStateOf(false) }

val searchBarPaddingStart by animateDpAsState(
targetValue = if (expanded) 0.dp else startPadding,
label = "search_bar_padding_start",
)

val searchBarPaddingEnd by animateDpAsState(
targetValue = if (expanded) 0.dp else endPadding,
label = "search_bar_padding_end",
val itemsPadding = PaddingValues(
start = paddingStart,
end = paddingEnd,
)

val contentTopPadding by animateDpAsState(
val contentPaddingTop by animateDpAsState(
targetValue = if (state.error != null) {
with(density) { WindowInsets.safeDrawing.getTop(this).toDp() + 136.dp }
} else {
Expand All @@ -121,85 +106,21 @@ private fun HomeScreenLayout(
.fillMaxSize()
.semantics { isTraversalGroup = true },
) {
SearchBar(
inputField = {
SearchBarDefaults.InputField(
query = searchQuery,
onQueryChange = { searchQuery = it },
onSearch = { expanded = true },
expanded = expanded,
onExpandedChange = { expanded = it },
placeholder = { Text(stringResource(FilmR.string.search_placeholder)) },
leadingIcon = {
AnimatedContent(
targetState = expanded,
label = "search_to_back",
) { targetExpanded ->
if (targetExpanded) {
IconButton(
onClick = {
expanded = false
},
) {
Icon(
painter = painterResource(CoreR.drawable.ic_arrow_left),
contentDescription = null,
)
}
} else {
Icon(
painter = painterResource(CoreR.drawable.ic_search),
contentDescription = null,
)
}
}
},
trailingIcon = {
AnimatedContent(
targetState = expanded,
label = "search_to_back",
) { targetExpanded ->
if (targetExpanded) {
IconButton(
onClick = {
searchQuery = ""
},
) {
Icon(
painter = painterResource(CoreR.drawable.ic_x),
contentDescription = null,
)
}
} else {
IconButton(
onClick = {},
) {
Icon(
painter = painterResource(CoreR.drawable.ic_user),
contentDescription = null,
)
}
}
}
},
)
},
expanded = expanded,
onExpandedChange = { expanded = it },
FilmSearchBar(
modifier = Modifier
.fillMaxWidth()
.padding(
start = searchBarPaddingStart,
end = searchBarPaddingEnd,
)
.semantics { traversalIndex = 0f },
) { }
paddingStart = paddingStart,
paddingEnd = paddingEnd,
inputPaddingStart = safePaddingStart,
inputPaddingEnd = safePaddingEnd,
)
LazyColumn(
modifier = Modifier
.fillMaxSize()
.semantics { traversalIndex = 1f },
contentPadding = PaddingValues(
top = contentTopPadding,
top = contentPaddingTop,
bottom = with(density) { WindowInsets.safeDrawing.getBottom(this).toDp() + MaterialTheme.spacings.default },
),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.small),
Expand Down Expand Up @@ -236,7 +157,9 @@ private fun HomeScreenLayout(
}
}
items(state.views, key = { it.id }) { view ->
Column {
Column(
modifier = Modifier.animateItem(),
) {
Box(
modifier = Modifier
.fillMaxWidth()
Expand Down Expand Up @@ -282,9 +205,9 @@ private fun HomeScreenLayout(
modifier = Modifier
.fillMaxWidth()
.padding(
start = startPadding,
start = paddingStart,
top = with(density) { WindowInsets.safeDrawing.getTop(this).toDp() + 80.dp },
end = endPadding,
end = paddingEnd,
),
)
if (showErrorDialog) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
package dev.jdtech.jellyfin.presentation.film

import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.jdtech.jellyfin.film.presentation.media.MediaAction
import dev.jdtech.jellyfin.film.presentation.media.MediaState
import dev.jdtech.jellyfin.film.presentation.media.MediaViewModel
import dev.jdtech.jellyfin.presentation.film.components.Direction
import dev.jdtech.jellyfin.presentation.film.components.FilmSearchBar
import dev.jdtech.jellyfin.presentation.film.components.ItemCard
import dev.jdtech.jellyfin.presentation.theme.spacings

Expand All @@ -42,20 +53,56 @@ private fun MediaScreenLayout(
state: MediaState,
onAction: (MediaAction) -> Unit,
) {
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 160.dp),
contentPadding = PaddingValues(MaterialTheme.spacings.default),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
) {
items(state.libraries, key = { it.id }) { library ->
ItemCard(
item = library,
direction = Direction.HORIZONTAL,
onClick = {
onAction(MediaAction.OnItemClick(library))
},
)
val density = LocalDensity.current
val layoutDirection = LocalLayoutDirection.current

val safePaddingStart = with(density) { WindowInsets.safeDrawing.getLeft(this, layoutDirection).toDp() }
val safePaddingEnd = with(density) { WindowInsets.safeDrawing.getRight(this, layoutDirection).toDp() }

val paddingStart = safePaddingStart + MaterialTheme.spacings.default
val paddingEnd = safePaddingEnd + MaterialTheme.spacings.default

val contentPaddingTop by animateDpAsState(
targetValue = if (state.error != null) {
with(density) { WindowInsets.safeDrawing.getTop(this).toDp() + 136.dp }
} else {
with(density) { WindowInsets.safeDrawing.getTop(this).toDp() + 88.dp }
},
label = "content_padding",
)

Box {
FilmSearchBar(
modifier = Modifier
.fillMaxWidth()
.semantics { traversalIndex = 0f },
paddingStart = paddingStart,
paddingEnd = paddingEnd,
inputPaddingStart = safePaddingStart,
inputPaddingEnd = safePaddingEnd,
)
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 160.dp),
contentPadding = PaddingValues(
start = paddingStart,
top = contentPaddingTop,
end = paddingEnd,
bottom = with(density) { WindowInsets.safeDrawing.getBottom(this).toDp() + MaterialTheme.spacings.default },
),
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacings.default),
) {
items(state.libraries, key = { it.id }) { library ->
ItemCard(
item = library,
direction = Direction.HORIZONTAL,
onClick = {
onAction(MediaAction.OnItemClick(library))
},
modifier = Modifier
.animateItem(),
)
}
}
}
}
Loading

0 comments on commit c20c460

Please sign in to comment.