diff --git a/SelfieCam.xcodeproj/project.xcworkspace/xcuserdata/mattbruce.xcuserdatad/UserInterfaceState.xcuserstate b/SelfieCam.xcodeproj/project.xcworkspace/xcuserdata/mattbruce.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..1f5e733 Binary files /dev/null and b/SelfieCam.xcodeproj/project.xcworkspace/xcuserdata/mattbruce.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/SelfieCam/Features/Camera/Views/ContentView.swift b/SelfieCam/Features/Camera/Views/ContentView.swift index f19985c..fd050d5 100644 --- a/SelfieCam/Features/Camera/Views/ContentView.swift +++ b/SelfieCam/Features/Camera/Views/ContentView.swift @@ -61,7 +61,11 @@ struct ContentView: View { } } .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.BrandColors.primary.ignoresSafeArea()) + // Background matches ring light color so rotation transitions are seamless + .background( + (settings.isRingLightEnabled ? settings.lightColor.opacity(settings.ringLightOpacity) : Color.black) + .ignoresSafeArea() + ) // Settings button overlay - only show when NOT in photo review mode .overlay(alignment: .topTrailing) { if !showPhotoReview { @@ -191,9 +195,9 @@ struct CameraContainerView: View, Equatable { let cameraPosition: CameraPosition let onImageCaptured: (UIImage) -> Void - // Only compare sessionKey for equality - ignore settings and callback changes + // Only compare sessionKey and cameraPosition for equality static func == (lhs: CameraContainerView, rhs: CameraContainerView) -> Bool { - lhs.sessionKey == rhs.sessionKey + lhs.sessionKey == rhs.sessionKey && lhs.cameraPosition == rhs.cameraPosition } var body: some View { diff --git a/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift b/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift index 3347afd..00ff53a 100644 --- a/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift +++ b/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift @@ -341,21 +341,30 @@ struct CustomCameraScreen: MCameraScreen { print("performActualCapture called - shouldUseCustomScreenFlash: \(shouldUseCustomScreenFlash)") if shouldUseCustomScreenFlash { - // Save original brightness and boost to max - originalBrightness = UIScreen.main.brightness - UIScreen.main.brightness = 1.0 - - // Show flash overlay - isShowingScreenFlash = true - - // Wait for camera to adjust to bright screen, then capture + // Emulate iPhone Retina Flash behavior: + // 1. Pre-flash (briefly show flash to let camera adjust exposure) + // 2. Sustain (peak brightness for capture) + // 3. Capture (timed during sustain) + Task { @MainActor in - try? await Task.sleep(for: .milliseconds(150)) - print("Calling captureOutput() with custom flash") + // Save original brightness + originalBrightness = UIScreen.main.brightness + + // 1. Pre-flash: Boost brightness and show overlay briefly + UIScreen.main.brightness = 1.0 + isShowingScreenFlash = true + + // Brief pre-flash duration to let auto-exposure settle + try? await Task.sleep(for: .milliseconds(200)) + + // 2. Sustain & 3. Capture + print("Calling captureOutput() during sustain phase") captureOutput() - - // Keep flash visible briefly after capture - try? await Task.sleep(for: .milliseconds(100)) + + // Keep flash visible briefly after capture to avoid abrupt cut-off + try? await Task.sleep(for: .milliseconds(150)) + + // Cleanup isShowingScreenFlash = false UIScreen.main.brightness = originalBrightness }