Add Trusted Devices Authentication

This commit is contained in:
Leon Böttger committed 2025-08-23 11:52:14 +02:00
1 parent 78df7fe227
commit 48164b8095
14 files changed
+621 -70

No files matched your search

+1 -1
View File
@@ -14,7 +14,7 @@ let configuration = LUIConfiguration(
copyrightInformation: licenseText,
loggingUrl: getAppGroupDirectory(),
loggingUrl: AppGroup.appGroupDirectory,
introductionViewInformation: "QuickDropWelcomeDescription",
+2 -1
View File
@@ -133,7 +133,8 @@ struct DeviceListView: View {
.font(.system(size: 14))
.foregroundColor(Color.primary.opacity(0.6))
ProgressView()
LoadingIndicator()
.opacity(0.75)
.frame(width: 12, height: 12)
}
.padding(.vertical, 16)
+25 -13
View File
@@ -26,15 +26,13 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
}
func obtainUserConsent(transfer: TransferMetadata, device: RemoteDeviceInfo) {
func obtainUserConsent(transfer: TransferMetadata, device: RemoteDeviceInfo, acceptAutomatically: Bool) {
#if os(macOS)
NSApp.activate(ignoringOtherApps: true)
AudioManager.playIncomingFileSound()
#endif
let acceptAutomatically = UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue)
let fileStr: String
if let textTitle = transfer.textDescription {
@@ -64,8 +62,8 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
let pinCodeMessage = String(format: "PinCode".localized(), arguments: [transfer.pinCode ?? "?"])
let transferID = transfer.id
if acceptAutomatically {
pressAcceptButton(transferID: transfer.id)
if acceptAutomatically && isMac() {
pressAcceptButton(transferID: transfer.id, trustDevice: false)
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, _ in
if granted {
@@ -89,9 +87,9 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
let title = "QuickDrop - \(pinCodeMessage)"
let primaryButtonTitle = "Accept".localized()
let primaryButtonAction = { self.pressAcceptButton(transferID: transferID) }
let primaryButtonAction = { (trustDevice: Bool) in self.pressAcceptButton(transferID: transferID, trustDevice: trustDevice) }
let secondaryButtonTitle = "Decline".localized()
let secondaryButtonAction = { NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: false, storeInTemp: false) }
let secondaryButtonAction = { NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: false, trustDevice: false, storeInTemp: false) }
#if os(macOS)
let alert = NSAlert()
@@ -101,18 +99,32 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
alert.informativeText = mainMessage
alert.addButton(withTitle: primaryButtonTitle)
alert.addButton(withTitle: secondaryButtonTitle)
if transfer.allowsToBeAddedAsTrustedDevice {
alert.showsSuppressionButton = true
alert.suppressionButton?.title = "AutoAcceptFromThisDevice".localized()
}
let result = alert.runModal()
if result == .alertFirstButtonReturn {
primaryButtonAction()
primaryButtonAction(alert.suppressionButton?.state == .on)
} else if result == .alertSecondButtonReturn {
secondaryButtonAction()
}
#else
// iOS
ProgressAlert.shared.askForUserPermission(title: title, message: mainMessage, acceptLabel: primaryButtonTitle, rejectLabel: secondaryButtonTitle) { accepted in
accepted ? primaryButtonAction() : secondaryButtonAction()
let alwaysAcceptLabel = transfer.allowsToBeAddedAsTrustedDevice ? "AlwaysAccept".localized() : nil
ProgressAlert.shared.askForUserPermission(title: title, message: mainMessage, acceptLabel: primaryButtonTitle, acceptAlwaysLabel: alwaysAcceptLabel, rejectLabel: secondaryButtonTitle, acceptAutomatically: acceptAutomatically) { accepted in
switch accepted {
case .Accept:
primaryButtonAction(false)
case .AcceptAlways:
primaryButtonAction(true)
case .Decline:
secondaryButtonAction()
}
}
#endif
}
@@ -181,13 +193,13 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
}
private func pressAcceptButton(transferID: String) {
private func pressAcceptButton(transferID: String, trustDevice: Bool) {
if isFileTransferRestricted() {
log("[ReceiveModel] Showing plus screen...")
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: true, storeInTemp: true)
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: true, trustDevice: trustDevice, storeInTemp: true)
controlPlusScreen(true)
} else {
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: true, storeInTemp: false)
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: true, trustDevice: trustDevice, storeInTemp: false)
}
}
}
+35 -14
View File
@@ -18,23 +18,37 @@ final class ProgressAlert {
private weak var progressView: UIProgressView?
// MARK: - Initial Accept / Decline
func askForUserPermission(title: String, message: String, acceptLabel: String, rejectLabel: String, onAccept: @escaping (Bool) -> Void) {
func askForUserPermission(title: String, message: String, acceptLabel: String, acceptAlwaysLabel: String?, rejectLabel: String, acceptAutomatically: Bool, onAccept: @escaping (AcceptAction) -> Void) {
guard let vc = topMostViewController() else { return }
let alert = UIAlertController(title: title,
message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: rejectLabel, style: .cancel, handler: { _ in
onAccept(false)
}))
alert.addAction(UIAlertAction(title: acceptLabel, style: .default, handler: { _ in
onAccept(true)
if acceptAutomatically {
onAccept(.Accept)
self.showProgressAlert(on: vc)
}))
vc.present(alert, animated: true)
}
else {
let alert = UIAlertController(title: title,
message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: rejectLabel, style: .cancel, handler: { _ in
onAccept(.Decline)
}))
alert.addAction(UIAlertAction(title: acceptLabel, style: .default, handler: { _ in
onAccept(.Accept)
self.showProgressAlert(on: vc)
}))
if let acceptAlways = acceptAlwaysLabel {
alert.addAction(UIAlertAction(title: acceptAlways, style: .default, handler: { _ in
onAccept(.AcceptAlways)
self.showProgressAlert(on: vc)
}))
}
vc.present(alert, animated: true)
}
}
// MARK: - Progress Alert
@@ -90,4 +104,11 @@ final class ProgressAlert {
if let presented = base?.presentedViewController { return topMostViewController(base: presented) }
return base
}
enum AcceptAction {
case Accept
case AcceptAlways
case Decline
}
}