@@ -30,11 +30,32 @@ import OneTimePassword
30
30
class TokenScannerViewController : UIViewController , QRScannerDelegate {
31
31
private let scanner = QRScanner ( )
32
32
private let videoLayer = AVCaptureVideoPreviewLayer ( )
33
- private let messageView = UIView ( )
33
+ private let messageView = UIButton ( )
34
34
35
35
private var viewModel : TokenScanner . ViewModel
36
36
private let dispatchAction : ( TokenScanner . Action ) -> Void
37
37
38
+ fileprivate let permissionLabel : UILabel = {
39
+ let linkTitle = " Go to Settings → "
40
+ let message = " To add a new token via QR code, Authenticator needs permission to access the camera. \n \( linkTitle) "
41
+ let paragraphStyle = NSMutableParagraphStyle ( )
42
+ paragraphStyle. lineHeightMultiple = 1.3
43
+ paragraphStyle. paragraphSpacing = 5
44
+ let attributedMessage = NSMutableAttributedString ( string: message, attributes: [
45
+ NSFontAttributeName: UIFont . systemFont ( ofSize: 15 , weight: UIFontWeightLight) ,
46
+ NSParagraphStyleAttributeName: paragraphStyle,
47
+ ] )
48
+ attributedMessage. addAttribute ( NSFontAttributeName, value: UIFont . boldSystemFont ( ofSize: 15 ) ,
49
+ range: ( attributedMessage. string as NSString ) . range ( of: linkTitle) )
50
+
51
+ let label = UILabel ( )
52
+ label. numberOfLines = 0
53
+ label. attributedText = attributedMessage
54
+ label. textAlignment = . center
55
+ label. textColor = UIColor . otpForegroundColor
56
+ return label
57
+ } ( )
58
+
38
59
// MARK: Initialization
39
60
40
61
init ( viewModel: TokenScanner . ViewModel , dispatchAction: @escaping ( TokenScanner . Action ) -> Void ) {
@@ -78,8 +99,13 @@ class TokenScannerViewController: UIViewController, QRScannerDelegate {
78
99
messageView. autoresizingMask = [ . flexibleWidth, . flexibleHeight]
79
100
messageView. frame = view. bounds
80
101
messageView. isHidden = true
102
+ messageView. addTarget ( self , action: #selector( TokenScannerViewController . editPermissions) , for: . touchUpInside)
81
103
view. addSubview ( messageView)
82
104
105
+ permissionLabel. autoresizingMask = [ . flexibleWidth, . flexibleHeight]
106
+ permissionLabel. frame = messageView. bounds. insetBy ( dx: 35 , dy: 35 )
107
+ messageView. addSubview ( permissionLabel)
108
+
83
109
if CommandLine . isDemo {
84
110
// If this is a demo, display an image in place of the AVCaptureVideoPreviewLayer.
85
111
let imageView = UIImageView ( frame: view. bounds)
@@ -90,6 +116,7 @@ class TokenScannerViewController: UIViewController, QRScannerDelegate {
90
116
}
91
117
92
118
let overlayView = ScannerOverlayView ( frame: view. bounds)
119
+ overlayView. isUserInteractionEnabled = false
93
120
view. addSubview ( overlayView)
94
121
}
95
122
@@ -141,6 +168,12 @@ class TokenScannerViewController: UIViewController, QRScannerDelegate {
141
168
dispatchAction ( . beginManualTokenEntry)
142
169
}
143
170
171
+ func editPermissions( ) {
172
+ if let applicationSettingsURL = URL ( string: UIApplicationOpenSettingsURLString) {
173
+ UIApplication . shared. openURL ( applicationSettingsURL)
174
+ }
175
+ }
176
+
144
177
// MARK: QRScannerDelegate
145
178
146
179
func handleDecodedText( _ text: String ) {
0 commit comments