-
Notifications
You must be signed in to change notification settings - Fork 289
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provides a qr view to scan for nsec. Completes: #1291
- Allow scanning of QR codes, and if detects a nsec, will provide it to the login prompt. - If nsec is found, provides option to keep nsec in keychain; default is to not store - User stays logged in until they logout, or app is force-quit if nsec is not stored. damusApp.swift: Obtains keypair from the notification generated to allow login. LoginView.swift: New views allowing for adding and logic handling the QR reader in QRScanNSECView.swift to enable QR scan for nsec. QRScanNSECView.swift: New view to scan for QR code. The sparkling magnifying glass is enable if the view calling the QR view changes the privKeyFound bound variable. npub1el277q4kesp8vhs7rq6qkwnhpxfp345u7tnuxykwr67d9wg0wvyslam5n0 Signed-off-by: Jericho Hasselbush <[email protected]> Signed-off-by: William Casarin <[email protected]>
- Loading branch information
Showing
3 changed files
with
252 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
// | ||
// QRScanNSECView.swift | ||
// damus | ||
// | ||
// Created by Jericho Hasselbush on 9/29/23. | ||
// | ||
|
||
import SwiftUI | ||
import VisionKit | ||
|
||
struct QRScanNSECView: View { | ||
@Binding var showQR: Bool | ||
@Binding var privKeyFound: Bool | ||
var scannedTextHandler: (String) -> Void | ||
|
||
var body: some View { | ||
ZStack { | ||
ZStack { | ||
DamusGradient() | ||
} | ||
VStack { | ||
Text("Scan Your Private Key QR", comment: "Text to prompt scanning a QR code of a user's privkey to login to their profile.") | ||
.padding(.top, 50) | ||
.font(.system(size: 24, weight: .heavy)) | ||
|
||
Spacer() | ||
|
||
if QRViewController.scannerAvailable { | ||
QRViewController(scannedTextHandler) | ||
.scaledToFit() | ||
.frame(width: 300, height: 300) | ||
.cornerRadius(10) | ||
.overlay(RoundedRectangle(cornerRadius: 10).stroke(DamusColors.white, lineWidth: 5.0)) | ||
.shadow(radius: 10) | ||
} else { | ||
ScannerEmptyView() | ||
} | ||
|
||
Button(action: { withAnimation(.bouncy(duration: 2.5, extraBounce: 2.5)) { showQR = false }}) { | ||
VStack { | ||
Image(systemName: privKeyFound ? "sparkle.magnifyingglass" : "magnifyingglass") | ||
.font(privKeyFound ? .title : .title3) | ||
}} | ||
.padding(.top) | ||
.buttonStyle(GradientButtonStyle()) | ||
|
||
Spacer() | ||
|
||
Spacer() | ||
} | ||
} | ||
} | ||
|
||
func ScannerEmptyView() -> some View { | ||
VStack { | ||
if #available(iOS 17.0, macOS 14.0, *) { | ||
ContentUnavailableView("No native support for QR Code Scanning", systemImage: "exclamationmark.triangle") | ||
} else { | ||
HStack { | ||
Spacer() | ||
VStack { | ||
Image(systemName: "exclamationmark.triangle") | ||
Text("No native support for QR Code Scanning", comment: "Device doesn't support scanning QR codes.") | ||
.multilineTextAlignment(.center) | ||
} | ||
.font(.largeTitle) | ||
.foregroundColor(.primary) | ||
Spacer() | ||
} | ||
} | ||
} | ||
|
||
} | ||
} | ||
|
||
#Preview { | ||
@State var showQR = true | ||
@State var privKeyFound = false | ||
@State var shouldSaveKey = true | ||
return QRScanNSECView(showQR: $showQR, | ||
privKeyFound: $privKeyFound, | ||
scannedTextHandler: { _ in }) | ||
} | ||
|
||
|
||
typealias RecognizedItemHandler = (String) -> Void | ||
|
||
@MainActor | ||
struct QRViewController: UIViewControllerRepresentable { | ||
typealias UIViewControllerType = DataScannerViewController | ||
var delegate: QRViewControllerDelegate | ||
|
||
init(_ itemHandler: @escaping RecognizedItemHandler) { | ||
self.delegate = QRViewControllerDelegate(itemHandler) | ||
} | ||
|
||
func makeUIViewController(context: Context) -> DataScannerViewController { | ||
let controller = DataScannerViewController(recognizedDataTypes: [.barcode(symbologies: [.qr])], | ||
qualityLevel: .accurate, | ||
recognizesMultipleItems: false, | ||
isHighFrameRateTrackingEnabled: true, | ||
isPinchToZoomEnabled: true, | ||
isGuidanceEnabled: true, | ||
isHighlightingEnabled: true) | ||
try? controller.startScanning() | ||
controller.delegate = delegate | ||
return controller | ||
} | ||
|
||
func updateUIViewController(_ uiViewController: DataScannerViewController, context: Context) { | ||
|
||
} | ||
|
||
static var scannerAvailable: Bool { | ||
DataScannerViewController.isSupported && | ||
DataScannerViewController.isAvailable | ||
} | ||
} | ||
|
||
class QRViewControllerDelegate: DataScannerViewControllerDelegate { | ||
var handleItem: RecognizedItemHandler | ||
|
||
init(_ handleItem: @escaping RecognizedItemHandler) { | ||
self.handleItem = handleItem | ||
} | ||
|
||
func dataScanner(_ dataScanner: DataScannerViewController, didAdd addedItems: [RecognizedItem], allItems: [RecognizedItem]) { | ||
guard let item = addedItems.first else { return } | ||
if case let .barcode(barcode) = item { | ||
let string = barcode.payloadStringValue ?? "" | ||
self.handleItem(string) | ||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters