128 lines
3.7 KiB
Swift
128 lines
3.7 KiB
Swift
|
import SwiftUI
|
||
|
import SFSafeSymbols
|
||
|
|
||
|
struct CameraView: View {
|
||
|
|
||
|
static let cameraImagePadding: CGFloat = 300
|
||
|
|
||
|
private static let circleSize: CGFloat = 180
|
||
|
private var circleSize: CGFloat {
|
||
|
CameraView.circleSize
|
||
|
}
|
||
|
|
||
|
static var circleCropFactor: CGFloat {
|
||
|
let fullWidth = UIScreen.main.bounds.width + 2 * cameraImagePadding
|
||
|
return circleSize / fullWidth
|
||
|
}
|
||
|
|
||
|
private let circleStrength: CGFloat = 3
|
||
|
|
||
|
private let circleColor: Color = .green
|
||
|
|
||
|
private let captureButtonSize: CGFloat = 110
|
||
|
private let captureButtonHeight: CGFloat = 40
|
||
|
private let captureButtonWidth: CGFloat = 50
|
||
|
|
||
|
private let cancelButtonSize: CGFloat = 75
|
||
|
private let cancelIconSize: CGFloat = 25
|
||
|
|
||
|
@Binding
|
||
|
var isPresented: Bool
|
||
|
|
||
|
@Binding
|
||
|
var image: UIImage?
|
||
|
|
||
|
@Binding
|
||
|
var capId: Int?
|
||
|
|
||
|
@StateObject
|
||
|
private var model = ContentViewModel()
|
||
|
|
||
|
@EnvironmentObject
|
||
|
var database: Database
|
||
|
|
||
|
var body: some View {
|
||
|
ZStack {
|
||
|
FrameView(image: model.frame)
|
||
|
.edgesIgnoringSafeArea(.all)
|
||
|
.padding(-CameraView.cameraImagePadding)
|
||
|
|
||
|
ErrorView(error: model.error)
|
||
|
VStack {
|
||
|
Spacer()
|
||
|
HStack {
|
||
|
Spacer()
|
||
|
Button(action: dismiss) {
|
||
|
Image(systemSymbol: .xmark)
|
||
|
.resizable()
|
||
|
.frame(width: cancelIconSize, height: cancelIconSize)
|
||
|
.padding((cancelButtonSize-cancelIconSize)/2)
|
||
|
.background(.thinMaterial)
|
||
|
.cornerRadius(cancelButtonSize/2)
|
||
|
}.padding()
|
||
|
}
|
||
|
}
|
||
|
VStack {
|
||
|
Spacer()
|
||
|
HStack {
|
||
|
Spacer()
|
||
|
Button(action: capture) {
|
||
|
Image(systemSymbol: .camera)
|
||
|
.resizable()
|
||
|
.frame(width: captureButtonWidth, height: captureButtonHeight)
|
||
|
.padding(.horizontal, (captureButtonSize - captureButtonWidth)/2)
|
||
|
.padding(.vertical, (captureButtonSize - captureButtonHeight)/2)
|
||
|
.background(.thinMaterial)
|
||
|
.cornerRadius(captureButtonSize / 2)
|
||
|
}.padding()
|
||
|
Spacer()
|
||
|
}
|
||
|
}
|
||
|
VStack {
|
||
|
Spacer()
|
||
|
HStack {
|
||
|
Spacer()
|
||
|
Text("")
|
||
|
.frame(width: circleSize, height: circleSize, alignment: .center)
|
||
|
.overlay(RoundedRectangle(cornerRadius: circleSize/2)
|
||
|
.stroke(lineWidth: circleStrength)
|
||
|
.foregroundColor(circleColor))
|
||
|
|
||
|
Spacer()
|
||
|
}
|
||
|
Spacer()
|
||
|
}.ignoresSafeArea()
|
||
|
|
||
|
}
|
||
|
.onAppear() {
|
||
|
model.startCapture()
|
||
|
}
|
||
|
.onDisappear {
|
||
|
model.endCapture()
|
||
|
}.onChange(of: model.image) { image in
|
||
|
if let capId = capId, let image = image {
|
||
|
database.save(image, for: capId)
|
||
|
} else {
|
||
|
database.image = image
|
||
|
}
|
||
|
dismiss()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private func dismiss() {
|
||
|
isPresented = false
|
||
|
}
|
||
|
|
||
|
private func capture() {
|
||
|
model.captureImage()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct CameraView_Previews: PreviewProvider {
|
||
|
static var previews: some View {
|
||
|
CameraView(isPresented: .constant(true),
|
||
|
image: .constant(nil),
|
||
|
capId: .constant(nil))
|
||
|
}
|
||
|
}
|