mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Improve search toolbar UX a little bit (#8102)
* Improve search toolbar UX a little. * Fix wrong stringResource import. * Revert `FocusRequester` change in favour of #8093.
This commit is contained in:
		| @@ -6,10 +6,12 @@ import androidx.compose.runtime.Composable | ||||
| import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.ui.platform.LocalUriHandler | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.paging.compose.collectAsLazyPagingItems | ||||
| import eu.kanade.domain.manga.model.Manga | ||||
| import eu.kanade.presentation.browse.components.BrowseSourceSearchToolbar | ||||
| import eu.kanade.presentation.components.Scaffold | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.source.LocalSource | ||||
| import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter | ||||
| import eu.kanade.tachiyomi.ui.more.MoreController | ||||
| @@ -39,6 +41,7 @@ fun SourceSearchScreen( | ||||
|             BrowseSourceSearchToolbar( | ||||
|                 searchQuery = presenter.searchQuery ?: "", | ||||
|                 onSearchQueryChanged = { presenter.searchQuery = it }, | ||||
|                 placeholderText = stringResource(R.string.action_search_hint), | ||||
|                 navigateUp = navigateUp, | ||||
|                 onResetClick = { presenter.searchQuery = "" }, | ||||
|                 onSearchClick = { presenter.search() }, | ||||
|   | ||||
| @@ -17,6 +17,8 @@ import androidx.compose.runtime.getValue | ||||
| import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.runtime.setValue | ||||
| import androidx.compose.ui.platform.LocalFocusManager | ||||
| import androidx.compose.ui.platform.LocalSoftwareKeyboardController | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.input.ImeAction | ||||
| import eu.kanade.domain.library.model.LibraryDisplayMode | ||||
| @@ -57,6 +59,7 @@ fun BrowseSourceToolbar( | ||||
|         BrowseSourceSearchToolbar( | ||||
|             searchQuery = state.searchQuery!!, | ||||
|             onSearchQueryChanged = { state.searchQuery = it }, | ||||
|             placeholderText = stringResource(R.string.action_search_hint), | ||||
|             navigateUp = { state.searchQuery = null }, | ||||
|             onResetClick = { state.searchQuery = "" }, | ||||
|             onSearchClick = onSearch, | ||||
| @@ -159,18 +162,25 @@ fun BrowseSourceRegularToolbar( | ||||
| fun BrowseSourceSearchToolbar( | ||||
|     searchQuery: String, | ||||
|     onSearchQueryChanged: (String) -> Unit, | ||||
|     placeholderText: String?, | ||||
|     navigateUp: () -> Unit, | ||||
|     onResetClick: () -> Unit, | ||||
|     onSearchClick: () -> Unit, | ||||
|     scrollBehavior: TopAppBarScrollBehavior?, | ||||
| ) { | ||||
|     val keyboardController = LocalSoftwareKeyboardController.current | ||||
|     val focusManager = LocalFocusManager.current | ||||
|  | ||||
|     SearchToolbar( | ||||
|         searchQuery = searchQuery, | ||||
|         onChangeSearchQuery = onSearchQueryChanged, | ||||
|         placeholderText = placeholderText, | ||||
|         keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search), | ||||
|         keyboardActions = KeyboardActions( | ||||
|             onSearch = { | ||||
|                 onSearchClick() | ||||
|                 focusManager.clearFocus() | ||||
|                 keyboardController?.hide() | ||||
|             }, | ||||
|         ), | ||||
|         onClickCloseSearch = navigateUp, | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package eu.kanade.presentation.components | ||||
|  | ||||
| import androidx.compose.animation.AnimatedVisibility | ||||
| import androidx.compose.foundation.interaction.MutableInteractionSource | ||||
| import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.RowScope | ||||
| import androidx.compose.foundation.layout.WindowInsets | ||||
| @@ -20,6 +21,7 @@ import androidx.compose.material3.Icon | ||||
| import androidx.compose.material3.IconButton | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.material3.TextFieldDefaults | ||||
| import androidx.compose.material3.TopAppBar | ||||
| import androidx.compose.material3.TopAppBarDefaults | ||||
| import androidx.compose.material3.TopAppBarScrollBehavior | ||||
| @@ -38,8 +40,10 @@ import androidx.compose.ui.graphics.SolidColor | ||||
| import androidx.compose.ui.graphics.vector.ImageVector | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.font.FontWeight | ||||
| import androidx.compose.ui.text.input.VisualTransformation | ||||
| import androidx.compose.ui.text.style.TextOverflow | ||||
| import androidx.compose.ui.unit.dp | ||||
| import androidx.compose.ui.unit.sp | ||||
| import eu.kanade.tachiyomi.R | ||||
|  | ||||
| @Composable | ||||
| @@ -63,7 +67,10 @@ fun AppBar( | ||||
|  | ||||
|     scrollBehavior: TopAppBarScrollBehavior? = null, | ||||
| ) { | ||||
|     val isActionMode by derivedStateOf { actionModeCounter > 0 } | ||||
|     val isActionMode by remember(actionModeCounter) { | ||||
|         derivedStateOf { actionModeCounter > 0 } | ||||
|     } | ||||
|  | ||||
|     AppBar( | ||||
|         modifier = modifier, | ||||
|         titleContent = { | ||||
| @@ -216,6 +223,7 @@ fun AppBarActions( | ||||
| fun SearchToolbar( | ||||
|     searchQuery: String, | ||||
|     onChangeSearchQuery: (String) -> Unit, | ||||
|     placeholderText: String? = null, | ||||
|     keyboardOptions: KeyboardOptions = KeyboardOptions.Default, | ||||
|     keyboardActions: KeyboardActions = KeyboardActions.Default, | ||||
|     onClickCloseSearch: () -> Unit, | ||||
| @@ -223,8 +231,11 @@ fun SearchToolbar( | ||||
|     incognitoMode: Boolean = false, | ||||
|     downloadedOnlyMode: Boolean = false, | ||||
|     scrollBehavior: TopAppBarScrollBehavior? = null, | ||||
|     visualTransformation: VisualTransformation = VisualTransformation.None, | ||||
|     interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, | ||||
| ) { | ||||
|     val focusRequester = remember { FocusRequester() } | ||||
|  | ||||
|     AppBar( | ||||
|         titleContent = { | ||||
|             BasicTextField( | ||||
| @@ -233,11 +244,40 @@ fun SearchToolbar( | ||||
|                 modifier = Modifier | ||||
|                     .fillMaxWidth() | ||||
|                     .focusRequester(focusRequester), | ||||
|                 textStyle = MaterialTheme.typography.bodyMedium.copy(color = MaterialTheme.colorScheme.onBackground), | ||||
|                 textStyle = MaterialTheme.typography.titleMedium.copy( | ||||
|                     color = MaterialTheme.colorScheme.onBackground, | ||||
|                     fontWeight = FontWeight.Normal, | ||||
|                     fontSize = 18.sp, | ||||
|                 ), | ||||
|                 keyboardOptions = keyboardOptions, | ||||
|                 keyboardActions = keyboardActions, | ||||
|                 singleLine = true, | ||||
|                 cursorBrush = SolidColor(MaterialTheme.colorScheme.onBackground), | ||||
|                 visualTransformation = visualTransformation, | ||||
|                 interactionSource = interactionSource, | ||||
|                 decorationBox = { innerTextField -> | ||||
|                     TextFieldDefaults.TextFieldDecorationBox( | ||||
|                         value = searchQuery, | ||||
|                         innerTextField = innerTextField, | ||||
|                         enabled = true, | ||||
|                         singleLine = true, | ||||
|                         visualTransformation = visualTransformation, | ||||
|                         interactionSource = interactionSource, | ||||
|                         placeholder = { | ||||
|                             if (!placeholderText.isNullOrEmpty()) { | ||||
|                                 Text( | ||||
|                                     text = placeholderText, | ||||
|                                     maxLines = 1, | ||||
|                                     overflow = TextOverflow.Ellipsis, | ||||
|                                     style = MaterialTheme.typography.titleMedium.copy( | ||||
|                                         fontSize = 18.sp, | ||||
|                                         fontWeight = FontWeight.Normal, | ||||
|                                     ), | ||||
|                                 ) | ||||
|                             } | ||||
|                         }, | ||||
|                     ) | ||||
|                 }, | ||||
|             ) | ||||
|         }, | ||||
|         navigationIcon = Icons.Outlined.ArrowBack, | ||||
|   | ||||
| @@ -22,6 +22,7 @@ fun TabbedScreen( | ||||
|     tabs: List<TabContent>, | ||||
|     startIndex: Int? = null, | ||||
|     searchQuery: String? = null, | ||||
|     @StringRes placeholderRes: Int? = null, | ||||
|     onChangeSearchQuery: (String?) -> Unit = {}, | ||||
|     incognitoMode: Boolean, | ||||
|     downloadedOnlyMode: Boolean, | ||||
| @@ -47,6 +48,7 @@ fun TabbedScreen( | ||||
|             } else { | ||||
|                 SearchToolbar( | ||||
|                     searchQuery = searchQuery, | ||||
|                     placeholderText = placeholderRes?.let { stringResource(it) }, | ||||
|                     onChangeSearchQuery = { | ||||
|                         onChangeSearchQuery(it) | ||||
|                     }, | ||||
|   | ||||
| @@ -1,5 +1,7 @@ | ||||
| package eu.kanade.presentation.history.components | ||||
|  | ||||
| import androidx.compose.foundation.text.KeyboardActions | ||||
| import androidx.compose.foundation.text.KeyboardOptions | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.outlined.DeleteSweep | ||||
| import androidx.compose.material.icons.outlined.Search | ||||
| @@ -7,7 +9,10 @@ import androidx.compose.material3.Icon | ||||
| import androidx.compose.material3.IconButton | ||||
| import androidx.compose.material3.TopAppBarScrollBehavior | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.platform.LocalFocusManager | ||||
| import androidx.compose.ui.platform.LocalSoftwareKeyboardController | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.input.ImeAction | ||||
| import eu.kanade.presentation.components.AppBar | ||||
| import eu.kanade.presentation.components.SearchToolbar | ||||
| import eu.kanade.tachiyomi.R | ||||
| @@ -21,6 +26,9 @@ fun HistoryToolbar( | ||||
|     incognitoMode: Boolean, | ||||
|     downloadedOnlyMode: Boolean, | ||||
| ) { | ||||
|     val keyboardController = LocalSoftwareKeyboardController.current | ||||
|     val focusManager = LocalFocusManager.current | ||||
|  | ||||
|     if (state.searchQuery == null) { | ||||
|         HistoryRegularToolbar( | ||||
|             onClickSearch = { state.searchQuery = "" }, | ||||
| @@ -33,10 +41,20 @@ fun HistoryToolbar( | ||||
|         SearchToolbar( | ||||
|             searchQuery = state.searchQuery!!, | ||||
|             onChangeSearchQuery = { state.searchQuery = it }, | ||||
|             placeholderText = stringResource(R.string.action_search_hint), | ||||
|             onClickCloseSearch = { state.searchQuery = null }, | ||||
|             onClickResetSearch = { state.searchQuery = "" }, | ||||
|             incognitoMode = incognitoMode, | ||||
|             downloadedOnlyMode = downloadedOnlyMode, | ||||
|             keyboardOptions = KeyboardOptions.Default.copy( | ||||
|                 imeAction = ImeAction.Search, | ||||
|             ), | ||||
|             keyboardActions = KeyboardActions( | ||||
|                 onSearch = { | ||||
|                     focusManager.clearFocus() | ||||
|                     keyboardController?.hide() | ||||
|                 }, | ||||
|             ), | ||||
|         ) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,8 @@ package eu.kanade.presentation.library.components | ||||
|  | ||||
| import androidx.compose.foundation.isSystemInDarkTheme | ||||
| import androidx.compose.foundation.layout.Row | ||||
| import androidx.compose.foundation.text.KeyboardActions | ||||
| import androidx.compose.foundation.text.KeyboardOptions | ||||
| import androidx.compose.material.icons.Icons | ||||
| import androidx.compose.material.icons.outlined.FilterList | ||||
| import androidx.compose.material.icons.outlined.FlipToBack | ||||
| @@ -17,7 +19,10 @@ import androidx.compose.material3.TopAppBarScrollBehavior | ||||
| import androidx.compose.runtime.Composable | ||||
| import androidx.compose.ui.Alignment | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.platform.LocalFocusManager | ||||
| import androidx.compose.ui.platform.LocalSoftwareKeyboardController | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.input.ImeAction | ||||
| import androidx.compose.ui.text.style.TextOverflow | ||||
| import androidx.compose.ui.unit.sp | ||||
| import eu.kanade.presentation.components.AppBar | ||||
| @@ -48,15 +53,30 @@ fun LibraryToolbar( | ||||
|         onClickSelectAll = onClickSelectAll, | ||||
|         onClickInvertSelection = onClickInvertSelection, | ||||
|     ) | ||||
|     state.searchQuery != null -> SearchToolbar( | ||||
|         searchQuery = state.searchQuery!!, | ||||
|         onChangeSearchQuery = { state.searchQuery = it }, | ||||
|         onClickCloseSearch = { state.searchQuery = null }, | ||||
|         onClickResetSearch = { state.searchQuery = "" }, | ||||
|         scrollBehavior = scrollBehavior, | ||||
|         incognitoMode = incognitoMode, | ||||
|         downloadedOnlyMode = downloadedOnlyMode, | ||||
|     ) | ||||
|     state.searchQuery != null -> { | ||||
|         val keyboardController = LocalSoftwareKeyboardController.current | ||||
|         val focusManager = LocalFocusManager.current | ||||
|  | ||||
|         SearchToolbar( | ||||
|             searchQuery = state.searchQuery!!, | ||||
|             onChangeSearchQuery = { state.searchQuery = it }, | ||||
|             onClickCloseSearch = { state.searchQuery = null }, | ||||
|             onClickResetSearch = { state.searchQuery = "" }, | ||||
|             scrollBehavior = scrollBehavior, | ||||
|             incognitoMode = incognitoMode, | ||||
|             downloadedOnlyMode = downloadedOnlyMode, | ||||
|             placeholderText = stringResource(R.string.action_search_hint), | ||||
|             keyboardOptions = KeyboardOptions.Default.copy( | ||||
|                 imeAction = ImeAction.Search, | ||||
|             ), | ||||
|             keyboardActions = KeyboardActions( | ||||
|                 onSearch = { | ||||
|                     focusManager.clearFocus() | ||||
|                     keyboardController?.hide() | ||||
|                 }, | ||||
|             ), | ||||
|         ) | ||||
|     } | ||||
|     else -> LibraryRegularToolbar( | ||||
|         title = title, | ||||
|         hasFilters = state.hasActiveFilters, | ||||
|   | ||||
| @@ -5,6 +5,8 @@ import androidx.compose.foundation.layout.Column | ||||
| import androidx.compose.foundation.layout.fillMaxWidth | ||||
| import androidx.compose.foundation.layout.padding | ||||
| import androidx.compose.foundation.lazy.items | ||||
| import androidx.compose.foundation.text.KeyboardActions | ||||
| import androidx.compose.foundation.text.KeyboardOptions | ||||
| import androidx.compose.material3.MaterialTheme | ||||
| import androidx.compose.material3.Text | ||||
| import androidx.compose.runtime.Composable | ||||
| @@ -14,11 +16,16 @@ import androidx.compose.runtime.mutableStateOf | ||||
| import androidx.compose.runtime.remember | ||||
| import androidx.compose.runtime.setValue | ||||
| import androidx.compose.ui.Modifier | ||||
| import androidx.compose.ui.platform.LocalFocusManager | ||||
| import androidx.compose.ui.platform.LocalSoftwareKeyboardController | ||||
| import androidx.compose.ui.res.stringResource | ||||
| import androidx.compose.ui.text.input.ImeAction | ||||
| import androidx.compose.ui.unit.dp | ||||
| import eu.kanade.presentation.components.Scaffold | ||||
| import eu.kanade.presentation.components.ScrollbarLazyColumn | ||||
| import eu.kanade.presentation.components.SearchToolbar | ||||
| import eu.kanade.presentation.util.horizontalPadding | ||||
| import eu.kanade.tachiyomi.R | ||||
| import eu.kanade.tachiyomi.ui.setting.SettingsController | ||||
| import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchHelper | ||||
| import eu.kanade.tachiyomi.ui.setting.search.SettingsSearchPresenter | ||||
| @@ -33,6 +40,9 @@ fun SettingsSearchScreen( | ||||
|     val results by presenter.state.collectAsState() | ||||
|     var query by remember { mutableStateOf("") } | ||||
|  | ||||
|     val keyboardController = LocalSoftwareKeyboardController.current | ||||
|     val focusManager = LocalFocusManager.current | ||||
|  | ||||
|     Scaffold( | ||||
|         topBar = { scrollBehavior -> | ||||
|             SearchToolbar( | ||||
| @@ -41,13 +51,20 @@ fun SettingsSearchScreen( | ||||
|                     query = it | ||||
|                     presenter.searchSettings(it) | ||||
|                 }, | ||||
|                 placeholderText = stringResource(R.string.action_search_settings), | ||||
|                 onClickCloseSearch = navigateUp, | ||||
|                 onClickResetSearch = { query = "" }, | ||||
|                 scrollBehavior = scrollBehavior, | ||||
|                 keyboardOptions = KeyboardOptions.Default.copy( | ||||
|                     imeAction = ImeAction.Search, | ||||
|                 ), | ||||
|                 keyboardActions = KeyboardActions( | ||||
|                     onSearch = { | ||||
|                         focusManager.clearFocus() | ||||
|                         keyboardController?.hide() | ||||
|                     }, | ||||
|                 ), | ||||
|             ) | ||||
|  | ||||
|             // TODO: search placeholder | ||||
|             // Text(stringResource(R.string.action_search_settings)) | ||||
|         }, | ||||
|     ) { contentPadding -> | ||||
|         ScrollbarLazyColumn( | ||||
|   | ||||
| @@ -45,6 +45,7 @@ class BrowseController : FullComposeController<BrowsePresenter>, RootController | ||||
|             startIndex = 1.takeIf { toExtensions }, | ||||
|             searchQuery = query, | ||||
|             onChangeSearchQuery = { presenter.extensionsPresenter.search(it) }, | ||||
|             placeholderRes = R.string.action_search_hint, | ||||
|             incognitoMode = presenter.isIncognitoMode, | ||||
|             downloadedOnlyMode = presenter.isDownloadOnly, | ||||
|         ) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user