Remove QR code stuff for now
This commit is contained in:
parent
20804eacc6
commit
de92923604
4 changed files with 15 additions and 168 deletions
|
|
@ -52,7 +52,6 @@
|
|||
94E9196C28353E0100F30170 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9474F216283531A200CDE4DD /* Log.swift */; };
|
||||
E27008102AF0F64B006E33BA /* SubscriptionsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */; };
|
||||
E27008122AF1030A006E33BA /* NotificationsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27008112AF1030A006E33BA /* NotificationsObservable.swift */; };
|
||||
E278CB332AECECCA004B9143 /* QRScannerUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E278CB322AECECCA004B9143 /* QRScannerUIView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -116,7 +115,6 @@
|
|||
94CD1969283E666900973B93 /* EmojiManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiManager.swift; sourceTree = "<group>"; };
|
||||
E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionsObservable.swift; sourceTree = "<group>"; };
|
||||
E27008112AF1030A006E33BA /* NotificationsObservable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsObservable.swift; sourceTree = "<group>"; };
|
||||
E278CB322AECECCA004B9143 /* QRScannerUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerUIView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -206,7 +204,6 @@
|
|||
94B736D4284AF9B2003D69FB /* SettingsView.swift */,
|
||||
94B736D6284AF9BE003D69FB /* MainView.swift */,
|
||||
9474F20728331F3900CDE4DD /* NotificationListView.swift */,
|
||||
E278CB322AECECCA004B9143 /* QRScannerUIView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -218,10 +215,10 @@
|
|||
9474F1FE28316ACE00CDE4DD /* Subscription.swift */,
|
||||
9474F1F82830835400CDE4DD /* Store.swift */,
|
||||
9474F20B283321C300CDE4DD /* Notification.swift */,
|
||||
94A3F7C7283734D900C48E79 /* SubscriptionManager.swift */,
|
||||
9407EDD9284ADE1F00C1C334 /* User.swift */,
|
||||
E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */,
|
||||
E27008112AF1030A006E33BA /* NotificationsObservable.swift */,
|
||||
94A3F7C7283734D900C48E79 /* SubscriptionManager.swift */,
|
||||
E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */,
|
||||
9407EDD9284ADE1F00C1C334 /* User.swift */,
|
||||
);
|
||||
path = Persistence;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -386,7 +383,6 @@
|
|||
E27008122AF1030A006E33BA /* NotificationsObservable.swift in Sources */,
|
||||
9486714A2841D0CE0093C7A4 /* ActionExecutor.swift in Sources */,
|
||||
9474F1FD2831311A00CDE4DD /* SubscriptionAddView.swift in Sources */,
|
||||
E278CB332AECECCA004B9143 /* QRScannerUIView.swift in Sources */,
|
||||
9474F1FF28316ACE00CDE4DD /* Subscription.swift in Sources */,
|
||||
94CD196A283E666900973B93 /* EmojiManager.swift in Sources */,
|
||||
9474F1C1282F2AA700CDE4DD /* AppMain.swift in Sources */,
|
||||
|
|
@ -561,7 +557,6 @@
|
|||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = ntfy/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
||||
INFOPLIST_KEY_NSCameraUsageDescription = "We need access to the camera to scan QR codes.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
|
|
@ -596,7 +591,6 @@
|
|||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = ntfy/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
||||
INFOPLIST_KEY_NSCameraUsageDescription = "We need access to the camera to scan QR codes.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<dict>
|
||||
<key>AppBaseURL</key>
|
||||
<string>$(APP_BASE_URL)</string>
|
||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||
<false/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
|
@ -18,9 +20,5 @@
|
|||
<array>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||
<false/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>We need access to the camera for QR code scanning.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
import AVFoundation
|
||||
import SwiftUI
|
||||
|
||||
struct QRScannerUIView: UIViewRepresentable {
|
||||
var onCodeDetected: (String) -> Void
|
||||
|
||||
func makeUIView(context: Context) -> some UIView {
|
||||
let view = QRScannerUIViewContainer()
|
||||
|
||||
let captureSession = AVCaptureSession()
|
||||
|
||||
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video),
|
||||
let videoInput = try? AVCaptureDeviceInput(device: videoCaptureDevice),
|
||||
captureSession.canAddInput(videoInput) else {
|
||||
return view
|
||||
}
|
||||
captureSession.addInput(videoInput)
|
||||
|
||||
let metadataOutput = AVCaptureMetadataOutput()
|
||||
captureSession.addOutput(metadataOutput)
|
||||
|
||||
metadataOutput.setMetadataObjectsDelegate(context.coordinator, queue: DispatchQueue.main)
|
||||
metadataOutput.metadataObjectTypes = [.qr]
|
||||
|
||||
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
|
||||
previewLayer.frame = view.layer.bounds
|
||||
previewLayer.videoGravity = .resizeAspectFill
|
||||
view.layer.insertSublayer(previewLayer, at: 0)
|
||||
|
||||
// Move the startRunning call to a background thread
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
captureSession.startRunning()
|
||||
}
|
||||
|
||||
view.previewLayer = previewLayer
|
||||
view.captureSession = captureSession
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: UIViewType, context: Context) {}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(onCodeDetected: onCodeDetected)
|
||||
}
|
||||
|
||||
class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
|
||||
var onCodeDetected: (String) -> Void
|
||||
private var lastScanDate: Date?
|
||||
private let debounceInterval: TimeInterval = 3.0
|
||||
|
||||
init(onCodeDetected: @escaping (String) -> Void) {
|
||||
self.onCodeDetected = onCodeDetected
|
||||
}
|
||||
|
||||
func qrCodeScanned(_ code: String) {
|
||||
let now = Date()
|
||||
|
||||
// If it's the first scan or the interval since the last scan is more than the debounce interval
|
||||
if let lastScan = lastScanDate, now.timeIntervalSince(lastScan) < debounceInterval {
|
||||
return
|
||||
}
|
||||
|
||||
onCodeDetected(code)
|
||||
lastScanDate = now
|
||||
}
|
||||
|
||||
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
|
||||
if let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject, let stringValue = metadataObject.stringValue {
|
||||
qrCodeScanned(stringValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class QRScannerUIViewContainer: UIView {
|
||||
var previewLayer: AVCaptureVideoPreviewLayer?
|
||||
var captureSession: AVCaptureSession?
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
previewLayer?.frame = self.bounds
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import SwiftUI
|
||||
import AVFoundation
|
||||
|
||||
struct SubscriptionAddView: View {
|
||||
private let tag = "SubscriptionAddView"
|
||||
|
|
@ -18,7 +17,6 @@ struct SubscriptionAddView: View {
|
|||
@State private var loading = false
|
||||
@State private var addError: String?
|
||||
@State private var loginError: String?
|
||||
@State private var hasCameraPermission: Bool = false
|
||||
|
||||
private var subscriptionManager: SubscriptionManager {
|
||||
return SubscriptionManager(store: store)
|
||||
|
|
@ -26,29 +24,19 @@ struct SubscriptionAddView: View {
|
|||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack {
|
||||
addView
|
||||
// TODO: hide this if permission not granted
|
||||
QRScannerUIView { code in
|
||||
onQRCodeScanned(text: code)
|
||||
}
|
||||
.frame(height: 250) // You can adjust the height as needed.
|
||||
.padding()
|
||||
.onAppear(perform: checkCameraPermission)
|
||||
}
|
||||
|
||||
// This is a little weird, but it works. The nagivation link for the login view
|
||||
// is rendered in the background (it's hidden), abd we toggle it manually.
|
||||
// is rendered in the backgroun (it's hidden), abd we toggle it manually.
|
||||
// If anyone has a better way to do a two-page layout let me know.
|
||||
|
||||
.background(Group {
|
||||
NavigationLink(
|
||||
destination: loginView,
|
||||
isActive: $showLogin
|
||||
) {
|
||||
EmptyView()
|
||||
}
|
||||
})
|
||||
addView
|
||||
.background(Group {
|
||||
NavigationLink(
|
||||
destination: loginView,
|
||||
isActive: $showLogin
|
||||
) {
|
||||
EmptyView()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -141,55 +129,6 @@ struct SubscriptionAddView: View {
|
|||
return topic.trimmingCharacters(in: .whitespaces)
|
||||
}
|
||||
|
||||
private func checkCameraPermission() {
|
||||
switch AVCaptureDevice.authorizationStatus(for: .video) {
|
||||
case .authorized:
|
||||
self.hasCameraPermission = true
|
||||
|
||||
case .notDetermined:
|
||||
AVCaptureDevice.requestAccess(for: .video) { granted in
|
||||
DispatchQueue.main.async {
|
||||
self.hasCameraPermission = granted
|
||||
if !granted {
|
||||
self.hasCameraPermission = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case .denied, .restricted:
|
||||
self.hasCameraPermission = false
|
||||
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func onQRCodeScanned(text: String){
|
||||
// Check if the text is a valid URL with HTTP or HTTPS scheme
|
||||
guard let url = URL(string: text), let scheme = url.scheme, ["http", "https"].contains(scheme) else {
|
||||
return
|
||||
}
|
||||
|
||||
// Extract the base URL without the path
|
||||
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
|
||||
components?.path = ""
|
||||
guard let foundBaseUrl = components?.url else {
|
||||
return
|
||||
}
|
||||
|
||||
// Extract the route from the original URL
|
||||
baseUrl = foundBaseUrl.absoluteString
|
||||
useAnother = baseUrl != store.getDefaultBaseUrl()
|
||||
|
||||
topic = url.path
|
||||
if (topic.hasPrefix("/")) {
|
||||
topic.removeFirst()
|
||||
}
|
||||
|
||||
print("------> \(baseUrl) : \(topic) : \(useAnother)")
|
||||
subscribeOrShowLoginAction()
|
||||
}
|
||||
|
||||
private func isAddViewValid() -> Bool {
|
||||
if sanitizedTopic.isEmpty {
|
||||
return false
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue