diff --git a/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift b/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift index 0b42317..e438d86 100644 --- a/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift +++ b/SelfieCam/Features/Camera/Views/CustomCameraScreen.swift @@ -31,6 +31,10 @@ struct CustomCameraScreen: MCameraScreen { @State private var isShowingScreenFlash: Bool = false @State private var originalBrightness: CGFloat = UIScreen.main.brightness + // Timer countdown state + @State private var countdownSeconds: Int = 0 + @State private var isCountdownActive: Bool = false + // Pinch to zoom gesture state @GestureState private var magnification: CGFloat = 1.0 @State private var lastMagnification: CGFloat = 1.0 @@ -95,8 +99,21 @@ struct CustomCameraScreen: MCameraScreen { isCenterStageActive: cameraSettings.isCenterStageEnabled ) - // Capture Button + // Capture Button with timer indicator badge CaptureButton(action: { performCapture() }) + .overlay(alignment: .bottomTrailing) { + if cameraSettings.selectedTimer.seconds > 0 { + ZStack { + Circle() + .fill(Color.black.opacity(Design.Opacity.accent)) + .frame(width: 24, height: 24) + Text(cameraSettings.selectedTimer.displayName) + .font(.system(size: 10, weight: .bold)) + .foregroundColor(.white) + } + .offset(x: 4, y: 4) + } + } .padding(.bottom, Design.Spacing.large) } .padding(.horizontal, Design.Spacing.large) @@ -106,6 +123,26 @@ struct CustomCameraScreen: MCameraScreen { + // Countdown overlay + if isCountdownActive { + ZStack { + Color.black.opacity(0.3) + .ignoresSafeArea() + + VStack { + Text("\(countdownSeconds)") + .font(.system(size: 120, weight: .bold, design: .rounded)) + .foregroundColor(.white) + .shadow(radius: 10) + + Text("Get ready!") + .font(.title2) + .foregroundColor(.white.opacity(0.8)) + } + } + .transition(.opacity) + } + // Screen flash overlay for front camera if isShowingScreenFlash { screenFlashColor @@ -114,6 +151,7 @@ struct CustomCameraScreen: MCameraScreen { } } .animation(.easeInOut(duration: 0.05), value: isShowingScreenFlash) + .animation(.easeInOut(duration: 0.3), value: isCountdownActive) .onAppear { // Set flash mode from saved settings setFlashMode(cameraSettings.flashMode.toMijickFlashMode) @@ -162,9 +200,40 @@ struct CustomCameraScreen: MCameraScreen { cameraPosition == .front && cameraSettings.flashMode != .off && cameraSettings.isFlashSyncedWithRingLight } - /// Performs capture with screen flash if needed + /// Performs capture with timer countdown and screen flash if needed private func performCapture() { - print("performCapture called - shouldUseCustomScreenFlash: \(shouldUseCustomScreenFlash)") + // Check if timer is enabled + let timerSeconds = cameraSettings.selectedTimer.seconds + + if timerSeconds > 0 && !isCountdownActive { + // Start countdown + startCountdown(seconds: timerSeconds) + } else if !isCountdownActive { + // No timer or countdown already running, proceed with capture + performActualCapture() + } + } + + /// Starts the countdown timer + private func startCountdown(seconds: Int) { + countdownSeconds = seconds + isCountdownActive = true + + Task { @MainActor in + while countdownSeconds > 0 { + try? await Task.sleep(for: .seconds(1)) + countdownSeconds -= 1 + } + + // Countdown finished, perform capture + isCountdownActive = false + performActualCapture() + } + } + + /// Performs the actual capture with screen flash if needed + private func performActualCapture() { + print("performActualCapture called - shouldUseCustomScreenFlash: \(shouldUseCustomScreenFlash)") if shouldUseCustomScreenFlash { // Save original brightness and boost to max originalBrightness = UIScreen.main.brightness diff --git a/SelfieCam/Resources/Localizable.xcstrings b/SelfieCam/Resources/Localizable.xcstrings index abb5498..dfd8236 100644 --- a/SelfieCam/Resources/Localizable.xcstrings +++ b/SelfieCam/Resources/Localizable.xcstrings @@ -210,6 +210,10 @@ "comment" : "Title of a toggle in the Settings view that controls whether the front flash is enabled.", "isCommentAutoGenerated" : true }, + "Get ready!" : { + "comment" : "A text displayed in the countdown overlay when a photo is about to be taken.", + "isCommentAutoGenerated" : true + }, "Go Pro" : { "comment" : "The title of the \"Go Pro\" button in the Pro paywall.", "isCommentAutoGenerated" : true