mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 23:24:32 +00:00
122 lines
4.8 KiB
Swift
122 lines
4.8 KiB
Swift
//
|
|
// WebcamView.swift
|
|
// DynamicIsland
|
|
//
|
|
// Created by Harsh Vardhan Goswami on 19/08/24.
|
|
//
|
|
|
|
import AVFoundation
|
|
import Defaults
|
|
import SwiftUI
|
|
|
|
struct CameraPreviewView: View {
|
|
@EnvironmentObject var vm: DynamicIslandViewModel
|
|
@ObservedObject var webcamManager: WebcamManager
|
|
|
|
// Track if authorization request is in progress to avoid multiple requests
|
|
@State private var isRequestingAuthorization: Bool = false
|
|
|
|
var body: some View {
|
|
GeometryReader { geometry in
|
|
ZStack {
|
|
if let previewLayer = webcamManager.previewLayer {
|
|
CameraPreviewLayerView(previewLayer: previewLayer)
|
|
.scaleEffect(x: -1, y: 1)
|
|
.clipShape(RoundedRectangle(cornerRadius: Defaults[.mirrorShape] == .rectangle ? !Defaults[.cornerRadiusScaling] ? MusicPlayerImageSizes.cornerRadiusInset.closed : MusicPlayerImageSizes.cornerRadiusInset.opened : 100))
|
|
.frame(width: geometry.size.width, height: geometry.size.width)
|
|
.opacity(webcamManager.isSessionRunning ? 1 : 0)
|
|
}
|
|
|
|
if !webcamManager.isSessionRunning {
|
|
ZStack {
|
|
RoundedRectangle(cornerRadius: Defaults[.mirrorShape] == .rectangle ? !Defaults[.cornerRadiusScaling] ? MusicPlayerImageSizes.cornerRadiusInset.closed : 12 : 100)
|
|
.fill(Color(red: 20/255, green: 20/255, blue: 20/255))
|
|
.strokeBorder(.white.opacity(0.04), lineWidth: 1)
|
|
.frame(width: geometry.size.width, height: geometry.size.width)
|
|
VStack(spacing: 8) {
|
|
Image(systemName: webcamManager.authorizationStatus == .denied ? "exclamationmark.triangle" : "web.camera")
|
|
.foregroundStyle(.gray)
|
|
.font(.system(size: geometry.size.width/3.5))
|
|
Text(webcamManager.authorizationStatus == .denied ? "Access Denied" : "Mirror")
|
|
.font(.caption2)
|
|
.foregroundColor(.gray)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.onTapGesture {
|
|
handleCameraTap()
|
|
}
|
|
.onDisappear {
|
|
webcamManager.stopSession()
|
|
}
|
|
}
|
|
.aspectRatio(1, contentMode: .fit)
|
|
}
|
|
|
|
private func handleCameraTap() {
|
|
if isRequestingAuthorization {
|
|
return // Prevent multiple authorization requests
|
|
}
|
|
|
|
switch webcamManager.authorizationStatus {
|
|
case .authorized:
|
|
if webcamManager.isSessionRunning {
|
|
webcamManager.stopSession()
|
|
} else if webcamManager.cameraAvailable {
|
|
webcamManager.startSession()
|
|
}
|
|
case .denied, .restricted:
|
|
DispatchQueue.main.async {
|
|
NSApp.setActivationPolicy(.regular)
|
|
NSApp.activate(ignoringOtherApps: true)
|
|
let alert = NSAlert()
|
|
alert.messageText = "Camera Access Required"
|
|
alert.informativeText = "Please allow camera access in System Settings to use the mirror feature."
|
|
alert.addButton(withTitle: "Open Settings")
|
|
alert.addButton(withTitle: "Cancel")
|
|
|
|
if alert.runModal() == .alertFirstButtonReturn {
|
|
if let settingsURL = URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Camera") {
|
|
NSWorkspace.shared.open(settingsURL)
|
|
}
|
|
}
|
|
NSApp.setActivationPolicy(.accessory)
|
|
NSApp.deactivate()
|
|
}
|
|
case .notDetermined:
|
|
isRequestingAuthorization = true
|
|
webcamManager.checkAndRequestVideoAuthorization()
|
|
// Reset the request flag after a reasonable delay
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
isRequestingAuthorization = false
|
|
}
|
|
@unknown default:
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
struct CameraPreviewLayerView: NSViewRepresentable {
|
|
let previewLayer: AVCaptureVideoPreviewLayer
|
|
|
|
func makeNSView(context: Context) -> NSView {
|
|
let view = NSView(frame: .zero)
|
|
previewLayer.frame = view.bounds
|
|
previewLayer.videoGravity = .resizeAspectFill
|
|
view.layer = previewLayer
|
|
view.wantsLayer = true
|
|
return view
|
|
}
|
|
|
|
func updateNSView(_ nsView: NSView, context: Context) {
|
|
CATransaction.begin()
|
|
CATransaction.setDisableActions(true)
|
|
previewLayer.frame = nsView.bounds
|
|
CATransaction.commit()
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
CameraPreviewView(webcamManager: WebcamManager.shared)
|
|
}
|