From 0a4069171123ed4beef4829cde5137ab5c9c6021 Mon Sep 17 00:00:00 2001
From: SuperDragonXD <70206496+SuperDragonXD@users.noreply.github.com>
Date: Mon, 28 Jul 2025 23:16:42 +0800
Subject: [PATCH] fix(search): Correct regressions found during final testing
---
lawnchair/res/values/strings.xml | 2 ++
.../search/adapter/SearchTargetFactory.kt | 13 +++++++---
.../LawnchairLocalSearchAlgorithm.kt | 5 ++--
.../search/algorithms/engine/SearchResult.kt | 1 +
.../algorithms/engine/SectionBuilder.kt | 1 +
.../provider/web/CustomWebSearchProvider.kt | 2 +-
.../components/search/FileSearchProvider.kt | 24 +++++++++++++------
.../search/SearchProviderPreference.kt | 2 +-
.../app/lawnchair/util/FileAccessManager.kt | 1 +
platform_frameworks_libs_systemui | 2 +-
10 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index b1eb6010b1..667afb9079 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -796,6 +796,8 @@
Calculator
+ Search on
+
Media, files, and more
Contacts and more
Via %1$s
diff --git a/lawnchair/src/app/lawnchair/search/adapter/SearchTargetFactory.kt b/lawnchair/src/app/lawnchair/search/adapter/SearchTargetFactory.kt
index 1abe6de13d..e06e316ee3 100644
--- a/lawnchair/src/app/lawnchair/search/adapter/SearchTargetFactory.kt
+++ b/lawnchair/src/app/lawnchair/search/adapter/SearchTargetFactory.kt
@@ -238,16 +238,23 @@ class SearchTargetFactory(
fun createWebSearchActionTarget(
query: String,
- providerName: String, // The actual display name, not an ID
- searchUrl: String, // The final, pre-formatted search URL
+ providerName: String,
+ searchUrl: String,
@DrawableRes providerIconRes: Int,
+ tintIcon: Boolean = false,
): SearchTargetCompat {
val id = "browser:$query:$providerName"
val browserIntent = Intent(Intent.ACTION_VIEW, searchUrl.toUri())
val title = context.getString(R.string.all_apps_search_on_web_message, providerName)
+ val icon = Icon.createWithResource(context, providerIconRes).apply {
+ if (tintIcon) {
+ setTint(ColorTokens.TextColorSecondary.resolveColor(context))
+ }
+ }
+
val action = SearchActionCompat.Builder(id, title)
- .setIcon(Icon.createWithResource(context, providerIconRes))
+ .setIcon(icon)
.setIntent(browserIntent)
.build()
diff --git a/lawnchair/src/app/lawnchair/search/algorithms/LawnchairLocalSearchAlgorithm.kt b/lawnchair/src/app/lawnchair/search/algorithms/LawnchairLocalSearchAlgorithm.kt
index 13ba5164e1..02341227e4 100644
--- a/lawnchair/src/app/lawnchair/search/algorithms/LawnchairLocalSearchAlgorithm.kt
+++ b/lawnchair/src/app/lawnchair/search/algorithms/LawnchairLocalSearchAlgorithm.kt
@@ -147,7 +147,7 @@ class LawnchairLocalSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm
val webProvider = provider.configure(context)
val providerName = if (webProvider is CustomWebSearchProvider) {
- webProvider.getDisplayName(context.getString(webProvider.label))
+ webProvider.getDisplayName()
} else {
context.getString(webProvider.label)
}
@@ -158,6 +158,7 @@ class LawnchairLocalSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm
providerName = providerName,
searchUrl = webProvider.getSearchUrl(query),
providerIconRes = webProvider.iconRes,
+ tintIcon = webProvider is CustomWebSearchProvider,
),
)
}
@@ -174,8 +175,8 @@ class LawnchairLocalSearchAlgorithm(context: Context) : LawnchairSearchAlgorithm
private val sectionBuilders: List = listOf(
AppsAndShortcutsSectionBuilder,
- WebSuggestionsSectionBuilder,
CalculationSectionBuilder,
+ WebSuggestionsSectionBuilder,
ContactsSectionBuilder,
FilesSectionBuilder,
SettingsSectionBuilder,
diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchResult.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchResult.kt
index a38e45d8c6..cdf6d6c685 100644
--- a/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchResult.kt
+++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/SearchResult.kt
@@ -30,6 +30,7 @@ sealed class SearchResult {
val providerName: String,
val searchUrl: String,
@DrawableRes val providerIconRes: Int,
+ val tintIcon: Boolean = false,
) : Action()
data class EmptyState(
@StringRes val titleRes: Int,
diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/SectionBuilder.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/SectionBuilder.kt
index 448303eba2..3885e6a91f 100644
--- a/lawnchair/src/app/lawnchair/search/algorithms/engine/SectionBuilder.kt
+++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/SectionBuilder.kt
@@ -176,6 +176,7 @@ object ActionsSectionBuilder : SectionBuilder {
providerName = webSearch.first().providerName,
searchUrl = webSearch.first().searchUrl,
providerIconRes = webSearch.first().providerIconRes,
+ tintIcon = webSearch.first().tintIcon,
).let {
targets.add(it)
}
diff --git a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/web/CustomWebSearchProvider.kt b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/web/CustomWebSearchProvider.kt
index c00e0cbc6e..9e0e12274f 100644
--- a/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/web/CustomWebSearchProvider.kt
+++ b/lawnchair/src/app/lawnchair/search/algorithms/engine/provider/web/CustomWebSearchProvider.kt
@@ -44,7 +44,7 @@ object CustomWebSearchProvider : WebSearchProvider {
private var displayName: String = ""
private val okHttpClient = OkHttpClient()
- fun getDisplayName(getDisplayNamedefault: String): String = displayName
+ fun getDisplayName(): String = displayName
override fun configure(context: Context): WebSearchProvider {
val prefs = PreferenceManager2.getInstance(context)
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/search/FileSearchProvider.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/search/FileSearchProvider.kt
index ec388bc2a9..e2c75bff92 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/components/search/FileSearchProvider.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/components/search/FileSearchProvider.kt
@@ -21,6 +21,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -81,6 +82,10 @@ fun FileSearchProvider(
val mainAdapter = prefs.searchResultFilesToggle.getAdapter()
val hasAnyPermissions by viewModel.hasAnyPermissions.collectAsStateWithLifecycle()
+ LaunchedEffect(Unit) {
+ viewModel.refreshAccessStates()
+ }
+
LifecycleResumeEffect(Unit) {
viewModel.refreshAccessStates()
onPauseOrDispose {}
@@ -93,18 +98,21 @@ fun FileSearchProvider(
enabled = hasAnyPermissions,
modifier = modifier,
)
- PreferenceGroup {
+ PreferenceGroup(
+ heading = stringResource(R.string.search_pref_files_search_on),
+ ) {
val allFilesAccessState by viewModel.allFilesAccessState.collectAsStateWithLifecycle()
+ val allFilesAccessAdapter = prefs.searchResultAllFiles.getAdapter()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
ManageExternalStorageSetting(
accessState = allFilesAccessState,
- adapter = prefs.searchResultAllFiles.getAdapter(),
+ adapter = allFilesAccessAdapter,
onPermissionRequest = viewModel::refreshAccessStates,
)
} else {
GenericAccessSetting(
- adapter = prefs.searchResultAllFiles.getAdapter(),
+ adapter = allFilesAccessAdapter,
requiredPermission = android.Manifest.permission.READ_EXTERNAL_STORAGE,
switchEnabled = { allFilesAccessState != FileAccessState.Denied },
label = stringResource(R.string.search_pref_result_all_files_title),
@@ -122,6 +130,7 @@ fun FileSearchProvider(
accessState = visualMediaAccessState,
adapter = prefs.searchResultVisualMedia.getAdapter(),
onPermissionRequest = viewModel::refreshAccessStates,
+ alwaysEnabled = allFilesAccessAdapter.state.value && allFilesAccessState == FileAccessState.Full,
)
GenericAccessSetting(
@@ -132,6 +141,7 @@ fun FileSearchProvider(
permissionTitle = stringResource(R.string.permissions_music_audio),
permissionDescription = stringResource(R.string.permissions_music_audio_description),
onPermissionResult = { viewModel.refreshAccessStates() },
+ alwaysEnabled = allFilesAccessAdapter.state.value && allFilesAccessState == FileAccessState.Full,
)
}
}
@@ -182,7 +192,7 @@ private fun ManageExternalStorageSetting(
showPermissionDialog = true
}
},
- switchEnabled = !isPlayStoreFlavor(),
+ switchEnabled = !isPlayStoreFlavor() && (accessState != FileAccessState.Denied),
modifier = modifier,
)
}
@@ -190,8 +200,8 @@ private fun ManageExternalStorageSetting(
if (showPermissionDialog) {
if (!isPlayStoreFlavor()) {
PermissionDialog(
- title = stringResource(R.string.permissions_photos_videos),
- text = stringResource(R.string.permissions_photos_videos_description),
+ title = stringResource(R.string.permissions_manage_storage),
+ text = stringResource(R.string.permissions_manage_storage_description),
isPermanentlyDenied = true,
onConfirm = { },
onDismiss = { showPermissionDialog = false },
@@ -273,7 +283,7 @@ private fun VisualMediaSetting(
PermissionDialog(
title = stringResource(R.string.permissions_photos_videos),
text = stringResource(R.string.permissions_photos_videos_description),
- isPermanentlyDenied = !permissionState.shouldShowRationale && !permissionState.allPermissionsGranted,
+ isPermanentlyDenied = permissionState.allPermissionsGranted,
onConfirm = { permissionState.launchMultiplePermissionRequest() },
onDismiss = { showPermissionDialog = false },
onGoToSettings = { context.openAppPermissionSettings() },
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/search/SearchProviderPreference.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/search/SearchProviderPreference.kt
index 75ed95c186..f93308b23a 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/components/search/SearchProviderPreference.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/components/search/SearchProviderPreference.kt
@@ -157,7 +157,7 @@ fun ContactsSearchProvider(
PermissionDialog(
title = stringResource(R.string.warn_contact_permission_title),
text = stringResource(id = R.string.warn_contact_permission_content),
- isPermanentlyDenied = !contactsPermissionState.status.isGranted && !contactsPermissionState.status.shouldShowRationale,
+ isPermanentlyDenied = contactsPermissionState.status.shouldShowRationale,
onConfirm = { contactsPermissionState.launchPermissionRequest() },
onDismiss = {
backDispatcher?.onBackPressed()
diff --git a/lawnchair/src/app/lawnchair/util/FileAccessManager.kt b/lawnchair/src/app/lawnchair/util/FileAccessManager.kt
index cb3f1a3c56..bfd864444e 100644
--- a/lawnchair/src/app/lawnchair/util/FileAccessManager.kt
+++ b/lawnchair/src/app/lawnchair/util/FileAccessManager.kt
@@ -102,6 +102,7 @@ class FileAccessManager private constructor(private val context: Context) : Safe
_allFilesAccessState.value = getCurrentAllFilesAccessState()
_visualMediaAccessState.value = getCurrentVisualMediaState()
_audioAccessState.value = getCurrentAudioState()
+ _hasAnyPermission.value = hasAnyPermissions()
}
private fun hasAnyPermissions(): Boolean {
diff --git a/platform_frameworks_libs_systemui b/platform_frameworks_libs_systemui
index efa9b01922..970a3b2f14 160000
--- a/platform_frameworks_libs_systemui
+++ b/platform_frameworks_libs_systemui
@@ -1 +1 @@
-Subproject commit efa9b019229547bfa0cb07fe07a10e76af62866b
+Subproject commit 970a3b2f1407c585c57f08245a35e416c465ab37