Aperture: Properly observe / remove observers from LiveDatas

* We don't want to remove all activities observers when we set view
  models in our views

Change-Id: If5069162680a57e040b2411cea6eca01c7991a5c
diff --git a/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt b/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
index 50bdd48..2d18bef 100644
--- a/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
+++ b/app/src/main/java/org/lineageos/aperture/ui/CapturePreviewLayout.kt
@@ -13,6 +13,7 @@
 import android.widget.ImageView
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.isVisible
+import androidx.lifecycle.Observer
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import androidx.media3.common.MediaItem
 import androidx.media3.exoplayer.ExoPlayer
@@ -42,6 +43,10 @@
     private val imageView by lazy { findViewById<ImageView>(R.id.imageView) }
     private val videoView by lazy { findViewById<PlayerView>(R.id.videoView) }
 
+    private val screenRotationObserver = Observer { screenRotation: Rotation ->
+        updateViewsRotation(screenRotation)
+    }
+
     /**
      * input is null == canceled
      * input is not null == confirmed
@@ -50,20 +55,14 @@
 
     internal var cameraViewModel: CameraViewModel? = null
         set(value) {
-            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
-
             // Unregister
-            field?.screenRotation?.removeObservers(lifecycleOwner)
+            field?.screenRotation?.removeObserver(screenRotationObserver)
 
             field = value
 
-            value?.let { cameraViewModel ->
-                cameraViewModel.screenRotation.observe(lifecycleOwner) {
-                    val screenRotation = it ?: return@observe
+            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
 
-                    updateViewsRotation(screenRotation)
-                }
-            }
+            value?.screenRotation?.observe(lifecycleOwner, screenRotationObserver)
         }
     private val screenRotation
         get() = cameraViewModel?.screenRotation?.value ?: Rotation.ROTATION_0
diff --git a/app/src/main/java/org/lineageos/aperture/ui/CountDownView.kt b/app/src/main/java/org/lineageos/aperture/ui/CountDownView.kt
index fe2a7f3..3f11ea7 100644
--- a/app/src/main/java/org/lineageos/aperture/ui/CountDownView.kt
+++ b/app/src/main/java/org/lineageos/aperture/ui/CountDownView.kt
@@ -18,6 +18,7 @@
 import androidx.annotation.IntRange
 import androidx.core.view.isInvisible
 import androidx.core.view.isVisible
+import androidx.lifecycle.Observer
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import org.lineageos.aperture.R
 import org.lineageos.aperture.camera.CameraViewModel
@@ -51,6 +52,10 @@
         }
     }
 
+    private val screenRotationObserver = Observer { screenRotation: Rotation ->
+        updateViewsRotation(screenRotation)
+    }
+
     /**
      * Returns whether countdown is on-going.
      */
@@ -59,20 +64,14 @@
 
     internal var cameraViewModel: CameraViewModel? = null
         set(value) {
-            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
-
             // Unregister
-            field?.screenRotation?.removeObservers(lifecycleOwner)
+            field?.screenRotation?.removeObserver(screenRotationObserver)
 
             field = value
 
-            value?.let { cameraViewModel ->
-                cameraViewModel.screenRotation.observe(lifecycleOwner) {
-                    val screenRotation = it ?: return@observe
+            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
 
-                    updateViewsRotation(screenRotation)
-                }
-            }
+            value?.screenRotation?.observe(lifecycleOwner, screenRotationObserver)
         }
 
     init {
diff --git a/app/src/main/java/org/lineageos/aperture/ui/InfoChipView.kt b/app/src/main/java/org/lineageos/aperture/ui/InfoChipView.kt
index 17b43a6..c28b5af 100644
--- a/app/src/main/java/org/lineageos/aperture/ui/InfoChipView.kt
+++ b/app/src/main/java/org/lineageos/aperture/ui/InfoChipView.kt
@@ -16,6 +16,7 @@
 import androidx.constraintlayout.widget.ConstraintLayout
 import androidx.core.view.isVisible
 import androidx.core.view.updateLayoutParams
+import androidx.lifecycle.Observer
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import org.lineageos.aperture.R
 import org.lineageos.aperture.camera.CameraMode
@@ -37,6 +38,18 @@
         resources.getInteger(android.R.integer.config_shortAnimTime).toLong()
     }
 
+    private val screenRotationObserver = Observer { screenRotation: Rotation ->
+        updateRotation(screenRotation)
+    }
+
+    private val cameraModeObserver = Observer { _: CameraMode ->
+        update()
+    }
+
+    private val videoMicModeObserver = Observer { _: Boolean ->
+        update()
+    }
+
     internal var batteryIntent: Intent? = null
         set(value) {
             field = value
@@ -45,28 +58,18 @@
         }
     internal var cameraViewModel: CameraViewModel? = null
         set(value) {
-            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
-
-            field?.let {
-                // Unregister
-                it.screenRotation.removeObservers(lifecycleOwner)
-                it.cameraMode.removeObservers(lifecycleOwner)
-                it.videoMicMode.removeObservers(lifecycleOwner)
-            }
+            // Unregister
+            field?.screenRotation?.removeObserver(screenRotationObserver)
+            field?.cameraMode?.removeObserver(cameraModeObserver)
+            field?.videoMicMode?.removeObserver(videoMicModeObserver)
 
             field = value
 
-            value?.let { cameraViewModel ->
-                cameraViewModel.screenRotation.observe(lifecycleOwner) {
-                    updateRotation()
-                }
-                cameraViewModel.cameraMode.observe(lifecycleOwner) {
-                    update()
-                }
-                cameraViewModel.videoMicMode.observe(lifecycleOwner) {
-                    update()
-                }
-            }
+            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
+
+            value?.screenRotation?.observe(lifecycleOwner, screenRotationObserver)
+            value?.cameraMode?.observe(lifecycleOwner, cameraModeObserver)
+            value?.videoMicMode?.observe(lifecycleOwner, videoMicModeObserver)
         }
 
     init {
@@ -77,6 +80,7 @@
         val cameraViewModel = cameraViewModel ?: return
 
         val cameraMode = cameraViewModel.cameraMode.value ?: return
+        val screenRotation = cameraViewModel.screenRotation.value ?: return
         val videoMicMode = cameraViewModel.videoMicMode.value ?: return
 
         // Get the new visibility values
@@ -100,7 +104,7 @@
             lowBatteryImageView.isVisible = lowBatteryImageViewVisible
             videoMicMutedImageView.isVisible = videoMicMutedImageViewVisible
 
-            updateRotation()
+            updateRotation(screenRotation)
         }
 
         if (shouldBeVisible && !isVisible) {
@@ -133,11 +137,7 @@
         }
     }
 
-    private fun updateRotation() {
-        val cameraViewModel = cameraViewModel ?: return
-
-        val screenRotation = cameraViewModel.screenRotation.value ?: return
-
+    private fun updateRotation(screenRotation: Rotation) {
         val compensationValue = screenRotation.compensationValue.toFloat()
 
         updateLayoutParams<LayoutParams> {
diff --git a/app/src/main/java/org/lineageos/aperture/ui/LensSelectorLayout.kt b/app/src/main/java/org/lineageos/aperture/ui/LensSelectorLayout.kt
index 5fcf155..9149d7a 100644
--- a/app/src/main/java/org/lineageos/aperture/ui/LensSelectorLayout.kt
+++ b/app/src/main/java/org/lineageos/aperture/ui/LensSelectorLayout.kt
@@ -14,6 +14,7 @@
 import androidx.appcompat.widget.LinearLayoutCompat
 import androidx.core.view.children
 import androidx.core.view.setMargins
+import androidx.lifecycle.Observer
 import androidx.lifecycle.findViewTreeLifecycleOwner
 import org.lineageos.aperture.R
 import org.lineageos.aperture.camera.Camera
@@ -39,33 +40,31 @@
     private val buttonToCamera = mutableMapOf<Button, Camera>()
     private val buttonToZoomRatio = mutableMapOf<Button, Float>()
 
+    private val cameraStateObserver = Observer { cameraState: CameraState ->
+        children.forEach { view ->
+            view.isSoundEffectsEnabled = cameraState == CameraState.IDLE
+        }
+    }
+
+    private val screenRotationObserver = Observer { screenRotation: Rotation ->
+        updateViewsRotation(screenRotation)
+    }
+
     var onCameraChangeCallback: (camera: Camera) -> Unit = {}
     var onZoomRatioChangeCallback: (zoomRatio: Float) -> Unit = {}
 
     internal var cameraViewModel: CameraViewModel? = null
         set(value) {
-            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
-
             // Unregister
-            field?.cameraState?.removeObservers(lifecycleOwner)
-            field?.screenRotation?.removeObservers(lifecycleOwner)
+            field?.cameraState?.removeObserver(cameraStateObserver)
+            field?.screenRotation?.removeObserver(screenRotationObserver)
 
             field = value
 
-            value?.let { cameraViewModel ->
-                cameraViewModel.cameraState.observe(lifecycleOwner) {
-                    val cameraState = it ?: return@observe
+            val lifecycleOwner = findViewTreeLifecycleOwner() ?: return
 
-                    children.forEach { view ->
-                        view.isSoundEffectsEnabled = cameraState == CameraState.IDLE
-                    }
-                }
-                cameraViewModel.screenRotation.observe(lifecycleOwner) {
-                    val screenRotation = it ?: return@observe
-
-                    updateViewsRotation(screenRotation)
-                }
-            }
+            value?.cameraState?.observe(lifecycleOwner, cameraStateObserver)
+            value?.screenRotation?.observe(lifecycleOwner, screenRotationObserver)
         }
     private val screenRotation
         get() = cameraViewModel?.screenRotation?.value ?: Rotation.ROTATION_0