diff --git a/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt b/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt
index 422a8c13b..a13899bfd 100644
--- a/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt
+++ b/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt
@@ -439,6 +439,9 @@ class SettingsRepository(
const val KEY_PIXEL_SEARCH_RESULT_FILES = "pixel_search_result_files"
const val KEY_PIXEL_SEARCH_BUBBLES_WEB = "pixel_search_bubbles_web"
const val KEY_PIXEL_SEARCH_ENGINE = "pixel_search_engine"
+ const val KEY_PIXEL_SEARCH_BLUR = "pixel_search_blur_enabled"
+ const val KEY_PIXEL_SEARCH_WALLPAPER_BG = "pixel_search_wallpaper_bg"
+ const val KEY_PIXEL_SEARCH_BLUR_RADIUS = "pixel_search_blur_radius"
const val KEY_AUTO_ACCESSIBILITY_ENABLED = "auto_accessibility_enabled"
const val KEY_USE_BLUR = "use_blur"
const val KEY_USE_RIPPLE = "use_ripple"
@@ -3702,6 +3705,15 @@ class SettingsRepository(
fun getPixelSearchEngine(): String = getString(KEY_PIXEL_SEARCH_ENGINE, "Google") ?: "Google"
fun setPixelSearchEngine(engine: String) = putString(KEY_PIXEL_SEARCH_ENGINE, engine)
+ fun isPixelSearchBlurEnabled(): Boolean = getBoolean(KEY_PIXEL_SEARCH_BLUR, true)
+ fun setPixelSearchBlurEnabled(enabled: Boolean) = putBoolean(KEY_PIXEL_SEARCH_BLUR, enabled)
+
+ fun isPixelSearchWallpaperBackgroundEnabled(): Boolean = getBoolean(KEY_PIXEL_SEARCH_WALLPAPER_BG, true)
+ fun setPixelSearchWallpaperBackgroundEnabled(enabled: Boolean) = putBoolean(KEY_PIXEL_SEARCH_WALLPAPER_BG, enabled)
+
+ fun getPixelSearchBlurRadius(): Float = getFloat(KEY_PIXEL_SEARCH_BLUR_RADIUS, 60f)
+ fun setPixelSearchBlurRadius(radius: Float) = putFloat(KEY_PIXEL_SEARCH_BLUR_RADIUS, radius)
+
fun isBubbleWebFullscreen(): Boolean = getBoolean(KEY_BUBBLE_WEB_FULLSCREEN, false)
fun setBubbleWebFullscreen(fullscreen: Boolean) = putBoolean(KEY_BUBBLE_WEB_FULLSCREEN, fullscreen)
diff --git a/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchResultsActivity.kt b/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchResultsActivity.kt
index aab20b7d8..e7908b67a 100644
--- a/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchResultsActivity.kt
+++ b/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchResultsActivity.kt
@@ -14,6 +14,8 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
+import android.graphics.PixelFormat
+import android.graphics.drawable.ColorDrawable
import android.os.Build
import android.os.Bundle
import android.provider.ContactsContract
@@ -155,6 +157,8 @@ class PixelSearchResultsActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)
+ window.setBackgroundDrawable(ColorDrawable(android.graphics.Color.TRANSPARENT))
+ window.setFormat(PixelFormat.TRANSLUCENT)
enableEdgeToEdge(
statusBarStyle = SystemBarStyle.auto(
android.graphics.Color.TRANSPARENT,
@@ -170,18 +174,7 @@ class PixelSearchResultsActivity : ComponentActivity() {
window.isNavigationBarContrastEnforced = false
}
- val isSystemDark = (resources.configuration.uiMode and android.content.res.Configuration.UI_MODE_NIGHT_MASK) == android.content.res.Configuration.UI_MODE_NIGHT_YES
- val dimAmount = if (isSystemDark) 0.2f else 0.08f
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
- window.attributes.blurBehindRadius = 60
- window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
- window.setDimAmount(dimAmount)
- } else {
- window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
- window.setDimAmount(if (isSystemDark) 0.35f else 0.15f)
- }
+ applyBlur()
val initialQuery = intent.getStringExtra(SearchManager.QUERY)
?: intent.getStringExtra("query")
@@ -200,9 +193,48 @@ class PixelSearchResultsActivity : ComponentActivity() {
}
}
+ override fun onResume() {
+ super.onResume()
+ applyBlur()
+ }
+
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
+ applyBlur()
+ }
+
+ private fun applyBlur() {
+ val isSystemDark = (resources.configuration.uiMode and android.content.res.Configuration.UI_MODE_NIGHT_MASK) == android.content.res.Configuration.UI_MODE_NIGHT_YES
+ val dimAmount = if (isSystemDark) 0.2f else 0.08f
+
+ val repository = SettingsRepository(this)
+ val isBlurEnabled = repository.isPixelSearchBlurEnabled()
+ val isWallpaperBg = repository.isPixelSearchWallpaperBackgroundEnabled()
+ val blurRadius = repository.getPixelSearchBlurRadius().toInt().coerceIn(1, 300)
+
+ if (isWallpaperBg) {
+ window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER)
+ } else {
+ window.clearFlags(WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER)
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val params = window.attributes
+ if (isBlurEnabled) {
+ window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
+ params.blurBehindRadius = blurRadius
+ } else {
+ window.clearFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
+ params.blurBehindRadius = 0
+ }
+ window.attributes = params
+ window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+ window.setDimAmount(dimAmount)
+ } else {
+ window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+ window.setDimAmount(if (isSystemDark) 0.35f else 0.15f)
+ }
}
}
@@ -637,7 +669,21 @@ fun PixelSearchResultsScreen(
}
}
- val scrimColor = MaterialTheme.colorScheme.surfaceContainer.copy(alpha = 0.55f)
+ val isWallpaperBg = remember { repository.isPixelSearchWallpaperBackgroundEnabled() }
+ val isBlurEffective = remember(context) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val windowManager = context.getSystemService(WindowManager::class.java)
+ repository.isPixelSearchBlurEnabled() && (windowManager?.isCrossWindowBlurEnabled == true)
+ } else {
+ false
+ }
+ }
+ val scrimAlpha = when {
+ !isBlurEffective -> 0.85f
+ !isWallpaperBg -> 0.45f
+ else -> 0.55f
+ }
+ val scrimColor = MaterialTheme.colorScheme.surfaceContainer.copy(alpha = scrimAlpha)
Box(
modifier = Modifier
diff --git a/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchbarSettingsActivity.kt b/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchbarSettingsActivity.kt
index 182ed120a..0ae050a25 100644
--- a/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchbarSettingsActivity.kt
+++ b/app/src/main/java/com/sameerasw/essentials/ui/activities/PixelSearchbarSettingsActivity.kt
@@ -87,6 +87,7 @@ import com.sameerasw.essentials.ui.core.containers.RoundedCardContainer
import com.sameerasw.essentials.ui.core.pickers.SegmentedPicker
import com.sameerasw.essentials.ui.core.sheets.FeatureHelpBottomSheet
import com.sameerasw.essentials.ui.core.sheets.PermissionsBottomSheet
+import com.sameerasw.essentials.ui.core.sheets.PixelSearchBlurOptionsBottomSheet
import com.sameerasw.essentials.ui.modifiers.BlurDirection
import com.sameerasw.essentials.ui.modifiers.progressiveBlur
import com.sameerasw.essentials.ui.modifiers.scrollMotionBlur
@@ -324,6 +325,7 @@ fun PixelSearchbarSettingsUI(
var pendingWidgetId by remember { mutableStateOf(AppWidgetManager.INVALID_APPWIDGET_ID) }
var showWidgetPicker by remember { mutableStateOf(false) }
var isWidgetUnsupported by remember { mutableStateOf(false) }
+ var showBlurOptionsSheet by remember { mutableStateOf(false) }
LaunchedEffect(currentType) {
while (currentType == "widget") {
@@ -988,11 +990,33 @@ fun PixelSearchbarSettingsUI(
}
}
}
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val blurEnabled = viewModel.pixelSearchBlur.value
+ IconToggleItem(
+ iconRes = R.drawable.rounded_blur_on_24,
+ title = stringResource(R.string.pref_pixel_search_blur_title),
+ description = stringResource(R.string.pref_pixel_search_blur_desc),
+ isChecked = blurEnabled,
+ onCheckedChange = { checked ->
+ HapticUtil.performVirtualKeyHaptic(view)
+ viewModel.setPixelSearchBlurEnabled(checked)
+ },
+ onSettingsClick = { showBlurOptionsSheet = true },
+ )
+ }
}
}
}
}
+ if (showBlurOptionsSheet) {
+ PixelSearchBlurOptionsBottomSheet(
+ viewModel = viewModel,
+ onDismissRequest = { showBlurOptionsSheet = false },
+ )
+ }
+
if (showPermissionSheet) {
val permissionItem =
remember(context, viewModel) {
diff --git a/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/PixelSearchBlurOptionsBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/PixelSearchBlurOptionsBottomSheet.kt
new file mode 100644
index 000000000..863c9c085
--- /dev/null
+++ b/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/PixelSearchBlurOptionsBottomSheet.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2026 sameerasw.com
+ * License: MIT License
+ *
+ * Feature Module: UI Core Sheets
+ * File: PixelSearchBlurOptionsBottomSheet.kt
+ * Description: Bottom sheet for configuring Pixel Search blur and wallpaper background options.
+ */
+
+package com.sameerasw.essentials.ui.core.sheets
+
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalView
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.sameerasw.essentials.R
+import com.sameerasw.essentials.ui.components.sliders.ConfigSliderItem
+import com.sameerasw.essentials.ui.core.cards.IconToggleItem
+import com.sameerasw.essentials.ui.core.containers.RoundedCardContainer
+import com.sameerasw.essentials.utils.HapticUtil
+import com.sameerasw.essentials.viewmodels.MainViewModel
+
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun PixelSearchBlurOptionsBottomSheet(
+ viewModel: MainViewModel,
+ onDismissRequest: () -> Unit,
+) {
+ val view = LocalView.current
+
+ EssentialsBottomSheet(onDismissRequest = onDismissRequest) {
+ Column(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 16.dp)
+ .padding(bottom = 24.dp),
+ verticalArrangement = Arrangement.spacedBy(16.dp),
+ ) {
+ Text(
+ text = stringResource(R.string.pixel_search_blur_options_title),
+ style = MaterialTheme.typography.titleLarge,
+ color = MaterialTheme.colorScheme.onSurface,
+ modifier = Modifier.padding(start = 8.dp, bottom = 4.dp),
+ )
+
+ RoundedCardContainer(spacing = 2.dp, cornerRadius = 24.dp) {
+ IconToggleItem(
+ iconRes = R.drawable.rounded_wallpaper_24,
+ title = stringResource(R.string.pref_pixel_search_wallpaper_bg_title),
+ isChecked = viewModel.pixelSearchWallpaperBackground.value,
+ onCheckedChange = { checked ->
+ HapticUtil.performVirtualKeyHaptic(view)
+ viewModel.setPixelSearchWallpaperBackgroundEnabled(checked)
+ },
+ )
+
+ ConfigSliderItem(
+ title = stringResource(R.string.pref_pixel_search_blur_intensity_title),
+ value = viewModel.pixelSearchBlurRadius.floatValue,
+ onValueChange = {
+ HapticUtil.performUIHaptic(view)
+ viewModel.setPixelSearchBlurRadius(it)
+ },
+ valueRange = 10f..150f,
+ increment = 5f,
+ iconRes = R.drawable.rounded_blur_on_24,
+ valueFormatter = { "${it.toInt()} dp" },
+ )
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/UnsupportedFeaturesConfirmationSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/UnsupportedFeaturesConfirmationSheet.kt
index 6517af9b7..2de0f142d 100644
--- a/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/UnsupportedFeaturesConfirmationSheet.kt
+++ b/app/src/main/java/com/sameerasw/essentials/ui/core/sheets/UnsupportedFeaturesConfirmationSheet.kt
@@ -74,7 +74,10 @@ fun UnsupportedFeaturesConfirmationSheet(
)
RoundedCardContainer(
- modifier = Modifier.fillMaxWidth(),
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .weight(1f, fill = false),
) {
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
diff --git a/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt b/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
index af2c0b880..bdb6e767b 100644
--- a/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
+++ b/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
@@ -2890,6 +2890,9 @@ class MainViewModel : ViewModel() {
pixelSearchResultShortcuts.value = settingsRepository.isPixelSearchResultShortcutsEnabled()
pixelSearchResultWeb.value = settingsRepository.isPixelSearchResultWebEnabled()
pixelSearchBubblesWeb.value = settingsRepository.isPixelSearchBubblesWebEnabled()
+ pixelSearchBlur.value = settingsRepository.isPixelSearchBlurEnabled()
+ pixelSearchWallpaperBackground.value = settingsRepository.isPixelSearchWallpaperBackgroundEnabled()
+ pixelSearchBlurRadius.floatValue = settingsRepository.getPixelSearchBlurRadius()
pixelSearchEngine.value = settingsRepository.getPixelSearchEngine()
isPocketModeEnabled.value =
settingsRepository.getBoolean(SettingsRepository.KEY_POCKET_MODE_ENABLED)
@@ -4682,6 +4685,9 @@ class MainViewModel : ViewModel() {
val pixelSearchResultShortcuts = mutableStateOf(true)
val pixelSearchResultWeb = mutableStateOf(true)
val pixelSearchBubblesWeb = mutableStateOf(false)
+ val pixelSearchBlur = mutableStateOf(true)
+ val pixelSearchWallpaperBackground = mutableStateOf(true)
+ val pixelSearchBlurRadius = mutableFloatStateOf(60f)
val pixelSearchEngine = mutableStateOf("Google")
fun setPixelSearchResultAppsEnabled(enabled: Boolean) {
@@ -4724,6 +4730,21 @@ class MainViewModel : ViewModel() {
settingsRepository.setPixelSearchBubblesWebEnabled(enabled)
}
+ fun setPixelSearchBlurEnabled(enabled: Boolean) {
+ pixelSearchBlur.value = enabled
+ settingsRepository.setPixelSearchBlurEnabled(enabled)
+ }
+
+ fun setPixelSearchWallpaperBackgroundEnabled(enabled: Boolean) {
+ pixelSearchWallpaperBackground.value = enabled
+ settingsRepository.setPixelSearchWallpaperBackgroundEnabled(enabled)
+ }
+
+ fun setPixelSearchBlurRadius(radius: Float) {
+ pixelSearchBlurRadius.floatValue = radius
+ settingsRepository.setPixelSearchBlurRadius(radius)
+ }
+
fun setPixelSearchEngine(engine: String) {
pixelSearchEngine.value = engine
settingsRepository.setPixelSearchEngine(engine)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 9f8312f3d..fab55033d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -2666,6 +2666,11 @@
Custom tap action
Use DIY tap action instead of widget\'s own
Music
+ Blur
+ Blur the background of search results
+ Blur options
+ Show wallpaper in background
+ Blur intensity
Restart Shizuku
Please enter Shizuku auth token in settings first
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index f7434c70f..5ec4b65e8 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -20,7 +20,6 @@
- @android:color/transparent
- @null
- true
- - true
- @null
- true
- @null