Skip to content

Commit b6f3576

Browse files
Update appearance of default preview
1 parent 53e21bd commit b6f3576

File tree

9 files changed

+228
-45
lines changed

9 files changed

+228
-45
lines changed

Example App/iOS Example.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@
297297
CODE_SIGN_IDENTITY = "Apple Development";
298298
CODE_SIGN_STYLE = Automatic;
299299
CURRENT_PROJECT_VERSION = 1;
300-
DEVELOPMENT_TEAM = 5KKK9SKF79;
300+
DEVELOPMENT_TEAM = U35323S562;
301301
GENERATE_INFOPLIST_FILE = YES;
302302
INFOPLIST_FILE = "iOS Example/Info.plist";
303303
INFOPLIST_KEY_NSCameraUsageDescription = "Need for testing purpose";
@@ -327,7 +327,7 @@
327327
CODE_SIGN_IDENTITY = "Apple Development";
328328
CODE_SIGN_STYLE = Automatic;
329329
CURRENT_PROJECT_VERSION = 1;
330-
DEVELOPMENT_TEAM = 5KKK9SKF79;
330+
DEVELOPMENT_TEAM = U35323S562;
331331
GENERATE_INFOPLIST_FILE = YES;
332332
INFOPLIST_FILE = "iOS Example/Info.plist";
333333
INFOPLIST_KEY_NSCameraUsageDescription = "Need for testing purpose";
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2020 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
24+
extension UIImageView {
25+
26+
func setImage(systemName: String) {
27+
if #available(iOS 13.0, *) {
28+
image = UIImage(systemName: systemName)
29+
}
30+
}
31+
32+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2020 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import Foundation
23+
24+
public enum SPQRCode {
25+
26+
case text(String)
27+
case url(URL)
28+
case ethWallet(String)
29+
30+
}

Sources/SPQRCode/Protocols/SPQRCameraDelegate.swift

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

2222
public protocol SPQRCameraDelegate: AnyObject {
2323

24-
func camera(_ viewController: SPQRCameraViewController, didFound stringValue: String)
24+
func camera(_ viewController: SPQRCameraViewController, didFound result: SPQRCode)
2525
func cameraDidPress(_ viewController: SPQRCameraViewController)
2626

2727
}

Sources/SPQRCode/Protocols/SPQRCameraHandlers.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2020
// SOFTWARE.
2121

22-
public typealias SPQRCameraFoundHandler = (String) -> Void
22+
public typealias SPQRCameraFoundHandler = (SPQRCode) -> Void
2323
public typealias SPQRCameraHandlerDidPressHandler = () -> Void
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// The MIT License (MIT)
2+
// Copyright © 2020 Ivan Vorobei ([email protected])
3+
//
4+
// Permission is hereby granted, free of charge, to any person obtaining a copy
5+
// of this software and associated documentation files (the "Software"), to deal
6+
// in the Software without restriction, including without limitation the rights
7+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
// copies of the Software, and to permit persons to whom the Software is
9+
// furnished to do so, subject to the following conditions:
10+
//
11+
// The above copyright notice and this permission notice shall be included in all
12+
// copies or substantial portions of the Software.
13+
//
14+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
// SOFTWARE.
21+
22+
import UIKit
23+
24+
public protocol SPQRCodeUpdatable {
25+
26+
func update(for result: SPQRCode)
27+
28+
}

Sources/SPQRCode/SPQRCameraViewController.swift

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,7 @@ open class SPQRCameraViewController: UIViewController {
3737
// MARK: - Private Static Properties
3838

3939
private static let supportedCodeTypes = [
40-
AVMetadataObject.ObjectType.upce,
41-
AVMetadataObject.ObjectType.code39,
42-
AVMetadataObject.ObjectType.code39Mod43,
43-
AVMetadataObject.ObjectType.code93,
44-
AVMetadataObject.ObjectType.code128,
45-
AVMetadataObject.ObjectType.ean8,
46-
AVMetadataObject.ObjectType.ean13,
4740
AVMetadataObject.ObjectType.aztec,
48-
AVMetadataObject.ObjectType.pdf417,
4941
AVMetadataObject.ObjectType.qr
5042
]
5143

@@ -103,14 +95,35 @@ open class SPQRCameraViewController: UIViewController {
10395
videoPreviewLayer.frame = view.layer.bounds
10496
}
10597

106-
open func updatePreviewView(for object: AVMetadataMachineReadableCodeObject) {
107-
if let string = object.stringValue {
108-
if let url = URL(string: string) {
109-
defaultPreviewView.text = "URL: \"\(url.absoluteString)\""
110-
} else {
111-
defaultPreviewView.text = "Text: \"\(string)\""
98+
open func updateViews(result: SPQRCode) {
99+
if let updatableFrameView = frameView as? SPQRCodeUpdatable {
100+
updatableFrameView.update(for: result)
101+
}
102+
103+
if let updatablePreviewView = previewView as? SPQRCodeUpdatable {
104+
updatablePreviewView.update(for: result)
105+
}
106+
}
107+
108+
open func convert(object: AVMetadataMachineReadableCodeObject) -> SPQRCode? {
109+
guard let string = object.stringValue else {
110+
return nil
111+
}
112+
113+
if let components = URLComponents(string: string), components.scheme != nil {
114+
if let url = components.url {
115+
return .url(url)
116+
}
117+
}
118+
119+
if let pattern = try? NSRegularExpression(pattern: "^0x[a-fA-F0-9]{40}$") {
120+
let range = NSRange(location: 0, length: string.count)
121+
if pattern.firstMatch(in: string, range: range) != nil {
122+
return .ethWallet(string)
112123
}
113124
}
125+
126+
return .text(string)
114127
}
115128

116129
// MARK: - Actions
@@ -147,12 +160,12 @@ private extension SPQRCameraViewController {
147160
let leadingPreviewConstraint = previewView.leadingAnchor.constraint(
148161
lessThanOrEqualTo: frameView.leadingAnchor
149162
)
150-
leadingPreviewConstraint.priority = .defaultHigh
163+
leadingPreviewConstraint.priority = .defaultLow
151164

152165
let trailingPreviewConstraint = previewView.trailingAnchor.constraint(
153166
greaterThanOrEqualTo: frameView.trailingAnchor
154167
)
155-
trailingPreviewConstraint.priority = .defaultHigh
168+
trailingPreviewConstraint.priority = .defaultLow
156169

157170
NSLayoutConstraint.activate([
158171
centerPreviewConstraint,
@@ -213,17 +226,23 @@ extension SPQRCameraViewController: AVCaptureMetadataOutputObjectsDelegate {
213226
return
214227
}
215228

216-
guard let qrString = metadataObj.stringValue else {
229+
guard let result = convert(object: metadataObj) else {
217230
return
218231
}
219232

220-
updatePreviewView(for: metadataObj)
221-
notifyFound(string: qrString)
233+
updateViews(result: result)
234+
notifyFound(result: result)
222235

223236
if frameView.isHidden {
224237
frameView.frame = frame
225238
} else {
226-
UIView.animate(withDuration: 0.3, delay: 0.0, options: [.allowUserInteraction, .beginFromCurrentState], animations: {
239+
let options: UIView.AnimationOptions = [
240+
.allowUserInteraction,
241+
.beginFromCurrentState,
242+
.curveEaseInOut,
243+
]
244+
245+
UIView.animate(withDuration: 0.2, delay: 0.0, options: options, animations: {
227246
self.frameView.frame = frame
228247
self.view.layoutIfNeeded()
229248
}, completion: nil)
@@ -233,7 +252,7 @@ extension SPQRCameraViewController: AVCaptureMetadataOutputObjectsDelegate {
233252
frameView.isHidden = false
234253

235254
updateTimer?.invalidate()
236-
updateTimer = Timer(fire: Date(timeIntervalSinceNow: 0.5), interval: 2, repeats: false, block: { _ in
255+
updateTimer = Timer(fire: Date(timeIntervalSinceNow: 0.8), interval: 2, repeats: false, block: { _ in
237256
self.frameView.isHidden = true
238257
self.previewView.isHidden = true
239258
})
@@ -273,11 +292,11 @@ private extension SPQRCameraViewController {
273292
return videoPreviewLayer
274293
}
275294

276-
private func notifyFound(string: String) {
295+
private func notifyFound(result: SPQRCode) {
277296
if let delegate = delegate {
278-
delegate.camera(self, didFound: string)
297+
delegate.camera(self, didFound: result)
279298
} else {
280-
cameraFoundHandler?(string)
299+
cameraFoundHandler?(result)
281300
}
282301
}
283302

Sources/SPQRCode/Views/SPFrameView.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
import UIKit
2323

24-
final class SPFrameView: UIView {
24+
public final class SPFrameView: UIView, SPQRCodeUpdatable {
2525

2626
// MARK: - Subviews
2727

@@ -40,7 +40,7 @@ final class SPFrameView: UIView {
4040
commonInit()
4141
}
4242

43-
override func layoutSubviews() {
43+
public override func layoutSubviews() {
4444
super.layoutSubviews()
4545
shapeLayer.frame = bounds
4646
updateMaskLayer()
@@ -49,6 +49,16 @@ final class SPFrameView: UIView {
4949

5050
}
5151

52+
// MARK: - Public Methods
53+
54+
public extension SPFrameView {
55+
56+
func update(for result: SPQRCode) {
57+
/* do nothing */
58+
}
59+
60+
}
61+
5262
// MARK: - Private Methods
5363

5464
private extension SPFrameView {

0 commit comments

Comments
 (0)