fix: automatically focus search views

This commit is contained in:
Robert 2024-05-27 22:49:08 +02:00
parent 6bfd9098d6
commit 1f671aba33
No known key found for this signature in database
GPG key ID: 887C470FCF872DC6
4 changed files with 118 additions and 90 deletions

View file

@ -0,0 +1,59 @@
package app.revanced.manager.ui.component
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.SearchBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchView(
query: String,
onQueryChange: (String) -> Unit,
onActiveChange: (Boolean) -> Unit,
placeholder: (@Composable () -> Unit)? = null,
content: @Composable ColumnScope.() -> Unit
) {
val focusRequester = remember { FocusRequester() }
val keyboardController = LocalSoftwareKeyboardController.current
SearchBar(
query = query,
onQueryChange = onQueryChange,
onSearch = {
keyboardController?.hide()
},
active = true,
onActiveChange = onActiveChange,
modifier = Modifier
.fillMaxSize()
.focusRequester(focusRequester),
placeholder = placeholder,
leadingIcon = {
IconButton({ onActiveChange(false) }) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
stringResource(R.string.back)
)
}
},
content = content
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}

View file

@ -6,7 +6,6 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.filled.Storage
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.*
@ -30,6 +29,7 @@ import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.component.NonSuggestedVersionDialog
import app.revanced.manager.ui.component.SearchView
import app.revanced.manager.ui.model.SelectedApp
import app.revanced.manager.ui.viewmodel.AppSelectorViewModel
import app.revanced.manager.util.APK_MIMETYPE
@ -75,79 +75,66 @@ fun AppSelectorScreen(
)
}
// TODO: find something better for this
if (search) {
SearchBar(
SearchView(
query = filterText,
onQueryChange = { filterText = it },
onSearch = { },
active = true,
onActiveChange = { search = it },
modifier = Modifier.fillMaxSize(),
placeholder = { Text(stringResource(R.string.search_apps)) },
leadingIcon = {
IconButton({ search = false }) {
placeholder = { Text(stringResource(R.string.search_apps)) }
) {
if (appList.isNotEmpty() && filterText.isNotEmpty()) {
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize()
) {
items(
items = filteredAppList,
key = { it.packageName }
) { app ->
ListItem(
modifier = Modifier.clickable { onAppClick(app.packageName) },
leadingContent = {
AppIcon(
app.packageInfo,
null,
Modifier.size(36.dp)
)
},
headlineContent = { AppLabel(app.packageInfo) },
supportingContent = { Text(app.packageName) },
trailingContent = app.patches?.let {
{
Text(
pluralStringResource(
R.plurals.patch_count,
it,
it
)
)
}
}
)
}
}
} else {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
stringResource(R.string.back)
imageVector = Icons.Outlined.Search,
contentDescription = stringResource(R.string.search),
modifier = Modifier.size(64.dp)
)
Text(
text = stringResource(R.string.type_anything),
style = MaterialTheme.typography.bodyLarge
)
}
},
content = {
if (appList.isNotEmpty() && filterText.isNotEmpty()) {
LazyColumnWithScrollbar(
modifier = Modifier.fillMaxSize()
) {
items(
items = filteredAppList,
key = { it.packageName }
) { app ->
ListItem(
modifier = Modifier.clickable { onAppClick(app.packageName) },
leadingContent = {
AppIcon(
app.packageInfo,
null,
Modifier.size(36.dp)
)
},
headlineContent = { AppLabel(app.packageInfo) },
supportingContent = { Text(app.packageName) },
trailingContent = app.patches?.let {
{
Text(
pluralStringResource(
R.plurals.patch_count,
it,
it
)
)
}
}
)
}
}
} else {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Outlined.Search,
contentDescription = stringResource(R.string.search),
modifier = Modifier.size(64.dp)
)
Text(
text = stringResource(R.string.type_anything),
style = MaterialTheme.typography.bodyLarge
)
}
}
}
)
}
}
Scaffold(

View file

@ -14,7 +14,6 @@ import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.FilterList
import androidx.compose.material.icons.outlined.Restore
@ -33,7 +32,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.SearchBar
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
@ -61,6 +59,7 @@ import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.Countdown
import app.revanced.manager.ui.component.DangerousActionDialogBase
import app.revanced.manager.ui.component.LazyColumnWithScrollbar
import app.revanced.manager.ui.component.SearchView
import app.revanced.manager.ui.component.patches.OptionItem
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_SUPPORTED
@ -208,28 +207,11 @@ fun PatchesSelectorScreen(
}
search?.let { query ->
SearchBar(
SearchView(
query = query,
onQueryChange = { new ->
search = new
},
onSearch = {},
active = true,
onActiveChange = { new ->
if (new) return@SearchBar
search = null
},
placeholder = {
Text(stringResource(R.string.search_patches))
},
leadingIcon = {
IconButton(onClick = { search = null }) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
stringResource(R.string.back)
)
}
}
onQueryChange = { search = it },
onActiveChange = { if (!it) search = null },
placeholder = { Text(stringResource(R.string.search_patches)) }
) {
val bundle = bundles[pagerState.currentPage]

View file

@ -119,7 +119,7 @@
<string name="select_from_storage_description">Select an APK file from storage using file picker</string>
<string name="suggested_version_info">Suggested version: %s</string>
<string name="type_anything">Type anything to continue</string>
<string name="search">Search</string>
<string name="search">Search patches…</string>
<string name="apply">Apply</string>
<string name="help">Help</string>
<string name="back">Back</string>