Skip to content

Commit 0916c59

Browse files
author
Erik Strottmann
authored
Merge pull request #15 from clutter/camera
Add Camera screen
2 parents 90ed1f7 + 2a0bf5d commit 0916c59

File tree

12 files changed

+1119
-12
lines changed

12 files changed

+1119
-12
lines changed

Example/.swiftlint.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ custom_rules:
1010
name: "Weak Root Coordinator"
1111
message: "Root coordinators should be weak to avoid reference cycles."
1212
regex: "(?<!weak )var rootCoordinator: RootCoordinator\\?(?! \\{ get (set )?\\})"
13-
dress_code_colors:
14-
name: "DressCode Colors"
15-
message: "Colors should be accessed via the Color type provided by DressCode."
16-
regex: '(?<=(\bUIColor)|[^\w])\.(black|darkGray|lightGray|white|gray|red|green|blue|cyan|yellow|magenta|orange|purple|brown|clear)\b(?!\()|UIColor(\.init)?\(\s*(white|hue|red|displayP3Red|named|ciColor|cgColor)'
1713
file_length:
1814
warning: 600
1915
identifier_name:

Example/Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PODS:
22
- SwiftLint (0.34.0)
3-
- TiltUp (0.5.0)
4-
- TiltUpTest (0.5.0)
3+
- TiltUp (1.0.0)
4+
- TiltUpTest (1.0.0)
55

66
DEPENDENCIES:
77
- SwiftLint
@@ -20,8 +20,8 @@ EXTERNAL SOURCES:
2020

2121
SPEC CHECKSUMS:
2222
SwiftLint: 79d48a17c6565dc286c37efb8322c7b450f95c67
23-
TiltUp: 3d2960016f9e2ff4cee3201b9418d1a76470a5cd
24-
TiltUpTest: 151fd6ff45b85f41ba5d3b5845c29464422e8914
23+
TiltUp: 93cf680bf6de3c6af72160638b0a257eb48808e5
24+
TiltUpTest: 5e4a394f76eb3c11b98babb1edcd22b53b23621f
2525

2626
PODFILE CHECKSUM: c3ad4c36e5d17d3b4a90d5cf5f5b66d3221db5dd
2727

TiltUp.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
Pod::Spec.new do |s|
1010
s.name = 'TiltUp'
11-
s.version = '0.5.0'
11+
s.version = '1.0.0'
1212
s.summary = 'Official Clutter SDK in Swift to access core iOS features.'
1313

1414
# This description is used to generate tags and improve search results.

TiltUp/Classes/Architecture/IdentifierView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//
22
// IdentifierView.swift
3-
// Clutter
3+
// TiltUp
44
//
55
// Created by Kevin Sylvestre on 2015-09-07.
66
// Copyright © 2015 Clutter. All rights reserved.
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// UIImage+Additions.swift
3+
// TiltUp
4+
//
5+
// Created by Robert Manson on 11/9/15.
6+
// Copyright © 2015 Clutter Inc. All rights reserved.
7+
//
8+
9+
import AVFoundation
10+
import UIKit
11+
12+
// MARK: - Scaling and HEIC data
13+
public extension UIImage {
14+
func scaled(to size: CGSize) -> UIImage {
15+
return UIGraphicsImageRenderer(size: size).image { _ in
16+
draw(in: CGRect(origin: .zero, size: size))
17+
}
18+
}
19+
20+
func heicData(compressionQuality: CGFloat) -> Data? {
21+
let data = NSMutableData()
22+
guard
23+
let destination = CGImageDestinationCreateWithData(data, AVFileType.heic as CFString, 1, nil),
24+
let cgImage = cgImage
25+
else { return nil }
26+
27+
let options = [kCGImageDestinationLossyCompressionQuality: compressionQuality]
28+
CGImageDestinationAddImage(destination, cgImage, options as CFDictionary)
29+
CGImageDestinationFinalize(destination)
30+
31+
return data as Data
32+
}
33+
}
34+
35+
// MARK: - Image from color
36+
public extension UIImage {
37+
static func make(color: UIColor, size: CGSize) -> UIImage {
38+
return UIGraphicsImageRenderer(size: size).image { context in
39+
color.setFill()
40+
context.fill(CGRect(origin: .zero, size: size))
41+
}
42+
}
43+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//
2+
// CameraController.swift
3+
// TiltUp
4+
//
5+
// Created by Jeremy Grenier on 10/17/19.
6+
// Copyright © 2019 Clutter. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
public final class CameraController: UIViewController {
12+
private let previewView = CameraPreviewView()
13+
private let overlayView: CameraOverlayView
14+
15+
private let generator = UIImpactFeedbackGenerator(style: .medium)
16+
17+
public let viewModel: CameraViewModel
18+
19+
public override var prefersStatusBarHidden: Bool { true }
20+
21+
public init(viewModel: CameraViewModel, hint: String?) {
22+
self.viewModel = viewModel
23+
overlayView = CameraOverlayView(hint: { _ in hint })
24+
25+
super.init(nibName: nil, bundle: nil)
26+
}
27+
28+
public init(viewModel: CameraViewModel, hint: @escaping (_ numberOfPhotos: Int) -> String?) {
29+
self.viewModel = viewModel
30+
overlayView = CameraOverlayView(hint: hint)
31+
32+
super.init(nibName: nil, bundle: nil)
33+
}
34+
35+
required init?(coder: NSCoder) {
36+
fatalError("init(coder:) has not been implemented")
37+
}
38+
39+
public override func viewDidLoad() {
40+
super.viewDidLoad()
41+
42+
view.backgroundColor = .black
43+
44+
viewModel.viewObservers.presentAlert = { [weak self] alert in
45+
DispatchQueue.main.async {
46+
self?.present(alert, animated: true)
47+
}
48+
}
49+
50+
viewModel.viewObservers.rotateInterface = { [weak self] orientation in
51+
DispatchQueue.main.async {
52+
self?.overlayView.interfaceOrientation = orientation
53+
}
54+
}
55+
56+
viewModel.viewObservers.updateOverlayState = { [weak self] state in
57+
DispatchQueue.main.async {
58+
self?.overlayView.state = state
59+
}
60+
}
61+
62+
viewModel.viewObservers.willCapturePhotoAnimation = { [weak self] in
63+
guard let self = self else { return }
64+
DispatchQueue.main.async {
65+
self.generator.impactOccurred()
66+
self.previewView.videoPreviewLayer.opacity = 0
67+
UIView.animate(withDuration: 0.25) {
68+
self.previewView.videoPreviewLayer.opacity = 1
69+
}
70+
}
71+
}
72+
73+
previewView.session = viewModel.session
74+
75+
view.addSubview(previewView)
76+
view.addSubview(overlayView)
77+
overlayView.delegate = viewModel
78+
79+
let pinch = UIPinchGestureRecognizer(target: self, action: #selector(handlePinch))
80+
overlayView.addGestureRecognizer(pinch)
81+
82+
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
83+
overlayView.addGestureRecognizer(tap)
84+
}
85+
86+
public override func viewWillAppear(_ animated: Bool) {
87+
super.viewWillAppear(animated)
88+
navigationController?.setNavigationBarHidden(true, animated: false)
89+
viewModel.viewWillAppear()
90+
}
91+
92+
public override func viewWillDisappear(_ animated: Bool) {
93+
viewModel.viewWillDisappear()
94+
super.viewWillDisappear(animated)
95+
}
96+
97+
public override func viewDidLayoutSubviews() {
98+
super.viewDidLayoutSubviews()
99+
100+
previewView.frame = CGRect(x: 0.0, y: 64.0, width: view.bounds.width, height: view.bounds.width * 4 / 3)
101+
overlayView.frame = view.bounds
102+
}
103+
}
104+
105+
extension CameraController {
106+
@objc private func handlePinch(_ pinch: UIPinchGestureRecognizer) {
107+
viewModel.handlePinch(pinch)
108+
}
109+
110+
@objc private func handleTap(_ tap: UITapGestureRecognizer) {
111+
let point = tap.location(in: previewView)
112+
113+
guard point.x.isFinite && point.y.isFinite else { return }
114+
115+
let devicePoint = previewView.videoPreviewLayer.captureDevicePointConverted(fromLayerPoint: point)
116+
117+
focusAnimation(at: point)
118+
viewModel.focusCamera(at: devicePoint)
119+
}
120+
121+
func focusAnimation(at point: CGPoint) {
122+
let focusView = UIView(frame: CGRect(x: 0, y: 0, width: 70, height: 70))
123+
focusView.layer.borderColor = UIColor(red: 0xFF / 0xFF, green: 0xB8 / 0xFF, blue: 0x18 / 0xFF, alpha: 1.0).cgColor
124+
focusView.layer.borderWidth = 1
125+
focusView.center = point
126+
focusView.alpha = 0.0
127+
previewView.subviews.forEach({ $0.removeFromSuperview() })
128+
previewView.addSubview(focusView)
129+
130+
let appearAnimation = {
131+
focusView.alpha = 1.0
132+
focusView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
133+
}
134+
135+
let disappearAnimation = {
136+
focusView.alpha = 0.0
137+
focusView.transform = CGAffineTransform(translationX: 0.6, y: 0.6)
138+
}
139+
140+
UIView.animate(withDuration: 0.25, delay: 0.0, options: .curveEaseInOut, animations: appearAnimation, completion: { _ in
141+
UIView.animate(withDuration: 0.15, delay: 0.5, options: .curveEaseInOut, animations: disappearAnimation) { _ in
142+
focusView.removeFromSuperview()
143+
}
144+
})
145+
}
146+
}

0 commit comments

Comments
 (0)