mirror of
https://github.com/bbara04/Purefin.git
synced 2026-03-31 17:10:08 +02:00
Added Profile dropdown menu
This commit is contained in:
@@ -20,29 +20,37 @@ fun SearchField(
|
|||||||
value: String,
|
value: String,
|
||||||
onValueChange: (String) -> Unit,
|
onValueChange: (String) -> Unit,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color = Color.Unspecified,
|
||||||
textColor: Color,
|
textColor: Color = Color.Unspecified,
|
||||||
cursorColor: Color,
|
cursorColor: Color = Color.Unspecified,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
val resolvedBackgroundColor =
|
||||||
|
if (backgroundColor == Color.Unspecified) scheme.surfaceVariant else backgroundColor
|
||||||
|
val resolvedTextColor = if (textColor == Color.Unspecified) scheme.onSurface else textColor
|
||||||
|
val resolvedCursorColor = if (cursorColor == Color.Unspecified) scheme.primary else cursorColor
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(32.dp)),
|
.clip(RoundedCornerShape(12.dp)),
|
||||||
placeholder = { Text(placeholder, color = scheme.onSurfaceVariant) },
|
singleLine = true,
|
||||||
leadingIcon =
|
placeholder = { Text(placeholder) },
|
||||||
{ Icon(imageVector = Icons.Outlined.Search, contentDescription = null, tint = scheme.onSurfaceVariant) },
|
leadingIcon = { Icon(imageVector = Icons.Outlined.Search, contentDescription = null) },
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
focusedContainerColor = backgroundColor,
|
focusedContainerColor = resolvedBackgroundColor,
|
||||||
unfocusedContainerColor = backgroundColor,
|
unfocusedContainerColor = resolvedBackgroundColor,
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
cursorColor = cursorColor,
|
cursorColor = resolvedCursorColor,
|
||||||
focusedTextColor = textColor,
|
focusedTextColor = resolvedTextColor,
|
||||||
unfocusedTextColor = textColor,
|
unfocusedTextColor = resolvedTextColor,
|
||||||
|
focusedLeadingIconColor = scheme.onSurfaceVariant,
|
||||||
|
unfocusedLeadingIconColor = scheme.onSurfaceVariant,
|
||||||
|
focusedPlaceholderColor = scheme.onSurfaceVariant,
|
||||||
|
unfocusedPlaceholderColor = scheme.onSurfaceVariant,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@@ -52,9 +52,6 @@ fun TvHomeTopBar(
|
|||||||
value = "",
|
value = "",
|
||||||
onValueChange = {},
|
onValueChange = {},
|
||||||
placeholder = "Search",
|
placeholder = "Search",
|
||||||
backgroundColor = scheme.secondaryContainer,
|
|
||||||
textColor = scheme.onSecondaryContainer,
|
|
||||||
cursorColor = scheme.onSecondaryContainer,
|
|
||||||
modifier = Modifier.weight(1.0f, true),
|
modifier = Modifier.weight(1.0f, true),
|
||||||
)
|
)
|
||||||
PurefinIconButton(
|
PurefinIconButton(
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ fun AppScreen(
|
|||||||
onMovieSelected = viewModel::onMovieSelected,
|
onMovieSelected = viewModel::onMovieSelected,
|
||||||
onSeriesSelected = viewModel::onSeriesSelected,
|
onSeriesSelected = viewModel::onSeriesSelected,
|
||||||
onEpisodeSelected = viewModel::onEpisodeSelected,
|
onEpisodeSelected = viewModel::onEpisodeSelected,
|
||||||
|
onProfileClick = {},
|
||||||
|
onSettingsClick = {},
|
||||||
|
onLogoutClick = viewModel::logout,
|
||||||
selectedTab = selectedTab,
|
selectedTab = selectedTab,
|
||||||
onTabSelected = { selectedTab = it },
|
onTabSelected = { selectedTab = it },
|
||||||
modifier = modifier.fillMaxSize()
|
modifier = modifier.fillMaxSize()
|
||||||
@@ -57,6 +60,9 @@ fun AppScreen(
|
|||||||
1 -> LibrariesScreen(
|
1 -> LibrariesScreen(
|
||||||
items = libraryNavItems,
|
items = libraryNavItems,
|
||||||
onLibrarySelected = { item -> viewModel.onLibrarySelected(item.id, item.label) },
|
onLibrarySelected = { item -> viewModel.onLibrarySelected(item.id, item.label) },
|
||||||
|
onProfileClick = {},
|
||||||
|
onSettingsClick = {},
|
||||||
|
onLogoutClick = viewModel::logout,
|
||||||
selectedTab = selectedTab,
|
selectedTab = selectedTab,
|
||||||
onTabSelected = { selectedTab = it },
|
onTabSelected = { selectedTab = it },
|
||||||
modifier = modifier.fillMaxSize()
|
modifier = modifier.fillMaxSize()
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ fun HomeScreen(
|
|||||||
onMovieSelected: (UUID) -> Unit,
|
onMovieSelected: (UUID) -> Unit,
|
||||||
onSeriesSelected: (UUID) -> Unit,
|
onSeriesSelected: (UUID) -> Unit,
|
||||||
onEpisodeSelected: (UUID, UUID, UUID) -> Unit,
|
onEpisodeSelected: (UUID, UUID, UUID) -> Unit,
|
||||||
|
onProfileClick: () -> Unit,
|
||||||
|
onSettingsClick: () -> Unit,
|
||||||
|
onLogoutClick: () -> Unit,
|
||||||
selectedTab: Int,
|
selectedTab: Int,
|
||||||
onTabSelected: (Int) -> Unit,
|
onTabSelected: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
@@ -34,7 +37,11 @@ fun HomeScreen(
|
|||||||
containerColor = MaterialTheme.colorScheme.background,
|
containerColor = MaterialTheme.colorScheme.background,
|
||||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||||
topBar = {
|
topBar = {
|
||||||
HomeTopBar()
|
HomeTopBar(
|
||||||
|
onProfileClick = onProfileClick,
|
||||||
|
onSettingsClick = onSettingsClick,
|
||||||
|
onLogoutClick = onLogoutClick
|
||||||
|
)
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
AppBottomBar(
|
AppBottomBar(
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ import hu.bbara.purefin.app.home.ui.LibrariesContent
|
|||||||
fun LibrariesScreen(
|
fun LibrariesScreen(
|
||||||
items: List<HomeNavItem>,
|
items: List<HomeNavItem>,
|
||||||
onLibrarySelected: (HomeNavItem) -> Unit,
|
onLibrarySelected: (HomeNavItem) -> Unit,
|
||||||
|
onProfileClick: () -> Unit,
|
||||||
|
onSettingsClick: () -> Unit,
|
||||||
|
onLogoutClick: () -> Unit,
|
||||||
selectedTab: Int,
|
selectedTab: Int,
|
||||||
onTabSelected: (Int) -> Unit,
|
onTabSelected: (Int) -> Unit,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
@@ -23,7 +26,11 @@ fun LibrariesScreen(
|
|||||||
containerColor = MaterialTheme.colorScheme.background,
|
containerColor = MaterialTheme.colorScheme.background,
|
||||||
contentColor = MaterialTheme.colorScheme.onBackground,
|
contentColor = MaterialTheme.colorScheme.onBackground,
|
||||||
topBar = {
|
topBar = {
|
||||||
HomeTopBar()
|
HomeTopBar(
|
||||||
|
onProfileClick = onProfileClick,
|
||||||
|
onSettingsClick = onSettingsClick,
|
||||||
|
onLogoutClick = onLogoutClick
|
||||||
|
)
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
AppBottomBar(
|
AppBottomBar(
|
||||||
|
|||||||
@@ -1,17 +1,28 @@
|
|||||||
package hu.bbara.purefin.app.home.ui
|
package hu.bbara.purefin.app.home.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.statusBarsPadding
|
import androidx.compose.foundation.layout.statusBarsPadding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.outlined.Person
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.zIndex
|
import androidx.compose.ui.zIndex
|
||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
@@ -21,10 +32,15 @@ import hu.bbara.purefin.feature.shared.search.SearchViewModel
|
|||||||
@Composable
|
@Composable
|
||||||
fun HomeTopBar(
|
fun HomeTopBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
searchViewModel: SearchViewModel = hiltViewModel()
|
searchViewModel: SearchViewModel = hiltViewModel(),
|
||||||
|
onProfileClick: () -> Unit = {},
|
||||||
|
onSettingsClick: () -> Unit = {},
|
||||||
|
onLogoutClick: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
val searchResult = searchViewModel.searchResult.collectAsState()
|
val searchResult = searchViewModel.searchResult.collectAsState()
|
||||||
|
var isProfileMenuExpanded by remember { mutableStateOf(false) }
|
||||||
|
var isSearchExpanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
@@ -32,13 +48,12 @@ fun HomeTopBar(
|
|||||||
.background(scheme.background.copy(alpha = 0.95f))
|
.background(scheme.background.copy(alpha = 0.95f))
|
||||||
.zIndex(1f)
|
.zIndex(1f)
|
||||||
) {
|
) {
|
||||||
Row(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.statusBarsPadding()
|
.statusBarsPadding()
|
||||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
.padding(horizontal = 16.dp, vertical = 16.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
contentAlignment = Alignment.CenterEnd
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.Start),
|
|
||||||
) {
|
) {
|
||||||
PurefinSearchBar(
|
PurefinSearchBar(
|
||||||
onQueryChange = {
|
onQueryChange = {
|
||||||
@@ -47,9 +62,62 @@ fun HomeTopBar(
|
|||||||
onSearch = {
|
onSearch = {
|
||||||
searchViewModel.search(it)
|
searchViewModel.search(it)
|
||||||
},
|
},
|
||||||
|
onExpandedChange = { expanded ->
|
||||||
|
isSearchExpanded = expanded
|
||||||
|
if (expanded) {
|
||||||
|
isProfileMenuExpanded = false
|
||||||
|
}
|
||||||
|
},
|
||||||
searchResults = searchResult.value,
|
searchResults = searchResult.value,
|
||||||
modifier = Modifier.weight(1.0f, true),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(end = if (isSearchExpanded) 0.dp else 72.dp),
|
||||||
|
)
|
||||||
|
if (!isSearchExpanded) {
|
||||||
|
Box {
|
||||||
|
IconButton(
|
||||||
|
onClick = { isProfileMenuExpanded = true },
|
||||||
|
modifier = Modifier
|
||||||
|
.size(56.dp)
|
||||||
|
.clip(CircleShape),
|
||||||
|
) {
|
||||||
|
HomeAvatar(
|
||||||
|
size = 56.dp,
|
||||||
|
borderWidth = 1.dp,
|
||||||
|
borderColor = scheme.outlineVariant,
|
||||||
|
backgroundColor = scheme.secondaryContainer,
|
||||||
|
icon = Icons.Outlined.Person,
|
||||||
|
iconTint = scheme.onSecondaryContainer
|
||||||
|
)
|
||||||
|
}
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = isProfileMenuExpanded,
|
||||||
|
onDismissRequest = { isProfileMenuExpanded = false },
|
||||||
|
) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Profile") },
|
||||||
|
onClick = {
|
||||||
|
isProfileMenuExpanded = false
|
||||||
|
onProfileClick()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Settings") },
|
||||||
|
onClick = {
|
||||||
|
isProfileMenuExpanded = false
|
||||||
|
onSettingsClick()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
DropdownMenuItem(
|
||||||
|
text = { Text("Logout") },
|
||||||
|
onClick = {
|
||||||
|
isProfileMenuExpanded = false
|
||||||
|
onLogoutClick()
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,10 +37,15 @@ fun PurefinSearchBar(
|
|||||||
onQueryChange: (String) -> Unit,
|
onQueryChange: (String) -> Unit,
|
||||||
onSearch: (String) -> Unit,
|
onSearch: (String) -> Unit,
|
||||||
searchResults: List<SearchResult>,
|
searchResults: List<SearchResult>,
|
||||||
|
onExpandedChange: (Boolean) -> Unit = {},
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
var query by remember { mutableStateOf("") }
|
var query by remember { mutableStateOf("") }
|
||||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
|
val setExpanded: (Boolean) -> Unit = {
|
||||||
|
expanded = it
|
||||||
|
onExpandedChange(it)
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier
|
modifier
|
||||||
@@ -61,22 +66,22 @@ fun PurefinSearchBar(
|
|||||||
},
|
},
|
||||||
onSearch = {
|
onSearch = {
|
||||||
onSearch(query)
|
onSearch(query)
|
||||||
expanded = false
|
setExpanded(false)
|
||||||
},
|
},
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
onExpandedChange = { expanded = it },
|
onExpandedChange = setExpanded,
|
||||||
placeholder = { Text("Search") }
|
placeholder = { Text("Search") }
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
expanded = expanded,
|
expanded = expanded,
|
||||||
onExpandedChange = { expanded = it },
|
onExpandedChange = setExpanded,
|
||||||
) {
|
) {
|
||||||
LazyVerticalGrid(
|
LazyVerticalGrid(
|
||||||
columns = GridCells.Adaptive(minSize = 120.dp),
|
columns = GridCells.Adaptive(minSize = 120.dp),
|
||||||
contentPadding = PaddingValues(16.dp),
|
contentPadding = PaddingValues(16.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||||
modifier = modifier.background(MaterialTheme.colorScheme.background)
|
modifier = Modifier.background(MaterialTheme.colorScheme.background)
|
||||||
) {
|
) {
|
||||||
items(searchResults) { item ->
|
items(searchResults) { item ->
|
||||||
SearchResultCard(item)
|
SearchResultCard(item)
|
||||||
|
|||||||
@@ -20,29 +20,37 @@ fun SearchField(
|
|||||||
value: String,
|
value: String,
|
||||||
onValueChange: (String) -> Unit,
|
onValueChange: (String) -> Unit,
|
||||||
placeholder: String,
|
placeholder: String,
|
||||||
backgroundColor: Color,
|
backgroundColor: Color = Color.Unspecified,
|
||||||
textColor: Color,
|
textColor: Color = Color.Unspecified,
|
||||||
cursorColor: Color,
|
cursorColor: Color = Color.Unspecified,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
val resolvedBackgroundColor =
|
||||||
|
if (backgroundColor == Color.Unspecified) scheme.surfaceVariant else backgroundColor
|
||||||
|
val resolvedTextColor = if (textColor == Color.Unspecified) scheme.onSurface else textColor
|
||||||
|
val resolvedCursorColor = if (cursorColor == Color.Unspecified) scheme.primary else cursorColor
|
||||||
|
|
||||||
TextField(
|
TextField(
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clip(RoundedCornerShape(32.dp)),
|
.clip(RoundedCornerShape(12.dp)),
|
||||||
placeholder = { Text(placeholder, color = scheme.onSurfaceVariant) },
|
singleLine = true,
|
||||||
leadingIcon =
|
placeholder = { Text(placeholder) },
|
||||||
{ Icon(imageVector = Icons.Outlined.Search, contentDescription = null, tint = scheme.onSurfaceVariant) },
|
leadingIcon = { Icon(imageVector = Icons.Outlined.Search, contentDescription = null) },
|
||||||
colors = TextFieldDefaults.colors(
|
colors = TextFieldDefaults.colors(
|
||||||
focusedContainerColor = backgroundColor,
|
focusedContainerColor = resolvedBackgroundColor,
|
||||||
unfocusedContainerColor = backgroundColor,
|
unfocusedContainerColor = resolvedBackgroundColor,
|
||||||
focusedIndicatorColor = Color.Transparent,
|
focusedIndicatorColor = Color.Transparent,
|
||||||
unfocusedIndicatorColor = Color.Transparent,
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
cursorColor = cursorColor,
|
cursorColor = resolvedCursorColor,
|
||||||
focusedTextColor = textColor,
|
focusedTextColor = resolvedTextColor,
|
||||||
unfocusedTextColor = textColor,
|
unfocusedTextColor = resolvedTextColor,
|
||||||
|
focusedLeadingIconColor = scheme.onSurfaceVariant,
|
||||||
|
unfocusedLeadingIconColor = scheme.onSurfaceVariant,
|
||||||
|
focusedPlaceholderColor = scheme.onSurfaceVariant,
|
||||||
|
unfocusedPlaceholderColor = scheme.onSurfaceVariant,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user