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 */; };
|
94E9196C28353E0100F30170 /* Log.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9474F216283531A200CDE4DD /* Log.swift */; };
|
||||||
E27008102AF0F64B006E33BA /* SubscriptionsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */; };
|
E27008102AF0F64B006E33BA /* SubscriptionsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */; };
|
||||||
E27008122AF1030A006E33BA /* NotificationsObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E27008112AF1030A006E33BA /* NotificationsObservable.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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
|
@ -116,7 +115,6 @@
|
||||||
94CD1969283E666900973B93 /* EmojiManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmojiManager.swift; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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 */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -206,7 +204,6 @@
|
||||||
94B736D4284AF9B2003D69FB /* SettingsView.swift */,
|
94B736D4284AF9B2003D69FB /* SettingsView.swift */,
|
||||||
94B736D6284AF9BE003D69FB /* MainView.swift */,
|
94B736D6284AF9BE003D69FB /* MainView.swift */,
|
||||||
9474F20728331F3900CDE4DD /* NotificationListView.swift */,
|
9474F20728331F3900CDE4DD /* NotificationListView.swift */,
|
||||||
E278CB322AECECCA004B9143 /* QRScannerUIView.swift */,
|
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -218,10 +215,10 @@
|
||||||
9474F1FE28316ACE00CDE4DD /* Subscription.swift */,
|
9474F1FE28316ACE00CDE4DD /* Subscription.swift */,
|
||||||
9474F1F82830835400CDE4DD /* Store.swift */,
|
9474F1F82830835400CDE4DD /* Store.swift */,
|
||||||
9474F20B283321C300CDE4DD /* Notification.swift */,
|
9474F20B283321C300CDE4DD /* Notification.swift */,
|
||||||
94A3F7C7283734D900C48E79 /* SubscriptionManager.swift */,
|
|
||||||
9407EDD9284ADE1F00C1C334 /* User.swift */,
|
|
||||||
E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */,
|
|
||||||
E27008112AF1030A006E33BA /* NotificationsObservable.swift */,
|
E27008112AF1030A006E33BA /* NotificationsObservable.swift */,
|
||||||
|
94A3F7C7283734D900C48E79 /* SubscriptionManager.swift */,
|
||||||
|
E270080F2AF0F64B006E33BA /* SubscriptionsObservable.swift */,
|
||||||
|
9407EDD9284ADE1F00C1C334 /* User.swift */,
|
||||||
);
|
);
|
||||||
path = Persistence;
|
path = Persistence;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -386,7 +383,6 @@
|
||||||
E27008122AF1030A006E33BA /* NotificationsObservable.swift in Sources */,
|
E27008122AF1030A006E33BA /* NotificationsObservable.swift in Sources */,
|
||||||
9486714A2841D0CE0093C7A4 /* ActionExecutor.swift in Sources */,
|
9486714A2841D0CE0093C7A4 /* ActionExecutor.swift in Sources */,
|
||||||
9474F1FD2831311A00CDE4DD /* SubscriptionAddView.swift in Sources */,
|
9474F1FD2831311A00CDE4DD /* SubscriptionAddView.swift in Sources */,
|
||||||
E278CB332AECECCA004B9143 /* QRScannerUIView.swift in Sources */,
|
|
||||||
9474F1FF28316ACE00CDE4DD /* Subscription.swift in Sources */,
|
9474F1FF28316ACE00CDE4DD /* Subscription.swift in Sources */,
|
||||||
94CD196A283E666900973B93 /* EmojiManager.swift in Sources */,
|
94CD196A283E666900973B93 /* EmojiManager.swift in Sources */,
|
||||||
9474F1C1282F2AA700CDE4DD /* AppMain.swift in Sources */,
|
9474F1C1282F2AA700CDE4DD /* AppMain.swift in Sources */,
|
||||||
|
|
@ -561,7 +557,6 @@
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = ntfy/Info.plist;
|
INFOPLIST_FILE = ntfy/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "We need access to the camera to scan QR codes.";
|
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
|
@ -596,7 +591,6 @@
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
INFOPLIST_FILE = ntfy/Info.plist;
|
INFOPLIST_FILE = ntfy/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
INFOPLIST_KEY_CFBundleDisplayName = ntfy;
|
||||||
INFOPLIST_KEY_NSCameraUsageDescription = "We need access to the camera to scan QR codes.";
|
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>AppBaseURL</key>
|
<key>AppBaseURL</key>
|
||||||
<string>$(APP_BASE_URL)</string>
|
<string>$(APP_BASE_URL)</string>
|
||||||
|
<key>FirebaseAppDelegateProxyEnabled</key>
|
||||||
|
<false/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
|
|
@ -18,9 +20,5 @@
|
||||||
<array>
|
<array>
|
||||||
<string>remote-notification</string>
|
<string>remote-notification</string>
|
||||||
</array>
|
</array>
|
||||||
<key>FirebaseAppDelegateProxyEnabled</key>
|
|
||||||
<false/>
|
|
||||||
<key>NSCameraUsageDescription</key>
|
|
||||||
<string>We need access to the camera for QR code scanning.</string>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</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 SwiftUI
|
||||||
import AVFoundation
|
|
||||||
|
|
||||||
struct SubscriptionAddView: View {
|
struct SubscriptionAddView: View {
|
||||||
private let tag = "SubscriptionAddView"
|
private let tag = "SubscriptionAddView"
|
||||||
|
|
@ -18,7 +17,6 @@ struct SubscriptionAddView: View {
|
||||||
@State private var loading = false
|
@State private var loading = false
|
||||||
@State private var addError: String?
|
@State private var addError: String?
|
||||||
@State private var loginError: String?
|
@State private var loginError: String?
|
||||||
@State private var hasCameraPermission: Bool = false
|
|
||||||
|
|
||||||
private var subscriptionManager: SubscriptionManager {
|
private var subscriptionManager: SubscriptionManager {
|
||||||
return SubscriptionManager(store: store)
|
return SubscriptionManager(store: store)
|
||||||
|
|
@ -26,29 +24,19 @@ struct SubscriptionAddView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
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
|
// 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.
|
// If anyone has a better way to do a two-page layout let me know.
|
||||||
|
|
||||||
.background(Group {
|
addView
|
||||||
NavigationLink(
|
.background(Group {
|
||||||
destination: loginView,
|
NavigationLink(
|
||||||
isActive: $showLogin
|
destination: loginView,
|
||||||
) {
|
isActive: $showLogin
|
||||||
EmptyView()
|
) {
|
||||||
}
|
EmptyView()
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,55 +129,6 @@ struct SubscriptionAddView: View {
|
||||||
return topic.trimmingCharacters(in: .whitespaces)
|
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 {
|
private func isAddViewValid() -> Bool {
|
||||||
if sanitizedTopic.isEmpty {
|
if sanitizedTopic.isEmpty {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue