diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index 3badca00a7..7f6c885f3e 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -319,4 +319,6 @@
Home Button Tap
Back Button Tap
%s & %s
+ App
+ Website
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt
index fdb049a010..23aebd28ac 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/DockPreferences.kt
@@ -16,19 +16,30 @@
package app.lawnchair.ui.preferences
-import androidx.compose.animation.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.navigation.NavGraphBuilder
import app.lawnchair.preferences.getAdapter
import app.lawnchair.preferences.preferenceManager
import app.lawnchair.preferences2.preferenceManager2
-import app.lawnchair.qsb.providers.QsbSearchProviderType
-import app.lawnchair.ui.preferences.components.*
+import app.lawnchair.qsb.providers.QsbSearchProvider
+import app.lawnchair.ui.preferences.components.DividerColumn
+import app.lawnchair.ui.preferences.components.ExpandAndShrink
+import app.lawnchair.ui.preferences.components.NavigationActionPreference
+import app.lawnchair.ui.preferences.components.PreferenceGroup
+import app.lawnchair.ui.preferences.components.PreferenceLayout
+import app.lawnchair.ui.preferences.components.SliderPreference
+import app.lawnchair.ui.preferences.components.SwitchPreference
import com.android.launcher3.R
+object DockRoutes {
+ const val SEARCH_PROVIDER = "searchProvider"
+}
+
fun NavGraphBuilder.dockGraph(route: String) {
- preferenceGraph(route, { DockPreferences() })
+ preferenceGraph(route, { DockPreferences() }) { subRoute ->
+ searchProviderGraph(subRoute(DockRoutes.SEARCH_PROVIDER))
+ }
}
@Composable
@@ -55,16 +66,16 @@ fun DockPreferences() {
valueRange = 0F..1F,
showAsPercentage = true,
)
- QsbProviderPreference()
- val hotseatQsbProviderAdapter =
- preferenceManager2().hotseatQsbProvider.getAdapter()
- ExpandAndShrink(visible = hotseatQsbProviderAdapter.state.value.type == QsbSearchProviderType.APP_AND_WEBSITE) {
- SwitchPreference(
- adapter = prefs2.hotseatQsbForceWebsite.getAdapter(),
- label = stringResource(R.string.always_open_website_label),
- description = stringResource(R.string.always_open_website_description),
- )
- }
+ val hotseatQsbProviderAdapter by preferenceManager2().hotseatQsbProvider.getAdapter()
+ NavigationActionPreference(
+ label = stringResource(R.string.search_provider),
+ destination = subRoute(DockRoutes.SEARCH_PROVIDER),
+ subtitle = stringResource(
+ id = QsbSearchProvider.values()
+ .first { it == hotseatQsbProviderAdapter }
+ .name,
+ ),
+ )
}
}
}
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/SearchProviderPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/SearchProviderPreferences.kt
new file mode 100644
index 0000000000..b5d2ca7834
--- /dev/null
+++ b/lawnchair/src/app/lawnchair/ui/preferences/SearchProviderPreferences.kt
@@ -0,0 +1,168 @@
+package app.lawnchair.ui.preferences
+
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.RadioButton
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import androidx.navigation.NavGraphBuilder
+import app.lawnchair.preferences.getAdapter
+import app.lawnchair.preferences2.preferenceManager2
+import app.lawnchair.qsb.providers.QsbSearchProvider
+import app.lawnchair.qsb.providers.QsbSearchProviderType
+import app.lawnchair.ui.preferences.components.ClickableIcon
+import app.lawnchair.ui.preferences.components.DividerColumn
+import app.lawnchair.ui.preferences.components.ExpandAndShrink
+import app.lawnchair.ui.preferences.components.PreferenceDivider
+import app.lawnchair.ui.preferences.components.PreferenceGroup
+import app.lawnchair.ui.preferences.components.PreferenceLayout
+import app.lawnchair.ui.preferences.components.PreferenceTemplate
+import com.android.launcher3.R
+
+fun NavGraphBuilder.searchProviderGraph(route: String) {
+ preferenceGraph(route, { SearchProviderPreferences() })
+}
+
+@Composable
+fun SearchProviderPreferences() {
+ val context = LocalContext.current
+ val adapter = preferenceManager2().hotseatQsbProvider.getAdapter()
+ val forceWebsiteAdapter = preferenceManager2().hotseatQsbForceWebsite.getAdapter()
+ PreferenceLayout(label = stringResource(R.string.search_provider)) {
+ PreferenceGroup {
+ QsbSearchProvider.values().forEach { qsbSearchProvider ->
+ val appInstalled = qsbSearchProvider.isDownloaded(context)
+ val selected = adapter.state.value == qsbSearchProvider
+ val hasAppAndWebsite = qsbSearchProvider.type == QsbSearchProviderType.APP_AND_WEBSITE
+ val showDownloadButton = qsbSearchProvider.type == QsbSearchProviderType.APP && !appInstalled
+ Column {
+ ListItem(
+ title = stringResource(id = qsbSearchProvider.name),
+ showDownloadButton = showDownloadButton,
+ enabled = qsbSearchProvider.type != QsbSearchProviderType.APP || appInstalled,
+ selected = selected,
+ onClick = { adapter.onChange(newValue = qsbSearchProvider) },
+ onDownloadClick = { qsbSearchProvider.launchOnAppMarket(context = context) },
+ description = if (showDownloadButton) {
+ stringResource(id = R.string.qsb_search_provider_app_required)
+ } else null,
+ )
+ ExpandAndShrink(visible = selected && hasAppAndWebsite) {
+ Options(
+ appEnabled = appInstalled,
+ appSelected = !forceWebsiteAdapter.state.value && appInstalled,
+ onAppClick = { forceWebsiteAdapter.onChange(newValue = false) },
+ onAppDownloadClick = { qsbSearchProvider.launchOnAppMarket(context = context) },
+ onWebsiteClick = { forceWebsiteAdapter.onChange(newValue = true) },
+ showAppDownloadButton = !appInstalled,
+ )
+ }
+ }
+ }
+ }
+ }
+}
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class)
+private fun ListItem(
+ title: String,
+ description: String?,
+ showDownloadButton: Boolean,
+ enabled: Boolean,
+ selected: Boolean,
+ onClick: () -> Unit,
+ onDownloadClick: () -> Unit,
+) {
+ Column {
+ PreferenceTemplate(
+ title = { Text(text = title) },
+ verticalPadding = if (showDownloadButton) 12.dp else 16.dp,
+ horizontalPadding = 0.dp,
+ enabled = enabled,
+ modifier = Modifier.clickable(enabled = enabled, onClick = onClick),
+ description = { if (description != null) Text(text = description) },
+ startWidget = {
+ RadioButton(
+ selected = selected,
+ onClick = null,
+ enabled = enabled,
+ modifier = Modifier.padding(start = 16.dp)
+ )
+ },
+ endWidget = {
+ if (showDownloadButton) {
+ ClickableIcon(
+ painter = painterResource(id = R.drawable.ic_download),
+ onClick = onDownloadClick,
+ tint = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(end = 4.dp),
+ )
+ }
+ },
+ )
+ }
+}
+
+@Composable
+@OptIn(ExperimentalMaterial3Api::class)
+private fun Options(
+ appEnabled: Boolean,
+ appSelected: Boolean,
+ showAppDownloadButton: Boolean,
+ onAppClick: () -> Unit,
+ onAppDownloadClick: () -> Unit,
+ onWebsiteClick: () -> Unit,
+) {
+ PreferenceDivider(startIndent = 40.dp)
+ DividerColumn(startIndent = 40.dp) {
+ PreferenceTemplate(
+ title = { Text(stringResource(id = R.string.app_label)) },
+ enabled = appEnabled,
+ verticalPadding = if (!appEnabled) 4.dp else 16.dp,
+ horizontalPadding = 0.dp,
+ modifier = Modifier.clickable(
+ enabled = appEnabled,
+ onClick = onAppClick,
+ ),
+ startWidget = {
+ RadioButton(
+ selected = appSelected,
+ onClick = null,
+ enabled = appEnabled,
+ modifier = Modifier.padding(start = 56.dp),
+ )
+ },
+ endWidget = {
+ if (showAppDownloadButton) {
+ ClickableIcon(
+ painter = painterResource(R.drawable.ic_download),
+ onClick = onAppDownloadClick,
+ tint = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.padding(end = 4.dp),
+ )
+ }
+ },
+ )
+ PreferenceTemplate(
+ title = { Text(text = stringResource(id = R.string.website_label)) },
+ modifier = Modifier.clickable(onClick = onWebsiteClick),
+ horizontalPadding = 0.dp,
+ startWidget = {
+ RadioButton(
+ selected = !appSelected,
+ onClick = null,
+ modifier = Modifier.padding(start = 56.dp),
+ )
+ },
+ )
+ }
+}
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/components/QsbProviderPreference.kt b/lawnchair/src/app/lawnchair/ui/preferences/components/QsbProviderPreference.kt
deleted file mode 100644
index ae202fb314..0000000000
--- a/lawnchair/src/app/lawnchair/ui/preferences/components/QsbProviderPreference.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-package app.lawnchair.ui.preferences.components
-
-import androidx.compose.foundation.clickable
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.lazy.LazyColumn
-import androidx.compose.foundation.lazy.itemsIndexed
-import androidx.compose.material.RadioButton
-import androidx.compose.material3.Icon
-import androidx.compose.material3.OutlinedButton
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalContext
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.res.stringResource
-import androidx.compose.ui.unit.dp
-import app.lawnchair.preferences.getAdapter
-import app.lawnchair.preferences2.preferenceManager2
-import app.lawnchair.qsb.providers.QsbSearchProvider
-import app.lawnchair.qsb.providers.QsbSearchProviderType
-import app.lawnchair.ui.AlertBottomSheetContent
-import app.lawnchair.ui.util.addIf
-import app.lawnchair.ui.util.bottomSheetHandler
-import com.android.launcher3.R
-
-@Composable
-fun QsbProviderPreference() {
- val adapter = preferenceManager2().hotseatQsbProvider.getAdapter()
- val context = LocalContext.current
- val entries = remember {
- QsbSearchProvider.values().map {
- // Enabled is true if provider type is not app or it is app & the app is installed
- val enabled = it.type != QsbSearchProviderType.APP || it.isDownloaded(context)
- ListPreferenceEntry(it, enabled) { stringResource(id = it.name) }
- }
- }
-
- QsbProviderListPreference(
- entries = entries,
- value = adapter.state.value,
- onValueChange = adapter::onChange,
- label = stringResource(R.string.search_provider),
- )
-}
-
-@Composable
-fun QsbProviderListPreference(
- entries: List>,
- value: QsbSearchProvider,
- onValueChange: (QsbSearchProvider) -> Unit,
- label: String,
- enabled: Boolean = true,
- description: String? = null,
-) {
- val context = LocalContext.current
-
- val bottomSheetHandler = bottomSheetHandler
- val currentDescription = description ?: entries
- .firstOrNull { it.value == value }
- ?.label?.invoke()
-
- val paddingVertical = 16.dp
- val paddingHorizontal = 16.dp
-
- PreferenceTemplate(
- title = { Text(text = label) },
- description = { currentDescription?.let { Text(text = it) } },
- enabled = enabled,
- modifier = Modifier.clickable(enabled) {
- bottomSheetHandler.show {
- AlertBottomSheetContent(
- title = { Text(label) },
- buttons = {
- OutlinedButton(onClick = { bottomSheetHandler.hide() }) {
- Text(text = stringResource(id = android.R.string.cancel))
- }
- }
- ) {
- LazyColumn {
- itemsIndexed(entries) { index, item ->
- if (index > 0) {
- PreferenceDivider(startIndent = 40.dp)
- }
- PreferenceTemplate(
- enabled = item.enabled,
- title = { Text(item.label()) },
- description = {
- if (item.value.type == QsbSearchProviderType.APP) {
- Text(stringResource(id = R.string.qsb_search_provider_app_required))
- }
- },
- applyPaddings = false,
- modifier = Modifier
- .clickable(item.enabled) {
- onValueChange(item.value)
- bottomSheetHandler.hide()
- },
- startWidget = {
- RadioButton(
- modifier = Modifier.padding(
- horizontal = paddingHorizontal,
- vertical = paddingVertical
- ),
- selected = item.value == value,
- onClick = null,
- enabled = item.enabled,
- )
- },
- endWidget = {
- if (item.value.type.downloadable) {
- val downloaded = item.value.isDownloaded(context)
- Icon(
- modifier = Modifier
- .addIf(!downloaded) {
- clickable {
- item.value.launchOnAppMarket(context = context)
- bottomSheetHandler.hide()
- }
- }
- .padding(
- horizontal = paddingHorizontal,
- vertical = paddingVertical
- ),
- painter = painterResource(id = if (downloaded) R.drawable.ic_tick else R.drawable.ic_download),
- contentDescription = null,
- )
- }
- }
- )
- }
- }
- }
- }
- }
- )
-}
\ No newline at end of file