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 debe3a5f9..3a012b9a4 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
@@ -108,6 +108,7 @@ class SettingsRepository(private val context: Context) {
const val KEY_FLASHLIGHT_PULSE_ENABLED = "flashlight_pulse_enabled"
const val KEY_FLASHLIGHT_PULSE_FACEDOWN_ONLY = "flashlight_pulse_facedown_only"
const val KEY_FLASHLIGHT_PULSE_MAX_INTENSITY = "flashlight_pulse_max_intensity"
+ const val KEY_FLASHLIGHT_POCKET_TURN_OFF_ENABLED = "flashlight_pocket_turn_off_enabled"
const val KEY_SCREEN_LOCKED_SECURITY_ENABLED = "screen_locked_security_enabled"
const val KEY_HIDE_SYSTEM_ICONS = "hide_system_icons"
diff --git a/app/src/main/java/com/sameerasw/essentials/domain/registry/FeatureRegistry.kt b/app/src/main/java/com/sameerasw/essentials/domain/registry/FeatureRegistry.kt
index 47dd20bfd..50c93722e 100644
--- a/app/src/main/java/com/sameerasw/essentials/domain/registry/FeatureRegistry.kt
+++ b/app/src/main/java/com/sameerasw/essentials/domain/registry/FeatureRegistry.kt
@@ -707,6 +707,12 @@ object FeatureRegistry {
R.string.search_remap_flashlight_desc,
"flashlight_toggle",
R.array.keywords_flashlight
+ ),
+ SearchSetting(
+ R.string.search_flashlight_pocket_title,
+ R.string.search_flashlight_pocket_desc,
+ "flashlight_options",
+ R.array.keywords_pocket_detection
)
),
parentFeatureId = "Input",
diff --git a/app/src/main/java/com/sameerasw/essentials/services/tiles/ScreenOffAccessibilityService.kt b/app/src/main/java/com/sameerasw/essentials/services/tiles/ScreenOffAccessibilityService.kt
index 0ea641a9a..8873814e0 100644
--- a/app/src/main/java/com/sameerasw/essentials/services/tiles/ScreenOffAccessibilityService.kt
+++ b/app/src/main/java/com/sameerasw/essentials/services/tiles/ScreenOffAccessibilityService.kt
@@ -62,6 +62,26 @@ class ScreenOffAccessibilityService : AccessibilityService(), SensorEventListene
FreezeManager.freezeAll(this)
}
+ // Pocket Detection
+ private val pocketFlashlightHandler = Handler(Looper.getMainLooper())
+ private val pocketFlashlightRunnable = Runnable {
+ val prefs = getSharedPreferences("essentials_prefs", MODE_PRIVATE)
+ val pocketTurnOffEnabled = prefs.getBoolean("flashlight_pocket_turn_off_enabled", false)
+ // Re-check at fire time — guards against external torch-off between scheduling and firing
+ if (pocketTurnOffEnabled && flashlightHandler.isProximityBlocked && flashlightHandler.isTorchOn) {
+ flashlightHandler.toggleFlashlight()
+ }
+ }
+
+ private fun schedulePocketFlashlightTurnOff() {
+ pocketFlashlightHandler.removeCallbacks(pocketFlashlightRunnable)
+ pocketFlashlightHandler.postDelayed(pocketFlashlightRunnable, 1500L)
+ }
+
+ private fun cancelPocketFlashlightTurnOff() {
+ pocketFlashlightHandler.removeCallbacks(pocketFlashlightRunnable)
+ }
+
private val preferenceChangeListener =
android.content.SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
if (key == "circle_to_search_gesture_enabled" ||
@@ -220,6 +240,7 @@ class ScreenOffAccessibilityService : AccessibilityService(), SensorEventListene
omniGestureOverlayHandler.removeOverlay()
statusBarIconHandler.unregister()
stopInputEventListener()
+ cancelPocketFlashlightTurnOff()
serviceScope.cancel()
getSharedPreferences("essentials_prefs", MODE_PRIVATE)
.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener)
@@ -244,6 +265,15 @@ class ScreenOffAccessibilityService : AccessibilityService(), SensorEventListene
val isBlocked = distance < maxRange && distance < 5f
flashlightHandler.isProximityBlocked = isBlocked
+
+ val prefs = getSharedPreferences("essentials_prefs", MODE_PRIVATE)
+ val pocketTurnOffEnabled = prefs.getBoolean("flashlight_pocket_turn_off_enabled", false)
+
+ if (pocketTurnOffEnabled && isBlocked && flashlightHandler.isTorchOn) {
+ schedulePocketFlashlightTurnOff()
+ } else {
+ cancelPocketFlashlightTurnOff()
+ }
}
}
diff --git a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/ButtonRemapSettingsUI.kt b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/ButtonRemapSettingsUI.kt
index b811fd1a1..ffee9124c 100644
--- a/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/ButtonRemapSettingsUI.kt
+++ b/app/src/main/java/com/sameerasw/essentials/ui/composables/configs/ButtonRemapSettingsUI.kt
@@ -527,6 +527,16 @@ fun ButtonRemapSettingsUI(
)
}
)
+
+ IconToggleItem(
+ iconRes = R.drawable.rounded_front_hand_24,
+ title = stringResource(R.string.flashlight_pocket_title),
+ description = stringResource(R.string.flashlight_pocket_desc),
+ isChecked = viewModel.isFlashlightPocketTurnOffEnabled.value,
+ onCheckedChange = {
+ viewModel.setFlashlightPocketTurnOffEnabled(it, context)
+ }
+ )
}
Button(
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 492ac93af..852eed2bb 100644
--- a/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
+++ b/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt
@@ -113,6 +113,7 @@ class MainViewModel : ViewModel() {
val isFlashlightPulseFacedownOnly = mutableStateOf(true)
val isFlashlightPulseUseLightingApps = mutableStateOf(true)
val flashlightPulseMaxIntensity = mutableFloatStateOf(0.5f)
+ val isFlashlightPocketTurnOffEnabled = mutableStateOf(false)
val isLocationPermissionGranted = mutableStateOf(false)
val isBackgroundLocationPermissionGranted = mutableStateOf(false)
val isFullScreenIntentPermissionGranted = mutableStateOf(false)
@@ -595,6 +596,10 @@ class MainViewModel : ViewModel() {
settingsRepository.getFloat(key, 0.5f)
}
+ SettingsRepository.KEY_FLASHLIGHT_POCKET_TURN_OFF_ENABLED -> {
+ isFlashlightPocketTurnOffEnabled.value = settingsRepository.getBoolean(key)
+ }
+
SettingsRepository.KEY_CIRCLE_TO_SEARCH_GESTURE_ENABLED -> {
isCircleToSearchGestureEnabled.value = settingsRepository.getBoolean(key)
}
@@ -1152,6 +1157,8 @@ class MainViewModel : ViewModel() {
SettingsRepository.KEY_FLASHLIGHT_PULSE_MAX_INTENSITY,
0.5f
)
+ isFlashlightPocketTurnOffEnabled.value =
+ settingsRepository.getBoolean(SettingsRepository.KEY_FLASHLIGHT_POCKET_TURN_OFF_ENABLED)
isPitchBlackThemeEnabled.value =
settingsRepository.getBoolean(SettingsRepository.KEY_PITCH_BLACK_THEME_ENABLED)
@@ -3313,6 +3320,14 @@ class MainViewModel : ViewModel() {
)
}
+ fun setFlashlightPocketTurnOffEnabled(enabled: Boolean, context: Context) {
+ isFlashlightPocketTurnOffEnabled.value = enabled
+ settingsRepository.putBoolean(
+ SettingsRepository.KEY_FLASHLIGHT_POCKET_TURN_OFF_ENABLED,
+ enabled
+ )
+ }
+
fun setFlashlightFadeEnabled(enabled: Boolean, context: Context) {
isFlashlightFadeEnabled.value = enabled
settingsRepository.putBoolean(SettingsRepository.KEY_FLASHLIGHT_FADE_ENABLED, enabled)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2d79cf8a2..af4e6e66d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -98,6 +98,8 @@
Other
Always turn off flashlight
Even while display is on
+ Pocket detection
+ Turn off flashlight when phone is in your pocket
Settings
@@ -584,6 +586,8 @@
Vibration feedback when remapped button is pressed
Flashlight toggle
Toggle flashlight with volume buttons
+ Flashlight pocket detection
+ Auto-turn off flashlight when placed in pocket
Enable Dynamic Night Light
Master switch for dynamic night light
Enable app lock
@@ -951,6 +955,13 @@
- pulse
- notification
+
+ - pocket
+ - proximity
+ - sensor
+ - torch
+ - auto
+
- awake
- developer