Propagate camera binding errors to UI

Add an error StateFlow to CameraManager so camera binding failures
are surfaced to the user instead of silently swallowed by
e.printStackTrace(). CameraScreen collects this flow and displays
errors using the existing red overlay UI. Added Log.e with proper
TAG for logcat visibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2026-02-27 15:21:38 +01:00
commit 6ed3e8e7b5
2 changed files with 25 additions and 2 deletions

View file

@ -2,6 +2,7 @@ package no.naiv.tiltshift.camera
import android.content.Context import android.content.Context
import android.graphics.SurfaceTexture import android.graphics.SurfaceTexture
import android.util.Log
import android.util.Size import android.util.Size
import android.view.Surface import android.view.Surface
import androidx.camera.core.Camera import androidx.camera.core.Camera
@ -24,6 +25,10 @@ import java.util.concurrent.Executor
*/ */
class CameraManager(private val context: Context) { class CameraManager(private val context: Context) {
companion object {
private const val TAG = "CameraManager"
}
private var cameraProvider: ProcessCameraProvider? = null private var cameraProvider: ProcessCameraProvider? = null
private var camera: Camera? = null private var camera: Camera? = null
private var preview: Preview? = null private var preview: Preview? = null
@ -32,6 +37,13 @@ class CameraManager(private val context: Context) {
val lensController = LensController() val lensController = LensController()
private val _error = MutableStateFlow<String?>(null)
val error: StateFlow<String?> = _error.asStateFlow()
fun clearError() {
_error.value = null
}
private val _zoomRatio = MutableStateFlow(1.0f) private val _zoomRatio = MutableStateFlow(1.0f)
val zoomRatio: StateFlow<Float> = _zoomRatio.asStateFlow() val zoomRatio: StateFlow<Float> = _zoomRatio.asStateFlow()
@ -117,8 +129,8 @@ class CameraManager(private val context: Context) {
} }
} catch (e: Exception) { } catch (e: Exception) {
// Camera binding failed Log.e(TAG, "Camera binding failed", e)
e.printStackTrace() _error.value = "Camera failed: ${e.message}"
} }
} }

View file

@ -104,6 +104,17 @@ fun CameraScreen(
val minZoom by cameraManager.minZoomRatio.collectAsState() val minZoom by cameraManager.minZoomRatio.collectAsState()
val maxZoom by cameraManager.maxZoomRatio.collectAsState() val maxZoom by cameraManager.maxZoomRatio.collectAsState()
val isFrontCamera by cameraManager.isFrontCamera.collectAsState() val isFrontCamera by cameraManager.isFrontCamera.collectAsState()
val cameraError by cameraManager.error.collectAsState()
// Show camera errors via the existing error UI
LaunchedEffect(cameraError) {
cameraError?.let { message ->
showSaveError = message
cameraManager.clearError()
delay(2000)
showSaveError = null
}
}
// Collect orientation updates // Collect orientation updates
LaunchedEffect(Unit) { LaunchedEffect(Unit) {