Refactor(LibrariesScreen): Add search
Add search and optimize top bar
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
package top.fatweb.oxygen.toolbox.icon
|
package top.fatweb.oxygen.toolbox.icon
|
||||||
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.AccessTime
|
import androidx.compose.material.icons.filled.AccessTime
|
||||||
import androidx.compose.material.icons.filled.Build
|
import androidx.compose.material.icons.filled.Build
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
import androidx.compose.material.icons.filled.Code
|
import androidx.compose.material.icons.filled.Code
|
||||||
import androidx.compose.material.icons.filled.Inbox
|
import androidx.compose.material.icons.filled.Inbox
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
@@ -18,10 +18,10 @@ import androidx.compose.material.icons.rounded.Search
|
|||||||
import androidx.compose.material.icons.rounded.Star
|
import androidx.compose.material.icons.rounded.Star
|
||||||
|
|
||||||
object OxygenIcons {
|
object OxygenIcons {
|
||||||
val ArrowBack = Icons.AutoMirrored.Rounded.ArrowBack
|
|
||||||
val ArrowDown = Icons.Rounded.KeyboardArrowDown
|
val ArrowDown = Icons.Rounded.KeyboardArrowDown
|
||||||
val Back = Icons.Rounded.ArrowBackIosNew
|
val Back = Icons.Rounded.ArrowBackIosNew
|
||||||
val Box = Icons.Default.Inbox
|
val Box = Icons.Default.Inbox
|
||||||
|
val Close = Icons.Default.Close
|
||||||
val Code = Icons.Default.Code
|
val Code = Icons.Default.Code
|
||||||
val Home = Icons.Rounded.Home
|
val Home = Icons.Rounded.Home
|
||||||
val HomeBorder = Icons.Outlined.Home
|
val HomeBorder = Icons.Outlined.Home
|
||||||
|
|||||||
@@ -4,5 +4,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||||
|
|
||||||
interface DepRepository {
|
interface DepRepository {
|
||||||
val dependencies: Flow<Dependencies>
|
fun searchName(name: String): Flow<Dependencies>
|
||||||
|
|
||||||
|
fun getSearchNameCount(): Flow<Int>
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,27 @@
|
|||||||
package top.fatweb.oxygen.toolbox.repository.lib
|
package top.fatweb.oxygen.toolbox.repository.lib
|
||||||
|
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import top.fatweb.oxygen.toolbox.data.lib.DepDataSource
|
import top.fatweb.oxygen.toolbox.data.lib.DepDataSource
|
||||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LocalDepRepository @Inject constructor(
|
class LocalDepRepository @Inject constructor(
|
||||||
depDataSource: DepDataSource
|
private val depDataSource: DepDataSource
|
||||||
) : DepRepository {
|
) : DepRepository {
|
||||||
override val dependencies: Flow<Dependencies> =
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
depDataSource.dependencies
|
override fun searchName(name: String): Flow<Dependencies> =
|
||||||
|
depDataSource.dependencies.flatMapLatest { dependencies ->
|
||||||
|
flowOf(dependencies.copy(
|
||||||
|
libraries = dependencies.libraries.filter {
|
||||||
|
it.name?.lowercase()?.contains(Regex("^.*${name.lowercase()}.*$")) ?: false
|
||||||
|
}
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
override fun getSearchNameCount(): Flow<Int> =
|
||||||
|
depDataSource.dependencies.flatMapLatest { flowOf(it.libraries.size) }
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ fun LazyStaggeredGridScope.librariesPanel(
|
|||||||
onClickLicense: (key: String) -> Unit
|
onClickLicense: (key: String) -> Unit
|
||||||
) {
|
) {
|
||||||
when (librariesScreenUiState) {
|
when (librariesScreenUiState) {
|
||||||
LibrariesScreenUiState.Loading -> Unit
|
LibrariesScreenUiState.Loading, LibrariesScreenUiState.Nothing, LibrariesScreenUiState.NotFound -> Unit
|
||||||
|
|
||||||
is LibrariesScreenUiState.Success -> {
|
is LibrariesScreenUiState.Success -> {
|
||||||
items(
|
items(
|
||||||
|
|||||||
@@ -73,7 +73,8 @@ internal fun LibrariesRoute(
|
|||||||
LibrariesScreen(
|
LibrariesScreen(
|
||||||
modifier = modifier.safeDrawingPadding(),
|
modifier = modifier.safeDrawingPadding(),
|
||||||
librariesScreenUiState = librariesScreenUiState,
|
librariesScreenUiState = librariesScreenUiState,
|
||||||
onBackClick = onBackClick
|
onBackClick = onBackClick,
|
||||||
|
onSearch = { viewModel.onSearchValueChange(it) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +83,8 @@ internal fun LibrariesRoute(
|
|||||||
internal fun LibrariesScreen(
|
internal fun LibrariesScreen(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
librariesScreenUiState: LibrariesScreenUiState,
|
librariesScreenUiState: LibrariesScreenUiState,
|
||||||
onBackClick: () -> Unit
|
onBackClick: () -> Unit,
|
||||||
|
onSearch: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
val configuration = LocalConfiguration.current
|
val configuration = LocalConfiguration.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
@@ -101,7 +103,10 @@ internal fun LibrariesScreen(
|
|||||||
var dialogContent by remember { mutableStateOf("") }
|
var dialogContent by remember { mutableStateOf("") }
|
||||||
var dialogUrl by remember { mutableStateOf("") }
|
var dialogUrl by remember { mutableStateOf("") }
|
||||||
|
|
||||||
val topAppBarScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
val topAppBarScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(canScroll = { state.canScrollForward })
|
||||||
|
|
||||||
|
var activeSearch by remember { mutableStateOf(false) }
|
||||||
|
var searchValue by remember { mutableStateOf("") }
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@@ -116,11 +121,26 @@ internal fun LibrariesScreen(
|
|||||||
navigationIconContentDescription = stringResource(R.string.core_back),
|
navigationIconContentDescription = stringResource(R.string.core_back),
|
||||||
actionIcon = OxygenIcons.Search,
|
actionIcon = OxygenIcons.Search,
|
||||||
actionIconContentDescription = stringResource(R.string.core_search),
|
actionIconContentDescription = stringResource(R.string.core_search),
|
||||||
|
activeSearch = activeSearch,
|
||||||
|
query = searchValue,
|
||||||
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
|
||||||
containerColor = Color.Transparent,
|
containerColor = Color.Transparent,
|
||||||
scrolledContainerColor = Color.Transparent
|
scrolledContainerColor = Color.Transparent
|
||||||
),
|
),
|
||||||
onNavigationClick = onBackClick
|
onNavigationClick = onBackClick,
|
||||||
|
onActionClick = {
|
||||||
|
activeSearch = true
|
||||||
|
},
|
||||||
|
onQueryChange = {
|
||||||
|
searchValue = it
|
||||||
|
onSearch(it)
|
||||||
|
},
|
||||||
|
onSearch = onSearch,
|
||||||
|
onCancelSearch = {
|
||||||
|
searchValue = ""
|
||||||
|
activeSearch = false
|
||||||
|
onSearch("")
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
) { padding ->
|
) { padding ->
|
||||||
@@ -140,6 +160,14 @@ internal fun LibrariesScreen(
|
|||||||
Text(text = stringResource(R.string.feature_settings_loading))
|
Text(text = stringResource(R.string.feature_settings_loading))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LibrariesScreenUiState.Nothing -> {
|
||||||
|
Text(text = "Nothing")
|
||||||
|
}
|
||||||
|
|
||||||
|
LibrariesScreenUiState.NotFound -> {
|
||||||
|
Text(text = "Not Found")
|
||||||
|
}
|
||||||
|
|
||||||
is LibrariesScreenUiState.Success -> {
|
is LibrariesScreenUiState.Success -> {
|
||||||
val handleOnClickLicense = { key: String ->
|
val handleOnClickLicense = { key: String ->
|
||||||
val license = librariesScreenUiState.dependencies.licenses[key]
|
val license = librariesScreenUiState.dependencies.licenses[key]
|
||||||
@@ -225,7 +253,7 @@ internal fun LibrariesScreen(
|
|||||||
|
|
||||||
fun howManyItems(librariesScreenUiState: LibrariesScreenUiState) =
|
fun howManyItems(librariesScreenUiState: LibrariesScreenUiState) =
|
||||||
when (librariesScreenUiState) {
|
when (librariesScreenUiState) {
|
||||||
LibrariesScreenUiState.Loading -> 0
|
LibrariesScreenUiState.Loading, LibrariesScreenUiState.Nothing, LibrariesScreenUiState.NotFound -> 0
|
||||||
|
|
||||||
is LibrariesScreenUiState.Success -> librariesScreenUiState.dependencies.libraries.size
|
is LibrariesScreenUiState.Success -> librariesScreenUiState.dependencies.libraries.size
|
||||||
}
|
}
|
||||||
@@ -234,6 +262,9 @@ fun howManyItems(librariesScreenUiState: LibrariesScreenUiState) =
|
|||||||
@Composable
|
@Composable
|
||||||
private fun LibrariesScreenLoadingPreview() {
|
private fun LibrariesScreenLoadingPreview() {
|
||||||
OxygenTheme {
|
OxygenTheme {
|
||||||
LibrariesScreen(librariesScreenUiState = LibrariesScreenUiState.Loading, onBackClick = {})
|
LibrariesScreen(
|
||||||
|
librariesScreenUiState = LibrariesScreenUiState.Loading,
|
||||||
|
onBackClick = {},
|
||||||
|
onSearch = {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package top.fatweb.oxygen.toolbox.ui.about
|
package top.fatweb.oxygen.toolbox.ui.about
|
||||||
|
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
import top.fatweb.oxygen.toolbox.model.lib.Dependencies
|
||||||
@@ -14,22 +18,49 @@ import kotlin.time.Duration.Companion.seconds
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class LibrariesScreenViewModel @Inject constructor(
|
class LibrariesScreenViewModel @Inject constructor(
|
||||||
depRepository: DepRepository
|
private val depRepository: DepRepository,
|
||||||
|
private val savedStateHandle: SavedStateHandle
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
private val searchValue = savedStateHandle.getStateFlow(SEARCH_VALUE, "")
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
val librariesScreenUiState: StateFlow<LibrariesScreenUiState> =
|
val librariesScreenUiState: StateFlow<LibrariesScreenUiState> =
|
||||||
depRepository.dependencies
|
depRepository.getSearchNameCount()
|
||||||
.map {
|
.flatMapLatest {totalCount ->
|
||||||
LibrariesScreenUiState.Success(it)
|
if (totalCount < SEARCH_MIN_COUNT) {
|
||||||
|
flowOf(LibrariesScreenUiState.Nothing)
|
||||||
|
} else {
|
||||||
|
searchValue.flatMapLatest {value ->
|
||||||
|
depRepository.searchName(value).map {
|
||||||
|
if (it.libraries.isEmpty()) {
|
||||||
|
LibrariesScreenUiState.NotFound
|
||||||
|
} else {
|
||||||
|
LibrariesScreenUiState.Success(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope = viewModelScope,
|
scope = viewModelScope,
|
||||||
initialValue = LibrariesScreenUiState.Loading,
|
initialValue = LibrariesScreenUiState.Loading,
|
||||||
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
|
started = SharingStarted.WhileSubscribed(5.seconds.inWholeMilliseconds)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun onSearchValueChange(value: String) {
|
||||||
|
savedStateHandle[SEARCH_VALUE] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface LibrariesScreenUiState {
|
sealed interface LibrariesScreenUiState {
|
||||||
data object Loading: LibrariesScreenUiState
|
data object Loading: LibrariesScreenUiState
|
||||||
|
|
||||||
|
data object Nothing: LibrariesScreenUiState
|
||||||
|
|
||||||
|
data object NotFound: LibrariesScreenUiState
|
||||||
|
|
||||||
data class Success(val dependencies: Dependencies) : LibrariesScreenUiState
|
data class Success(val dependencies: Dependencies) : LibrariesScreenUiState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val SEARCH_MIN_COUNT = 1
|
||||||
|
private const val SEARCH_VALUE = "searchValue"
|
||||||
|
|||||||
@@ -2,23 +2,40 @@ package top.fatweb.oxygen.toolbox.ui.component
|
|||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.animation.core.animateIntAsState
|
import androidx.compose.animation.core.animateIntAsState
|
||||||
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.WindowInsets
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
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.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TextFieldDefaults
|
||||||
import androidx.compose.material3.TopAppBarColors
|
import androidx.compose.material3.TopAppBarColors
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
|
import androidx.compose.ui.focus.focusRequester
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
|
import androidx.compose.ui.input.key.Key
|
||||||
|
import androidx.compose.ui.input.key.key
|
||||||
|
import androidx.compose.ui.input.key.onKeyEvent
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import top.fatweb.oxygen.toolbox.R
|
||||||
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
import top.fatweb.oxygen.toolbox.icon.OxygenIcons
|
||||||
import top.fatweb.oxygen.toolbox.ui.theme.OxygenPreviews
|
import top.fatweb.oxygen.toolbox.ui.theme.OxygenPreviews
|
||||||
import top.fatweb.oxygen.toolbox.ui.theme.OxygenTheme
|
import top.fatweb.oxygen.toolbox.ui.theme.OxygenTheme
|
||||||
@@ -34,18 +51,77 @@ fun OxygenTopAppBar(
|
|||||||
navigationIconContentDescription: String? = null,
|
navigationIconContentDescription: String? = null,
|
||||||
actionIcon: ImageVector? = null,
|
actionIcon: ImageVector? = null,
|
||||||
actionIconContentDescription: String? = null,
|
actionIconContentDescription: String? = null,
|
||||||
|
activeSearch: Boolean = false,
|
||||||
|
query: String = "",
|
||||||
colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
|
colors: TopAppBarColors = TopAppBarDefaults.centerAlignedTopAppBarColors(),
|
||||||
onNavigationClick: () -> Unit = {},
|
onNavigationClick: () -> Unit = {},
|
||||||
onActionClick: () -> Unit = {}
|
onActionClick: () -> Unit = {},
|
||||||
|
onQueryChange: (String) -> Unit = {},
|
||||||
|
onSearch: (String) -> Unit = {},
|
||||||
|
onCancelSearch: () -> Unit = {}
|
||||||
) {
|
) {
|
||||||
val topInset by animateIntAsState(
|
val topInset by animateIntAsState(
|
||||||
if (scrollBehavior != null && -scrollBehavior.state.heightOffset >= with(LocalDensity.current) { 64.0.dp.toPx() }) 0
|
if (scrollBehavior != null && -scrollBehavior.state.heightOffset >= with(LocalDensity.current) { 64.0.dp.toPx() }) 0
|
||||||
else TopAppBarDefaults.windowInsets.getTop(LocalDensity.current), label = ""
|
else TopAppBarDefaults.windowInsets.getTop(LocalDensity.current), label = ""
|
||||||
)
|
)
|
||||||
|
val keyboardController = LocalSoftwareKeyboardController.current
|
||||||
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
|
val onSearchExplicitlyTriggered = {
|
||||||
|
keyboardController?.hide()
|
||||||
|
onSearch(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(activeSearch) {
|
||||||
|
if (activeSearch) {
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CenterAlignedTopAppBar(
|
CenterAlignedTopAppBar(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
scrollBehavior = scrollBehavior,
|
scrollBehavior = scrollBehavior,
|
||||||
title = { Text(stringResource(titleRes)) },
|
title = {
|
||||||
|
if (activeSearch) TextField(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(Color.Transparent)
|
||||||
|
.focusRequester(focusRequester)
|
||||||
|
.onKeyEvent {
|
||||||
|
if (it.key == Key.Enter) {
|
||||||
|
onSearchExplicitlyTriggered()
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value = query,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
||||||
|
keyboardActions = KeyboardActions(
|
||||||
|
onSearch = {
|
||||||
|
onSearchExplicitlyTriggered()
|
||||||
|
}
|
||||||
|
),
|
||||||
|
colors = TextFieldDefaults.colors(
|
||||||
|
unfocusedContainerColor = Color.Transparent,
|
||||||
|
focusedContainerColor = Color.Transparent,
|
||||||
|
unfocusedIndicatorColor = Color.Transparent,
|
||||||
|
focusedIndicatorColor = Color.Transparent
|
||||||
|
),
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(
|
||||||
|
imageVector = OxygenIcons.Search,
|
||||||
|
contentDescription = stringResource(R.string.core_search)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
maxLines = 1,
|
||||||
|
singleLine = true,
|
||||||
|
onValueChange = {
|
||||||
|
if ("\n" !in it) onQueryChange(it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
else Text(stringResource(titleRes))
|
||||||
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
navigationIcon?.let {
|
navigationIcon?.let {
|
||||||
IconButton(onClick = onNavigationClick) {
|
IconButton(onClick = onNavigationClick) {
|
||||||
@@ -58,7 +134,13 @@ fun OxygenTopAppBar(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
actionIcon?.let {
|
if (activeSearch) IconButton(onClick = onCancelSearch) {
|
||||||
|
Icon(
|
||||||
|
imageVector = OxygenIcons.Close,
|
||||||
|
contentDescription = stringResource(R.string.core_close)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else actionIcon?.let {
|
||||||
IconButton(onClick = onActionClick) {
|
IconButton(onClick = onActionClick) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = actionIcon,
|
imageVector = actionIcon,
|
||||||
|
|||||||
Reference in New Issue
Block a user