From 13c4c14531a0d3f475d4a226360be957c85bdb32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Garci=CC=81a?= Date: Tue, 27 Aug 2024 14:20:09 +0200 Subject: [PATCH 1/3] replace launchedEffect by DisposableEffect #ANDROID-15102 --- .../java/com/telefonica/tweaks/Tweaks.kt | 20 +++++++++------ .../utils/DisposableEffectExtensions.kt | 25 +++++++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt diff --git a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt index 6ea00b8..c00cf19 100644 --- a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt +++ b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt @@ -10,8 +10,9 @@ import android.os.Build import android.os.VibrationEffect import android.os.Vibrator import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.DisposableEffect import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.core.content.ContextCompat import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder @@ -28,6 +29,7 @@ import com.telefonica.tweaks.domain.TweaksBusinessLogic import com.telefonica.tweaks.domain.TweaksGraph import com.telefonica.tweaks.ui.TweaksCategoryScreen import com.telefonica.tweaks.ui.TweaksScreen +import com.telefonica.tweaks.utils.onStart import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map @@ -94,14 +96,18 @@ open class Tweaks : TweaksContract { @Composable fun NavController.navigateToTweaksOnShake() { val context = LocalContext.current + val lifeCycleOwner = LocalLifecycleOwner.current val sensorManager: SensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager - LaunchedEffect(true) { - val shakeDetector = ShakeDetector { - vibrateIfAble(context) - navigate(TWEAKS_NAVIGATION_ENTRYPOINT) + + DisposableEffect(true) { + this.onStart(lifeCycleOwner) { + val shakeDetector = ShakeDetector { + vibrateIfAble(context) + navigate(TWEAKS_NAVIGATION_ENTRYPOINT) + } + shakeDetector.start(sensorManager, SENSOR_DELAY_NORMAL) } - shakeDetector.start(sensorManager, SENSOR_DELAY_NORMAL) } } @@ -171,4 +177,4 @@ fun NavGraphBuilder.addTweakGraph( } } -private fun TweakCategory.navigationRoute(): String = "${this.title.replace(" ", "")}-tweak-screen" \ No newline at end of file +private fun TweakCategory.navigationRoute(): String = "${this.title.replace(" ", "")}-tweak-screen" diff --git a/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt b/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt new file mode 100644 index 0000000..f372731 --- /dev/null +++ b/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt @@ -0,0 +1,25 @@ +package com.telefonica.tweaks.utils + +import androidx.compose.runtime.DisposableEffectResult +import androidx.compose.runtime.DisposableEffectScope +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver +import androidx.lifecycle.LifecycleOwner + + +fun DisposableEffectScope.onStart( + lifeCycleOwner: LifecycleOwner, + onStart: () -> Unit +): DisposableEffectResult { + val observer = LifecycleEventObserver { _, event -> + if (event == Lifecycle.Event.ON_START) { + onStart() + } + } + + lifeCycleOwner.lifecycle.addObserver(observer) + + return onDispose { + lifeCycleOwner.lifecycle.removeObserver(observer) + } +} From b0658bfbe4b293fbd9330100a911dd9e8d9a4ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Garci=CC=81a?= Date: Fri, 6 Sep 2024 16:26:23 +0200 Subject: [PATCH 2/3] undo last commit, fix crash #ANDROID-15102 --- .../java/com/telefonica/tweaks/Tweaks.kt | 30 +++++++++++-------- .../utils/DisposableEffectExtensions.kt | 25 ---------------- 2 files changed, 18 insertions(+), 37 deletions(-) delete mode 100644 library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt diff --git a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt index c00cf19..1d23a0b 100644 --- a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt +++ b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt @@ -5,14 +5,16 @@ import android.annotation.SuppressLint import android.content.Context import android.content.pm.PackageManager import android.hardware.SensorManager -import android.hardware.SensorManager.SENSOR_DELAY_NORMAL import android.os.Build import android.os.VibrationEffect import android.os.Vibrator import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.core.content.ContextCompat import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder @@ -29,7 +31,6 @@ import com.telefonica.tweaks.domain.TweaksBusinessLogic import com.telefonica.tweaks.domain.TweaksGraph import com.telefonica.tweaks.ui.TweaksCategoryScreen import com.telefonica.tweaks.ui.TweaksScreen -import com.telefonica.tweaks.utils.onStart import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map @@ -96,17 +97,22 @@ open class Tweaks : TweaksContract { @Composable fun NavController.navigateToTweaksOnShake() { val context = LocalContext.current - val lifeCycleOwner = LocalLifecycleOwner.current val sensorManager: SensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager - DisposableEffect(true) { - this.onStart(lifeCycleOwner) { - val shakeDetector = ShakeDetector { - vibrateIfAble(context) - navigate(TWEAKS_NAVIGATION_ENTRYPOINT) - } - shakeDetector.start(sensorManager, SENSOR_DELAY_NORMAL) + var shouldNavigate by rememberSaveable { mutableStateOf(false) } + + LaunchedEffect(true) { + val shakeDetector = ShakeDetector { + vibrateIfAble(context) + shouldNavigate = true + } + shakeDetector.start(sensorManager, SensorManager.SENSOR_DELAY_NORMAL) + } + + if (shouldNavigate) { + LaunchedEffect(shouldNavigate) { + navigate(TWEAKS_NAVIGATION_ENTRYPOINT) } } } diff --git a/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt b/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt deleted file mode 100644 index f372731..0000000 --- a/library/src/enabled/java/com/telefonica/tweaks/utils/DisposableEffectExtensions.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.telefonica.tweaks.utils - -import androidx.compose.runtime.DisposableEffectResult -import androidx.compose.runtime.DisposableEffectScope -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleEventObserver -import androidx.lifecycle.LifecycleOwner - - -fun DisposableEffectScope.onStart( - lifeCycleOwner: LifecycleOwner, - onStart: () -> Unit -): DisposableEffectResult { - val observer = LifecycleEventObserver { _, event -> - if (event == Lifecycle.Event.ON_START) { - onStart() - } - } - - lifeCycleOwner.lifecycle.addObserver(observer) - - return onDispose { - lifeCycleOwner.lifecycle.removeObserver(observer) - } -} From 756d57f77ab113230f686dea378918f056d43342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Garci=CC=81a?= Date: Wed, 11 Sep 2024 14:00:05 +0200 Subject: [PATCH 3/3] create new function to navigate on shakes which does not depends on navController #ANDROID-15102 --- README.md | 9 +++++++- .../java/com/telefonica/tweaks/Tweaks.kt | 22 +++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e50e109..19e7b28 100644 --- a/README.md +++ b/README.md @@ -275,10 +275,17 @@ addTweakGraph( ``` ## Shake gesture support: -The tweaks can be opened when the user shakes the device, to do this you need to add to your navigation controller: + +The tweaks can be opened when the user shakes the device. To achieve this, you can either add the following to your navigation controller: ```kotlin navController.navigateToTweaksOnShake() ``` +or call: +```kotlin +NavigateToTweaksOnShake(onOpenTweaks: () -> Unit) +``` +and handle the navigation action yourself. + And also, optionally ```xml diff --git a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt index 1d23a0b..6419242 100644 --- a/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt +++ b/library/src/enabled/java/com/telefonica/tweaks/Tweaks.kt @@ -90,12 +90,24 @@ open class Tweaks : TweaksContract { component.inject(reference) } } +} +@Composable +fun NavController.navigateToTweaksOnShake() { + DetectShakeAndNavigate { + navigate(TWEAKS_NAVIGATION_ENTRYPOINT) + } +} +@Composable +fun NavigateToTweaksOnShake(onOpenTweaks: () -> Unit) { + DetectShakeAndNavigate { + onOpenTweaks() + } } @Composable -fun NavController.navigateToTweaksOnShake() { +private fun DetectShakeAndNavigate(onShakeDetected: () -> Unit) { val context = LocalContext.current val sensorManager: SensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager @@ -110,13 +122,15 @@ fun NavController.navigateToTweaksOnShake() { shakeDetector.start(sensorManager, SensorManager.SENSOR_DELAY_NORMAL) } - if (shouldNavigate) { - LaunchedEffect(shouldNavigate) { - navigate(TWEAKS_NAVIGATION_ENTRYPOINT) + LaunchedEffect(shouldNavigate) { + if (shouldNavigate) { + onShakeDetected() + shouldNavigate = false } } } + @SuppressLint("MissingPermission") private fun vibrateIfAble(context: Context) { if (ContextCompat.checkSelfPermission(