25 Commits
Author SHA1 Message Date
Leon Böttger 66acbf25a3 Fix logging 2025-09-23 12:02:43 +02:00
Leon Böttger 93537094e4 iOS: UI improvements 2025-09-21 18:53:53 +02:00
Leon Böttger b6b11c00c0 Add support for iPhone 17 Series 2025-09-21 14:49:04 +02:00
Leon Böttger 92671d8983 Clean up screenshots 2025-09-14 21:21:23 +02:00
Leon Böttger bfc23fde15 Add QR Code View to iOS 2025-09-14 21:02:39 +02:00
Leon Böttger a39a5a324a Fix App Icon for iOS 2025-09-13 16:15:02 +02:00
Leon Böttger fd7dfd959b Add Liquid Glass Icon 2025-09-13 15:13:18 +02:00
Leon Böttger bd4b181a49 Refactoring 2025-09-12 11:48:24 +02:00
Leon Böttger f066a11608 Fix: iOS app advertised to scan even though not connected to Wi-Fi 2025-09-12 11:37:48 +02:00
Leon Böttger 5429126c1e Fix: Only one file would be saved for multiple incoming files with same name 2025-09-12 11:20:28 +02:00
Leon Böttger 4bf8a9052d Disable Liquid Glass for now 2025-09-11 15:48:15 +02:00
Leon Böttger f786af9d12 Improve logging 2025-09-11 15:47:12 +02:00
Leon Böttger 6def7dbc9f Refactoring 2025-09-09 14:35:25 +02:00
Leon Böttger fcc0ce0818 If selecting custom folder, automatically enable "openFinderAfterReceiving" 2025-09-09 14:11:54 +02:00
Leon Böttger fd6978cc90 Add alert when selecting invalid folder for storing files 2025-09-09 13:58:36 +02:00
Leon Böttger 12ef87c4da Simplify Menu Bar Items 2025-09-09 12:49:56 +02:00
Leon Böttger 518fabcd33 Add translations for InfoPlist 2025-09-09 12:33:56 +02:00
Leon Böttger eb6bb8fc4d Add more languages 2025-09-09 12:10:47 +02:00
Leon Böttger d443412697 Fix iOS 2025-09-09 11:40:27 +02:00
Leon Böttger 110b0a4ae7 Add alert if share extension disabled 2025-09-09 11:35:44 +02:00
Leon Böttger 2b272c81c1 Refactoring 2025-09-09 11:14:29 +02:00
Leon Böttger 11afc232ab Refactoring UserDefaults 2025-09-09 11:08:13 +02:00
Leon Böttger 943414db58 Fix iOS compilation 2025-09-05 19:31:29 +02:00
Leon Böttger b135229d30 Fix: Mac showed no connection when connected using Ethernet 2025-09-05 19:25:56 +02:00
Leon Böttger 6126d9428d Merge pull request #3 from leonboe1/ios
Add QuickDrop for iOS
2025-09-05 18:56:26 +02:00
104 changed files with 18939 additions and 820 deletions

No files matched your search

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 488 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 492 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -392,6 +392,13 @@ class InboundNearbyConnection: NearbyConnection {
let pkeFrame = frame.v1.pairedKeyEncryption
if frame.v1.certificateInfo.publicCertificate.isEmpty {
log("[InboundNearbyConnection \(self.id)] Detected legacy peer.")
}
else {
log("[InboundNearbyConnection \(self.id)] Detected QuickDrop peer.")
}
// Check if we can accept the connection automatically
if !pkeFrame.secretIDHash.isEmpty,
let trustedCertData = TrustStore.shared.findTrustedKey(for: pkeFrame.secretIDHash),
@@ -461,9 +468,11 @@ class InboundNearbyConnection: NearbyConnection {
}
private func makeFileDestinationURL(_ initialDest: URL) -> URL {
private func makeFileDestinationURL(_ initialDest: URL, usedDestinations: Set<URL>) -> URL {
var dest = initialDest
if FileManager.default.fileExists(atPath: dest.path) {
let fm = FileManager.default
if fm.fileExists(atPath: dest.path) || usedDestinations.contains(dest) {
var counter = 1
var path: String
let ext = dest.pathExtension
@@ -474,8 +483,8 @@ class InboundNearbyConnection: NearbyConnection {
path += ".\(ext)"
}
counter += 1
} while FileManager.default.fileExists(atPath: path)
dest = URL(fileURLWithPath: path)
dest = URL(fileURLWithPath: path)
} while fm.fileExists(atPath: dest.path) || usedDestinations.contains(dest)
}
return dest
}
@@ -487,12 +496,18 @@ class InboundNearbyConnection: NearbyConnection {
if frame.v1.introduction.fileMetadata.count > 0 && frame.v1.introduction.textMetadata.isEmpty {
let saveDirectory = SaveFilesManager.shared.getSaveDirectory()
var usedDestinations = Set<URL>()
for file in frame.v1.introduction.fileMetadata {
let dest = makeFileDestinationURL(saveDirectory.appendingPathComponent(file.name))
let info = InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
payloadID: file.payloadID,
destinationURL: dest)
let initialDest = saveDirectory.appendingPathComponent(file.name)
let dest = makeFileDestinationURL(initialDest, usedDestinations: usedDestinations)
usedDestinations.insert(dest)
let info = InternalFileInfo(
meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
payloadID: file.payloadID,
destinationURL: dest
)
filesToBeReceived[file.payloadID] = info
bytesToBeTransferred += file.size
}
@@ -524,7 +539,7 @@ class InboundNearbyConnection: NearbyConnection {
func checkIfCanProceed(metadata: TransferMetadata) {
let acceptAutomatically = isAuthenticated || UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue)
let acceptAutomatically = isAuthenticated || Settings.shared.automaticallyAcceptFiles
DispatchQueue.main.async {
self.delegate?.obtainUserConsent(transfer: metadata, device: self.remoteDeviceInfo!, connection: self, acceptAutomatically: acceptAutomatically)
@@ -638,12 +653,7 @@ class InboundNearbyConnection: NearbyConnection {
#endif
guard file.created else { continue }
do {
try FileManager.default.removeItem(at: file.destinationURL)
}
catch {
// if it fails, we don't care. Could be because file was not created yet
}
try? FileManager.default.removeItem(at: file.destinationURL)
}
}
}
@@ -7,7 +7,7 @@
#if os(iOS)
import UIKit
import RNDeviceName
import DeviceKit
#endif
import Foundation
@@ -16,6 +16,7 @@ import System
import SwiftECC
import CryptoKit
import SwiftUI
import QRCode
public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearbyConnectionDelegate, OutboundNearbyConnectionDelegate, ObservableObject {
@@ -44,12 +45,12 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
public static let shared = NearbyConnectionManager()
@Published var attachments: AttachmentDetails? = nil
@Published var hasLocalNetworkAccess = true
@Published var isConnectedViaWiFi = true
@Published var hasLocalNetworkPermission = true
@Published var isConnectedToLocalNetwork = true
public var connectionUpdateCallback: (Bool) -> Void = { _ in } {
didSet {
connectionUpdateCallback(isConnectedViaWiFi)
connectionUpdateCallback(isConnectedToLocalNetwork)
}
}
@@ -58,7 +59,7 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
#if os(macOS)
self.deviceInfo = EndpointInfo(name: Host.current().localizedName ?? "Mac", deviceType: .computer)
#else
let marketingName = UIDevice.current.marketingName.withoutBracketedContent
let marketingName = Device.current.description.withoutBracketedContent
let isiPad = UIDevice.current.model == "iPad"
self.deviceInfo = EndpointInfo(name: marketingName, deviceType: isiPad ? .tablet : .phone)
@@ -69,18 +70,23 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
super.init()
hasConnectionMonitor.pathUpdateHandler = { path in
if path.usesInterfaceType(.wifi) {
log("[NearbyConnectionManager] Connected via WiFi.")
DispatchQueue.main.async {
self.isConnectedViaWiFi = true
self.connectionUpdateCallback(true)
}
} else {
log("[NearbyConnectionManager] WiFi connection lost.")
DispatchQueue.main.async {
self.isConnectedViaWiFi = false
self.connectionUpdateCallback(false)
#if os(macOS)
// On Mac, the local network is available as long as the path is satisfied, since Macs do not have cellular modems
let isConnected = path.status == .satisfied
#else
// On iPhone and iPad, the local network is only available using Wi-Fi or Ethernet
let isConnected = path.usesInterfaceType(.wifi) || path.usesInterfaceType(.wiredEthernet)
#endif
DispatchQueue.main.async {
if isConnected {
log("[NearbyConnectionManager] Connected to local network.")
} else {
log("[NearbyConnectionManager] Local network lost.")
}
self.isConnectedToLocalNetwork = isConnected
self.connectionUpdateCallback(isConnected)
}
}
@@ -130,12 +136,10 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
private static func generateEndpointID() -> [UInt8] {
let userDefaultsKey = UserDefaultsKeys.endpointID.rawValue
// Try to retrieve from UserDefaults
if let savedString = UserDefaults.standard.string(forKey: userDefaultsKey),
let savedData = savedString.data(using: .utf8)
{
if let savedString = Settings.shared.endpointID,
let savedData = savedString.data(using: .utf8) {
return [UInt8](savedData)
}
@@ -148,7 +152,7 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
// Save to UserDefaults as String
let idString = String(bytes: id, encoding: .utf8) ?? ""
UserDefaults.standard.set(idString, forKey: userDefaultsKey)
Settings.shared.endpointID = idString
return id
}
@@ -245,13 +249,13 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
log("[NearbyConnectionManager] Browser failed: \(error)")
case .ready:
log("[NearbyConnectionManager] Browser ready")
self.hasLocalNetworkAccess = true
self.hasLocalNetworkPermission = true
case .waiting(let error):
log("[NearbyConnectionManager] Browser waiting: \(error)")
if error == NWError.dns(DNSServiceErrorType(kDNSServiceErr_PolicyDenied)) {
log("[NearbyConnectionManager] Local network access not granted.")
self.hasLocalNetworkAccess = false
self.hasLocalNetworkPermission = false
}
default:
break
@@ -394,13 +398,17 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
}
public func generateQrCodeKey() -> String{
public func generateQrCodeKey() -> Image? {
log("[NearbyConnectionManager] Generating new QR code key")
let domain = Domain.instance(curve: .EC256r1)
let (pubKey, privKey) = domain.makeKeyPair()
qrCodePrivateKey = privKey
var keyData = Data()
keyData.append(contentsOf: [0, 0, 2])
let keyBytes = Data(pubKey.w.x.asSignedBytes())
// Sometimes, for some keys, there will be a leading zero byte. Strip that, Android really hates it (it breaks the endpoint info)
keyData.append(keyBytes.suffixOfAtMost(numBytes: 32))
@@ -408,7 +416,26 @@ public class NearbyConnectionManager: NSObject, NetServiceDelegate, InboundNearb
qrCodeAdvertisingToken = HKDF.deriveKey(ikm: ikm, salt: Data(), info: "advertisingContext".data(using: .utf8)!, outputLength: 16).data()
qrCodeNameEncryptionKey = HKDF.deriveKey(ikm: ikm, salt: Data(), info: "encryptionKey".data(using: .utf8)!, outputLength: 16)
return keyData.urlSafeBase64EncodedString()
do {
let qrKey = keyData.urlSafeBase64EncodedString()
let qrCodeImage = try QRCode.build
.text("https://quickshare.google/qrcode#key=\(qrKey)")
.backgroundColor(CGColor(srgbRed: 1, green: 1, blue: 1, alpha: 0))
.quietZonePixelCount(3)
.onPixels.shape(.circle())
.eye.shape(.squircle())
.errorCorrection(.low)
.generate
.image(dimension: 1000)
return Image(decorative: qrCodeImage, scale: 1.0, orientation: .up)
}
catch {
log("Error generating QR code: \(error)")
}
return nil
}
+3 -20
View File
@@ -110,23 +110,11 @@ extension String {
}
public enum UserDefaultsKeys: String, CaseIterable {
case isEligibleForIap = "isEligibleForIap"
case appLaunchedBefore = "ShowedWelcomeScreen"
case plusVersion = "isPlusVersion"
case transmissionCount = "reviewRequestCountKey"
case automaticallyAcceptFiles = "automaticallyAcceptFiles"
case saveFolderBookmark = "saveFolderBookmark"
case openFinderAfterReceiving = "openFinderAfterReceiving"
case endpointID = "endpointID"
}
public func isPlusVersion() -> Bool {
public func fullVersion() -> Bool {
#if os(macOS)
// Enable full functionality if app distributed directly
return DistributionDetector.isDirectDistributionEnabled || UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue)
return Settings.shared.gotPlus || DistributionDetector.isDirectDistributionEnabled
#else
// iOS
return true
@@ -135,10 +123,5 @@ public func isPlusVersion() -> Bool {
public func isFileTransferRestricted() -> Bool {
(!isPlusVersion() && incomingTransmissionCount() > 1)
}
public func incomingTransmissionCount() -> Int {
return UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue)
(!fullVersion() && Settings.shared.incomingTransmissionCount > 1)
}
+3 -3
View File
@@ -59,7 +59,7 @@ public class SaveFilesManager {
public func movePendingFilesToTarget() {
if isPlusVersion() {
if fullVersion() {
do {
let fileManager = FileManager.default
let files = try fileManager.contentsOfDirectory(at: tempDirectory, includingPropertiesForKeys: nil)
@@ -119,7 +119,7 @@ public class SaveFilesManager {
if !filesFinishedDownloadingSinceLastRun.isEmpty && !isFileTransferRestricted() {
#if os(macOS)
if UserDefaults.standard.bool(forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue) {
if Settings.shared.openFinderAfterReceiving {
log("[SaveFilesManager] Opening \(filesFinishedDownloadingSinceLastRun.count) file(s) in Finder.")
NSWorkspace.shared.activateFileViewerSelecting(filesFinishedDownloadingSinceLastRun)
}
@@ -171,7 +171,7 @@ public class SaveFilesManager {
return securityScopeUrl
}
if let bookmarkData = UserDefaults.standard.data(forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) {
if let bookmarkData = Settings.shared.saveFolderBookmark {
var isStale = false
do {
+114 -102
View File
@@ -17,6 +17,20 @@
EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; };
EB05DFBF2E59FD0A00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; };
EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */; };
EB1325D32E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; };
EB1325D42E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; };
EB1325D52E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; };
EB1325D62E701D8E00FD749C /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325D22E701D8900FD749C /* Settings.swift */; };
EB1325EB2E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; };
EB1325EC2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; };
EB1325ED2E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; };
EB1325F42E7025D900FD749C /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E92E7025D900FD749C /* ApIsolationTester.swift */; };
EB1325F52E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */; };
EB1325F62E7025D900FD749C /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */; };
EB1325F82E70288300FD749C /* SendToExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325F72E70287C00FD749C /* SendToExtension.swift */; };
EB1325FA2E70288300FD749C /* SendToExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB1325F72E70287C00FD749C /* SendToExtension.swift */; };
EB1325FD2E7034B000FD749C /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = EB1325FC2E7034B000FD749C /* InfoPlist.xcstrings */; };
EB1325FE2E7034B000FD749C /* InfoPlist.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = EB1325FC2E7034B000FD749C /* InfoPlist.xcstrings */; };
EB16B6122E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; };
EB16B6132E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; };
EB16B6142E58B4B9007D9792 /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB16B6112E58B4B9007D9792 /* IdentityManager.swift */; };
@@ -97,16 +111,18 @@
EB704A822E4A7BB3008E608F /* DistributionDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB704A812E4A7BAE008E608F /* DistributionDetector.swift */; };
EB704A832E4B10D4008E608F /* DistributionDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB704A812E4A7BAE008E608F /* DistributionDetector.swift */; };
EB704A842E4B10D4008E608F /* DistributionDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB704A812E4A7BAE008E608F /* DistributionDetector.swift */; };
EB721F242E75AFA900F2099F /* QuickDropIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = EB721F232E75AFA900F2099F /* QuickDropIcon.icon */; };
EB721F252E75AFA900F2099F /* QuickDropIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = EB721F232E75AFA900F2099F /* QuickDropIcon.icon */; };
EB7654782E525ACC006B4AA3 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = EB7654772E525ACC006B4AA3 /* MainMenu.xib */; };
EB7654A12E53252D006B4AA3 /* AttachmentDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB950B762E521712002D68FA /* AttachmentDetails.swift */; };
EB7654C02E534A8E006B4AA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DA9A1329E0BF5200A442DA /* Assets.xcassets */; };
EB7654C12E534A8E006B4AA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 69DA9A1329E0BF5200A442DA /* Assets.xcassets */; };
EB7654C42E534E89006B4AA3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EB7654C32E534E89006B4AA3 /* InfoPlist.strings */; };
EB7654C62E534E89006B4AA3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EB7654C32E534E89006B4AA3 /* InfoPlist.strings */; };
EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; };
EB7F54122D78E96000989564 /* TutorialView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7F54112D78E95C00989564 /* TutorialView.swift */; };
EB7F54142D78E9E700989564 /* LicenseWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7F54132D78E9E400989564 /* LicenseWindow.swift */; };
EB821C992E76FE5300036963 /* SmallSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */; };
EB821C9A2E76FE5300036963 /* SmallSheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB96ED8A2D7F7CF4004B3FF1 /* SmallSheetView.swift */; };
EB886E522E4E19390052B7D9 /* HKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB886E512E4E19390052B7D9 /* HKDF.swift */; };
EB886E532E4E19390052B7D9 /* HKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB886E512E4E19390052B7D9 /* HKDF.swift */; };
EB886E542E4E19390052B7D9 /* HKDF.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB886E512E4E19390052B7D9 /* HKDF.swift */; };
@@ -152,7 +168,6 @@
EB950B612E520674002D68FA /* SwiftECC in Frameworks */ = {isa = PBXBuildFile; productRef = EB950B602E520674002D68FA /* SwiftECC */; };
EB950B632E52067A002D68FA /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = EB950B622E52067A002D68FA /* QRCode */; };
EB950B652E52067D002D68FA /* LUI in Frameworks */ = {isa = PBXBuildFile; productRef = EB950B642E52067D002D68FA /* LUI */; };
EB950B672E520680002D68FA /* RNDeviceName in Frameworks */ = {isa = PBXBuildFile; productRef = EB950B662E520680002D68FA /* RNDeviceName */; };
EB950B6F2E5206E2002D68FA /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB950B6B2E5206E2002D68FA /* ShareViewController.swift */; };
EB950B702E520734002D68FA /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = EB5C36922E34EBBD0052EFD7 /* Localizable.xcstrings */; };
EB950B742E520957002D68FA /* Attachments.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB950B732E520954002D68FA /* Attachments.swift */; };
@@ -173,7 +188,6 @@
EB979F9A2E50CAA6008B8C5C /* PieProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB979F992E50CAA6008B8C5C /* PieProgressView.swift */; };
EB97A00F2E511124008B8C5C /* ReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB97A00E2E511120008B8C5C /* ReceiveModel.swift */; };
EB97A0102E51CD13008B8C5C /* ReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB97A00E2E511120008B8C5C /* ReceiveModel.swift */; };
EB97A0132E51D6B2008B8C5C /* RNDeviceName in Frameworks */ = {isa = PBXBuildFile; productRef = EB97A0122E51D6B2008B8C5C /* RNDeviceName */; };
EB97A0142E51DD00008B8C5C /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB5C36E32E34EC0E0052EFD7 /* License.txt */; };
EB97A0152E51DD00008B8C5C /* timeIsNow.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = EBC05C8A2E33B59E00EECC18 /* timeIsNow.mp3 */; };
EB97A01A2E51EAA2008B8C5C /* UIAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB97A0192E51EA9C008B8C5C /* UIAlert.swift */; };
@@ -183,16 +197,13 @@
EB9925852E45EF0900357055 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = EB9925842E45EF0900357055 /* QRCode */; };
EB9925872E45F12F00357055 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = EB9925862E45F12F00357055 /* QRCode */; };
EB9925892E45F13500357055 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = EB9925882E45F13500357055 /* QRCode */; };
EBADEB8F2E8029750021B5E4 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = EBADEB8E2E8029750021B5E4 /* DeviceKit */; };
EBADEB912E802A830021B5E4 /* DeviceKit in Frameworks */ = {isa = PBXBuildFile; productRef = EBADEB902E802A830021B5E4 /* DeviceKit */; };
EBC05C5B2E33937200EECC18 /* ErrorAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C5A2E33936C00EECC18 /* ErrorAlertHandler.swift */; };
EBC05C5C2E3394EF00EECC18 /* ErrorAlertHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C5A2E33936C00EECC18 /* ErrorAlertHandler.swift */; };
EBC05C712E33B57D00EECC18 /* Converter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6D2E33B57D00EECC18 /* Converter.swift */; };
EBC05C722E33B57D00EECC18 /* Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6E2E33B57D00EECC18 /* Helper.swift */; };
EBC05C732E33B57D00EECC18 /* PlusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C6F2E33B57D00EECC18 /* PlusView.swift */; };
EBC05C782E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */; };
EBC05C792E33B58100EECC18 /* ApIsolation6Tester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */; };
EBC05C7A2E33B58100EECC18 /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */; };
EBC05C7B2E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */; };
EBC05C7C2E33B58100EECC18 /* ApIsolationTester.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */; };
EBC05C822E33B58300EECC18 /* ApIsolationIssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7D2E33B58300EECC18 /* ApIsolationIssueView.swift */; };
EBC05C832E33B58300EECC18 /* FirewallIssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7E2E33B58300EECC18 /* FirewallIssueView.swift */; };
EBC05C842E33B58300EECC18 /* IssueView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBC05C7F2E33B58300EECC18 /* IssueView.swift */; };
@@ -303,6 +314,12 @@
69DA9A2C29E18CB500A442DA /* securegcm.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securegcm.pb.swift; sourceTree = "<group>"; };
69DA9A2D29E18CB500A442DA /* securemessage.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = securemessage.pb.swift; sourceTree = "<group>"; };
EB05DFBD2E59FC8000EF567A /* TrustedDevicesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustedDevicesView.swift; sourceTree = "<group>"; };
EB1325D22E701D8900FD749C /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveNetworkInterface.swift; sourceTree = "<group>"; };
EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolation6Tester.swift; sourceTree = "<group>"; };
EB1325E92E7025D900FD749C /* ApIsolationTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationTester.swift; sourceTree = "<group>"; };
EB1325F72E70287C00FD749C /* SendToExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendToExtension.swift; sourceTree = "<group>"; };
EB1325FC2E7034B000FD749C /* InfoPlist.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = InfoPlist.xcstrings; sourceTree = "<group>"; };
EB16B6112E58B4B9007D9792 /* IdentityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityManager.swift; sourceTree = "<group>"; };
EB16B6162E58B4C8007D9792 /* TrustStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TrustStore.swift; sourceTree = "<group>"; };
EB16B7762E59BA9F007D9792 /* AppGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppGroup.swift; sourceTree = "<group>"; };
@@ -319,23 +336,8 @@
EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchAtLogin.swift; sourceTree = "<group>"; };
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
EB704A812E4A7BAE008E608F /* DistributionDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DistributionDetector.swift; sourceTree = "<group>"; };
EB721F232E75AFA900F2099F /* QuickDropIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = folder.iconcomposer.icon; path = QuickDropIcon.icon; sourceTree = "<group>"; };
EB7654772E525ACC006B4AA3 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = "<group>"; };
EB7654C22E534E89006B4AA3 /* InfoPlist.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = de.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654C82E534F2C006B4AA3 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654C92E534F2D006B4AA3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
EB7654CA2E534F31006B4AA3 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654CB2E534F32006B4AA3 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654CC2E534F33006B4AA3 /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654CD2E534F33006B4AA3 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654CE2E534F34006B4AA3 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654CF2E534F35006B4AA3 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654D02E534F35006B4AA3 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
EB7654D12E534F41006B4AA3 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/InfoPlist.strings"; sourceTree = "<group>"; };
EB7654D22E534F42006B4AA3 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654D32E534F43006B4AA3 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654D42E534F43006B4AA3 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654D52E534F44006B4AA3 /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7654D62E534F45006B4AA3 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
EB7F54112D78E95C00989564 /* TutorialView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TutorialView.swift; sourceTree = "<group>"; };
EB7F54132D78E9E400989564 /* LicenseWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicenseWindow.swift; sourceTree = "<group>"; };
@@ -364,9 +366,6 @@
EBC05C6D2E33B57D00EECC18 /* Converter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Converter.swift; sourceTree = "<group>"; };
EBC05C6E2E33B57D00EECC18 /* Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Helper.swift; sourceTree = "<group>"; };
EBC05C6F2E33B57D00EECC18 /* PlusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlusView.swift; sourceTree = "<group>"; };
EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveNetworkInterface.swift; sourceTree = "<group>"; };
EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolation6Tester.swift; sourceTree = "<group>"; };
EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationTester.swift; sourceTree = "<group>"; };
EBC05C7D2E33B58300EECC18 /* ApIsolationIssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApIsolationIssueView.swift; sourceTree = "<group>"; };
EBC05C7E2E33B58300EECC18 /* FirewallIssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirewallIssueView.swift; sourceTree = "<group>"; };
EBC05C7F2E33B58300EECC18 /* IssueView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IssueView.swift; sourceTree = "<group>"; };
@@ -402,8 +401,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EB97A0132E51D6B2008B8C5C /* RNDeviceName in Frameworks */,
EB5C37F02E377C3F0052EFD7 /* SwiftECC in Frameworks */,
EBADEB8F2E8029750021B5E4 /* DeviceKit in Frameworks */,
EB886E582E4E66420052B7D9 /* LUI in Frameworks */,
EB5C37EE2E377C3F0052EFD7 /* SwiftProtobuf in Frameworks */,
EB9925892E45F13500357055 /* QRCode in Frameworks */,
@@ -414,8 +413,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
EB950B672E520680002D68FA /* RNDeviceName in Frameworks */,
EB950B612E520674002D68FA /* SwiftECC in Frameworks */,
EBADEB912E802A830021B5E4 /* DeviceKit in Frameworks */,
EB950B652E52067D002D68FA /* LUI in Frameworks */,
EB950B5F2E520671002D68FA /* SwiftProtobuf in Frameworks */,
EB950B632E52067A002D68FA /* QRCode in Frameworks */,
@@ -450,6 +449,7 @@
69DA9A0529E0BF5100A442DA = {
isa = PBXGroup;
children = (
EB721F232E75AFA900F2099F /* QuickDropIcon.icon */,
69DA9A1029E0BF5100A442DA /* QuickDrop */,
699DEBA22AB0573200115D22 /* ShareExtension */,
69DCF4822AB70D0600CBE2CC /* NearbyShare */,
@@ -476,8 +476,9 @@
isa = PBXGroup;
children = (
69DA9A1129E0BF5100A442DA /* AppDelegate.swift */,
EB1325D22E701D8900FD749C /* Settings.swift */,
EB1325EA2E7025D900FD749C /* SelfTest */,
EBC05C6A2E33B55100EECC18 /* View */,
EBC05C772E33B58100EECC18 /* SelfTest */,
EBC05C6B2E33B57100EECC18 /* Util */,
EBC05C702E33B57D00EECC18 /* Plus */,
69DA9A1329E0BF5200A442DA /* Assets.xcassets */,
@@ -511,6 +512,16 @@
path = NearbyShare;
sourceTree = "<group>";
};
EB1325EA2E7025D900FD749C /* SelfTest */ = {
isa = PBXGroup;
children = (
EB1325E72E7025D900FD749C /* ActiveNetworkInterface.swift */,
EB1325E82E7025D900FD749C /* ApIsolation6Tester.swift */,
EB1325E92E7025D900FD749C /* ApIsolationTester.swift */,
);
path = SelfTest;
sourceTree = "<group>";
};
EB5C371C2E3669010052EFD7 /* Util */ = {
isa = PBXGroup;
children = (
@@ -573,7 +584,7 @@
isa = PBXGroup;
children = (
EB97A0162E51DF4F008B8C5C /* Info.plist */,
EB7654C32E534E89006B4AA3 /* InfoPlist.strings */,
EB1325FC2E7034B000FD749C /* InfoPlist.xcstrings */,
EB979F8D2E50CA23008B8C5C /* Configuration.swift */,
EB979F8E2E50CA23008B8C5C /* ContentView.swift */,
EB979F8F2E50CA23008B8C5C /* FilePicker.swift */,
@@ -604,6 +615,7 @@
EBC05C6B2E33B57100EECC18 /* Util */ = {
isa = PBXGroup;
children = (
EB1325F72E70287C00FD749C /* SendToExtension.swift */,
EB5C383E2E38C49D0052EFD7 /* LaunchAtLogin.swift */,
EB886E662E4F2F7C0052B7D9 /* License.swift */,
EB36435F2D73A29F009CDFF8 /* AudioManager.swift */,
@@ -623,16 +635,6 @@
path = Plus;
sourceTree = "<group>";
};
EBC05C772E33B58100EECC18 /* SelfTest */ = {
isa = PBXGroup;
children = (
EBC05C742E33B58100EECC18 /* ActiveNetworkInterface.swift */,
EBC05C752E33B58100EECC18 /* ApIsolation6Tester.swift */,
EBC05C762E33B58100EECC18 /* ApIsolationTester.swift */,
);
path = SelfTest;
sourceTree = "<group>";
};
EBC05C812E33B58300EECC18 /* IssueViews */ = {
isa = PBXGroup;
children = (
@@ -722,7 +724,7 @@
EB5C37EF2E377C3F0052EFD7 /* SwiftECC */,
EB9925882E45F13500357055 /* QRCode */,
EB886E572E4E66420052B7D9 /* LUI */,
EB97A0122E51D6B2008B8C5C /* RNDeviceName */,
EBADEB8E2E8029750021B5E4 /* DeviceKit */,
);
productName = QuickDropiOS;
productReference = EB5C37E22E377C2E0052EFD7 /* QuickDropiOS.app */;
@@ -746,7 +748,7 @@
EB950B602E520674002D68FA /* SwiftECC */,
EB950B622E52067A002D68FA /* QRCode */,
EB950B642E52067D002D68FA /* LUI */,
EB950B662E520680002D68FA /* RNDeviceName */,
EBADEB902E802A830021B5E4 /* DeviceKit */,
);
productName = iOSShareExtension;
productReference = EB950B2D2E52027F002D68FA /* iOSShareExtension.appex */;
@@ -760,7 +762,7 @@
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 1640;
LastUpgradeCheck = 1640;
LastUpgradeCheck = 2600;
TargetAttributes = {
699DEBA02AB0573200115D22 = {
CreatedOnToolsVersion = 14.3.1;
@@ -808,7 +810,7 @@
EB2F9BFC2DA05F48004010A2 /* XCRemoteSwiftPackageReference "BezelNotification" */,
EB9925832E45EF0900357055 /* XCRemoteSwiftPackageReference "qrcode" */,
EB886E562E4E66420052B7D9 /* XCRemoteSwiftPackageReference "LUI" */,
EB97A0112E51D6B2008B8C5C /* XCRemoteSwiftPackageReference "RNDeviceName" */,
EBADEB8B2E8029420021B5E4 /* XCRemoteSwiftPackageReference "DeviceKit" */,
);
productRefGroup = 69DA9A0F29E0BF5100A442DA /* Products */;
projectDirPath = "";
@@ -845,6 +847,7 @@
EB5C36E42E34EC0E0052EFD7 /* License.txt in Resources */,
EB5C36932E34EBBD0052EFD7 /* Localizable.xcstrings in Resources */,
EBC05C8C2E33B59E00EECC18 /* timeIsNow.mp3 in Resources */,
EB721F252E75AFA900F2099F /* QuickDropIcon.icon in Resources */,
EB5C38392E38C1F60052EFD7 /* justMaybe.mp3 in Resources */,
EB7654782E525ACC006B4AA3 /* MainMenu.xib in Resources */,
);
@@ -855,9 +858,10 @@
buildActionMask = 2147483647;
files = (
EB5C383B2E38C1F60052EFD7 /* justMaybe.mp3 in Resources */,
EB7654C42E534E89006B4AA3 /* InfoPlist.strings in Resources */,
EB1325FD2E7034B000FD749C /* InfoPlist.xcstrings in Resources */,
EB97A0142E51DD00008B8C5C /* License.txt in Resources */,
EB97A0152E51DD00008B8C5C /* timeIsNow.mp3 in Resources */,
EB721F242E75AFA900F2099F /* QuickDropIcon.icon in Resources */,
EB886E552E4E50F40052B7D9 /* Localizable.xcstrings in Resources */,
EB7654C02E534A8E006B4AA3 /* Assets.xcassets in Resources */,
);
@@ -868,7 +872,7 @@
buildActionMask = 2147483647;
files = (
EB950B5B2E52065A002D68FA /* timeIsNow.mp3 in Resources */,
EB7654C62E534E89006B4AA3 /* InfoPlist.strings in Resources */,
EB1325FE2E7034B000FD749C /* InfoPlist.xcstrings in Resources */,
EB950B702E520734002D68FA /* Localizable.xcstrings in Resources */,
EB950B5C2E52065A002D68FA /* justMaybe.mp3 in Resources */,
EB950B5D2E52065A002D68FA /* License.txt in Resources */,
@@ -885,6 +889,7 @@
files = (
EB704A832E4B10D4008E608F /* DistributionDetector.swift in Sources */,
EB96ED902D7F8114004B3FF1 /* Localized.swift in Sources */,
EB1325F82E70288300FD749C /* SendToExtension.swift in Sources */,
EB16B6172E58B4C8007D9792 /* TrustStore.swift in Sources */,
EB886E542E4E19390052B7D9 /* HKDF.swift in Sources */,
EBC05C862E33B58300EECC18 /* NetworkFilterIssueView.swift in Sources */,
@@ -901,13 +906,12 @@
EB5C37C82E377A780052EFD7 /* ukey.pb.swift in Sources */,
EB5C37C92E377A780052EFD7 /* device_to_device_messages.pb.swift in Sources */,
EB950B742E520957002D68FA /* Attachments.swift in Sources */,
EB1325D32E701D8E00FD749C /* Settings.swift in Sources */,
EB16B7782E59BAA1007D9792 /* AppGroup.swift in Sources */,
EB5C383C2E38C2D90052EFD7 /* AudioManager.swift in Sources */,
EB5C37CA2E377A780052EFD7 /* offline_wire_formats.pb.swift in Sources */,
EB16B6122E58B4B9007D9792 /* IdentityManager.swift in Sources */,
EBC05C5C2E3394EF00EECC18 /* ErrorAlertHandler.swift in Sources */,
EBC05C7B2E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */,
EBC05C7C2E33B58100EECC18 /* ApIsolationTester.swift in Sources */,
691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */,
EB5C383F2E38C49D0052EFD7 /* LaunchAtLogin.swift in Sources */,
EB5C37BC2E377A700052EFD7 /* SleepManager.swift in Sources */,
@@ -918,6 +922,9 @@
EB5C37D32E377A7F0052EFD7 /* InboundNearbyConnection.swift in Sources */,
EB5C37D42E377A7F0052EFD7 /* NearbyConnectionManager.swift in Sources */,
EB5C37BD2E377A700052EFD7 /* Helpers.swift in Sources */,
EB1325EB2E7025D900FD749C /* ApIsolationTester.swift in Sources */,
EB1325EC2E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */,
EB1325ED2E7025D900FD749C /* ApIsolation6Tester.swift in Sources */,
EB5C37BE2E377A700052EFD7 /* SaveFilesManager.swift in Sources */,
EB9925822E45D53E00357055 /* sharing_enums.pb.swift in Sources */,
);
@@ -936,6 +943,7 @@
EB05DFBE2E59FC8900EF567A /* TrustedDevicesView.swift in Sources */,
EB16B6182E58B4C8007D9792 /* TrustStore.swift in Sources */,
EBC05C5B2E33937200EECC18 /* ErrorAlertHandler.swift in Sources */,
EB1325D42E701D8E00FD749C /* Settings.swift in Sources */,
EBC05C712E33B57D00EECC18 /* Converter.swift in Sources */,
EB886E5D2E4F13EB0052B7D9 /* Zip.swift in Sources */,
EBC05C722E33B57D00EECC18 /* Helper.swift in Sources */,
@@ -948,15 +956,12 @@
EB16B6152E58B4B9007D9792 /* IdentityManager.swift in Sources */,
EB5C37C42E377A780052EFD7 /* securegcm.pb.swift in Sources */,
EB97A0102E51CD13008B8C5C /* ReceiveModel.swift in Sources */,
EBC05C782E33B58100EECC18 /* ActiveNetworkInterface.swift in Sources */,
EB5C37CB2E377A7F0052EFD7 /* NearbyConnection.swift in Sources */,
EB5C37CC2E377A7F0052EFD7 /* DataModel.swift in Sources */,
EB5C37CD2E377A7F0052EFD7 /* OutboundNearbyConnection.swift in Sources */,
EB5C37CE2E377A7F0052EFD7 /* InboundNearbyConnection.swift in Sources */,
EB5C37CF2E377A7F0052EFD7 /* NearbyConnectionManager.swift in Sources */,
EBC05C792E33B58100EECC18 /* ApIsolation6Tester.swift in Sources */,
EB7654A12E53252D006B4AA3 /* AttachmentDetails.swift in Sources */,
EBC05C7A2E33B58100EECC18 /* ApIsolationTester.swift in Sources */,
EB886E522E4E19390052B7D9 /* HKDF.swift in Sources */,
EB96ED8C2D7F7E7B004B3FF1 /* SmallSheetView.swift in Sources */,
EB886E682E4F2F800052B7D9 /* License.swift in Sources */,
@@ -971,6 +976,10 @@
EB16B77A2E59BAA1007D9792 /* AppGroup.swift in Sources */,
EBC05C822E33B58300EECC18 /* ApIsolationIssueView.swift in Sources */,
EBC05C832E33B58300EECC18 /* FirewallIssueView.swift in Sources */,
EB1325FA2E70288300FD749C /* SendToExtension.swift in Sources */,
EB1325F42E7025D900FD749C /* ApIsolationTester.swift in Sources */,
EB1325F52E7025D900FD749C /* ActiveNetworkInterface.swift in Sources */,
EB1325F62E7025D900FD749C /* ApIsolation6Tester.swift in Sources */,
EBC05C842E33B58300EECC18 /* IssueView.swift in Sources */,
EBC05C852E33B58300EECC18 /* NetworkFilterIssueView.swift in Sources */,
);
@@ -980,6 +989,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
EB821C992E76FE5300036963 /* SmallSheetView.swift in Sources */,
EB05DFBF2E59FD0A00EF567A /* TrustedDevicesView.swift in Sources */,
EB5C37F12E377CE70052EFD7 /* ukey.pb.swift in Sources */,
EB5C37F22E377CE70052EFD7 /* NearbyConnection.swift in Sources */,
@@ -998,6 +1008,7 @@
EB5C37FB2E377CE70052EFD7 /* InboundNearbyConnection.swift in Sources */,
EB9925802E45D53E00357055 /* sharing_enums.pb.swift in Sources */,
EB5C37FC2E377CE70052EFD7 /* OutboundNearbyConnection.swift in Sources */,
EB1325D62E701D8E00FD749C /* Settings.swift in Sources */,
EB5C37FD2E377CE70052EFD7 /* Logger.swift in Sources */,
EB97A00F2E511124008B8C5C /* ReceiveModel.swift in Sources */,
EB5C37FE2E377CE70052EFD7 /* offline_wire_formats.pb.swift in Sources */,
@@ -1044,7 +1055,9 @@
EB05DFC02E5A2EAA00EF567A /* TrustedDevicesView.swift in Sources */,
EB950B542E520436002D68FA /* HKDF.swift in Sources */,
EB950B552E520436002D68FA /* SaveFilesManager.swift in Sources */,
EB1325D52E701D8E00FD749C /* Settings.swift in Sources */,
EB950B562E520436002D68FA /* DataModel.swift in Sources */,
EB821C9A2E76FE5300036963 /* SmallSheetView.swift in Sources */,
EB950B3E2E52038A002D68FA /* SendModel.swift in Sources */,
EB950B772E521712002D68FA /* AttachmentDetails.swift in Sources */,
EB16B6192E58B4C8007D9792 /* TrustStore.swift in Sources */,
@@ -1085,29 +1098,6 @@
name = ShareViewController.xib;
sourceTree = "<group>";
};
EB7654C32E534E89006B4AA3 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
EB7654C22E534E89006B4AA3 /* InfoPlist.strings */,
EB7654C82E534F2C006B4AA3 /* ar */,
EB7654C92E534F2D006B4AA3 /* zh-Hans */,
EB7654CA2E534F31006B4AA3 /* nl */,
EB7654CB2E534F32006B4AA3 /* fr */,
EB7654CC2E534F33006B4AA3 /* hu */,
EB7654CD2E534F33006B4AA3 /* it */,
EB7654CE2E534F34006B4AA3 /* ja */,
EB7654CF2E534F35006B4AA3 /* ko */,
EB7654D02E534F35006B4AA3 /* pt-BR */,
EB7654D12E534F41006B4AA3 /* pt-PT */,
EB7654D22E534F42006B4AA3 /* ro */,
EB7654D32E534F43006B4AA3 /* ru */,
EB7654D42E534F43006B4AA3 /* es */,
EB7654D52E534F44006B4AA3 /* th */,
EB7654D62E534F45006B4AA3 /* uk */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -1121,7 +1111,11 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "${SHARED_BUILD}";
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = QuickDrop;
@@ -1155,7 +1149,11 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "${SHARED_BUILD}";
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_USER_SELECTED_FILES = readonly;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = ShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = QuickDrop;
@@ -1241,8 +1239,9 @@
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SHARED_BUILD = 68;
SHARED_VERSION = 2.2.1;
SHARED_BUILD = 74;
SHARED_VERSION = 2.4.1;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -1303,8 +1302,9 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SHARED_BUILD = 68;
SHARED_VERSION = 2.2.1;
SHARED_BUILD = 74;
SHARED_VERSION = 2.4.1;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
@@ -1314,7 +1314,7 @@
69DA9A1C29E0BF5200A442DA /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_APPICON_NAME = QuickDropIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = QuickDrop/QuickDrop.entitlements;
@@ -1324,7 +1324,12 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "${SHARED_BUILD}";
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readwrite;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_USER_SELECTED_FILES = readwrite;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = QuickDrop/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = QuickDrop;
@@ -1355,7 +1360,7 @@
69DA9A1D29E0BF5200A442DA /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_APPICON_NAME = QuickDropIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = QuickDrop/QuickDrop.entitlements;
@@ -1365,7 +1370,12 @@
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = "${SHARED_BUILD}";
DEAD_CODE_STRIPPING = YES;
ENABLE_APP_SANDBOX = YES;
ENABLE_FILE_ACCESS_DOWNLOADS_FOLDER = readwrite;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_USER_SELECTED_FILES = readwrite;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = QuickDrop/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = QuickDrop;
@@ -1395,7 +1405,7 @@
EB5C37EB2E377C310052EFD7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_APPICON_NAME = QuickDropIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = QuickDropiOS/QuickDropiOS.entitlements;
CODE_SIGN_STYLE = Automatic;
@@ -1408,6 +1418,7 @@
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Leon Böttger";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "Local network access is needed to detect devices and transfer files over your Wi-Fi network.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -1438,7 +1449,7 @@
EB5C37EC2E377C310052EFD7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_APPICON_NAME = QuickDropIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = QuickDropiOS/QuickDropiOS.entitlements;
CODE_SIGN_STYLE = Automatic;
@@ -1451,6 +1462,7 @@
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2025 Leon Böttger";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "Local network access is needed to detect devices and transfer files over your Wi-Fi network.";
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
@@ -1622,14 +1634,6 @@
kind = branch;
};
};
EB97A0112E51D6B2008B8C5C /* XCRemoteSwiftPackageReference "RNDeviceName" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/souzainf3/RNDeviceName";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.1.0;
};
};
EB9925832E45EF0900357055 /* XCRemoteSwiftPackageReference "qrcode" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/dagronf/qrcode.git";
@@ -1638,6 +1642,14 @@
minimumVersion = 26.10.0;
};
};
EBADEB8B2E8029420021B5E4 /* XCRemoteSwiftPackageReference "DeviceKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/devicekit/DeviceKit";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.7.0;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
@@ -1701,16 +1713,6 @@
package = EB886E562E4E66420052B7D9 /* XCRemoteSwiftPackageReference "LUI" */;
productName = LUI;
};
EB950B662E520680002D68FA /* RNDeviceName */ = {
isa = XCSwiftPackageProductDependency;
package = EB97A0112E51D6B2008B8C5C /* XCRemoteSwiftPackageReference "RNDeviceName" */;
productName = RNDeviceName;
};
EB97A0122E51D6B2008B8C5C /* RNDeviceName */ = {
isa = XCSwiftPackageProductDependency;
package = EB97A0112E51D6B2008B8C5C /* XCRemoteSwiftPackageReference "RNDeviceName" */;
productName = RNDeviceName;
};
EB9925842E45EF0900357055 /* QRCode */ = {
isa = XCSwiftPackageProductDependency;
package = EB9925832E45EF0900357055 /* XCRemoteSwiftPackageReference "qrcode" */;
@@ -1726,6 +1728,16 @@
package = EB9925832E45EF0900357055 /* XCRemoteSwiftPackageReference "qrcode" */;
productName = QRCode;
};
EBADEB8E2E8029750021B5E4 /* DeviceKit */ = {
isa = XCSwiftPackageProductDependency;
package = EBADEB8B2E8029420021B5E4 /* XCRemoteSwiftPackageReference "DeviceKit" */;
productName = DeviceKit;
};
EBADEB902E802A830021B5E4 /* DeviceKit */ = {
isa = XCSwiftPackageProductDependency;
package = EBADEB8B2E8029420021B5E4 /* XCRemoteSwiftPackageReference "DeviceKit" */;
productName = DeviceKit;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 69DA9A0629E0BF5100A442DA /* Project object */;
@@ -1,5 +1,5 @@
{
"originHash" : "212cf044c2b0bab89578ca93a3666a656e0c44fb54a69f813c4cc4fae07827d7",
"originHash" : "270e8bfd245fae589b12faf08b86042cbbe7c809d59c5b0b8b735c7fb3a8d4bd",
"pins" : [
{
"identity" : "applewatchscreensize",
@@ -37,13 +37,22 @@
"version" : "1.21.0"
}
},
{
"identity" : "devicekit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/devicekit/DeviceKit",
"state" : {
"revision" : "581df61650bc457ec00373a592a84be3e7468eb1",
"version" : "5.7.0"
}
},
{
"identity" : "lui",
"kind" : "remoteSourceControl",
"location" : "https://github.com/leonboe1/LUI.git",
"state" : {
"branch" : "main",
"revision" : "5b2fe7161069c2314c5be17810ec7471b9decc8a"
"revision" : "123192312165c23271cd49492ae7e4fc676d7711"
}
},
{
@@ -55,15 +64,6 @@
"version" : "26.10.0"
}
},
{
"identity" : "rndevicename",
"kind" : "remoteSourceControl",
"location" : "https://github.com/souzainf3/RNDeviceName",
"state" : {
"revision" : "68ada02a7135381425b01778aeb8719ce3bf8f62",
"version" : "2.1.0"
}
},
{
"identity" : "swift-cross-kit-types",
"kind" : "remoteSourceControl",
@@ -124,7 +124,7 @@
"location" : "https://github.com/siteline/swiftui-introspect",
"state" : {
"branch" : "main",
"revision" : "9bedf1e79c7b7c34b35b74bef126f56d2400ef7f"
"revision" : "d620dacd1423d9545635eee3fc42c1fa1ab2f665"
}
}
],
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1640"
LastUpgradeVersion = "2600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1640"
LastUpgradeVersion = "2600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
@@ -32,8 +32,8 @@
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1640"
LastUpgradeVersion = "2600"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1640"
LastUpgradeVersion = "2600"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
+16 -13
View File
@@ -38,14 +38,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
let menu = NSMenu()
let visibleItem = NSMenuItem(
title: "VisibleToEveryone".localized(),
title: getDefaultVisibleLabel(),
action: nil,
keyEquivalent: ""
)
self.visibleItem = visibleItem
menu.addItem(visibleItem)
menu.addItem(withTitle: String(format: "DeviceName".localized(), arguments: [Host.current().localizedName ?? "Mac"]), action: nil, keyEquivalent: "")
menu.addItem(NSMenuItem.separator())
@@ -70,23 +68,23 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
log("[AppDelegate] Downloaded directly: \(DistributionDetector.isDirectDistributionEnabled)")
// app did not lauch before
if !UserDefaults.standard.bool(forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) {
if !Settings.shared.appLaunchedBefore {
log("[AppDelegate] Opening Welcome Screen")
// open welcome screen
openWelcomeScreen()
UserDefaults.standard.set(true, forKey: UserDefaultsKeys.appLaunchedBefore.rawValue)
Settings.shared.appLaunchedBefore = true
// user installed the app after the IAP was implemented, set the user as eligible for IAP
UserDefaults.standard.set(true, forKey: UserDefaultsKeys.isEligibleForIap.rawValue)
Settings.shared.isEligibleForIap = true
} else {
// app launched before
// user installed the app before the IAP was implemented, grant the plus version
if !UserDefaults.standard.bool(forKey: UserDefaultsKeys.isEligibleForIap.rawValue) {
if !Settings.shared.isEligibleForIap {
log("[AppDelegate] Granting QuickDrop+ for old user")
UserDefaults.standard.set(true, forKey: UserDefaultsKeys.plusVersion.rawValue)
Settings.shared.gotPlus = true
} else {
if !isPlusVersion() {
if !fullVersion() {
log("[AppDelegate] New user - QuickDrop+ not available")
}
else {
@@ -116,7 +114,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
NearbyConnectionManager.shared.connectionUpdateCallback = { isConnected in
if isConnected {
self.statusItem?.button?.image = NSImage(named: "MenuBarIcon")
self.visibleItem?.title = "VisibleToEveryone".localized()
self.visibleItem?.title = self.getDefaultVisibleLabel()
}
else {
self.statusItem?.button?.image = NSImage(named: "MenuBarIconSlash")
@@ -124,7 +122,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
}
log("Application did finish launching")
log("[AppDelegate] Application did finish launching")
}
@@ -191,8 +189,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
}
else {
let sharingService = NSSharingService(named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension"))
sharingService?.perform(withItems: [clipboardString])
sendToSharingService(items: [clipboardString])
}
}
@@ -338,6 +335,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele
}
}
}
private func getDefaultVisibleLabel() -> String {
let name = NearbyConnectionManager.shared.deviceInfo.name ?? "Unknown".localized()
return String(format: "VisibleAs".localized(), name)
}
}
struct TransferInfo {
Binary file not shown.

After

Width:  |  Height:  |  Size: 585 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1016 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 KiB

After

Width:  |  Height:  |  Size: 672 KiB

@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "1024-1024 1.png",
"filename" : "1024-1024 1 2.png",
"idiom" : "universal",
"scale" : "1x"
},
Binary file not shown.

Before

Width:  |  Height:  |  Size: 752 KiB

After

Width:  |  Height:  |  Size: 672 KiB

+1 -1
View File
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "FileTransfer Kopie-1024.png",
"filename" : "FileTransfer Kopie-512.png",
"idiom" : "universal",
"scale" : "1x"
},
Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

+2
View File
@@ -15,5 +15,7 @@
</array>
</dict>
</array>
<key>UIDesignRequiresCompatibility</key>
<true/>
</dict>
</plist>
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -13,7 +13,7 @@ let plusViewHeight: CGFloat = 200
struct PlusView: View {
@AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false
@ObservedObject private var settings = Settings.shared
@ObservedObject private var iaphelper = IAPManager.sharedInstance
let closeView: () -> Void
@@ -115,7 +115,7 @@ struct PlusView: View {
if success {
log("[LUI] Restored purchases successfully")
withAnimation {
isPlusVersion = true
settings.gotPlus = true
}
boughtSuccessAlert = true
} else {
@@ -146,7 +146,7 @@ struct PlusView: View {
if success {
withAnimation {
isPlusVersion = true
settings.gotPlus = true
}
boughtSuccessAlert = true
@@ -193,7 +193,7 @@ struct PlusView: View {
case .success(_):
withAnimation {
isPlusVersion = true
settings.gotPlus = true
boughtSuccessAlert = true
warning = false
}
-10
View File
@@ -2,19 +2,9 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.application-groups</key>
<array>
<string>group.com.leonboettger.neardrop</string>
</array>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
</dict>
</plist>
+79
View File
@@ -0,0 +1,79 @@
//
// Settings.swift
// QuickDrop
//
// Created by Leon Böttger on 09.09.25.
//
import SwiftUI
class Settings: ObservableObject {
private init() {}
static var shared = Settings()
// MARK: - Published UserDefaults Backed Properties
@Published var gotPlus = UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue)
{ didSet { UserDefaults.standard.set(gotPlus, forKey: UserDefaultsKeys.plusVersion.rawValue) }}
@Published var automaticallyAcceptFiles: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue)
{ didSet { UserDefaults.standard.set(automaticallyAcceptFiles, forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue) }}
@Published var openFinderAfterReceiving: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue)
{ didSet { UserDefaults.standard.set(openFinderAfterReceiving, forKey: UserDefaultsKeys.openFinderAfterReceiving.rawValue) }}
@Published var saveFolderBookmark: Data? = UserDefaults.standard.data(forKey: UserDefaultsKeys.saveFolderBookmark.rawValue)
{ didSet { UserDefaults.standard.set(saveFolderBookmark, forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) }}
// MARK: - Non-Published UserDefaults Backed Properties
var incomingTransmissionCount: Int = UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue)
{ didSet { UserDefaults.standard.set(incomingTransmissionCount, forKey: UserDefaultsKeys.transmissionCount.rawValue) }}
var endpointID: String? = UserDefaults.standard.string(forKey: UserDefaultsKeys.endpointID.rawValue)
{ didSet { UserDefaults.standard.set(endpointID, forKey: UserDefaultsKeys.endpointID.rawValue) }}
var isEligibleForIap: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.isEligibleForIap.rawValue)
{ didSet { UserDefaults.standard.set(isEligibleForIap, forKey: UserDefaultsKeys.isEligibleForIap.rawValue) }}
var appLaunchedBefore: Bool = UserDefaults.standard.bool(forKey: UserDefaultsKeys.appLaunchedBefore.rawValue)
{ didSet { UserDefaults.standard.set(appLaunchedBefore, forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) }}
// MARK: - Debug
func deleteAllUserDefaults() {
for key in UserDefaultsKeys.allCases {
UserDefaults.standard.removeObject(forKey: key.rawValue)
}
Settings.shared = Settings()
}
// MARK: - UserDefaults Keys
public enum UserDefaultsKeys: String, CaseIterable {
case isEligibleForIap = "isEligibleForIap"
case appLaunchedBefore = "ShowedWelcomeScreen"
case plusVersion = "isPlusVersion"
case transmissionCount = "reviewRequestCountKey"
case automaticallyAcceptFiles = "automaticallyAcceptFiles"
case saveFolderBookmark = "saveFolderBookmark"
case openFinderAfterReceiving = "openFinderAfterReceiving"
case endpointID = "endpointID"
}
}
+1 -1
View File
@@ -84,7 +84,7 @@ class ErrorAlertHandler {
let title = String(format: "TransferError".localized(), arguments: [deviceName])
log("Showing alert with title: \"\(title)\" and description: \"\(description)\"")
log("Unsuccessful transmission. Already successful transmissions: \(incomingTransmissionCount())")
log("Unsuccessful transmission. Already successful transmissions: \(Settings.shared.incomingTransmissionCount)")
#if os(macOS)
+27
View File
@@ -0,0 +1,27 @@
//
// SendToExtension.swift
// QuickDrop
//
// Created by Leon Böttger on 09.09.25.
//
import Foundation
import AppKit
func sendToSharingService(items: [Any]) {
if let sharingService = NSSharingService(named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension")) {
sharingService.perform(withItems: items)
}
else {
DispatchQueue.main.async {
// show alert
AudioManager.playErrorSound()
let alert = NSAlert()
alert.alertStyle = .critical
alert.messageText = "ShareExtensionDisabledTitle".localized()
alert.informativeText = "ShareExtensionDisabledDescription".localized()
alert.addButton(withTitle: "CloseAlert".localized())
alert.runModal()
}
}
}
+26 -9
View File
@@ -10,15 +10,13 @@ import AppKit
struct SettingsView: View {
@AppStorage(UserDefaultsKeys.automaticallyAcceptFiles.rawValue) private var automaticallyAcceptFiles = false
@AppStorage(UserDefaultsKeys.openFinderAfterReceiving.rawValue) private var openFinderAfterReceiving = false
@AppStorage(UserDefaultsKeys.saveFolderBookmark.rawValue) private var saveFolderPath: Data = Data()
@ObservedObject var settings = Settings.shared
var body: some View {
LargeAppIconView(title: "Settings") {
Form {
Toggle("AutomaticallyAcceptFiles", isOn: $automaticallyAcceptFiles)
Toggle("AutomaticallyAcceptFiles", isOn: $settings.automaticallyAcceptFiles)
.padding(.top, 10)
Text("AutomaticallyAcceptFilesFooter")
@@ -33,7 +31,7 @@ struct SettingsView: View {
Text("SaveFilesTo")
Spacer()
Text(getSavedFolderPath() ?? "DownloadsFolder".localized())
.foregroundColor(saveFolderPath.isEmpty ? .gray : .primary)
.foregroundColor((settings.saveFolderBookmark ?? Data()).isEmpty ? .gray : .primary)
Button("SaveFilesToButton") {
selectFolder()
}
@@ -42,7 +40,7 @@ struct SettingsView: View {
Divider()
.padding(.vertical, 10)
Toggle("OpenFinderAfterReceiving", isOn: $openFinderAfterReceiving)
Toggle("OpenFinderAfterReceiving", isOn: $settings.openFinderAfterReceiving)
.padding(.top, 5)
if #available(macOS 13.0, *) {
@@ -72,10 +70,10 @@ struct SettingsView: View {
private func getSavedFolderPath() -> String? {
if !saveFolderPath.isEmpty {
if let bookmark = settings.saveFolderBookmark, !bookmark.isEmpty {
var isStale = false
do {
let url = try URL(resolvingBookmarkData: saveFolderPath, options: [], relativeTo: nil, bookmarkDataIsStale: &isStale)
let url = try URL(resolvingBookmarkData: bookmark, options: [], relativeTo: nil, bookmarkDataIsStale: &isStale)
return url.lastPathComponent // Returns the folder path as a string
} catch {
log("Failed to resolve bookmark: \(error)")
@@ -96,11 +94,30 @@ struct SettingsView: View {
do {
log("Selected folder: \(url)")
if url.description == "file:///" {
throw NSError(domain: "InvalidSelection", code: 0, userInfo: [NSLocalizedDescriptionKey: "Cannot select root directory. Please choose a specific folder."])
}
let bookmarkData = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
UserDefaults.standard.set(bookmarkData, forKey: UserDefaultsKeys.saveFolderBookmark.rawValue)
Settings.shared.saveFolderBookmark = bookmarkData
Settings.shared.openFinderAfterReceiving = true
} catch {
log("Failed to save security-scoped bookmark: \(error)")
DispatchQueue.main.asyncAfter(deadline: .now()) {
AudioManager.playErrorSound()
// show alert
let alert = NSAlert()
alert.alertStyle = .critical
alert.messageText = "FolderSelectionFailedTitle".localized()
alert.informativeText = "FolderSelectionFailedMessage".localized()
alert.addButton(withTitle: "CloseAlert".localized())
alert.runModal()
}
}
}
}
+4 -6
View File
@@ -15,7 +15,7 @@ struct TutorialView: View {
let openPlus: () -> Void
@State private var licenseWindow: NSWindow?
@AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false
@ObservedObject var settings = Settings.shared
var body: some View {
@@ -40,7 +40,7 @@ struct TutorialView: View {
}
.buttonStyle(.plain)
if !isPlusVersion {
if !settings.gotPlus {
Button {
openPlus()
} label: {
@@ -54,11 +54,9 @@ struct TutorialView: View {
#if DEBUG
Button {
for key in UserDefaultsKeys.allCases {
UserDefaults.standard.removeObject(forKey: key.rawValue)
}
Settings.shared.deleteAllUserDefaults()
} label: {
Text("Reset UD")
Text("ResetAllSettings")
.underline()
.font(.footnote)
.opacity(0.5)
-6
View File
@@ -138,12 +138,6 @@ struct WelcomeScreen: View {
}
}
}
func sendToSharingService(items: [Any]) {
if let sharingService = NSSharingService(named: NSSharingService.Name("com.leonboettger.neardrop.ShareExtension")) {
sharingService.perform(withItems: items)
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

+37
View File
@@ -0,0 +1,37 @@
{
"fill" : {
"linear-gradient" : [
"display-p3:0.31273,0.68878,0.97563,1.00000",
"display-p3:0.22962,0.42793,0.95758,1.00000"
]
},
"groups" : [
{
"layers" : [
{
"image-name" : "QuickDropArrows.png",
"name" : "QuickDropArrows"
},
{
"image-name" : "QuickDropCircle.png",
"name" : "QuickDropCircle",
"opacity" : 0.5
}
],
"shadow" : {
"kind" : "neutral",
"opacity" : 0.5
},
"translucency" : {
"enabled" : true,
"value" : 0.52
}
}
],
"supported-platforms" : {
"circles" : [
"watchOS"
],
"squares" : "shared"
}
}
+6
View File
@@ -10,6 +10,10 @@ import LUI
let configuration = LUIConfiguration(
appName: "QuickDrop",
inAppPurchaseName: "plusversion",
plusVersionInfo: GetPlusViewInformation(description: "plusview_description_phone", plusVersionFeatures: [], settingsLabelColor: .orange, settingsFooter: "plusview_footer_phone"),
hasRoundedFont: false,
copyrightInformation: licenseText,
@@ -24,6 +28,8 @@ let configuration = LUIConfiguration(
supportsSplitView: false,
supportsLiquidGlass: true,
supportsPortraitSplitView: false,
supportsDarkModeShadow: false
+48 -31
View File
@@ -12,13 +12,14 @@ import StoreKit
struct ContentView: View {
@ObservedObject var luiSettings = LUISettings.sharedInstance
@ObservedObject var settings = Settings.shared
var body: some View {
AppRootView(isPlus: .constant(true), phoneView: {
AppRootView(isPlus: $settings.gotPlus, phoneView: {
DeviceListView()
.environment(\.sheetActive, isShareExtension())
}, settingsView: {
CustomSection {
CustomSection(header: settings.gotPlus ? "" : "General", footer: "TrustedDevicesFooterShort") {
LUIButton {
SaveFilesManager.shared.openDownloadedFilesFolder()
} label: {
@@ -37,6 +38,7 @@ struct ContentView: View {
struct DeviceListView: View {
@State private var qrCode: Image? = nil
@StateObject var sendModel = SendModel()
#if !EXTENSION
@@ -44,12 +46,15 @@ struct DeviceListView: View {
#endif
@Environment(\.scenePhase) var scenePhase
@AppStorage("requestedReview") private var requestedReview = false
@Environment(\.sheetActive) var sheetActive
@ObservedObject var nearbyConnectionManager = NearbyConnectionManager.shared
@ObservedObject var settings = Settings.shared
var body: some View {
NavigationSubView(header: "QuickDrop ", navigationBarLayout: isShareExtension() ? .SmallOnlyAlways : .Default) {
let showsLoadingIndicator = nearbyConnectionManager.hasLocalNetworkPermission && nearbyConnectionManager.isConnectedToLocalNetwork
BottomBarView(header: "QuickDrop ", navigationBarLayout: isShareExtension() ? .SmallOnlyAlways : .Default, bottomViewHeight: 30) {
VStack {
VStack(alignment: .leading, spacing: 8) {
@@ -72,14 +77,14 @@ struct DeviceListView: View {
}
.padding(.horizontal, 16)
.padding(.vertical, 6)
.background(Color.defaultForegroundColor)
.background(sheetActive ? Color.sheetForegroundColor : Color.defaultForegroundColor)
.cornerRadius(24)
}
.padding(.horizontal)
.padding(.top, 8)
.frame(maxWidth: .infinity, alignment: .leading)
if !nearbyConnectionManager.hasLocalNetworkAccess {
if !nearbyConnectionManager.hasLocalNetworkPermission {
CardView(backgroundColor: .red, title: "NoNetworkAccess", titleSymbol: "network.slash") {
CardSubView(symbol: "exclamationmark.triangle.fill", text: "NoLocalNetworkAccessDescription")
}
@@ -93,16 +98,22 @@ struct DeviceListView: View {
CustomSection(header: "NoDevicesFound") {
let hasWifi = nearbyConnectionManager.isConnectedViaWiFi
let hasWifi = nearbyConnectionManager.isConnectedToLocalNetwork
HStack(spacing: 12) {
Image(systemName: hasWifi ? "arrow.down.circle.fill" : "wifi.slash")
.font(.system(size: 30))
.foregroundColor(.blue)
.padding(.leading, -10)
.frame(width: 30)
.background(
Circle()
.fill(Color.white)
.padding(3)
.opacity(hasWifi ? 1 : 0)
)
.frame(width: 32)
Text(hasWifi ? "DownloadQuickDropOnPlayStore" : "NoWiFiConnectionDescription")
LUIText(hasWifi ? "DownloadQuickDropOnPlayStore" : "NoWiFiConnectionDescription")
.frame(maxWidth: .infinity, alignment: .leading)
}
.animation(.default, value: hasWifi)
.padding(.vertical)
@@ -119,9 +130,7 @@ struct DeviceListView: View {
if let attachments = NearbyConnectionManager.shared.attachments {
LUIButton {
lightVibration()
sendModel.urls = attachments.urls
sendModel.textToSend = attachments.textToSend
sendModel.selectDevice(device: device)
sendModel.selectDevice(device: device, with: attachments)
} label: {
DeviceButtonLabel(device: device, isSelected: isSelected, progress: sendModel.progressState, progressValue: sendModel.progressValue)
}
@@ -137,7 +146,7 @@ struct DeviceListView: View {
}
if nearbyConnectionManager.hasLocalNetworkAccess && nearbyConnectionManager.isConnectedViaWiFi {
if showsLoadingIndicator {
HStack(spacing: 8) {
Text("SearchingForDevices")
.font(.system(size: 14))
@@ -151,28 +160,37 @@ struct DeviceListView: View {
}
}
.frame(maxWidth: 700)
} bottomView: {
LUIButton {
qrCode = NearbyConnectionManager.shared.generateQrCodeKey()
sendModel.showQrCodeView = true
} label: {
UnderlineText(label: "DeviceNotShown")
.padding()
}
.opacity(showsLoadingIndicator ? 1 : 0)
}
.luiSheet(isPresented: $sendModel.showQrCodeView, content: {
NavigationView {
NavigationSubView(header: "ConnectDevice", navigationBarLayout: .SmallOnlyAlways) {
SmallSheetView(type: .sendToDeviceQrCode, dynamicQrCode: qrCode, closeView: {})
}
.navigationBarItems(trailing: XButton(action: { sendModel.showQrCodeView = false }))
}
})
.onChange(of: scenePhase) { newValue in
if newValue == .active {
log("App became active")
log("[ScenePhase] App became active")
NearbyConnectionManager.shared.startDeviceDiscovery()
#if !EXTENSION
NearbyConnectionManager.shared.becomeVisible()
if incomingTransmissionCount() > 0 && !requestedReview {
if Settings.shared.incomingTransmissionCount > 0 {
runAfter(seconds: 0.3) {
if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
log("Requesting Review...")
SKStoreReviewController.requestReview(in: scene)
requestedReview = true
}
else {
log("Error Requesting Review!")
}
requestReviewOnce()
}
}
#endif
@@ -180,14 +198,15 @@ struct DeviceListView: View {
if newValue == .background {
log("App went to background")
log("[ScenePhase] App went to background")
#if !EXTENSION
NearbyConnectionManager.shared.becomeInvisible()
#endif
NearbyConnectionManager.shared.stopDeviceDiscovery()
}
}
.animation(.smooth, value: nearbyConnectionManager.hasLocalNetworkAccess)
.animation(.smooth, value: nearbyConnectionManager.hasLocalNetworkPermission)
.animation(.smooth, value: nearbyConnectionManager.isConnectedToLocalNetwork)
.navigationBarItems(trailing: ZStack {
if isShareExtension() {
XButton(action: { NearbyConnectionManager.shared.attachments?.closeView?() })
@@ -215,9 +234,7 @@ struct DeviceFilePickerButton: View {
DeviceButtonLabel(device: device, isSelected: isPreparing || isSelected, progress: isPreparing ? "Preparing".localized() : progressState, progressValue: progressValue)
} onResult: { urls, text in
isPreparing = false
sendModel.urls = urls ?? []
sendModel.textToSend = text
sendModel.selectDevice(device: device)
sendModel.selectDevice(device: device, with: AttachmentDetails(urls: urls ?? [], textToSend: text, shortDescription: ""))
} onPrepare: {
isPreparing = true
}
+275
View File
@@ -0,0 +1,275 @@
{
"sourceLanguage" : "en",
"strings" : {
"CFBundleDisplayName" : {
"comment" : "Bundle display name",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "QuickDrop"
}
}
}
},
"CFBundleName" : {
"comment" : "Bundle name",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "QuickDropiOS"
}
}
}
},
"NSHumanReadableCopyright" : {
"comment" : "Copyright (human-readable)",
"extractionState" : "extracted_with_value",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : ""
}
}
}
},
"NSLocalNetworkUsageDescription" : {
"comment" : "Privacy - Local Network Usage Description",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "الوصول إلى الشبكة المحلية مطلوب لاكتشاف الأجهزة ونقل الملفات عبر شبكة Wi-Fi الخاصة بك."
}
},
"ca" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cal accés a la xarxa local per detectar dispositius i transferir fitxers a través de la teva xarxa Wi-Fi."
}
},
"cs" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pro přenos souborů a detekci zařízení přes vaši Wi-Fi síť je třeba povolit přístup k místní síti."
}
},
"da" : {
"stringUnit" : {
"state" : "translated",
"value" : "Adgang til lokalt netværk er nødvendig for at finde enheder og overføre filer via dit Wi-Fi-netværk."
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "Der Zugriff auf das lokale Netzwerk ist erforderlich, um Geräte zu erkennen und Dateien über WLAN zu übertragen."
}
},
"el" : {
"stringUnit" : {
"state" : "translated",
"value" : "Απαιτείται πρόσβαση στο τοπικό δίκτυο για ανίχνευση συσκευών και μεταφορά αρχείων μέσω του Wi-Fi δικτύου σας."
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Local network access is needed to detect devices and transfer files over your Wi-Fi network."
}
},
"en-AU" : {
"stringUnit" : {
"state" : "translated",
"value" : "Local network access is required to find devices and transfer files over your Wi-Fi network."
}
},
"en-CA" : {
"stringUnit" : {
"state" : "translated",
"value" : "Local network access is required to find devices and transfer files over your Wi-Fi network."
}
},
"en-GB" : {
"stringUnit" : {
"state" : "translated",
"value" : "Local network access is required to discover devices and transfer files via your Wi-Fi network."
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "Se necesita acceso a la red local para detectar dispositivos y transferir archivos a través de su red Wi-Fi."
}
},
"es-419" : {
"stringUnit" : {
"state" : "translated",
"value" : "Se necesita acceso a la red local para detectar dispositivos y transferir archivos por tu red Wi-Fi."
}
},
"fi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Lähiverkkoyhteys tarvitaan laitteiden tunnistamiseen ja tiedostojen siirtoon Wi-Fi-verkossasi."
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "L’accès au réseau local est nécessaire pour détecter les appareils et transférer des fichiers via votre réseau Wi-Fi."
}
},
"fr-CA" : {
"stringUnit" : {
"state" : "translated",
"value" : "L’accès au réseau local est nécessaire pour détecter les appareils et transférer des fichiers sur votre réseau Wi-Fi."
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "נדרש גישה לרשת המקומית כדי לזהות מכשירים ולהעביר קבצים דרך רשת ה-Wi-Fi שלך."
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "डिवाइस का पता लगाने और अपने Wi-Fi नेटवर्क पर फाइल ट्रांसफर के लिए लोकल नेटवर्क एक्सेस आवश्यक है।"
}
},
"hr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Pristup lokalnoj mreži potreban je za pronalaženje uređaja i prijenos datoteka putem vaše Wi-Fi mreže."
}
},
"hu" : {
"stringUnit" : {
"state" : "translated",
"value" : "Helyi hálózati hozzáférés szükséges az eszközök felismeréséhez és a fájlok átviteléhez a Wi-Fi hálózatán keresztül."
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "Akses jaringan lokal diperlukan untuk mendeteksi perangkat dan mentransfer file melalui jaringan Wi-Fi Anda."
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "È necessario l’accesso alla rete locale per rilevare i dispositivi e trasferire file tramite la tua rete Wi-Fi."
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "ローカルネットワークへのアクセスは、デバイスを検出し、Wi-Fi ネットワーク経由でファイルを転送するために必要です。"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "장치를 감지하고 Wi-Fi 네트워크를 통해 파일을 전송하려면 로컬 네트워크 접근이 필요합니다."
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "Akses rangkaian tempatan diperlukan untuk mengesan peranti dan memindahkan fail melalui rangkaian Wi-Fi anda."
}
},
"nb" : {
"stringUnit" : {
"state" : "translated",
"value" : "Tilgang til lokalt nettverk er nødvendig for å oppdage enheter og overføre filer via Wi-Fi-nettverket ditt."
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Lokale netwerktoegang is nodig om apparaten te detecteren en bestanden over uw Wi-Fi-netwerk te verzenden."
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "Dostęp do sieci lokalnej jest potrzebny, aby wykrywać urządzenia i przesyłać pliki przez Twoją sieć Wi-Fi."
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "O acesso à rede local é necessário para detectar dispositivos e transferir arquivos pela sua rede Wi-Fi."
}
},
"pt-PT" : {
"stringUnit" : {
"state" : "translated",
"value" : "O acesso à rede local é necessário para detetar dispositivos e transferir ficheiros através da sua rede Wi-Fi."
}
},
"ro" : {
"stringUnit" : {
"state" : "translated",
"value" : "Accesul la rețeaua locală este necesar pentru a detecta dispozitivele și a transfera fișiere prin rețeaua Wi-Fi."
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "Доступ к локальной сети необходим для обнаружения устройств и передачи файлов через вашу сеть Wi-Fi."
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "Åtkomst till lokalt nätverk krävs för att upptäcka enheter och överföra filer via ditt Wi-Fi-nätverk."
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "การเข้าถึงเครือข่ายภายในเครื่องจำเป็นสำหรับการตรวจหาดีไวซ์และการถ่ายโอนไฟล์ผ่านเครือข่าย Wi-Fi ของคุณ"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cihazları algılamak ve dosya aktarmak için yerel ağa erişim gereklidir."
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "Доступ до локальної мережі потрібен для виявлення пристроїв та передавання файлів через вашу мережу Wi-Fi."
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "Cần truy cập mạng nội bộ để phát hiện thiết bị và truyền tệp qua Wi-Fi của bạn."
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "需要本地网络访问以检测设备并通过您的 Wi-Fi 网络传输文件。"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "需要本機網路存取權才能偵測裝置並透過 Wi-Fi 網路傳輸檔案。"
}
}
}
}
},
"version" : "1.0"
}
+2 -2
View File
@@ -174,7 +174,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
showCopiedToClipboardAlert()
}
let currentCount = incomingTransmissionCount()
let currentCount = Settings.shared.incomingTransmissionCount
#if os(macOS)
if currentCount == 0 {
@@ -184,7 +184,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate {
}
#endif
UserDefaults.standard.set(currentCount + 1, forKey: UserDefaultsKeys.transmissionCount.rawValue)
Settings.shared.incomingTransmissionCount = currentCount + 1
log("[ReceiveModel] Successful transmission. Current count: \(currentCount)")
}
}
+28 -2
View File
@@ -12,6 +12,8 @@ import LUI
class SendModel: ObservableObject, OutboundAppDelegate {
@Published var showQrCodeView: Bool = false
@Published var foundDevices: [RemoteDeviceInfo] = []
@Published var selectedDevice: RemoteDeviceInfo?
@@ -24,29 +26,34 @@ class SendModel: ObservableObject, OutboundAppDelegate {
private var connectionEstablished = false
private var timeoutDispatchWorkItem: DispatchWorkItem? = nil
init() {
NearbyConnectionManager.shared.startDeviceDiscovery()
NearbyConnectionManager.shared.addShareExtensionDelegate(self)
}
func addDevice(device: RemoteDeviceInfo) {
withAnimation(.smooth) {
foundDevices.append(device)
}
}
func removeDevice(id: String) {
withAnimation(.smooth) {
foundDevices.removeAll { $0.id == id }
}
}
func connectionWasEstablished(pinCode: String) {
connectionEstablished = true
progressState = String(format: "PinCode".localized(), arguments: [pinCode])
progressValue = 0
}
func connectionFailed(error: any Error) {
#if os(iOS)
@@ -59,14 +66,17 @@ class SendModel: ObservableObject, OutboundAppDelegate {
selectedDevice = nil
}
func transferAccepted() {
progressState = "Sending".localized()
}
func transferProgress(progress: Double) {
progressValue = progress
}
func transferFinished() {
#if os(iOS)
@@ -78,13 +88,28 @@ class SendModel: ObservableObject, OutboundAppDelegate {
progressState = "TransferFinished".localized()
NearbyConnectionManager.shared.attachments?.closeView?()
#if !EXTENSION
requestReviewOnce()
#endif
}
func startTransferWithQrCode(device: RemoteDeviceInfo) {
selectDevice(device: device)
showQrCodeView = false
#if EXTENSION
if let attachments = NearbyConnectionManager.shared.attachments {
self.selectDevice(device:device, with: attachments)
}
#endif
}
func selectDevice(device: RemoteDeviceInfo) {
func selectDevice(device: RemoteDeviceInfo, with attachments: AttachmentDetails) {
self.urls = attachments.urls
self.textToSend = attachments.textToSend
// already selected, cancel transfer
if device == selectedDevice {
@@ -94,6 +119,7 @@ class SendModel: ObservableObject, OutboundAppDelegate {
NearbyConnectionManager.shared.cancelOutgoingTransfer(id: device.id!)
}
else {
progressValue = 0
progressState = "Connecting".localized()
selectedDevice = device
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "الوصول إلى الشبكة المحلية مطلوب لاكتشاف الأجهزة ونقل الملفات عبر شبكة Wi-Fi الخاصة بك.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Der Zugriff auf das lokale Netzwerk ist erforderlich, um Geräte zu erkennen und Dateien über WLAN zu übertragen.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Se necesita acceso a la red local para detectar dispositivos y transferir archivos a través de su red Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "L’accès au réseau local est nécessaire pour détecter les appareils et transférer des fichiers via votre réseau Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Helyi hálózati hozzáférés szükséges az eszközök felismeréséhez és a fájlok átviteléhez a Wi-Fi hálózatán keresztül.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "È necessario l’accesso alla rete locale per rilevare i dispositivi e trasferire file tramite la tua rete Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "ローカルネットワークへのアクセスは、デバイスを検出し、Wi-Fi ネットワーク経由でファイルを転送するために必要です。";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "장치를 감지하고 Wi-Fi 네트워크를 통해 파일을 전송하려면 로컬 네트워크 접근이 필요합니다.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Lokale netwerktoegang is nodig om apparaten te detecteren en bestanden over uw Wi-Fi-netwerk te verzenden.";
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "O acesso à rede local é necessário para detectar dispositivos e transferir arquivos pela sua rede Wi-Fi.";
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "O acesso à rede local é necessário para detetar dispositivos e transferir ficheiros através da sua rede Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Accesul la rețeaua locală este necesar pentru a detecta dispozitivele și a transfera fișiere prin rețeaua Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Доступ к локальной сети необходим для обнаружения устройств и передачи файлов через вашу сеть Wi-Fi.";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "การเข้าถึงเครือข่ายภายในเครื่องจำเป็นสำหรับการตรวจหาดีไวซ์และการถ่ายโอนไฟล์ผ่านเครือข่าย Wi-Fi ของคุณ";
-10
View File
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "Доступ до локальної мережі потрібен для виявлення пристроїв та передавання файлів через вашу мережу Wi-Fi.";
@@ -1,10 +0,0 @@
/*
InfoPlist.strings
AirGuard
Created by Leon Böttger on 23.08.22.
*/
NSLocalNetworkUsageDescription = "需要本地网络访问以检测设备并通过您的 Wi-Fi 网络传输文件。";
+3 -3
View File
@@ -896,9 +896,9 @@ Neither the name of Google Inc. nor the names of its contributors may be used to
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
RNDeviceName
https://github.com/souzainf3/RNDeviceName
Copyright (c) 2014 Romilson Nunes <souzainf3@yahoo.com.br>
DeviceKit
https://github.com/devicekit/DeviceKit
Copyright (c) 2015 Dennis Weissmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+2
View File
@@ -14,5 +14,7 @@
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
</dict>
<key>UIDesignRequiresCompatibility</key>
<true/>
</dict>
</plist>
Loaded 100 of 104 files, more files were not shown because too many files have changed in this diff. Show more