Skip to content

Commit

Permalink
Patch 2.1.1
Browse files Browse the repository at this point in the history
fix: 
- Fixed a problem with the tap and zoom gestures not working in release build configuration (#52)
- Fixed an issue with icons not loading in the latest iOS version (#48)
- Fixed an issue with camera output rotation when camera rotation is locked (#40)
  • Loading branch information
FulcrumOne authored Nov 22, 2024
1 parent 0ff7c42 commit 024ebee
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 76 deletions.
11 changes: 11 additions & 0 deletions Sources/Internal/Extensions/AVCaptureVideoOrientation++.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,14 @@ extension AVCaptureVideoOrientation {
default: .up
}}
}

// MARK: - To UIDeviceOrientation
extension AVCaptureVideoOrientation {
func toDeviceOrientation() -> UIDeviceOrientation { switch self {
case .portrait: .portrait
case .portraitUpsideDown: .portraitUpsideDown
case .landscapeLeft: .landscapeLeft
case .landscapeRight: .landscapeRight
default: .portrait
}}
}
7 changes: 6 additions & 1 deletion Sources/Internal/Extensions/Bundle++.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,10 @@
import Foundation

extension Bundle {
static var mijick: Bundle { .init(identifier: "MijickCameraView-MijickCameraView-resources") ?? .main }
static var mijick: Bundle {
.allBundles
.compactMap { $0.resourceURL?.appendingPathComponent("MijickCameraView_MijickCameraView", isDirectory: false).appendingPathExtension("bundle") }
.compactMap { Bundle(url: $0) }
.first ?? .main
}
}
41 changes: 26 additions & 15 deletions Sources/Internal/Managers/CameraManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ private extension CameraManager {
cameraMetalView = nil
cameraGridView = nil
cameraBlurView = nil
cameraFocusView = .init()
cameraFocusView = .create(image: .iconCrosshair, tintColor: .yellow, size: 92)
motionManager = .init()
}
func removeObservers() {
Expand Down Expand Up @@ -305,18 +305,6 @@ extension CameraManager {
}
}

// MARK: - Camera Rotation
extension CameraManager {
func fixCameraRotation() { if !orientationLocked {
redrawGrid()
}}
}
private extension CameraManager {
func redrawGrid() {
cameraGridView?.draw(.zero)
}
}

// MARK: - Changing Output Type
extension CameraManager {
func changeOutputType(_ newOutputType: CameraOutputType) throws { if newOutputType != attributes.outputType && !isChanging {
Expand Down Expand Up @@ -398,7 +386,7 @@ private extension CameraManager {
animateCameraFocusView()
}}
func setCameraFocus(_ touchPoint: CGPoint, _ device: AVCaptureDevice) throws {
let focusPoint = cameraLayer.captureDevicePointConverted(fromLayerPoint: touchPoint)
let focusPoint = convertTouchPointToFocusPoint(touchPoint)
try configureCameraFocus(focusPoint, device)
}
}
Expand All @@ -417,6 +405,10 @@ private extension CameraManager {
UIView.animate(withDuration: 0.5, delay: 3.5) { [self] in cameraFocusView.alpha = 0 }
}
}
func convertTouchPointToFocusPoint(_ touchPoint: CGPoint) -> CGPoint { .init(
x: touchPoint.y / cameraView.frame.height,
y: 1 - touchPoint.x / cameraView.frame.width
)}
func configureCameraFocus(_ focusPoint: CGPoint, _ device: AVCaptureDevice) throws { try withLockingDeviceForConfiguration(device) { device in
setFocusPointOfInterest(focusPoint, device)
setExposurePointOfInterest(focusPoint, device)
Expand Down Expand Up @@ -684,7 +676,22 @@ private extension CameraManager {

extension CameraManager: AVCapturePhotoCaptureDelegate {
public func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: (any Swift.Error)?) {
attributes.capturedMedia = .create(imageData: photo, orientation: frameOrientation, filters: attributes.cameraFilters)
attributes.capturedMedia = .create(imageData: photo, orientation: fixedFrameOrientation(), filters: attributes.cameraFilters)
}
}
private extension CameraManager {
func fixedFrameOrientation() -> CGImagePropertyOrientation { guard UIDevice.current.orientation != attributes.deviceOrientation.toDeviceOrientation() else { return frameOrientation }
return switch (attributes.deviceOrientation, attributes.cameraPosition) {
case (.portrait, .front): .left
case (.portrait, .back): .right
case (.landscapeLeft, .back): .down
case (.landscapeRight, .back): .up
case (.landscapeLeft, .front) where attributes.mirrorOutput: .up
case (.landscapeLeft, .front): .upMirrored
case (.landscapeRight, .front) where attributes.mirrorOutput: .down
case (.landscapeRight, .front): .downMirrored
default: .right
}
}
}

Expand Down Expand Up @@ -751,6 +758,7 @@ private extension CameraManager {
updateDeviceOrientation(newDeviceOrientation)
updateUserBlockedScreenRotation()
updateFrameOrientation()
redrawGrid()
}}
}
private extension CameraManager {
Expand All @@ -772,6 +780,9 @@ private extension CameraManager {
let newFrameOrientation = getNewFrameOrientation(orientationLocked ? .portrait : UIDevice.current.orientation)
updateFrameOrientation(newFrameOrientation)
}}
func redrawGrid() { if !orientationLocked {
cameraGridView?.draw(.zero)
}}
}
private extension CameraManager {
func getNewUserBlockedScreenRotation() -> Bool { switch attributes.deviceOrientation.rawValue == UIDevice.current.orientation.rawValue {
Expand Down
102 changes: 43 additions & 59 deletions Sources/Internal/Views/Main/CameraInputBridgeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,84 +11,68 @@

import SwiftUI

struct CameraInputBridgeView: UIViewRepresentable {
struct CameraInputBridgeView {
let cameraManager: CameraManager
private var inputView: UICameraInputView = .init()

init(_ cameraManager: CameraManager) { self.cameraManager = cameraManager }
}
extension CameraInputBridgeView {
func makeUIView(context: Context) -> some UIView {
inputView.cameraManager = cameraManager
return inputView.view
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
}
extension CameraInputBridgeView: Equatable {
static func == (lhs: Self, rhs: Self) -> Bool { true }
let inputView: UIView = .init()
}


// MARK: - UIViewController
fileprivate class UICameraInputView: UIViewController {
var cameraManager: CameraManager!
// MARK: - PROTOCOLS CONFORMANCE


override func viewDidLoad() {
super.viewDidLoad()

// MARK: UIViewRepresentable
extension CameraInputBridgeView: UIViewRepresentable {
func makeUIView(context: Context) -> some UIView {
setupCameraManager()
setupTapGesture()
setupPinchGesture()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

cameraManager.fixCameraRotation()
setupTapGesture(context)
setupPinchGesture(context)
return inputView
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
func makeCoordinator() -> Coordinator { .init(self) }
}

// MARK: - Setup
private extension UICameraInputView {
private extension CameraInputBridgeView {
func setupCameraManager() {
cameraManager.setup(in: view)
cameraManager.setup(in: inputView)
}
func setupTapGesture() {
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
view.addGestureRecognizer(tapRecognizer)
func setupTapGesture(_ context: Context) {
let tapRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.onTapGesture))
inputView.addGestureRecognizer(tapRecognizer)
}
func setupPinchGesture() {
let pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture))
view.addGestureRecognizer(pinchRecognizer)
func setupPinchGesture(_ context: Context) {
let pinchRecognizer = UIPinchGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.onPinchGesture))
inputView.addGestureRecognizer(pinchRecognizer)
}
}

// MARK: - Gestures

// MARK: Tap
private extension UICameraInputView {
@objc func handleTapGesture(_ tap: UITapGestureRecognizer) {
let touchPoint = tap.location(in: view)
setCameraFocus(touchPoint)
}
// MARK: Equatable
extension CameraInputBridgeView: Equatable {
static func ==(lhs: Self, rhs: Self) -> Bool { true }
}
private extension UICameraInputView {
func setCameraFocus(_ touchPoint: CGPoint) {
do { try cameraManager.setCameraFocus(touchPoint) }
catch {}


// MARK: - LOGIC
extension CameraInputBridgeView { class Coordinator: NSObject { init(_ parent: CameraInputBridgeView) { self.parent = parent }
let parent: CameraInputBridgeView
}}

// MARK: On Tap
extension CameraInputBridgeView.Coordinator {
@objc func onTapGesture(_ tap: UITapGestureRecognizer) {
do {
let touchPoint = tap.location(in: parent.inputView)
try parent.cameraManager.setCameraFocus(touchPoint)
} catch {}
}
}

// MARK: Pinch
private extension UICameraInputView {
@objc func handlePinchGesture(_ pinch: UIPinchGestureRecognizer) { if pinch.state == .changed {
let desiredZoomFactor = cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33)
changeZoomFactor(desiredZoomFactor)
// MARK: On Pinch
extension CameraInputBridgeView.Coordinator {
@objc func onPinchGesture(_ pinch: UIPinchGestureRecognizer) { if pinch.state == .changed {
do {
let desiredZoomFactor = parent.cameraManager.attributes.zoomFactor + atan2(pinch.velocity, 33)
try parent.cameraManager.changeZoomFactor(desiredZoomFactor)
} catch {}
}}
}
private extension UICameraInputView {
func changeZoomFactor(_ desiredZoomFactor: CGFloat) {
do { try cameraManager.changeZoomFactor(desiredZoomFactor) }
catch {}
}
}
2 changes: 1 addition & 1 deletion Sources/Public/View Protocols/Public+MCameraView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public protocol MCameraView: View {

// MARK: - Use-only View Methods
public extension MCameraView {
func createCameraView() -> some View { CameraInputBridgeView(cameraManager).equatable() }
func createCameraView() -> some View { CameraInputBridgeView(cameraManager: cameraManager).equatable() }
}

// MARK: - Use-only Logic Methods
Expand Down

0 comments on commit 024ebee

Please sign in to comment.