diff --git a/SelfieCam/Features/Camera/Views/ScreenshotCameraPlaceholder.swift b/SelfieCam/Features/Camera/Views/ScreenshotCameraPlaceholder.swift new file mode 100644 index 0000000..b0d2c2e --- /dev/null +++ b/SelfieCam/Features/Camera/Views/ScreenshotCameraPlaceholder.swift @@ -0,0 +1,139 @@ +import SwiftUI +import Bedrock + +struct ScreenshotCameraPlaceholder: View { + let ringWidth: CGFloat + let ringColor: Color + let ringOpacity: Double + + init( + ringWidth: CGFloat = 70, + ringColor: Color = .white, + ringOpacity: Double = 0.7 + ) { + self.ringWidth = ringWidth + self.ringColor = ringColor + self.ringOpacity = ringOpacity + } + + private var backgroundImage: UIImage? { + guard let imageURL = Bundle.main.url(forResource: "image", withExtension: "png") else { + return nil + } + return UIImage(contentsOfFile: imageURL.path) + } + + @ViewBuilder + private func cameraImageLayer(size: CGSize) -> some View { + if let backgroundImage { + Image(uiImage: backgroundImage) + .resizable() + .scaledToFill() + .frame(width: size.width, height: size.height, alignment: .center) + .clipped() + } else { + Color.black + .frame(width: size.width, height: size.height) + } + } + + var body: some View { + GeometryReader { geometry in + let size = geometry.size + ZStack { + cameraImageLayer(size: size) + + ringColor + .opacity(ringOpacity) + .ignoresSafeArea() + + cameraImageLayer(size: size) + .mask { + RoundedRectangle(cornerRadius: Design.CornerRadius.large) + .padding(ringWidth) + } + + PlaceholderGridOverlay(ringWidth: ringWidth) + .allowsHitTesting(false) + + VStack(spacing: 0) { + HStack { + Spacer() + PlaceholderTopButton( + systemImage: "gearshape.fill", + accessibilityLabel: "Settings" + ) + } + .padding(.top, ringWidth + Design.Spacing.medium) + .padding(.trailing, Design.Spacing.medium) + + Spacer() + + VStack(spacing: Design.Spacing.medium) { + ZoomControlView( + zoomFactor: 1.0, + isCenterStageActive: false + ) + CaptureButton(action: { }) + .padding(.bottom, Design.Spacing.large) + } + } + } + } + .ignoresSafeArea() + .accessibilityIdentifier("screenshot-green-screen") + } +} + +private struct PlaceholderTopButton: View { + let systemImage: String + let accessibilityLabel: String + + var body: some View { + Image(systemName: systemImage) + .font(.title3) + .foregroundStyle(.white) + .frame(width: 44, height: 44) + .background(Color.black.opacity(Design.Opacity.medium), in: Circle()) + .overlay { + Circle() + .strokeBorder(Color.white.opacity(Design.Opacity.subtle), lineWidth: Design.LineWidth.thin) + } + .shadow(radius: Design.Shadow.radiusSmall) + .accessibilityLabel(accessibilityLabel) + } +} + +private struct PlaceholderGridOverlay: View { + let ringWidth: CGFloat + + var body: some View { + GeometryReader { geometry in + let insetRect = CGRect( + x: ringWidth, + y: ringWidth, + width: geometry.size.width - (ringWidth * 2), + height: geometry.size.height - (ringWidth * 2) + ) + + Path { path in + for index in 1...2 { + let x = insetRect.minX + (insetRect.width * CGFloat(index) / 3) + path.move(to: CGPoint(x: x, y: insetRect.minY)) + path.addLine(to: CGPoint(x: x, y: insetRect.maxY)) + } + + for index in 1...2 { + let y = insetRect.minY + (insetRect.height * CGFloat(index) / 3) + path.move(to: CGPoint(x: insetRect.minX, y: y)) + path.addLine(to: CGPoint(x: insetRect.maxX, y: y)) + } + } + .stroke(Color.white.opacity(Design.Opacity.subtle), lineWidth: Design.LineWidth.thin) + } + } +} + +#Preview { + ScreenshotCameraPlaceholder(ringWidth: 70.0, ringColor: .white, ringOpacity: 0.7) +}