davidliu
Committed by GitHub

Fix ScaleZoomHelper to properly handle multiple zoom actions (#429)

@@ -23,6 +23,7 @@ import android.view.ScaleGestureDetector @@ -23,6 +23,7 @@ import android.view.ScaleGestureDetector
23 import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener 23 import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener
24 import androidx.camera.core.Camera 24 import androidx.camera.core.Camera
25 import androidx.camera.core.CameraControl 25 import androidx.camera.core.CameraControl
  26 +import com.google.common.util.concurrent.ListenableFuture
26 import io.livekit.android.camerax.ui.ScaleZoomHelper.Companion.createGestureDetector 27 import io.livekit.android.camerax.ui.ScaleZoomHelper.Companion.createGestureDetector
27 import io.livekit.android.room.track.LocalVideoTrack 28 import io.livekit.android.room.track.LocalVideoTrack
28 import io.livekit.android.util.LKLog 29 import io.livekit.android.util.LKLog
@@ -71,9 +72,17 @@ class ScaleZoomHelper( @@ -71,9 +72,17 @@ class ScaleZoomHelper(
71 } 72 }
72 } 73 }
73 74
  75 + /**
  76 + * Track the current target zoom, since cameraInfo.zoomState is on LiveData timers and can be out of date.
  77 + */
74 private var targetZoom: Float? = null 78 private var targetZoom: Float? = null
75 79
76 /** 80 /**
  81 + * Track the current active zoom futures; only clear targetZoom when all futures are completed.
  82 + */
  83 + private var activeZoomFutures = mutableSetOf<ListenableFuture<Void>>()
  84 +
  85 + /**
77 * Scales the current zoom value by [factor]. 86 * Scales the current zoom value by [factor].
78 * 87 *
79 * This method handles clamping the resulting zoom value to within the camera's 88 * This method handles clamping the resulting zoom value to within the camera's
@@ -92,15 +101,20 @@ class ScaleZoomHelper( @@ -92,15 +101,20 @@ class ScaleZoomHelper(
92 101
93 if (newZoom != currentZoom) { 102 if (newZoom != currentZoom) {
94 targetZoom = newZoom 103 targetZoom = newZoom
95 - camera.cameraControl.setZoomRatio(newZoom)  
96 - .addListener(  
97 - {  
98 - synchronized(this) { 104 + val future = camera.cameraControl.setZoomRatio(newZoom)
  105 +
  106 + activeZoomFutures.add(future)
  107 + future.addListener(
  108 + {
  109 + synchronized(this) {
  110 + activeZoomFutures.remove(future)
  111 + if (activeZoomFutures.isEmpty()) {
99 targetZoom = null 112 targetZoom = null
100 } 113 }
101 - },  
102 - { it.run() },  
103 - ) 114 + }
  115 + },
  116 + { it.run() },
  117 + )
104 } 118 }
105 } 119 }
106 120