diff --git a/1_anytime.pxd/QuickLook/Icon.webp b/1_anytime.pxd/QuickLook/Icon.webp index aed0f43..fb1ad3e 100644 Binary files a/1_anytime.pxd/QuickLook/Icon.webp and b/1_anytime.pxd/QuickLook/Icon.webp differ diff --git a/1_anytime.pxd/QuickLook/Thumbnail.webp b/1_anytime.pxd/QuickLook/Thumbnail.webp index 37b5cc1..e28257c 100644 Binary files a/1_anytime.pxd/QuickLook/Thumbnail.webp and b/1_anytime.pxd/QuickLook/Thumbnail.webp differ diff --git a/1_anytime.pxd/data/19E05FA3-992C-47C8-AE6C-12DAD263AB24 b/1_anytime.pxd/data/19E05FA3-992C-47C8-AE6C-12DAD263AB24 new file mode 100644 index 0000000..d87cf2e Binary files /dev/null and b/1_anytime.pxd/data/19E05FA3-992C-47C8-AE6C-12DAD263AB24 differ diff --git a/1_anytime.pxd/data/99B3DBAB-E0AB-465E-BB81-B586F85BCADE b/1_anytime.pxd/data/99B3DBAB-E0AB-465E-BB81-B586F85BCADE index 3b5bee9..ba84770 100644 Binary files a/1_anytime.pxd/data/99B3DBAB-E0AB-465E-BB81-B586F85BCADE and b/1_anytime.pxd/data/99B3DBAB-E0AB-465E-BB81-B586F85BCADE differ diff --git a/1_anytime.pxd/data/selectionForContentTransform/meta b/1_anytime.pxd/data/selectionForContentTransform/meta new file mode 100644 index 0000000..b4e4a3e --- /dev/null +++ b/1_anytime.pxd/data/selectionForContentTransform/meta @@ -0,0 +1,33 @@ + + + + + backingScale + 1 + mode + 0 + shapeSelectionFilename + shapeSelection + size + + NC10UHpTVFAQAAAAQGHAAAAAAABALAAAAAAAAA== + + softness + 0.0 + timestamp + 762463132.862221 + transform + + 1 + 0.0 + 0.0 + 1.2142857142857142 + 0.0 + -271.07142857142844 + 0.0 + 0.0 + + version + 2 + + diff --git a/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/meta b/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/meta new file mode 100644 index 0000000..0acda1a --- /dev/null +++ b/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/meta @@ -0,0 +1,12 @@ + + + + + backingScale + 1 + pathFilename + path + version + 1 + + diff --git a/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/path b/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/path new file mode 100644 index 0000000..e073e9e Binary files /dev/null and b/1_anytime.pxd/data/selectionForContentTransform/shapeSelection/path differ diff --git a/1_anytime.pxd/metadata.info b/1_anytime.pxd/metadata.info index 264083e..0ece2ef 100644 Binary files a/1_anytime.pxd/metadata.info and b/1_anytime.pxd/metadata.info differ diff --git a/2_copy copy.pxd b/2_copy copy.pxd deleted file mode 100644 index f02f1e9..0000000 Binary files a/2_copy copy.pxd and /dev/null differ diff --git a/2_copy.pxd/QuickLook/Icon.webp b/2_copy.pxd/QuickLook/Icon.webp index 0d9fa13..840cb50 100644 Binary files a/2_copy.pxd/QuickLook/Icon.webp and b/2_copy.pxd/QuickLook/Icon.webp differ diff --git a/2_copy.pxd/QuickLook/Thumbnail.webp b/2_copy.pxd/QuickLook/Thumbnail.webp index 2c355b8..02cf792 100644 Binary files a/2_copy.pxd/QuickLook/Thumbnail.webp and b/2_copy.pxd/QuickLook/Thumbnail.webp differ diff --git a/2_copy.pxd/data/12B58170-683E-41DB-AC70-DDBF20670A12-OriginalContentSource b/2_copy.pxd/data/12B58170-683E-41DB-AC70-DDBF20670A12-OriginalContentSource deleted file mode 100644 index 92353ec..0000000 Binary files a/2_copy.pxd/data/12B58170-683E-41DB-AC70-DDBF20670A12-OriginalContentSource and /dev/null differ diff --git a/2_copy.pxd/data/21B54899-609A-4C6A-9ECC-3CA7CCD99F0F b/2_copy.pxd/data/21B54899-609A-4C6A-9ECC-3CA7CCD99F0F new file mode 100644 index 0000000..9f8812a Binary files /dev/null and b/2_copy.pxd/data/21B54899-609A-4C6A-9ECC-3CA7CCD99F0F differ diff --git a/2_copy.pxd/metadata.info b/2_copy.pxd/metadata.info index 6318974..ad0fbb4 100644 Binary files a/2_copy.pxd/metadata.info and b/2_copy.pxd/metadata.info differ diff --git a/Logger.swift b/Logger.swift new file mode 100644 index 0000000..d9e0437 --- /dev/null +++ b/Logger.swift @@ -0,0 +1,147 @@ +// +// Logger.swift +// QuickDrop +// +// Created by Leon Böttger on 26.02.25. +// + +import Foundation +import os + +fileprivate let loggerQueue = DispatchQueue(label: "loggerQueue") + +/// Manages logging functionality +final class LogManager { + + /// The URL of the log file + let logFileURL: URL? + + /// The private initializer + private init() { + + /// Get documents directory + let directory = getDocumentsDirectory() + + /// Create file name from date + let formatter = DateFormatter() + formatter.dateFormat = "dd-MM-yyyy" + let dateString = formatter.string(from: Date()) + let fileName = "\(dateString).log" + + /// Create file URL from file name + self.logFileURL = directory.appendingPathComponent(fileName) + } + + /// The shared instance. + public static let sharedInstance = LogManager() + @Published var loggingEnabled = true + + + /// Writes a specified string to the log file. + func writeToFile(string: String) { + + /// Make sure the URL is not nil + guard let logFileURL = logFileURL else { + return + } + + /// Get current timestamp + let formatter = DateFormatter() + formatter.dateFormat = "HH:mm:ss" + let timestamp = formatter.string(from: Date()) + + /// Create data from string and timestamp + guard let data = (timestamp + " - " + string + "\n").data(using: .utf8) else { return } + + /// a log file exists already + if FileManager.default.fileExists(atPath: logFileURL.path) { + + /// we try to get a handle to write to the log file + if let file = try? FileHandle(forWritingTo: logFileURL) { + + /// go to end of file + file.seekToEndOfFile() + + /// write string to end + file.write(data) + + ///close file + file.closeFile() + } + } else { + + /// Clean up older logs + deleteLogs() + + /// create new log file + try? data.write(to: logFileURL, options: .atomicWrite) + } + } + + func getLogString() -> String { + + if let logFileURL = logFileURL { + let fileURL = URL(fileURLWithPath: logFileURL.path) + do { + let content = try String(contentsOf: fileURL, encoding: .utf8) + return String(content.suffix(10000)) + + } catch { + log("[LUI] Error reading file: \(error.localizedDescription)") + } + } + return "" + } + + /// Deletes all log files. + func deleteLogs() { + + log("[LUI] Deleting all logs...") + + let fileManager = FileManager.default + + let documentsDirectory = getDocumentsDirectory() + + guard let allFiles = try? fileManager.contentsOfDirectory(at: documentsDirectory, includingPropertiesForKeys: nil) else { + return + } + + let logFiles = allFiles.filter { $0.pathExtension.elementsEqual("log") } + + for file in logFiles { + + do { + log("[LUI] Removing \(file.description)") + try fileManager.removeItem(at: file) + + } catch { + print(error.localizedDescription) + } + } + } +} + + +/// Logs a specified string. +public func log(_ text: String) { + + let logger = LogManager.sharedInstance + + if logger.loggingEnabled { + loggerQueue.async { + print(text) + + // Weird bug? +#if !os(tvOS) + logger.writeToFile(string: text) +#endif + } + } +} + + +/// Returns the URL of the documents directory. +func getDocumentsDirectory() -> URL { + return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! +} + diff --git a/NearDrop/AppDelegate.swift b/NearDrop/AppDelegate.swift index c88a3be..92b2215 100644 --- a/NearDrop/AppDelegate.swift +++ b/NearDrop/AppDelegate.swift @@ -1,6 +1,6 @@ // // AppDelegate.swift -// NearDrop +// QuickDrop // // Created by Grishka on 08.04.2023. // @@ -12,11 +12,13 @@ import SwiftUI import StoreKit @main -class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate, MainAppDelegate{ +class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{ private var statusItem:NSStatusItem? private var activeIncomingTransfers:[String:TransferInfo]=[:] - var window: NSWindow? + var welcomeWindow: NSWindow? + var plusWindow: NSWindow? + private var iapManager: IAPManager? func applicationDidFinishLaunching(_ aNotification: Notification) { let menu=NSMenu() @@ -24,9 +26,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele menu.addItem(withTitle: String(format: NSLocalizedString("DeviceName", value: "Device name: %@", comment: ""), arguments: [Host.current().localizedName!]), action: nil, keyEquivalent: "") menu.addItem(NSMenuItem.separator()) - // Add "Recommended Apps" menu item - let recommendedAppsItem = NSMenuItem(title: NSLocalizedString("RecommendedApps", value: "Recommended Apps", comment: ""), action: #selector(openRecommendedApps), keyEquivalent: "") - menu.addItem(recommendedAppsItem) +// // Add "Recommended Apps" menu item +// let recommendedAppsItem = NSMenuItem(title: NSLocalizedString("RecommendedApps", value: "Recommended Apps", comment: ""), action: #selector(openRecommendedApps), keyEquivalent: "") +// menu.addItem(recommendedAppsItem) // Add "Privacy Policy" menu item let privacyPolicyItem = NSMenuItem(title: NSLocalizedString("PrivacyPolicy", value: "Privacy Policy", comment: ""), action: #selector(openPrivacyPolicy), keyEquivalent: "") @@ -37,7 +39,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele let userManualItem = NSMenuItem(title: NSLocalizedString("UserManual", value: "User Manual", comment: ""), action: #selector(openWelcomeScreen), keyEquivalent: "") menu.addItem(userManualItem) - menu.addItem(withTitle: NSLocalizedString("Quit", value: "Quit NearDrop", comment: ""), action: #selector(NSApplication.terminate(_:)), keyEquivalent: "") + menu.addItem(withTitle: NSLocalizedString("Quit", value: "Quit QuickDrop", comment: ""), action: #selector(NSApplication.terminate(_:)), keyEquivalent: "") statusItem=NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) @@ -45,50 +47,101 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele statusItem?.menu=menu statusItem?.behavior = .removalAllowed - let nc=UNUserNotificationCenter.current() - nc.requestAuthorization(options: [.alert, .sound]) { granted, err in - if !granted{ - DispatchQueue.main.async { - self.showNotificationsDeniedAlert() - } - } - } - nc.delegate=self - let incomingTransfersCategory=UNNotificationCategory(identifier: "INCOMING_TRANSFERS", actions: [ - UNNotificationAction(identifier: "ACCEPT", title: NSLocalizedString("Accept", comment: ""), options: UNNotificationActionOptions.authenticationRequired) - ], intentIdentifiers: []) - let errorsCategory=UNNotificationCategory(identifier: "ERRORS", actions: [], intentIdentifiers: []) - nc.setNotificationCategories([incomingTransfersCategory, errorsCategory]) NearbyConnectionManager.shared.mainAppDelegate=self NearbyConnectionManager.shared.becomeVisible() - if !UserDefaults.standard.bool(forKey: "ShowedWelcomeScreen"){ + iapManager = IAPManager.sharedInstance + iapManager?.startObserving() + + // app did not lauch before + if !UserDefaults.standard.bool(forKey: UserDefaultsKeys.appLaunchedBefore.rawValue){ + + log("Opening welcome screen") + // open welcome screen openWelcomeScreen() - UserDefaults.standard.set(true, forKey: "ShowedWelcomeScreen") + UserDefaults.standard.set(true, forKey: UserDefaultsKeys.appLaunchedBefore.rawValue) + + // user installed the app after the IAP was implemented, set the user as eligible for IAP + UserDefaults.standard.set(true, forKey: UserDefaultsKeys.isEligibleForIap.rawValue) + } + 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) { + log("Granting plus version for old user") + UserDefaults.standard.set(true, forKey: UserDefaultsKeys.plusVersion.rawValue) + } + else { + if !isPlusVersion() { + log("New user - plus version cannot be granted") + } + } } } @objc func openWelcomeScreen() { // Create the welcome screen SwiftUI view - let welcomeView = WelcomeScreen() + let welcomeView = WelcomeScreen { + self.openPlusScreen(continueTransfer: {}) + } // Create an NSWindow to host the SwiftUI view - window = NSWindow( + welcomeWindow = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 400, height: 300), styleMask: [.titled, .closable], backing: .buffered, defer: false ) - window?.center() - window?.isReleasedWhenClosed = false - window?.setFrameAutosaveName("WelcomeScreen") - window?.contentView = NSHostingView(rootView: welcomeView) + welcomeWindow?.center() + welcomeWindow?.isReleasedWhenClosed = false + welcomeWindow?.setFrameAutosaveName("WelcomeScreen") + welcomeWindow?.contentView = NSHostingView(rootView: welcomeView) + + welcomeWindow?.isOpaque = false + welcomeWindow?.backgroundColor = .clear // Ensure the window is always on top - window?.level = .floating + NSApp.activate(ignoringOtherApps: true) // Brings the whole app to the front + welcomeWindow?.makeKeyAndOrderFront(nil) + welcomeWindow?.level = .normal + } + + + @objc func openPlusScreen(continueTransfer: @escaping () -> Void) { + // Create the welcome screen SwiftUI view + let plusView = GetPlusView(closeView: { + self.plusWindow?.close() + continueTransfer() + }) - window?.makeKeyAndOrderFront(nil) + // Create an NSWindow to host the SwiftUI view + plusWindow = NSWindow( + contentRect: NSRect(x: 0, y: 0, width: 400, height: 300), + styleMask: [.titled, .closable], + backing: .buffered, + defer: false + ) + + plusWindow?.center() + plusWindow?.isReleasedWhenClosed = false + plusWindow?.setFrameAutosaveName("PlusScreen") + plusWindow?.contentView = NSHostingView(rootView: plusView) + + // Ensure the window is always on top + NSApp.activate(ignoringOtherApps: true) // Brings the whole app to the front + plusWindow?.makeKeyAndOrderFront(nil) + plusWindow?.level = .normal + } + + + func isPlusVersion() -> Bool { + return UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue) + } + + func transmissionCount() -> Int { + return UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue) } @@ -113,106 +166,130 @@ class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDele func applicationWillTerminate(_ aNotification: Notification) { UNUserNotificationCenter.current().removeAllDeliveredNotifications() + iapManager?.stopObserving() } func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { return true } - func showNotificationsDeniedAlert(){ - let alert=NSAlert() - alert.alertStyle = .critical - alert.messageText=NSLocalizedString("NotificationsDenied.Title", value: "Notification Permission Required", comment: "") - alert.informativeText=NSLocalizedString("NotificationsDenied.Message", value: "NearDrop needs to be able to display notifications for incoming file transfers. Please allow notifications in System Settings.", comment: "") - alert.addButton(withTitle: NSLocalizedString("NotificationsDenied.OpenSettings", value: "Open settings", comment: "")) - alert.addButton(withTitle: NSLocalizedString("Quit", value: "Quit NearDrop", comment: "")) - let result=alert.runModal() - if result==NSApplication.ModalResponse.alertFirstButtonReturn{ - NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.notifications")!) - }else if result==NSApplication.ModalResponse.alertSecondButtonReturn{ - NSApplication.shared.terminate(nil) - } - } - - func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { - let transferID=response.notification.request.content.userInfo["transferID"]! as! String - NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: response.actionIdentifier=="ACCEPT") - if response.actionIdentifier != "ACCEPT"{ + public func continueTransmission(accept: Bool, transferID: String) { + NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: accept) + + if !accept { activeIncomingTransfers.removeValue(forKey: transferID) } - completionHandler() - } - - public func userNotificationCenter(_ center: UNUserNotificationCenter, - willPresent notification: UNNotification, - withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { - completionHandler([.sound, .banner]) } func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo) { - let fileStr:String - if let textTitle=transfer.textDescription{ - fileStr=textTitle - }else if transfer.files.count==1{ - fileStr=transfer.files[0].name - }else{ - fileStr=String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count) + self.activeIncomingTransfers[transfer.id] = TransferInfo(device: device, transfer: transfer) + + NSSound(named: NSSound.Name("NSUserNotificationDefaultSoundName"))?.play() + + let alert = NSAlert() + alert.alertStyle = .informational + + let fileStr: String + + if let textTitle = transfer.textDescription{ + fileStr = textTitle + } else if transfer.files.count == 1 { + fileStr = transfer.files[0].name + } else { + fileStr = String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count) } - let notificationContent=UNMutableNotificationContent() - notificationContent.title="NearDrop" - notificationContent.subtitle=String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!]) - notificationContent.body=String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr]) - notificationContent.sound = .default - notificationContent.categoryIdentifier="INCOMING_TRANSFERS" - notificationContent.userInfo=["transferID": transfer.id] - if #available(macOS 11.0, *){ - NDNotificationCenterHackery.removeDefaultAction(notificationContent) + + let mainMessage = String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr]) + let pinCodeMessage = String(format:NSLocalizedString("PinCode", value: "PIN: %@", comment: ""), arguments: [transfer.pinCode!]) + let transferID = transfer.id + + alert.messageText = "QuickDrop - \(pinCodeMessage)" + alert.informativeText = mainMessage + alert.addButton(withTitle: NSLocalizedString("Accept", comment: "")) + alert.addButton(withTitle: NSLocalizedString("Decline", comment: "")) + + let result = alert.runModal() + + if result == .alertFirstButtonReturn { + + if !isPlusVersion() && transmissionCount() > 0 { + self.openPlusScreen { + self.continueTransmission(accept: self.isPlusVersion(), transferID: transferID) + } + } + else { + continueTransmission(accept: true, transferID: transferID) + } + + } else if result == .alertSecondButtonReturn { + + continueTransmission(accept: false, transferID: transferID) } - let notificationReq=UNNotificationRequest(identifier: "transfer_"+transfer.id, content: notificationContent, trigger: nil) - UNUserNotificationCenter.current().add(notificationReq) - self.activeIncomingTransfers[transfer.id]=TransferInfo(device: device, transfer: transfer) } func incomingTransfer(id: String, didFinishWith error: Error?) { - guard let transfer=self.activeIncomingTransfers[id] else {return} - if let error=error{ - let notificationContent=UNMutableNotificationContent() - notificationContent.title=String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [transfer.device.name]) - if let ne=(error as? NearbyError){ - switch ne{ + guard let transfer = self.activeIncomingTransfers[id] else { return } + if let error = error { + + let alert = NSAlert() + alert.alertStyle = .critical + + alert.messageText = String(format: NSLocalizedString("TransferError", value: "Failed to receive files from %@", comment: ""), arguments: [transfer.device.name]) + var description = "" + + if let ne = (error as? NearbyError){ + switch ne { case .inputOutput: - notificationContent.body="I/O Error"; + description = "I/O Error"; case .protocolError(_): - notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "") + description = NSLocalizedString("Error.Protocol", value: "Communication error", comment: "") case .requiredFieldMissing: - notificationContent.body=NSLocalizedString("Error.Protocol", value: "Communication error", comment: "") + description = NSLocalizedString("Error.Protocol", value: "Communication error", comment: "") case .ukey2: - notificationContent.body=NSLocalizedString("Error.Crypto", value: "Encryption error", comment: "") + description = NSLocalizedString("Error.Crypto", value: "Encryption error", comment: "") case .canceled(reason: _): break; // can't happen for incoming transfers } - }else{ - notificationContent.body=error.localizedDescription + } else { + description = error.localizedDescription } - notificationContent.categoryIdentifier="ERRORS" - UNUserNotificationCenter.current().add(UNNotificationRequest(identifier: "transferError_"+id, content: notificationContent, trigger: nil)) + + alert.informativeText = description + let _ = alert.runModal() } - UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["transfer_"+id]) + else { + let currentCount = transmissionCount() + + if currentCount % 20 == 0 { + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + SKStoreReviewController.requestReview() + } + } + + UserDefaults.standard.set(currentCount + 1, forKey: UserDefaultsKeys.transmissionCount.rawValue) + } + self.activeIncomingTransfers.removeValue(forKey: id) - - let currentCount = UserDefaults.standard.integer(forKey: "reviewRequestCountKey") - - if currentCount % 20 == 0 { - DispatchQueue.main.asyncAfter(deadline: .now() + 2) { - SKStoreReviewController.requestReview() - } - } - - UserDefaults.standard.set(currentCount + 1, forKey: "reviewRequestCountKey") } } -struct TransferInfo{ - let device:RemoteDeviceInfo - let transfer:TransferMetadata +struct TransferInfo { + let device: RemoteDeviceInfo + let transfer: TransferMetadata +} + +class WindowDelegate: NSObject, NSWindowDelegate { + + let willClose: () -> Void + + init(willClose: @escaping () -> Void) { + self.willClose = willClose + } + + + func windowWillClose(_ notification: Notification) { + print("Window closed!") + // Perform any cleanup or state updates here + willClose() + } } diff --git a/NearDrop/Assets.xcassets/DefaultBackgroundColor.colorset/Contents.json b/NearDrop/Assets.xcassets/DefaultBackgroundColor.colorset/Contents.json new file mode 100644 index 0000000..1a3ddad --- /dev/null +++ b/NearDrop/Assets.xcassets/DefaultBackgroundColor.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "1.000", + "green" : "1.000", + "red" : "1.000" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "display-p3", + "components" : { + "alpha" : "1.000", + "blue" : "0.200", + "green" : "0.200", + "red" : "0.200" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar1x.png b/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar1x.png index b46b27e..f4fd9be 100644 Binary files a/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar1x.png and b/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar1x.png differ diff --git a/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar2x.png b/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar2x.png index 9874c2d..3b6511f 100644 Binary files a/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar2x.png and b/NearDrop/Assets.xcassets/MenuBarIcon.imageset/menubar2x.png differ diff --git a/NearDrop/Base.lproj/Localizable.strings b/NearDrop/Base.lproj/Localizable.strings index f0a8698..935f8be 100644 --- a/NearDrop/Base.lproj/Localizable.strings +++ b/NearDrop/Base.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d files"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop needs to be able to display notifications for incoming file transfers. Please allow notifications in System Settings."; +"NotificationsDenied.Message" = "QuickDrop needs to be able to display notifications for incoming file transfers. Please allow notifications in System Settings."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Open settings"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Quit NearDrop"; +"Quit" = "Close QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Failed to receive files from %@"; @@ -40,20 +40,38 @@ /* No comment provided by engineer. */ "VisibleToEveryone" = "Visible to everyone"; -"WelcomeToNearDrop" = "Welcome to NearDrop"; +"WelcomeToQuickDrop" = "Welcome to QuickDrop"; "Acknowledgements" = "Acknowledgements"; +"SupportQuickDrop" = "Support QuickDrop"; + "RecommendedApps" = "Recommended Apps"; "PrivacyPolicy" = "Privacy Policy"; "UserManual" = "User Manual"; -"UserManualDescription" = "When NearDrop is running, it will appear in the menu bar at the top of your screen. Click the NearDrop icon if you would like to stop receiving files. +"UserManualDescription" = "When QuickDrop is running, it will appear in the menu bar at the top of your screen. Click the QuickDrop icon if you would like to stop receiving files. Important: Your Android device and your Mac need to be on the same WiFi network to transfer files. If you are promted to allow incoming connections, please allow them. To send files from your Android device to your Mac, tap on the share icon on your phone, and select \"Quick Share\" or \"Nearby Share\". Your Mac will be listed as an available device. After that, you will see a notification on your Mac. Hover over the notification to accept or decline the file transfer."; + + +"plusview_title" = "Thanks for using QuickDrop!"; +"plusview_description" = "Unlock QuickDrop+ to continue receiving files. QuickDrop+ is a one-time purchase – you can keep the app forever, no subscription required."; +"plusview_success_title" = "Thanks for your purchase!"; +"plusview_success_description" = "You can now continue receiving files without restrictions."; +"plusview_success_button" = "Got it!"; +"plusview_unlock_label" = "Support QuickDrop"; + +"plusview_restorepurchase" = "Already bought?"; +"plusview_restorefailed" = "There was a problem restoring your purchase"; +"plusview_restorefailed_proceed" = "Okay"; +"plusview_purchasefailed" = "Purchase failed"; +"plusview_purchasefaileddescription" = "If this message appeared unexpectedly, please make sure that you are connected to the Internet and In-App-Purchases are enabled for your device and then try again."; +"plusview_nothingtorestore" = "There is nothing to restore!"; +"plusview_productRequestFailed" = "Unable to fetch In-App Purchases at the moment."; diff --git a/NearDrop/IAP/GetPlusView.swift b/NearDrop/IAP/GetPlusView.swift new file mode 100644 index 0000000..348e727 --- /dev/null +++ b/NearDrop/IAP/GetPlusView.swift @@ -0,0 +1,245 @@ +// +// GetPlusView.swift +// QuickDrop +// +// Created by Leon Böttger on 23.02.25. +// + +import SwiftUI +import StoreKit + +struct GetPlusView: View { + + @AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false + @ObservedObject private var iaphelper = IAPManager.sharedInstance + let closeView: () -> Void + + @State private var restoring = false + @State private var showRestoreError = false + @State private var restoreError = "" + + @Environment(\.colorScheme) var colorScheme + @State var products = [SKProduct]() + @State var price: String = "" + @State var warning = false + @State var buying = false + @State var errorText = "" + + @State var boughtSuccessAlert = false + + + var body: some View { + + ZStack { + Color.defaultBackground + .edgesIgnoringSafeArea(.all) + + let validPrice = price != "" + + VStack(spacing: 12) { + Text("plusview_title") + .font(.title) + .bold() + + Text("plusview_description") + .multilineTextAlignment(.center) + .padding() + .padding(.top, -10) + .alert(isPresented: $boughtSuccessAlert, content: { + Alert(title: Text("plusview_success_title"), message: Text("plusview_success_description"), dismissButton: .default(Text("plusview_success_button"), action: { + closeView() + })) + }) + + HStack(spacing: 10) { + Button("plusview_restorepurchase") { + restorePurchases() + } + .keyboardShortcut(.cancelAction) + .alert(isPresented: $showRestoreError, content: { + Alert(title: Text("plusview_restorefailed"), message: Text(restoreError), dismissButton: .default(Text("plusview_restorefailed_proceed"))) + }) + .opacity(restoring ? 0 : 1) + .overlay( + ProgressView() + .scaleEffect(0.5) + .opacity(restoring ? 1 : 0) + ) + + let priceString = validPrice ? " (\(price))" : "" + + Button("plusview_unlock_label".localized() + priceString) { + buttonAction() + } + .keyboardShortcut(.defaultAction) + .alert(isPresented: $warning, content: { + Alert(title: Text("plusview_purchasefailed"), message: Text("plusview_purchasefaileddescription".localized() + (errorText != "" ? " Error: " : "") + errorText), dismissButton: .default(Text("plusview_restorefailed_proceed"))) + }) + } + .opacity(buying || restoring ? 0 : 1) + .overlay( + ProgressView() + .scaleEffect(0.5) + .opacity(buying || restoring ? 1 : 0) + ) + } + .onAppear { + loadProducts(shouldBuy: false) + } + .animation(.default, value: validPrice) + .padding() + } + .frame(width: 400, height: 200) + } + + + func restorePurchases() { + + withAnimation { + restoring = true + } + + iaphelper.restorePurchases { result in + DispatchQueue.main.async { + + switch result { + case .success(let success): + if success { + withAnimation { + isPlusVersion = true + } + boughtSuccessAlert = true + } else { + //nothing to restore + restoreFailed(message: "plusview_nothingtorestore") + } + + case .failure(let error): + log(error.localizedDescription) + restoreFailed(message: error.localizedDescription) + } + } + } + + func restoreFailed(message: String) { + + #if targetEnvironment(simulator) + isPlusVersion = true + dismissView() + #else + + // now, try to convert from old version + IAPConverter.shared.restoreIAPfromPreviousPurchase { success in + + DispatchQueue.main.async { + + if success { + withAnimation { + isPlusVersion = true + } + + boughtSuccessAlert = true + } + else { + restoreError = message + showRestoreError = true + + withAnimation { + restoring = false + } + } + } + } + #endif + } + } + + func buttonAction() { + if let product = products.first { + purchase(product: product) + } + else { + loadProducts(shouldBuy: true) + } + } + + + func purchase(product: SKProduct) { + if !iaphelper.canMakePayments() { + warning = true + } else { + withAnimation{ + buying = true + } + + iaphelper.buy(product: product) { (result) in + DispatchQueue.main.async { + withAnimation{ + buying = false + } + + switch result { + case .success(_): + + withAnimation { + isPlusVersion = true + boughtSuccessAlert = true + warning = false + } + + case .failure(let error): + warning = true + errorText = error.localizedDescription + } + } + } + } + } + + func loadProducts(shouldBuy: Bool) { + iaphelper.getProducts { (result) in + DispatchQueue.main.async { + + switch result { + case .success(let products): + self.products = products + price = products.first?.localizedPrice ?? "" + + if let product = products.first, shouldBuy { + purchase(product: product) + } + + case .failure(let error): + errorText = error.localizedDescription + + if(shouldBuy){ + warning = true + } + + withAnimation{ + buying = false + } + } + } + } + } +} + + +extension SKProduct { + var localizedPrice: String { + let formatter = NumberFormatter() + formatter.numberStyle = .currency + formatter.locale = priceLocale + if let price = formatter.string(from: price) { + return price + } + return "" + } +} + + + +#Preview { + GetPlusView(closeView: {}) +} diff --git a/NearDrop/IAP/IAPConverter.swift b/NearDrop/IAP/IAPConverter.swift new file mode 100644 index 0000000..98e0bf2 --- /dev/null +++ b/NearDrop/IAP/IAPConverter.swift @@ -0,0 +1,66 @@ +// +// StoreChecker.swift +// LUI +// +// Created by Leon Böttger on 19.08.24. +// +import StoreKit + +class IAPConverter: NSObject, SKRequestDelegate { + + let switchToIAPAfterBundleVersion = "6" + + static let shared = IAPConverter() + + private override init() { + super.init() + } + + func restoreIAPfromPreviousPurchase(success: ((Bool) -> ())? = nil) { + Task { + do { + // Get the appTransaction. + + if #available(macOS 13.0, *) { + let shared = try await AppTransaction.shared + + if case .verified(let appTransaction) = shared { + + let originalVersion = appTransaction.originalAppVersion + let newModelVersion = switchToIAPAfterBundleVersion + log("[LUI] Original Purchased Version: \(originalVersion) | New Model Version: \(newModelVersion)") + + if originalVersion.compare(newModelVersion, options: .numeric) == .orderedAscending { + grant(success: success) + return + } + } + } else { + // Fallback on earlier versions + // Grant IAP, as we cannot check the original purchase date. + DispatchQueue.main.async { + log("[LUI] Cannot check version - Plus Version Granted!") + success?(true) + } + } + } + catch { + // Handle errors. + log("[LUI] Error: \(error.localizedDescription)") + } + + DispatchQueue.main.async { + log("[LUI] Plus Version Denied!") + success?(false) + } + } + } + + private func grant(success: ((Bool) -> ())? = nil) { + log("[LUI] Existing User - Plus Version Granted!") + + DispatchQueue.main.async { + success?(true) + } + } +} diff --git a/NearDrop/IAP/PurchaseHelper.swift b/NearDrop/IAP/PurchaseHelper.swift new file mode 100644 index 0000000..125f259 --- /dev/null +++ b/NearDrop/IAP/PurchaseHelper.swift @@ -0,0 +1,195 @@ +// +// PurchaseHelper.swift +// Loop +// +// Created by Leon Böttger on 26.10.20. +// Copyright © 2020 Leon Böttger. All rights reserved. +// + +import StoreKit + +let iapName = "plusversion" + +class IAPManager: NSObject, ObservableObject { + + enum IAPManagerError: Error { + case noProductIDsFound + case noProductsFound + case paymentWasCancelled + case productRequestFailed + } + + static let plusVersionID = iapName + static let sharedInstance = IAPManager() + var onReceiveProductsHandler: ((Result<[SKProduct], IAPManagerError>) -> Void)? + var onBuyProductHandler: ((Result) -> Void)? + var totalRestoredPurchases = 0 + var isActive = false + + private override init() { + super.init() + getProducts { _ in } + } + + fileprivate func getProductIDs() -> [String]? { + return [IAPManager.plusVersionID] + } + + func startObserving() { + SKPaymentQueue.default().add(self) + } + + + func stopObserving() { + SKPaymentQueue.default().remove(self) + } + + + func canMakePayments() -> Bool { + return SKPaymentQueue.canMakePayments() + } + + func getProducts(withHandler productsReceiveHandler: @escaping (_ result: Result<[SKProduct], IAPManagerError>) -> Void) { + // Keep the handler (closure) that will be called when requesting for + // products on the App Store is finished. + onReceiveProductsHandler = productsReceiveHandler + + // Get the product identifiers. + guard let productIDs = getProductIDs() else { + productsReceiveHandler(.failure(.noProductIDsFound)) + return + } + + // Initialize a product request. + let request = SKProductsRequest(productIdentifiers: Set(productIDs)) + + // Set self as the its delegate. + request.delegate = self + + // Make the request. + request.start() + } + + func buy(product: SKProduct, withHandler handler: @escaping ((_ result: Result) -> Void)) { + let payment = SKPayment(product: product) + SKPaymentQueue.default().add(payment) + + // Keep the completion handler. + onBuyProductHandler = handler + } + + + func restorePurchases(withHandler handler: @escaping ((_ result: Result) -> Void)) { + onBuyProductHandler = handler + totalRestoredPurchases = 0 + SKPaymentQueue.default().restoreCompletedTransactions() + } +} + +extension IAPManager: SKPaymentTransactionObserver { + func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) { + transactions.forEach { (transaction) in + + switch transaction.transactionState { + case .purchased: + onBuyProductHandler?(.success(true)) + SKPaymentQueue.default().finishTransaction(transaction) + + case .restored: + totalRestoredPurchases += 1 + onBuyProductHandler?(.success(true)) + SKPaymentQueue.default().finishTransaction(transaction) + + case .failed: + log("[LUI] IAP failed") + if let error = transaction.error as? SKError { + if error.code != .paymentCancelled { + onBuyProductHandler?(.failure(error)) + } else { + onBuyProductHandler?(.failure(IAPManagerError.paymentWasCancelled)) + } + log("[LUI] IAP Error:" + error.localizedDescription) + } + onBuyProductHandler?(.failure(transaction.error ?? IAPManagerError.productRequestFailed)) + SKPaymentQueue.default().finishTransaction(transaction) + + case .deferred, .purchasing: log("[LUI] other cases") + @unknown default: log("[LUI] other default cases") + } + } + } + + + + func paymentQueueRestoreCompletedTransactionsFinished(_ queue: SKPaymentQueue) { + if totalRestoredPurchases != 0 { + onBuyProductHandler?(.success(true)) + } else { + log("[LUI] IAP: No purchases to restore!") + onBuyProductHandler?(.success(false)) + } + } + + + func paymentQueue(_ queue: SKPaymentQueue, restoreCompletedTransactionsFailedWithError error: Error) { + if let error = error as? SKError { + if error.code != .paymentCancelled { + log("[LUI] IAP Restore Error:" + error.localizedDescription) + onBuyProductHandler?(.failure(error)) + } else { + onBuyProductHandler?(.failure(IAPManagerError.paymentWasCancelled)) + } + } + } +} + +extension IAPManager: SKProductsRequestDelegate { + func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) { + // Get the available products contained in the response. + let products = response.products + + // Check if there are any products available. + if products.count > 0 { + // Call the following handler passing the received products. + onReceiveProductsHandler?(.success(products)) + } else { + // No products were found. + onReceiveProductsHandler?(.failure(.noProductsFound)) + } + } + + + func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool { + return true + } + + + func request(_ request: SKRequest, didFailWithError error: Error) { + onReceiveProductsHandler?(.failure(.productRequestFailed)) + } + + + func requestDidFinish(_ request: SKRequest) { + // Implement this method OPTIONALLY and add any custom logic + // you want to apply when a product request is finished. + } +} + +extension IAPManager.IAPManagerError: LocalizedError { + var errorDescription: String? { + switch self { + case .noProductIDsFound: return "No In-App Purchase product identifiers were found." + case .noProductsFound: return "No In-App Purchases were found." + case .productRequestFailed: return "plusview_productRequestFailed".localized() + case .paymentWasCancelled: return "In-App Purchase process was cancelled." + } + } +} + + +public extension String { + func localized() -> String { + let localizedString = NSLocalizedString(self, comment: "") + return localizedString + } +} diff --git a/NearDrop/NDNotificationCenterHackery.h b/NearDrop/NDNotificationCenterHackery.h deleted file mode 100644 index 65a4679..0000000 --- a/NearDrop/NDNotificationCenterHackery.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// NDNotificationCenterHackery.h -// NearDrop -// -// Created by Grishka on 10.04.2023. -// - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface NDNotificationCenterHackery : NSObject - -+ (void)removeDefaultAction:(UNMutableNotificationContent*) content; - -@end - -NS_ASSUME_NONNULL_END diff --git a/NearDrop/NDNotificationCenterHackery.m b/NearDrop/NDNotificationCenterHackery.m deleted file mode 100644 index 5142c93..0000000 --- a/NearDrop/NDNotificationCenterHackery.m +++ /dev/null @@ -1,42 +0,0 @@ -// -// NDNotificationCenterHackery.m -// NearDrop -// -// Created by Grishka on 10.04.2023. -// - -#import -#import -#import "NDNotificationCenterHackery.h" - -@interface UNMutableNotificationCategory : UNNotificationCategory -@property(copy) NSString *actionsMenuTitle; -@property(copy) UNNotificationAction *alternateAction; -@property(copy) NSArray *minimalActions; -@property unsigned long long backgroundStyle; -@property(copy) NSArray *actions; -@end - -@interface UNNotificationIcon : NSObject -+ (id)iconForApplicationIdentifier:(id)arg1; -+ (id)iconAtPath:(id)arg1; -+ (id)iconNamed:(id)arg1; -@end - -@interface UNMutableNotificationContent (NDPrivateAPIs) -@property BOOL hasDefaultAction; -@property(copy) NSString *defaultActionTitle; -@property(copy) NSString *header; -@property (assign,nonatomic) BOOL shouldDisplayActionsInline; -@property (assign,nonatomic) BOOL shouldShowSubordinateIcon; -@property (nonatomic,copy) NSString * accessoryImageName; -@property(copy) UNNotificationIcon *icon; -@end - -@implementation NDNotificationCenterHackery - -+ (void)removeDefaultAction:(UNMutableNotificationContent*) content{ - content.hasDefaultAction=false; -} - -@end diff --git a/NearDrop/NearDrop-Bridging-Header.h b/NearDrop/NearDrop-Bridging-Header.h deleted file mode 100644 index 939f4a1..0000000 --- a/NearDrop/NearDrop-Bridging-Header.h +++ /dev/null @@ -1,5 +0,0 @@ -// -// Use this file to import your target's public headers that you would like to expose to Swift. -// - -#import "NDNotificationCenterHackery.h" diff --git a/NearDrop/UserDefaultsKeys.swift b/NearDrop/UserDefaultsKeys.swift new file mode 100644 index 0000000..8506928 --- /dev/null +++ b/NearDrop/UserDefaultsKeys.swift @@ -0,0 +1,15 @@ +// +// UserDefaultKeys.swift +// QuickDrop +// +// Created by Leon Böttger on 26.02.25. +// + +import Foundation + +enum UserDefaultsKeys: String, CaseIterable { + case isEligibleForIap = "isEligibleForIap" + case appLaunchedBefore = "ShowedWelcomeScreen" + case plusVersion = "isPlusVersion" + case transmissionCount = "reviewRequestCountKey" +} diff --git a/NearDrop/WelcomeScreen.swift b/NearDrop/WelcomeScreen.swift index 981fec4..a5c04fd 100644 --- a/NearDrop/WelcomeScreen.swift +++ b/NearDrop/WelcomeScreen.swift @@ -1,6 +1,6 @@ // // WelcomeScreen.swift -// NearDrop +// QuickDrop // // Created by Leon Böttger on 03.01.25. // @@ -10,9 +10,18 @@ import SwiftUI struct WelcomeScreen: View { @State private var newWindow: NSWindow? // Retain the NSWindow object + @AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false + + @Environment(\.colorScheme) var colorScheme + @State var taps = 0 + + let openIAP: () -> Void var body: some View { - + ZStack { + Color.defaultBackground + .edgesIgnoringSafeArea(.all) + ScrollView { VStack { @@ -20,8 +29,18 @@ struct WelcomeScreen: View { .resizable() .frame(width: 150, height: 150) .padding(.top, 50) + .onTapGesture { + taps += 1 + print("Tapped \(taps) times") + + if taps == 5 { + let logString = LogManager.sharedInstance.getLogString() + copyToClipboard(logString) + print("Copied log to clipboard") + } + } - Text("WelcomeToNearDrop") + Text("WelcomeToQuickDrop") .font(.largeTitle) .padding() @@ -29,27 +48,65 @@ struct WelcomeScreen: View { .multilineTextAlignment(.center) .padding() - - Button { - openNewWindow() - } label: { - Text("Acknowledgements") - .underline() - .font(.footnote) - .opacity(0.5) + HStack(spacing: 30) { + + Button { + openNewWindow() + } label: { + Text("Acknowledgements") + .underline() + .font(.footnote) + .opacity(0.5) + } + .buttonStyle(.plain) + + if !isPlusVersion { + Button { + openIAP() + } label: { + Text("SupportQuickDrop") + .underline() + .font(.footnote) + .opacity(0.5) + } + .buttonStyle(.plain) + } + + #if DEBUG + Button { + for key in UserDefaultsKeys.allCases { + UserDefaults.standard.removeObject(forKey: key.rawValue) + } + } label: { + Text("Reset UD") + .underline() + .font(.footnote) + .opacity(0.5) + } + .buttonStyle(.plain) + #endif + } + .onAppear { +// #if DEBUG +// isPlusVersion = false +// #endif } - .buttonStyle(.plain) .padding() - - } .frame(maxWidth: 500) .frame(maxWidth: .infinity) } + } .frame(width: 1000, height: 600) } + func copyToClipboard(_ text: String) { + let pasteboard = NSPasteboard.general + pasteboard.clearContents() + pasteboard.setString(text, forType: .string) + } + func openNewWindow() { // Create a new NSWindow and retain it in the `newWindow` property let window = NSWindow( @@ -62,19 +119,46 @@ struct WelcomeScreen: View { window.isReleasedWhenClosed = false window.title = NSLocalizedString("Acknowledgements", value: "Acknowledgements", comment: "") window.contentView = NSHostingView(rootView: LicensePage()) - window.level = .floating + + // Ensure the window is always on top + NSApp.activate(ignoringOtherApps: true) // Brings the whole app to the front window.makeKeyAndOrderFront(nil) + window.level = .normal // Retain the window to prevent deallocation newWindow = window } } +import SwiftUI +import AppKit + +struct VisualEffectBlur: NSViewRepresentable { + var material: NSVisualEffectView.Material + var blendingMode: NSVisualEffectView.BlendingMode + + func makeNSView(context: Context) -> NSVisualEffectView { + let view = NSVisualEffectView() + view.material = material + view.blendingMode = blendingMode + view.state = .active + return view + } + + func updateNSView(_ nsView: NSVisualEffectView, context: Context) { + nsView.material = material + nsView.blendingMode = blendingMode + } +} + struct LicensePage: View { var body: some View { - ScrollView { - Text(""" + ZStack { + Color.defaultBackground + .edgesIgnoringSafeArea(.all) + ScrollView { + Text(""" NearDrop https://github.com/grishka/NearDrop @@ -193,12 +277,13 @@ See the License for the specific language governing permissions and limitations under the License. """) - .padding() + .padding() + } } } } #Preview { - WelcomeScreen() + WelcomeScreen(openIAP: {}) } diff --git a/NearDrop/ar.lproj/Localizable.strings b/NearDrop/ar.lproj/Localizable.strings index 47dfe61..9fe2170 100644 --- a/NearDrop/ar.lproj/Localizable.strings +++ b/NearDrop/ar.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d ملفات"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "يحتاج NearDrop إلى القدرة على عرض الإشعارات لنقل الملفات الواردة. يرجى السماح بالإشعارات في إعدادات النظام."; +"NotificationsDenied.Message" = "يحتاج QuickDrop إلى القدرة على عرض الإشعارات لنقل الملفات الواردة. يرجى السماح بالإشعارات في إعدادات النظام."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "افتح الإعدادات"; @@ -32,7 +32,7 @@ "PinCode" = "الرمز السري: %@"; /* No comment provided by engineer. */ -"Quit" = "إنهاء NearDrop"; +"Quit" = "إنهاء QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "فشل في استقبال الملفات من %@"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "سياسة الخصوصية"; "UserManual" = "دليل المستخدم"; -"WelcomeToNearDrop" = "مرحبًا بك في NearDrop"; +"WelcomeToQuickDrop" = "مرحبًا بك في QuickDrop"; "Acknowledgements" = "الشكر والتقدير"; +"SupportQuickDrop" = "ادعم QuickDrop"; -"UserManualDescription" = "عندما يكون NearDrop قيد التشغيل، سيظهر في شريط القائمة في الجزء العلوي من شاشتك. انقر على أيقونة NearDrop إذا كنت ترغب في التوقف عن تلقي الملفات. +"UserManualDescription" = "عندما يكون QuickDrop قيد التشغيل، سيظهر في شريط القائمة في الجزء العلوي من شاشتك. انقر على أيقونة QuickDrop إذا كنت ترغب في التوقف عن تلقي الملفات. مهم: يجب أن يكون جهاز Android الخاص بك وMac متصلين بنفس شبكة Wi-Fi لنقل الملفات. إذا تم مطالبتك بالسماح بالاتصالات الواردة، يرجى السماح بها. لإرسال الملفات من جهاز Android إلى جهاز Mac، انقر على أيقونة المشاركة في هاتفك واختر \"Quick Share\" أو \"Nearby Share\". سيظهر جهاز Mac الخاص بك كجهاز متاح. بعد ذلك، سترى إشعارًا على جهاز Mac الخاص بك. مرر الماوس فوق الإشعار لقبول أو رفض نقل الملفات."; + +"plusview_title" = "شكرًا لاستخدامك QuickDrop!"; +"plusview_description" = "قم بفتح QuickDrop+ لمواصلة استقبال الملفات. QuickDrop+ هو عملية شراء لمرة واحدة – يمكنك الاحتفاظ بالتطبيق إلى الأبد بدون اشتراك."; +"plusview_success_title" = "شكرًا لشرائك!"; +"plusview_success_description" = "يمكنك الآن متابعة استقبال الملفات بدون قيود."; +"plusview_success_button" = "حسنًا!"; +"plusview_unlock_label" = "ادعم QuickDrop"; + +"plusview_restorepurchase" = "هل اشتريته بالفعل؟"; +"plusview_restorefailed" = "حدثت مشكلة أثناء استعادة عملية الشراء"; +"plusview_restorefailed_proceed" = "موافق"; +"plusview_purchasefailed" = "فشل الشراء"; +"plusview_purchasefaileddescription" = "إذا ظهر هذا الرسالة بشكل غير متوقع، يرجى التأكد من اتصالك بالإنترنت وأن عمليات الشراء داخل التطبيق مفعّلة على جهازك، ثم حاول مرة أخرى."; +"plusview_nothingtorestore" = "لا يوجد شيء لاستعادته!"; +"plusview_productRequestFailed" = "تعذر جلب عمليات الشراء داخل التطبيق في الوقت الحالي."; diff --git a/NearDrop/de.lproj/Localizable.strings b/NearDrop/de.lproj/Localizable.strings index 1eedba4..702bb8b 100644 --- a/NearDrop/de.lproj/Localizable.strings +++ b/NearDrop/de.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d Dateien"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop benötigt die Erlaubnis, Mitteilungen für eingehende Übertragungen anzuzeigen. Bitte erlaube Mitteilungen in den Systemeinstellungen."; +"NotificationsDenied.Message" = "QuickDrop benötigt die Erlaubnis, Mitteilungen für eingehende Übertragungen anzuzeigen. Bitte erlaube Mitteilungen in den Systemeinstellungen."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Einstellungen öffnen"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "NearDrop beenden"; +"Quit" = "QuickDrop beenden"; /* No comment provided by engineer. */ "TransferError" = "Die Daten von %@ konnten nicht empfangen werden"; @@ -46,14 +46,30 @@ "UserManual" = "Benutzerhandbuch"; -"WelcomeToNearDrop" = "Willkommen bei NearDrop"; +"WelcomeToQuickDrop" = "Willkommen bei QuickDrop"; "Acknowledgements" = "Danksagungen"; +"SupportQuickDrop" = "QuickDrop unterstützen"; -"UserManualDescription" = "Wenn NearDrop ausgeführt wird, wird es in der Menüleiste am oberen Rand des Bildschirms angezeigt. Klicke auf das NearDrop-Symbol, um den Empfang von Dateien zu beenden. +"UserManualDescription" = "Wenn QuickDrop ausgeführt wird, wird es in der Menüleiste am oberen Rand des Bildschirms angezeigt. Klicke auf das QuickDrop-Symbol, um den Empfang von Dateien zu beenden. Wichtig: Dein Android-Gerät und dein Mac müssen sich im selben Netzwerk befinden, um Dateien zu übertragen. Wenn du aufgefordert wirst, eingehende Verbindungen zuzulassen, lasse sie bitte zu. Um Dateien von deinem Android-Gerät an deinen Mac zu senden, tippe auf deinem Handy auf das Teilen-Symbol und wähle „Quick Share“ oder „Nearby Share“. Dein Mac wird als verfügbares Gerät aufgelistet. Daraufhin wird eine Benachrichtigung auf deinem Mac angezeigt. Bewege den Mauszeiger über die Benachrichtigung, um die Dateiübertragung zu akzeptieren oder abzulehnen."; + +"plusview_title" = "Danke, dass du QuickDrop benutzt!"; +"plusview_description" = "Schalte QuickDrop+ frei, um weiterhin Dateien zu empfangen. QuickDrop+ ist ein einmaliger Kauf – du kannst die App für immer behalten, kein Abonnement erforderlich."; +"plusview_success_title" = "Danke für deinen Kauf!"; +"plusview_success_description" = "Du kannst nun weiterhin Dateien ohne Einschränkungen empfangen."; +"plusview_success_button" = "Alles klar!"; +"plusview_unlock_label" = "Unterstütze QuickDrop"; + +"plusview_restorepurchase" = "Bereits gekauft?"; +"plusview_restorefailed" = "Es gab ein Problem beim Wiederherstellen deines Kaufs"; +"plusview_restorefailed_proceed" = "Okay"; +"plusview_purchasefailed" = "Kauf fehlgeschlagen"; +"plusview_purchasefaileddescription" = "Falls diese Nachricht unerwartet erscheint, stelle sicher, dass du mit dem Internet verbunden bist und In-App-Käufe auf deinem Gerät aktiviert sind, und versuche es erneut."; +"plusview_nothingtorestore" = "Es gibt nichts wiederherzustellen!"; +"plusview_productRequestFailed" = "In-App-Käufe können momentan nicht abgerufen werden."; diff --git a/NearDrop/es.lproj/Localizable.strings b/NearDrop/es.lproj/Localizable.strings index f11e4a9..62b7d55 100644 --- a/NearDrop/es.lproj/Localizable.strings +++ b/NearDrop/es.lproj/Localizable.strings @@ -20,7 +20,7 @@ //"NFiles" = "%d files"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop necesita poder mostrar notificaciones para las transferencias de archivos entrantes. Permite las notificaciones en la configuración del sistema."; +"NotificationsDenied.Message" = "QuickDrop necesita poder mostrar notificaciones para las transferencias de archivos entrantes. Permite las notificaciones en la configuración del sistema."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Abrir la configuración del sistema"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Salir de NearDrop"; +"Quit" = "Salir de QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Error al recibir archivos de %@"; @@ -44,14 +44,31 @@ "PrivacyPolicy" = "Política de privacidad"; "UserManual" = "Manual de usuario"; -"WelcomeToNearDrop" = "Bienvenido a NearDrop"; +"WelcomeToQuickDrop" = "Bienvenido a QuickDrop"; "Acknowledgements" = "Agradecimientos"; +"SupportQuickDrop" = "Apoyar QuickDrop"; -"UserManualDescription" = "Cuando NearDrop está en ejecución, aparecerá en la barra de menú en la parte superior de tu pantalla. Haz clic en el icono de NearDrop si deseas dejar de recibir archivos. +"UserManualDescription" = "Cuando QuickDrop está en ejecución, aparecerá en la barra de menú en la parte superior de tu pantalla. Haz clic en el icono de QuickDrop si deseas dejar de recibir archivos. Importante: Tu dispositivo Android y tu Mac deben estar conectados a la misma red WiFi para transferir archivos. Si se te solicita permitir conexiones entrantes, por favor, acéptalas. Para enviar archivos desde tu dispositivo Android a tu Mac, toca el icono de compartir en tu teléfono y selecciona \"Quick Share\" o \"Nearby Share\". Tu Mac aparecerá como un dispositivo disponible. Después de esto, verás una notificación en tu Mac. Pasa el cursor sobre la notificación para aceptar o rechazar la transferencia del archivo."; + + +"plusview_title" = "¡Gracias por usar QuickDrop!"; +"plusview_description" = "Desbloquea QuickDrop+ para seguir recibiendo archivos. QuickDrop+ es una compra única: puedes conservar la aplicación para siempre, sin necesidad de suscripción."; +"plusview_success_title" = "¡Gracias por tu compra!"; +"plusview_success_description" = "Ahora puedes seguir recibiendo archivos sin restricciones."; +"plusview_success_button" = "¡Entendido!"; +"plusview_unlock_label" = "Apoyar QuickDrop"; + +"plusview_restorepurchase" = "¿Ya lo compraste?"; +"plusview_restorefailed" = "Hubo un problema al restaurar tu compra"; +"plusview_restorefailed_proceed" = "Aceptar"; +"plusview_purchasefailed" = "La compra ha fallado"; +"plusview_purchasefaileddescription" = "Si este mensaje apareció inesperadamente, asegúrate de estar conectado a Internet y que las compras dentro de la aplicación estén habilitadas en tu dispositivo, luego intenta nuevamente."; +"plusview_nothingtorestore" = "¡No hay nada que restaurar!"; +"plusview_productRequestFailed" = "No se pueden recuperar las compras dentro de la aplicación en este momento."; diff --git a/NearDrop/fr.lproj/Localizable.strings b/NearDrop/fr.lproj/Localizable.strings index 4462fda..2c5ee17 100644 --- a/NearDrop/fr.lproj/Localizable.strings +++ b/NearDrop/fr.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d fichiers"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop doit pouvoir afficher des notifications pour les transferts de fichiers entrants. Veuillez autoriser les notifications dans les paramètres système."; +"NotificationsDenied.Message" = "QuickDrop doit pouvoir afficher des notifications pour les transferts de fichiers entrants. Veuillez autoriser les notifications dans les paramètres système."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Ouvrir les paramètres"; @@ -32,7 +32,7 @@ "PinCode" = "CODE PIN : %@"; /* No comment provided by engineer. */ -"Quit" = "Quitter NearDrop"; +"Quit" = "Quitter QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Échec de la réception des fichiers de %@"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "Politique de confidentialité"; "UserManual" = "Manuel d'utilisateur"; -"WelcomeToNearDrop" = "Bienvenue sur NearDrop"; +"WelcomeToQuickDrop" = "Bienvenue sur QuickDrop"; "Acknowledgements" = "Remerciements"; +"SupportQuickDrop" = "Soutenir QuickDrop"; -"UserManualDescription" = "Lorsque NearDrop est en cours d'exécution, il apparaît dans la barre de menu en haut de votre écran. Cliquez sur l'icône NearDrop si vous souhaitez arrêter de recevoir des fichiers. +"UserManualDescription" = "Lorsque QuickDrop est en cours d'exécution, il apparaît dans la barre de menu en haut de votre écran. Cliquez sur l'icône QuickDrop si vous souhaitez arrêter de recevoir des fichiers. Important : Votre appareil Android et votre Mac doivent être connectés au même réseau Wi-Fi pour transférer des fichiers. Si vous êtes invité à autoriser les connexions entrantes, veuillez les autoriser. Pour envoyer des fichiers de votre appareil Android vers votre Mac, appuyez sur l'icône de partage sur votre téléphone et sélectionnez \"Quick Share\" ou \"Nearby Share\". Votre Mac sera affiché comme un appareil disponible. Après cela, vous verrez une notification sur votre Mac. Survolez la notification pour accepter ou refuser le transfert de fichiers."; + +"plusview_title" = "Merci d'utiliser QuickDrop !"; +"plusview_description" = "Débloquez QuickDrop+ pour continuer à recevoir des fichiers. QuickDrop+ est un achat unique – vous pourrez conserver l'application à vie, sans abonnement."; +"plusview_success_title" = "Merci pour votre achat !"; +"plusview_success_description" = "Vous pouvez maintenant continuer à recevoir des fichiers sans restrictions."; +"plusview_success_button" = "D'accord !"; +"plusview_unlock_label" = "Soutenir QuickDrop"; + +"plusview_restorepurchase" = "Déjà acheté ?"; +"plusview_restorefailed" = "Un problème est survenu lors de la restauration de votre achat"; +"plusview_restorefailed_proceed" = "OK"; +"plusview_purchasefailed" = "Échec de l'achat"; +"plusview_purchasefaileddescription" = "Si ce message est apparu de manière inattendue, assurez-vous d'être connecté à Internet et que les achats intégrés sont activés sur votre appareil, puis réessayez."; +"plusview_nothingtorestore" = "Aucun achat à restaurer !"; +"plusview_productRequestFailed" = "Impossible de récupérer les achats intégrés pour le moment."; diff --git a/NearDrop/hu.lproj/Localizable.strings b/NearDrop/hu.lproj/Localizable.strings index 4490fcc..047c5fc 100644 --- a/NearDrop/hu.lproj/Localizable.strings +++ b/NearDrop/hu.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d fájl"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "A NearDrop-nak szüksége van értesítéseket küldeni a bejövő fájlok fogadásához. Kérlek engedélyezd az értesítésekhez való hozzáférést a Rendszerbeállításokban."; +"NotificationsDenied.Message" = "A QuickDrop-nak szüksége van értesítéseket küldeni a bejövő fájlok fogadásához. Kérlek engedélyezd az értesítésekhez való hozzáférést a Rendszerbeállításokban."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Beállítások megnyitása"; @@ -32,7 +32,7 @@ "PinCode" = "JELKÓD: %@"; /* No comment provided by engineer. */ -"Quit" = "NearDrop bezárása"; +"Quit" = "QuickDrop bezárása"; /* No comment provided by engineer. */ "TransferError" = "Nem sikerült %@-tól/től fájlokat fogadni"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "Adatvédelmi irányelvek"; "UserManual" = "Felhasználói kézikönyv"; -"WelcomeToNearDrop" = "Üdvözlünk a NearDropban"; +"WelcomeToQuickDrop" = "Üdvözlünk a QuickDropban"; "Acknowledgements" = "Köszönetnyilvánítás"; +"SupportQuickDrop" = "Támogasd a QuickDropot"; -"UserManualDescription" = "Amikor a NearDrop fut, az megjelenik a képernyő tetején található menüsorban. Kattints a NearDrop ikonra, ha szeretnéd leállítani a fájlok fogadását. +"UserManualDescription" = "Amikor a QuickDrop fut, az megjelenik a képernyő tetején található menüsorban. Kattints a QuickDrop ikonra, ha szeretnéd leállítani a fájlok fogadását. Fontos: Az Android-eszközödnek és a Mac számítógépednek ugyanarra a Wi-Fi hálózatra kell csatlakozniuk a fájlok átviteléhez. Ha megjelenik egy kérdés a bejövő kapcsolatok engedélyezésére, kérjük, engedélyezd azokat. Fájlok küldéséhez az Android-eszközödről a Mac-re érintsd meg a megosztás ikont a telefonodon, majd válaszd a \"Quick Share\" vagy a \"Nearby Share\" lehetőséget. A Mac-ed elérhető eszközként fog megjelenni. Ezt követően értesítést fogsz látni a Mac-en. Vidd az egérmutatót az értesítés fölé, hogy elfogadd vagy elutasítsd a fájlátvitelt."; + +"plusview_title" = "Köszönjük, hogy használod a QuickDropot!"; +"plusview_description" = "Oldd fel a QuickDrop+ funkciót, hogy továbbra is fogadhass fájlokat. A QuickDrop+ egy egyszeri vásárlás – az alkalmazást örökre megtarthatod, előfizetés nélkül."; +"plusview_success_title" = "Köszönjük a vásárlást!"; +"plusview_success_description" = "Mostantól korlátozások nélkül fogadhatsz fájlokat."; +"plusview_success_button" = "Értettem!"; +"plusview_unlock_label" = "Támogasd a QuickDropot"; + +"plusview_restorepurchase" = "Már megvásároltad?"; +"plusview_restorefailed" = "Hiba történt a vásárlás visszaállítása során"; +"plusview_restorefailed_proceed" = "Rendben"; +"plusview_purchasefailed" = "A vásárlás sikertelen"; +"plusview_purchasefaileddescription" = "Ha ez az üzenet váratlanul jelent meg, ellenőrizd az internetkapcsolatot, és győződj meg róla, hogy az alkalmazáson belüli vásárlások engedélyezve vannak az eszközödön, majd próbáld újra."; +"plusview_nothingtorestore" = "Nincs visszaállítható vásárlás!"; +"plusview_productRequestFailed" = "Jelenleg nem lehet lekérni az alkalmazáson belüli vásárlásokat."; diff --git a/NearDrop/it.lproj/Localizable.strings b/NearDrop/it.lproj/Localizable.strings index 7fed386..4df08dc 100644 --- a/NearDrop/it.lproj/Localizable.strings +++ b/NearDrop/it.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d files"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop deve essere in grado di visualizzare le notifiche per i trasferimenti di file in entrata. Consenti le notifiche nelle Impostazioni di sistema."; +"NotificationsDenied.Message" = "QuickDrop deve essere in grado di visualizzare le notifiche per i trasferimenti di file in entrata. Consenti le notifiche nelle Impostazioni di sistema."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Apri le impostazioni"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Esci da NearDrop"; +"Quit" = "Esci da QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Impossibile ricevere i file da %@"; @@ -44,14 +44,31 @@ "PrivacyPolicy" = "Informativa sulla privacy"; "UserManual" = "Manuale utente"; -"WelcomeToNearDrop" = "Benvenuto su NearDrop"; +"WelcomeToQuickDrop" = "Benvenuto su QuickDrop"; "Acknowledgements" = "Ringraziamenti"; +"SupportQuickDrop" = "Supporta QuickDrop"; -"UserManualDescription" = "Quando NearDrop è in esecuzione, verrà visualizzato nella barra dei menu in alto sullo schermo. Fai clic sull'icona di NearDrop se desideri interrompere la ricezione dei file. +"UserManualDescription" = "Quando QuickDrop è in esecuzione, verrà visualizzato nella barra dei menu in alto sullo schermo. Fai clic sull'icona di QuickDrop se desideri interrompere la ricezione dei file. Importante: Il tuo dispositivo Android e il tuo Mac devono essere connessi alla stessa rete WiFi per trasferire file. Se ti viene richiesto di consentire connessioni in entrata, per favore consenti. Per inviare file dal tuo dispositivo Android al tuo Mac, tocca l'icona di condivisione sul tuo telefono e seleziona \"Quick Share\" o \"Nearby Share\". Il tuo Mac verrà elencato come dispositivo disponibile. Dopo di ciò, vedrai una notifica sul tuo Mac. Passa il cursore sulla notifica per accettare o rifiutare il trasferimento del file."; + + +"plusview_title" = "Grazie per aver usato QuickDrop!"; +"plusview_description" = "Sblocca QuickDrop+ per continuare a ricevere file. QuickDrop+ è un acquisto unico: puoi tenere l'app per sempre, senza bisogno di un abbonamento."; +"plusview_success_title" = "Grazie per il tuo acquisto!"; +"plusview_success_description" = "Ora puoi continuare a ricevere file senza restrizioni."; +"plusview_success_button" = "Capito!"; +"plusview_unlock_label" = "Supporta QuickDrop"; + +"plusview_restorepurchase" = "Già acquistato?"; +"plusview_restorefailed" = "Si è verificato un problema durante il ripristino dell'acquisto"; +"plusview_restorefailed_proceed" = "Ok"; +"plusview_purchasefailed" = "Acquisto non riuscito"; +"plusview_purchasefaileddescription" = "Se questo messaggio è apparso inaspettatamente, assicurati di essere connesso a Internet e che gli acquisti in-app siano abilitati sul tuo dispositivo, quindi riprova."; +"plusview_nothingtorestore" = "Non c'è nulla da ripristinare!"; +"plusview_productRequestFailed" = "Impossibile recuperare gli acquisti in-app al momento."; diff --git a/NearDrop/ja.lproj/Localizable.strings b/NearDrop/ja.lproj/Localizable.strings index c6973e2..4aacaa8 100644 --- a/NearDrop/ja.lproj/Localizable.strings +++ b/NearDrop/ja.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%dつのファイル"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDropでファイル受信の通知を表示できる必要があります。システム設定で通知を許可してください。"; +"NotificationsDenied.Message" = "QuickDropでファイル受信の通知を表示できる必要があります。システム設定で通知を許可してください。"; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "設定を開く"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "NearDropを終了"; +"Quit" = "QuickDropを終了"; /* No comment provided by engineer. */ "TransferError" = "%@からのファイル受信に失敗しました。"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "プライバシーポリシー"; "UserManual" = "ユーザーマニュアル"; -"WelcomeToNearDrop" = "NearDropへようこそ"; +"WelcomeToQuickDrop" = "QuickDropへようこそ"; "Acknowledgements" = "謝辞"; +"SupportQuickDrop" = "QuickDrop をサポート"; -"UserManualDescription" = "NearDropが実行中の場合、画面上部のメニューバーに表示されます。ファイルの受信を停止したい場合は、NearDropのアイコンをクリックしてください。 +"UserManualDescription" = "QuickDropが実行中の場合、画面上部のメニューバーに表示されます。ファイルの受信を停止したい場合は、QuickDropのアイコンをクリックしてください。 重要: AndroidデバイスとMacは、ファイルを転送するために同じWi-Fiネットワークに接続している必要があります。接続の許可を求められた場合は、それを許可してください。 AndroidデバイスからMacにファイルを送信するには、電話の共有アイコンをタップし、\"クイックシェア\"Quick Share\"Nearby Share\"を選択してください。Macは利用可能なデバイスとして表示されます。 その後、Macに通知が表示されます。通知にカーソルを合わせて、ファイル転送を承認または拒否してください。"; + +"plusview_title" = "QuickDropをご利用いただきありがとうございます!"; +"plusview_description" = "QuickDrop+をアンロックして、引き続きファイルを受信しましょう。QuickDrop+は一度購入すれば、サブスクリプションなしで永久にアプリを利用できます。"; +"plusview_success_title" = "ご購入ありがとうございます!"; +"plusview_success_description" = "これで、制限なくファイルを受信できます。"; +"plusview_success_button" = "了解!"; +"plusview_unlock_label" = "QuickDropをサポート"; + +"plusview_restorepurchase" = "すでに購入済みですか?"; +"plusview_restorefailed" = "購入の復元中に問題が発生しました"; +"plusview_restorefailed_proceed" = "OK"; +"plusview_purchasefailed" = "購入に失敗しました"; +"plusview_purchasefaileddescription" = "このメッセージが予期せず表示された場合、インターネット接続を確認し、アプリ内購入が有効になっていることを確認した上で再試行してください。"; +"plusview_nothingtorestore" = "復元するものがありません!"; +"plusview_productRequestFailed" = "現在、アプリ内購入情報を取得できません。"; diff --git a/NearDrop/ko.lproj/Localizable.strings b/NearDrop/ko.lproj/Localizable.strings index deaa02c..4b34230 100644 --- a/NearDrop/ko.lproj/Localizable.strings +++ b/NearDrop/ko.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d개의 파일"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop에서 파일 수신에 대한 알림을 표시할 수 있어야 합니다. 시스템 설정에서 알림을 허용하세요."; +"NotificationsDenied.Message" = "QuickDrop에서 파일 수신에 대한 알림을 표시할 수 있어야 합니다. 시스템 설정에서 알림을 허용하세요."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "설정 열기"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "NearDrop 종료"; +"Quit" = "QuickDrop 종료"; /* No comment provided by engineer. */ "TransferError" = "%@에서 전송한 Nearby Share가 실패했습니다."; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "개인정보 처리방침"; "UserManual" = "사용자 매뉴얼"; -"WelcomeToNearDrop" = "NearDrop에 오신 것을 환영합니다"; +"WelcomeToQuickDrop" = "QuickDrop에 오신 것을 환영합니다"; "Acknowledgements" = "감사의 말"; +"SupportQuickDrop" = "QuickDrop 지원하기"; -"UserManualDescription" = "NearDrop이 실행 중이면 화면 상단 메뉴 막대에 나타납니다. 파일 수신을 중지하려면 NearDrop 아이콘을 클릭하세요. +"UserManualDescription" = "QuickDrop이 실행 중이면 화면 상단 메뉴 막대에 나타납니다. 파일 수신을 중지하려면 QuickDrop 아이콘을 클릭하세요. 중요: Android 기기와 Mac이 파일을 전송하려면 동일한 WiFi 네트워크에 연결되어 있어야 합니다. 들어오는 연결을 허용하라는 메시지가 표시되면 허용하세요. Android 기기에서 Mac으로 파일을 전송하려면 휴대전화에서 공유 아이콘을 탭한 다음 \"Quick Share\" 또는 \"Nearby Share\"를 선택하세요. Mac이 사용 가능한 장치로 표시됩니다. 그 후, Mac에서 알림이 표시됩니다. 알림 위에 커서를 올려 파일 전송을 수락하거나 거부하세요."; + +"plusview_title" = "QuickDrop을 사용해 주셔서 감사합니다!"; +"plusview_description" = "QuickDrop+를 잠금 해제하여 파일을 계속 받을 수 있습니다. QuickDrop+는 1회 구매로, 구독 없이 앱을 영구적으로 사용할 수 있습니다."; +"plusview_success_title" = "구매해 주셔서 감사합니다!"; +"plusview_success_description" = "이제 제한 없이 파일을 받을 수 있습니다."; +"plusview_success_button" = "알겠습니다!"; +"plusview_unlock_label" = "QuickDrop 지원하기"; + +"plusview_restorepurchase" = "이미 구매하셨나요?"; +"plusview_restorefailed" = "구매 복원 중 문제가 발생했습니다."; +"plusview_restorefailed_proceed" = "확인"; +"plusview_purchasefailed" = "구매 실패"; +"plusview_purchasefaileddescription" = "이 메시지가 예상치 않게 나타난 경우, 인터넷에 연결되어 있는지 확인하고 기기에서 인앱 결제가 활성화되어 있는지 확인한 후 다시 시도해 주세요."; +"plusview_nothingtorestore" = "복원할 항목이 없습니다!"; +"plusview_productRequestFailed" = "현재 인앱 구매 정보를 가져올 수 없습니다."; diff --git a/NearDrop/nl.lproj/Localizable.strings b/NearDrop/nl.lproj/Localizable.strings index 86c1122..8595c2b 100644 --- a/NearDrop/nl.lproj/Localizable.strings +++ b/NearDrop/nl.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d bestanden"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop moet meldingen kunnen weergeven voor inkomende bestandsoverdrachten. Sta meldingen toe in de systeeminstellingen."; +"NotificationsDenied.Message" = "QuickDrop moet meldingen kunnen weergeven voor inkomende bestandsoverdrachten. Sta meldingen toe in de systeeminstellingen."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Instellingen openen"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "NearDrop afsluiten"; +"Quit" = "QuickDrop afsluiten"; /* No comment provided by engineer. */ "TransferError" = "Mislukt om bestanden te ontvangen van %@"; @@ -46,14 +46,30 @@ "UserManual" = "Gebruikershandleiding"; -"WelcomeToNearDrop" = "Welkom bij NearDrop"; +"WelcomeToQuickDrop" = "Welkom bij QuickDrop"; "Acknowledgements" = "Erkenningen"; +"SupportQuickDrop" = "Ondersteun QuickDrop"; -"UserManualDescription" = "Wanneer NearDrop actief is, verschijnt het in de menubalk bovenaan je scherm. Klik op het NearDrop-pictogram als je wilt stoppen met het ontvangen van bestanden. +"UserManualDescription" = "Wanneer QuickDrop actief is, verschijnt het in de menubalk bovenaan je scherm. Klik op het QuickDrop-pictogram als je wilt stoppen met het ontvangen van bestanden. Belangrijk: Je Android-apparaat en je Mac moeten verbonden zijn met hetzelfde WiFi-netwerk om bestanden over te dragen. Als je wordt gevraagd om inkomende verbindingen toe te staan, geef dan toestemming. Om bestanden van je Android-apparaat naar je Mac te verzenden, tik op het deelpictogram op je telefoon en selecteer \"Quick Share\" of \"Nearby Share\". Je Mac wordt weergegeven als een beschikbaar apparaat. Daarna zie je een melding op je Mac. Beweeg de muis over de melding om het bestandsoverdracht te accepteren of te weigeren."; + +"plusview_title" = "Bedankt voor het gebruiken van QuickDrop!"; +"plusview_description" = "Ontgrendel QuickDrop+ om bestanden te blijven ontvangen. QuickDrop+ is een eenmalige aankoop – je kunt de app voor altijd behouden, geen abonnement nodig."; +"plusview_success_title" = "Bedankt voor je aankoop!"; +"plusview_success_description" = "Je kunt nu bestanden blijven ontvangen zonder beperkingen."; +"plusview_success_button" = "Begrepen!"; +"plusview_unlock_label" = "Ondersteun QuickDrop"; + +"plusview_restorepurchase" = "Al gekocht?"; +"plusview_restorefailed" = "Er was een probleem bij het herstellen van je aankoop"; +"plusview_restorefailed_proceed" = "Oké"; +"plusview_purchasefailed" = "Aankoop mislukt"; +"plusview_purchasefaileddescription" = "Als dit bericht onverwachts verschijnt, controleer dan of je verbonden bent met internet en of in-app aankopen zijn ingeschakeld op je apparaat, en probeer het opnieuw."; +"plusview_nothingtorestore" = "Er is niets om te herstellen!"; +"plusview_productRequestFailed" = "In-app aankopen kunnen momenteel niet worden opgehaald."; diff --git a/NearDrop/pt-BR.lproj/Localizable.strings b/NearDrop/pt-BR.lproj/Localizable.strings index 30d7886..ed584a8 100644 --- a/NearDrop/pt-BR.lproj/Localizable.strings +++ b/NearDrop/pt-BR.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d arquivos"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "O NearDrop precisa ser capaz de exibir notificações para o recebimento de arquivos. Por favor, habilite as notificações em Ajustes do Sistema."; +"NotificationsDenied.Message" = "O QuickDrop precisa ser capaz de exibir notificações para o recebimento de arquivos. Por favor, habilite as notificações em Ajustes do Sistema."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Abrir configurações"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Sair do NearDrop"; +"Quit" = "Sair do QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Falha ao receber arquivos de %@"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "Política de Privacidade"; "UserManual" = "Manual do Usuário"; -"WelcomeToNearDrop" = "Bem-vindo ao NearDrop"; +"WelcomeToQuickDrop" = "Bem-vindo ao QuickDrop"; "Acknowledgements" = "Agradecimentos"; +"SupportQuickDrop" = "Apoie o QuickDrop"; -"UserManualDescription" = "Quando o NearDrop estiver em execução, ele aparecerá na barra de menu na parte superior da sua tela. Clique no ícone do NearDrop se quiser parar de receber arquivos. +"UserManualDescription" = "Quando o QuickDrop estiver em execução, ele aparecerá na barra de menu na parte superior da sua tela. Clique no ícone do QuickDrop se quiser parar de receber arquivos. Importante: Seu dispositivo Android e seu Mac precisam estar conectados à mesma rede Wi-Fi para transferir arquivos. Se for solicitado que você permita conexões de entrada, por favor, permita. Para enviar arquivos do seu dispositivo Android para o seu Mac, toque no ícone de compartilhamento no seu telefone e selecione \"Quick Share\" ou \"Nearby Share\". O seu Mac será exibido como um dispositivo disponível. Depois disso, você verá uma notificação no seu Mac. Passe o cursor sobre a notificação para aceitar ou recusar a transferência do arquivo."; + +"plusview_title" = "Obrigado por usar o QuickDrop!"; +"plusview_description" = "Desbloqueie o QuickDrop+ para continuar recebendo arquivos. O QuickDrop+ é uma compra única – você pode ficar com o aplicativo para sempre, sem necessidade de assinatura."; +"plusview_success_title" = "Obrigado pela sua compra!"; +"plusview_success_description" = "Agora você pode continuar recebendo arquivos sem restrições."; +"plusview_success_button" = "Entendi!"; +"plusview_unlock_label" = "Apoie o QuickDrop"; + +"plusview_restorepurchase" = "Já comprou?"; +"plusview_restorefailed" = "Houve um problema ao restaurar sua compra"; +"plusview_restorefailed_proceed" = "OK"; +"plusview_purchasefailed" = "Falha na compra"; +"plusview_purchasefaileddescription" = "Se esta mensagem apareceu inesperadamente, verifique se você está conectado à internet e se as compras dentro do app estão ativadas no seu dispositivo e tente novamente."; +"plusview_nothingtorestore" = "Nada para restaurar!"; +"plusview_productRequestFailed" = "Não foi possível recuperar as compras dentro do aplicativo no momento."; diff --git a/NearDrop/pt-PT.lproj/Localizable.strings b/NearDrop/pt-PT.lproj/Localizable.strings index 1a745c4..047be27 100644 --- a/NearDrop/pt-PT.lproj/Localizable.strings +++ b/NearDrop/pt-PT.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d ficheiros"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "O NearDrop precisa ser capaz de mostrar notificações para receber ficheiros. Por favor, active as notificações em Definições do Sistema."; +"NotificationsDenied.Message" = "O QuickDrop precisa ser capaz de mostrar notificações para receber ficheiros. Por favor, active as notificações em Definições do Sistema."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Abrir definições"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Sair do NearDrop"; +"Quit" = "Sair do QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Falha ao receber ficheiros de %@"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "Política de privacidade"; "UserManual" = "Manual do usuário"; -"WelcomeToNearDrop" = "Bem-vindo ao NearDrop"; +"WelcomeToQuickDrop" = "Bem-vindo ao QuickDrop"; "Acknowledgements" = "Agradecimentos"; +"SupportQuickDrop" = "Apoie o QuickDrop"; -"UserManualDescription" = "Quando o NearDrop estiver em execução, ele aparecerá na barra de menu na parte superior da sua tela. Clique no ícone do NearDrop se quiser parar de receber arquivos. +"UserManualDescription" = "Quando o QuickDrop estiver em execução, ele aparecerá na barra de menu na parte superior da sua tela. Clique no ícone do QuickDrop se quiser parar de receber arquivos. Importante: Seu dispositivo Android e seu Mac precisam estar conectados à mesma rede Wi-Fi para transferir arquivos. Se for solicitado que você permita conexões de entrada, por favor, permita. Para enviar arquivos do seu dispositivo Android para o seu Mac, toque no ícone de compartilhamento no seu telefone e selecione \"Quick Share\" ou \"Nearby Share\". O seu Mac será exibido como um dispositivo disponível. Depois disso, você verá uma notificação no seu Mac. Passe o cursor sobre a notificação para aceitar ou recusar a transferência do arquivo."; + +"plusview_title" = "Obrigado por usar o QuickDrop!"; +"plusview_description" = "Desbloqueie o QuickDrop+ para continuar recebendo arquivos. QuickDrop+ é uma compra única – você pode manter o app para sempre, sem necessidade de assinatura."; +"plusview_success_title" = "Obrigado pela sua compra!"; +"plusview_success_description" = "Agora você pode continuar enviando arquivos sem restrições."; +"plusview_success_button" = "Entendido!"; +"plusview_unlock_label" = "Apoiar QuickDrop"; + +"plusview_restorepurchase" = "Já comprou?"; +"plusview_restorefailed" = "Houve um problema ao restaurar sua compra"; +"plusview_restorefailed_proceed" = "Ok"; +"plusview_purchasefailed" = "Falha na compra"; +"plusview_purchasefaileddescription" = "Se esta mensagem apareceu inesperadamente, certifique-se de estar conectado à Internet e que as compras dentro do app estejam ativadas no seu dispositivo, depois tente novamente."; +"plusview_nothingtorestore" = "Não há nada para restaurar!"; +"plusview_productRequestFailed" = "Não foi possível recuperar as compras dentro do app no momento."; diff --git a/NearDrop/ro.lproj/Localizable.strings b/NearDrop/ro.lproj/Localizable.strings index 915b1ad..3bfd29f 100644 --- a/NearDrop/ro.lproj/Localizable.strings +++ b/NearDrop/ro.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d fișiere"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop trebuie să poată afișa notificări pentru transferurile de fișiere primite. Vă rugăm să permiteți notificările în Setările Sistemului."; +"NotificationsDenied.Message" = "QuickDrop trebuie să poată afișa notificări pentru transferurile de fișiere primite. Vă rugăm să permiteți notificările în Setările Sistemului."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Deschide setările"; @@ -32,7 +32,7 @@ "PinCode" = "COD PIN : %@"; /* No comment provided by engineer. */ -"Quit" = "Închide NearDrop"; +"Quit" = "Închide QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Recepționarea fișierelor de la %@ a eșuat"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "Politica de confidențialitate"; "UserManual" = "Manualul utilizatorului"; -"WelcomeToNearDrop" = "Bine ai venit la NearDrop"; +"WelcomeToQuickDrop" = "Bine ai venit la QuickDrop"; "Acknowledgements" = "Mulțumiri"; +"SupportQuickDrop" = "Susține QuickDrop"; -"UserManualDescription" = "Când NearDrop este în funcțiune, va apărea în bara de meniu din partea de sus a ecranului. Fă clic pe iconița NearDrop dacă dorești să oprești primirea fișierelor. +"UserManualDescription" = "Când QuickDrop este în funcțiune, va apărea în bara de meniu din partea de sus a ecranului. Fă clic pe iconița QuickDrop dacă dorești să oprești primirea fișierelor. Important: Dispozitivul tău Android și Mac-ul tău trebuie să fie conectate la aceeași rețea Wi-Fi pentru a transfera fișiere. Dacă ți se solicită să permiți conexiunile intrante, te rugăm să le permiți. Pentru a trimite fișiere de pe dispozitivul tău Android pe Mac, apasă pe iconița de partajare de pe telefon și selectează „Quick Share” sau „Nearby Share”. Mac-ul tău va apărea ca dispozitiv disponibil. După aceea, vei vedea o notificare pe Mac. Plasează cursorul peste notificare pentru a accepta sau a respinge transferul fișierelor."; + +"plusview_title" = "Mulțumim că folosești QuickDrop!"; +"plusview_description" = "Deblochează QuickDrop+ pentru a continua să primești fișiere. QuickDrop+ este o achiziție unică – poți păstra aplicația pentru totdeauna, fără abonament."; +"plusview_success_title" = "Mulțumim pentru achiziție!"; +"plusview_success_description" = "Acum poți continua să primești fișiere fără restricții."; +"plusview_success_button" = "Înțeles!"; +"plusview_unlock_label" = "Susține QuickDrop"; + +"plusview_restorepurchase" = "Deja cumpărat?"; +"plusview_restorefailed" = "A apărut o problemă la restaurarea achiziției"; +"plusview_restorefailed_proceed" = "OK"; +"plusview_purchasefailed" = "Achiziția a eșuat"; +"plusview_purchasefaileddescription" = "Dacă acest mesaj a apărut neașteptat, asigură-te că ești conectat la internet și că achizițiile în aplicație sunt activate pe dispozitivul tău, apoi încearcă din nou."; +"plusview_nothingtorestore" = "Nu există nimic de restaurat!"; +"plusview_productRequestFailed" = "Momentan, nu se pot obține informații despre achizițiile în aplicație."; diff --git a/NearDrop/ru.lproj/Localizable.strings b/NearDrop/ru.lproj/Localizable.strings index b7c5b34..a23aa5e 100644 --- a/NearDrop/ru.lproj/Localizable.strings +++ b/NearDrop/ru.lproj/Localizable.strings @@ -23,7 +23,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Завершить NearDrop"; +"Quit" = "Завершить QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Не удалость принять файлы от %@"; @@ -32,7 +32,7 @@ "VisibleToEveryone" = "Видимость: все"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop необходима возможность показывать уведомления о входящих файлах. Пожалуйста, разрешите уведомления в Системных настройках."; +"NotificationsDenied.Message" = "QuickDrop необходима возможность показывать уведомления о входящих файлах. Пожалуйста, разрешите уведомления в Системных настройках."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Открыть настройки"; @@ -46,14 +46,30 @@ "UserManual" = "Руководство пользователя"; -"WelcomeToNearDrop" = "Добро пожаловать в NearDrop"; +"WelcomeToQuickDrop" = "Добро пожаловать в QuickDrop"; "Acknowledgements" = "Благодарности"; +"SupportQuickDrop" = "Поддержать QuickDrop"; -"UserManualDescription" = "Когда NearDrop запущен, он отображается в строке меню в верхней части экрана. Нажмите на значок NearDrop, если вы хотите прекратить получение файлов. +"UserManualDescription" = "Когда QuickDrop запущен, он отображается в строке меню в верхней части экрана. Нажмите на значок QuickDrop, если вы хотите прекратить получение файлов. Важно: Ваше устройство Android и Mac должны быть подключены к одной и той же сети Wi-Fi для передачи файлов. Если появится запрос на разрешение входящих подключений, пожалуйста, разрешите их. Чтобы отправить файлы с вашего устройства Android на Mac, нажмите на значок «Поделиться» на вашем телефоне и выберите \"Quick Share\" или \"Nearby Share\". Ваш Mac отобразится в списке доступных устройств. После этого на вашем Mac появится уведомление. Наведите курсор на уведомление, чтобы принять или отклонить передачу файла."; + +"plusview_title" = "Спасибо за использование QuickDrop!"; +"plusview_description" = "Разблокируйте QuickDrop+, чтобы продолжать получать файлы. QuickDrop+ — это разовая покупка: приложение останется у вас навсегда, без подписки."; +"plusview_success_title" = "Спасибо за покупку!"; +"plusview_success_description" = "Теперь вы можете продолжать получать файлы без ограничений."; +"plusview_success_button" = "Понял!"; +"plusview_unlock_label" = "Поддержать QuickDrop"; + +"plusview_restorepurchase" = "Уже куплено?"; +"plusview_restorefailed" = "Произошла ошибка при восстановлении покупки"; +"plusview_restorefailed_proceed" = "Окей"; +"plusview_purchasefailed" = "Ошибка покупки"; +"plusview_purchasefaileddescription" = "Если это сообщение появилось неожиданно, убедитесь, что у вас есть доступ к интернету и включены встроенные покупки на вашем устройстве, затем попробуйте снова."; +"plusview_nothingtorestore" = "Нет покупок для восстановления!"; +"plusview_productRequestFailed" = "Не удалось получить данные о встроенных покупках."; diff --git a/NearDrop/th.lproj/Localizable.strings b/NearDrop/th.lproj/Localizable.strings index 71c7373..5b62273 100644 --- a/NearDrop/th.lproj/Localizable.strings +++ b/NearDrop/th.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d ไฟล์"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop ไม่สามารถแสดงการแจ้งเตือนไฟล์ที่เข้ามาได้ โปรดให้สิทธิ์การแจ้งเตือน ในการตั้งค่าระบบ"; +"NotificationsDenied.Message" = "QuickDrop ไม่สามารถแสดงการแจ้งเตือนไฟล์ที่เข้ามาได้ โปรดให้สิทธิ์การแจ้งเตือน ในการตั้งค่าระบบ"; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "การตั้งค่า"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "ออก NearDrop"; +"Quit" = "ออก QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "เกิดข้อผิดพลาดในการรับไฟล์จาก %@"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "นโยบายความเป็นส่วนตัว"; "UserManual" = "คู่มือการใช้งาน"; -"WelcomeToNearDrop" = "ยินดีต้อนรับสู่ NearDrop"; +"WelcomeToQuickDrop" = "ยินดีต้อนรับสู่ QuickDrop"; "Acknowledgements" = "คำขอบคุณ"; +"SupportQuickDrop" = "สนับสนุน QuickDrop"; -"UserManualDescription" = "เมื่อ NearDrop กำลังทำงานอยู่ ไอคอนจะปรากฏในแถบเมนูที่ด้านบนของหน้าจอของคุณ คลิกที่ไอคอน NearDrop หากคุณต้องการหยุดรับไฟล์ +"UserManualDescription" = "เมื่อ QuickDrop กำลังทำงานอยู่ ไอคอนจะปรากฏในแถบเมนูที่ด้านบนของหน้าจอของคุณ คลิกที่ไอคอน QuickDrop หากคุณต้องการหยุดรับไฟล์ สำคัญ: อุปกรณ์ Android และ Mac ของคุณจะต้องเชื่อมต่อกับเครือข่าย WiFi เดียวกันเพื่อถ่ายโอนไฟล์ หากมีการแจ้งเตือนให้อนุญาตการเชื่อมต่อขาเข้า โปรดอนุญาต ในการส่งไฟล์จากอุปกรณ์ Android ของคุณไปยัง Mac ให้แตะที่ไอคอนแชร์บนโทรศัพท์ของคุณ และเลือก \"Quick Share\" หรือ \"Nearby Share\" Mac ของคุณจะแสดงในรายการอุปกรณ์ที่พร้อมใช้งาน หลังจากนั้น คุณจะเห็นการแจ้งเตือนบน Mac ของคุณ วางเคอร์เซอร์เหนือการแจ้งเตือนเพื่อยอมรับหรือปฏิเสธการถ่ายโอนไฟล์"; + +"plusview_title" = "ขอบคุณที่ใช้ QuickDrop!"; +"plusview_description" = "ปลดล็อก QuickDrop+ เพื่อรับไฟล์ต่อไป QuickDrop+ เป็นการซื้อครั้งเดียว – คุณสามารถใช้แอปได้ตลอดไปโดยไม่ต้องสมัครสมาชิก"; +"plusview_success_title" = "ขอบคุณสำหรับการซื้อ!"; +"plusview_success_description" = "คุณสามารถรับไฟล์ได้ต่อไปโดยไม่มีข้อจำกัดแล้ว"; +"plusview_success_button" = "รับทราบ!"; +"plusview_unlock_label" = "สนับสนุน QuickDrop"; + +"plusview_restorepurchase" = "เคยซื้อแล้ว?"; +"plusview_restorefailed" = "เกิดปัญหาในการกู้คืนการซื้อของคุณ"; +"plusview_restorefailed_proceed" = "ตกลง"; +"plusview_purchasefailed" = "การซื้อล้มเหลว"; +"plusview_purchasefaileddescription" = "หากข้อความนี้ปรากฏขึ้นโดยไม่คาดคิด โปรดตรวจสอบว่าคุณเชื่อมต่ออินเทอร์เน็ตและเปิดใช้งานการซื้อภายในแอปในอุปกรณ์ของคุณแล้วลองอีกครั้ง"; +"plusview_nothingtorestore" = "ไม่มีรายการที่ต้องกู้คืน!"; +"plusview_productRequestFailed" = "ไม่สามารถดึงข้อมูลการซื้อภายในแอปได้ในขณะนี้"; diff --git a/NearDrop/uk.lproj/Localizable.strings b/NearDrop/uk.lproj/Localizable.strings index 3ac69d4..2be0b70 100644 --- a/NearDrop/uk.lproj/Localizable.strings +++ b/NearDrop/uk.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d files"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop потрібна можливість показувати сповіщення про вхідні файли. Будь ласка, дозвольте сповіщення у Системних налаштуваннях."; +"NotificationsDenied.Message" = "QuickDrop потрібна можливість показувати сповіщення про вхідні файли. Будь ласка, дозвольте сповіщення у Системних налаштуваннях."; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "Відкрити налаштування"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "Завершити NearDrop"; +"Quit" = "Завершити QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "Не вдалося отримати файли від %@"; @@ -45,14 +45,30 @@ "UserManual" = "Посібник користувача"; -"WelcomeToNearDrop" = "Ласкаво просимо до NearDrop"; +"WelcomeToQuickDrop" = "Ласкаво просимо до QuickDrop"; "Acknowledgements" = "Подяки"; +"SupportQuickDrop" = "Підтримати QuickDrop"; -"UserManualDescription" = "Коли NearDrop працює, він з'являється в рядку меню в верхній частині екрана. Клікніть на значок NearDrop, якщо ви хочете припинити отримувати файли. +"UserManualDescription" = "Коли QuickDrop працює, він з'являється в рядку меню в верхній частині екрана. Клікніть на значок QuickDrop, якщо ви хочете припинити отримувати файли. Важливо: Ваш пристрій Android і Mac повинні бути підключені до однієї WiFi-мережі для передачі файлів. Якщо вам запропонують дозволити вхідні підключення, будь ласка, дозвольте їх. Щоб надіслати файли з вашого пристрою Android на Mac, торкніться іконки спільного доступу на вашому телефоні та виберіть \"Quick Share\" або \"Nearby Share\". Ваш Mac буде відображатися як доступний пристрій. Після цього ви побачите сповіщення на вашому Mac. Наведіть курсор на сповіщення, щоб прийняти або відхилити передачу файлів."; + +"plusview_title" = "Дякуємо за використання QuickDrop!"; +"plusview_description" = "Розблокуйте QuickDrop+, щоб продовжити отримання файлів. QuickDrop+ — це одноразова покупка, додаток залишиться у вас назавжди, без необхідності підписки."; +"plusview_success_title" = "Дякуємо за покупку!"; +"plusview_success_description" = "Тепер ви можете продовжувати отримувати файли без обмежень."; +"plusview_success_button" = "Зрозуміло!"; +"plusview_unlock_label" = "Підтримати QuickDrop"; + +"plusview_restorepurchase" = "Вже куплено?"; +"plusview_restorefailed" = "Сталася помилка під час відновлення покупки"; +"plusview_restorefailed_proceed" = "Гаразд"; +"plusview_purchasefailed" = "Помилка покупки"; +"plusview_purchasefaileddescription" = "Якщо це повідомлення з’явилося несподівано, переконайтеся, що у вас є підключення до Інтернету, а покупки в додатках увімкнені на вашому пристрої, і спробуйте ще раз."; +"plusview_nothingtorestore" = "Немає покупок для відновлення!"; +"plusview_productRequestFailed" = "Наразі неможливо отримати інформацію про покупки в додатку."; diff --git a/NearDrop/zh-Hans.lproj/Localizable.strings b/NearDrop/zh-Hans.lproj/Localizable.strings index 3e946c5..38b0474 100644 --- a/NearDrop/zh-Hans.lproj/Localizable.strings +++ b/NearDrop/zh-Hans.lproj/Localizable.strings @@ -20,7 +20,7 @@ "NFiles" = "%d files"; /* No comment provided by engineer. */ -"NotificationsDenied.Message" = "NearDrop 需显示是否接收文件传输的通知。请在 系统设置 中允许通知。"; +"NotificationsDenied.Message" = "QuickDrop 需显示是否接收文件传输的通知。请在 系统设置 中允许通知。"; /* No comment provided by engineer. */ "NotificationsDenied.OpenSettings" = "打开设置"; @@ -32,7 +32,7 @@ "PinCode" = "PIN: %@"; /* No comment provided by engineer. */ -"Quit" = "退出 NearDrop"; +"Quit" = "退出 QuickDrop"; /* No comment provided by engineer. */ "TransferError" = "无法从 %@ 接收文件"; @@ -44,14 +44,30 @@ "PrivacyPolicy" = "隐私政策"; "UserManual" = "用户手册"; -"WelcomeToNearDrop" = "欢迎使用 NearDrop"; +"WelcomeToQuickDrop" = "欢迎使用 QuickDrop"; "Acknowledgements" = "致谢"; +"SupportQuickDrop" = "支持 QuickDrop"; -"UserManualDescription" = "当 NearDrop 运行时,它会出现在屏幕顶部的菜单栏中。如果您想停止接收文件,请点击 NearDrop 图标。 +"UserManualDescription" = "当 QuickDrop 运行时,它会出现在屏幕顶部的菜单栏中。如果您想停止接收文件,请点击 QuickDrop 图标。 重要提示:您的 Android 设备和 Mac 需要连接到同一个 WiFi 网络才能传输文件。如果系统提示允许传入连接,请选择允许。 要将文件从 Android 设备发送到 Mac,请点击手机上的分享图标,然后选择“Quick Share”或“Nearby Share”。您的 Mac 将显示为可用设备。 之后,您将在 Mac 上看到一条通知。将鼠标悬停在通知上以接受或拒绝文件传输。"; + +"plusview_title" = "感谢使用 QuickDrop!"; +"plusview_description" = "解锁 QuickDrop+ 以继续接收文件。QuickDrop+ 是一次性购买 – 无需订阅,你可以永久保留此应用。"; +"plusview_success_title" = "感谢您的购买!"; +"plusview_success_description" = "您现在可以无限制地接收文件了。"; +"plusview_success_button" = "知道了!"; +"plusview_unlock_label" = "支持 QuickDrop"; + +"plusview_restorepurchase" = "已购买?"; +"plusview_restorefailed" = "恢复购买时出现问题"; +"plusview_restorefailed_proceed" = "确定"; +"plusview_purchasefailed" = "购买失败"; +"plusview_purchasefaileddescription" = "如果此消息意外出现,请确保您已连接到互联网,并且设备已启用应用内购买功能,然后重试。"; +"plusview_nothingtorestore" = "没有可恢复的购买!"; +"plusview_productRequestFailed" = "暂时无法获取应用内购买信息。"; diff --git a/NearDrop/zh-Hans.lproj/NearDrop-InfoPlist.strings b/NearDrop/zh-Hans.lproj/NearDrop-InfoPlist.strings deleted file mode 100644 index 55763cb..0000000 --- a/NearDrop/zh-Hans.lproj/NearDrop-InfoPlist.strings +++ /dev/null @@ -1,3 +0,0 @@ -/* Bundle name */ -"CFBundleName" = "NearDrop"; - diff --git a/NearbyShare/Data+Extensions.swift b/NearbyShare/Data+Extensions.swift index efa8472..5d3013e 100644 --- a/NearbyShare/Data+Extensions.swift +++ b/NearbyShare/Data+Extensions.swift @@ -1,6 +1,6 @@ // // Data+URLSafeBase64.swift -// NearDrop +// QuickDrop // // Created by Grishka on 08.04.2023. // diff --git a/NearbyShare/InboundNearbyConnection.swift b/NearbyShare/InboundNearbyConnection.swift index e50ae19..d7ddb2e 100644 --- a/NearbyShare/InboundNearbyConnection.swift +++ b/NearbyShare/InboundNearbyConnection.swift @@ -1,6 +1,6 @@ // // InboundNearbyConnection.swift -// NearDrop +// QuickDrop // // Created by Grishka on 08.04.2023. // @@ -37,7 +37,7 @@ class InboundNearbyConnection: NearbyConnection{ do{ try deletePartiallyReceivedFiles() }catch{ - print("Error deleting partially received files: \(error)") + log("Error deleting partially received files: \(error)") } DispatchQueue.main.async { self.delegate?.connectionWasTerminated(connection: self, error: self.lastError) @@ -66,7 +66,7 @@ class InboundNearbyConnection: NearbyConnection{ } }catch{ lastError=error - print("Deserialization error: \(error) in state \(currentState)") + log("Deserialization error: \(error) in state \(currentState)") #if !DEBUG protocolError() #endif @@ -75,7 +75,7 @@ class InboundNearbyConnection: NearbyConnection{ override internal func processTransferSetupFrame(_ frame:Sharing_Nearby_Frame) throws{ if frame.hasV1 && frame.v1.hasType, case .cancel = frame.v1.type { - print("Transfer canceled") + log("Transfer canceled") try sendDisconnectionAndDisconnect() return } @@ -87,8 +87,8 @@ class InboundNearbyConnection: NearbyConnection{ case .receivedPairedKeyResult: try processIntroductionFrame(frame) default: - print("Unexpected connection state in processTransferSetupFrame: \(currentState)") - print(frame) + log("Unexpected connection state in processTransferSetupFrame: \(currentState)") + log(frame.debugDescription) } } @@ -259,7 +259,7 @@ class InboundNearbyConnection: NearbyConnection{ try sendTransferSetupFrame(pairedEncryption) currentState = .sentConnectionResponse } else { - print("Unhandled offline frame plaintext: \(frame)") + log("Unhandled offline frame plaintext: \(frame)") } } @@ -390,7 +390,7 @@ class InboundNearbyConnection: NearbyConnection{ try sendTransferSetupFrame(frame) try sendDisconnectionAndDisconnect() }catch{ - print("Error \(error)") + log("Error \(error)") protocolError() } } diff --git a/NearbyShare/NearbyConnection.swift b/NearbyShare/NearbyConnection.swift index 2303aa3..24d87d3 100644 --- a/NearbyShare/NearbyConnection.swift +++ b/NearbyShare/NearbyConnection.swift @@ -1,6 +1,6 @@ // // NearbyConnection.swift -// NearDrop +// QuickDrop // // Created by Grishka on 09.04.2023. // @@ -16,7 +16,7 @@ import BigInt class NearbyConnection{ internal static let SANE_FRAME_LENGTH=5*1024*1024 - private static let dispatchQueue=DispatchQueue(label: "me.grishka.NearDrop.queue", qos: .utility) // FIFO (non-concurrent) queue to avoid those exciting concurrency bugs + private static let dispatchQueue=DispatchQueue(label: "com.leonboettger.quickdrop.queue", qos: .utility) // FIFO (non-concurrent) queue to avoid those exciting concurrency bugs internal let connection:NWConnection internal var remoteDeviceInfo:RemoteDeviceInfo? @@ -57,7 +57,7 @@ class NearbyConnection{ self.receiveFrameAsync() } else if case .failed(let err) = state { self.lastError=err - print("Error opening socket: \(err)") + log("Error opening socket: \(err)") self.handleConnectionClosure() } } @@ -68,7 +68,7 @@ class NearbyConnection{ func connectionReady(){} internal func handleConnectionClosure(){ - print("Connection closed") + log("Connection closed") } internal func protocolError(){ @@ -295,11 +295,11 @@ class NearbyConnection{ } }else if offlineFrame.hasV1 && offlineFrame.v1.hasType, case .keepAlive = offlineFrame.v1.type{ #if DEBUG - print("Sent keep-alive") + log("Sent keep-alive") #endif sendKeepAlive(ack: true) }else{ - print("Unhandled offline frame encrypted: \(offlineFrame)") + log("Unhandled offline frame encrypted: \(offlineFrame)") } } @@ -444,7 +444,7 @@ class NearbyConnection{ sendFrameAsync(try offlineFrame.serializedData()) } }catch{ - print("Error sending KEEP_ALIVE: \(error)") + log("Error sending KEEP_ALIVE: \(error)") } } } diff --git a/NearbyShare/NearbyConnectionManager.swift b/NearbyShare/NearbyConnectionManager.swift index 0fbb222..c9d29dd 100644 --- a/NearbyShare/NearbyConnectionManager.swift +++ b/NearbyShare/NearbyConnectionManager.swift @@ -1,6 +1,6 @@ // // NearbyConnectionManager.swift -// NearDrop +// QuickDrop // // Created by Grishka on 08.04.2023. // @@ -296,19 +296,19 @@ public class NearbyConnectionManager : NSObject, NetServiceDelegate, InboundNear private func maybeAddFoundDevice(service:NWBrowser.Result){ #if DEBUG - print("found service \(service)") + log("found service \(service)") #endif for interface in service.interfaces{ if case .loopback=interface.type{ #if DEBUG - print("ignoring localhost service") + log("ignoring localhost service") #endif return } } guard let endpointID=endpointID(for: service) else {return} #if DEBUG - print("service name is valid, endpoint ID \(endpointID)") + log("service name is valid, endpoint ID \(endpointID)") #endif var foundService=FoundServiceInfo(service: service) diff --git a/NearbyShare/OutboundNearbyConnection.swift b/NearbyShare/OutboundNearbyConnection.swift index 8000a20..e3c4423 100644 --- a/NearbyShare/OutboundNearbyConnection.swift +++ b/NearbyShare/OutboundNearbyConnection.swift @@ -80,7 +80,7 @@ class OutboundNearbyConnection:NearbyConnection{ override func processReceivedFrame(frameData: Data) { do{ #if DEBUG - print("received \(frameData), state is \(currentState)") + log("received \(frameData), state is \(currentState)") #endif switch currentState { case .initial: @@ -105,12 +105,12 @@ class OutboundNearbyConnection:NearbyConnection{ override func processTransferSetupFrame(_ frame: Sharing_Nearby_Frame) throws { if frame.hasV1 && frame.v1.hasType, case .cancel = frame.v1.type { - print("Transfer canceled") + log("Transfer canceled") try sendDisconnectionAndDisconnect() delegate?.outboundConnection(connection: self, failedWithError: NearbyError.canceled(reason: .userCanceled)) return } - print(frame) + log(frame.debugDescription) switch currentState{ case .sentPairedKeyEncryption: try processPairedKeyEncryption(frame: frame) @@ -224,7 +224,7 @@ class OutboundNearbyConnection:NearbyConnection{ private func processConnectionResponse(frame:Location_Nearby_Connections_OfflineFrame) throws{ #if DEBUG - print("connection response: \(frame)") + log("connection response: \(frame)") #endif guard frame.version == .v1 else {throw NearbyError.protocolError("Unexpected offline frame version \(frame.version)")} guard frame.v1.type == .connectionResponse else {throw NearbyError.protocolError("Unexpected frame type \(frame.v1.type)")} @@ -306,7 +306,7 @@ class OutboundNearbyConnection:NearbyConnection{ } } #if DEBUG - print("sent introduction: \(introduction)") + log("sent introduction: \(introduction)") #endif try sendTransferSetupFrame(introduction) @@ -355,7 +355,7 @@ class OutboundNearbyConnection:NearbyConnection{ } if queue.isEmpty{ #if DEBUG - print("Disconnecting because all files have been transferred") + log("Disconnecting because all files have been transferred") #endif try sendDisconnectionAndDisconnect() delegate?.outboundConnectionTransferFinished(connection: self) @@ -399,7 +399,7 @@ class OutboundNearbyConnection:NearbyConnection{ } }) #if DEBUG - print("sent file chunk, current transfer: \(String(describing: currentTransfer))") + log("sent file chunk, current transfer: \(String(describing: currentTransfer))") #endif totalBytesSent+=Int64(fileBuffer.count) delegate?.outboundConnection(connection: self, transferProgress: Double(totalBytesSent)/Double(totalBytesToSend)) @@ -422,7 +422,7 @@ class OutboundNearbyConnection:NearbyConnection{ wrapper.v1.payloadTransfer=transfer try encryptAndSendOfflineFrame(wrapper) #if DEBUG - print("sent EOF, current transfer: \(String(describing: currentTransfer))") + log("sent EOF, current transfer: \(String(describing: currentTransfer))") #endif } } diff --git a/NearDrop.xcodeproj/project.pbxproj b/QuickDrop.xcodeproj/project.pbxproj similarity index 91% rename from NearDrop.xcodeproj/project.pbxproj rename to QuickDrop.xcodeproj/project.pbxproj index 958ce96..5ada8a5 100644 --- a/NearDrop.xcodeproj/project.pbxproj +++ b/QuickDrop.xcodeproj/project.pbxproj @@ -3,22 +3,19 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ - 18637D0E2AC2A25300AF8072 /* NearDrop-InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18637D0C2AC2A25300AF8072 /* NearDrop-InfoPlist.strings */; }; - 18637D112AC2A25300AF8072 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 18637D0F2AC2A25300AF8072 /* InfoPlist.strings */; }; 691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691F53B92ABB70840089FD92 /* DeviceListCell.swift */; }; 691F53BC2ABB70840089FD92 /* DeviceListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 691F53BA2ABB70840089FD92 /* DeviceListCell.xib */; }; 691F53BE2ABF03820089FD92 /* OutboundNearbyConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 691F53BD2ABF03820089FD92 /* OutboundNearbyConnection.swift */; }; 691F53C72AC2594E0089FD92 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C52AC2594E0089FD92 /* Localizable.strings */; }; 691F53CB2AC2599B0089FD92 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 691F53C92AC2599B0089FD92 /* Localizable.stringsdict */; }; - 698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */ = {isa = PBXBuildFile; fileRef = 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */; }; 699B03452AB5FBA300E0D718 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 699B03442AB5FBA300E0D718 /* Assets.xcassets */; }; 699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 699DEBA52AB0573200115D22 /* ShareViewController.swift */; }; 699DEBA92AB0573200115D22 /* ShareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 699DEBA72AB0573200115D22 /* ShareViewController.xib */; }; - 699DEBAE2AB0573200115D22 /* NearDropShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 699DEBA12AB0573200115D22 /* NearDropShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 699DEBAE2AB0573200115D22 /* QuickDropShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 699DEBA12AB0573200115D22 /* QuickDropShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 69D2C32D29E77F2200EC7E30 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C32B29E77F2200EC7E30 /* Localizable.strings */; }; 69D2C32F29E7898C00EC7E30 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C32E29E7898C00EC7E30 /* MainMenu.xib */; }; 69D2C33829E78DF400EC7E30 /* Localizable.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = 69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */; }; @@ -40,6 +37,10 @@ 69DCF49C2AB8C58500CBE2CC /* SwiftECC in Frameworks */ = {isa = PBXBuildFile; productRef = 69DCF49B2AB8C58500CBE2CC /* SwiftECC */; }; 69DCF49D2AB8C9A500CBE2CC /* libNearbyShare.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 69DCF4812AB70D0600CBE2CC /* libNearbyShare.dylib */; }; 69DCF49E2AB8C9A500CBE2CC /* libNearbyShare.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 69DCF4812AB70D0600CBE2CC /* libNearbyShare.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + EB7CD1432D6FAEB400CB0CB5 /* UserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1422D6FAEAF00CB0CB5 /* UserDefaultsKeys.swift */; }; + EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; }; + EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; }; + EB7CD1472D6FB0E800CB0CB5 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */; }; EBD2A2172D2860C100BCB8E2 /* WelcomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */; }; /* End PBXBuildFile section */ @@ -74,7 +75,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( - 699DEBAE2AB0573200115D22 /* NearDropShareExtension.appex in Embed Foundation Extensions */, + 699DEBAE2AB0573200115D22 /* QuickDropShareExtension.appex in Embed Foundation Extensions */, ); name = "Embed Foundation Extensions"; runOnlyForDeploymentPostprocessing = 0; @@ -119,8 +120,6 @@ 15C3ECC82AC269FB00FC5082 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; 15C3ECC92AC269FB00FC5082 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = ""; }; 15C3ECCA2AC269FB00FC5082 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; - 18637D0D2AC2A25300AF8072 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/NearDrop-InfoPlist.strings"; sourceTree = ""; }; - 18637D102AC2A25300AF8072 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/InfoPlist.strings"; sourceTree = ""; }; 1884486A2AC294C3003EC2A3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/ShareViewController.strings"; sourceTree = ""; }; 1884486B2AC294C3003EC2A3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.stringsdict"; sourceTree = ""; }; 1884486C2AC294C3003EC2A3 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/Localizable.strings"; sourceTree = ""; }; @@ -150,11 +149,8 @@ 698DFAE529E2F91A0064F247 /* NearbyConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NearbyConnection.swift; sourceTree = ""; }; 698DFAED29E353220064F247 /* UserNotifications.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotifications.framework; path = System/Library/Frameworks/UserNotifications.framework; sourceTree = SDKROOT; }; 698DFAEF29E353220064F247 /* UserNotificationsUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UserNotificationsUI.framework; path = System/Library/Frameworks/UserNotificationsUI.framework; sourceTree = SDKROOT; }; - 698DFB0029E362140064F247 /* NearDrop-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NearDrop-Bridging-Header.h"; sourceTree = ""; }; - 698DFB0129E362140064F247 /* NDNotificationCenterHackery.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NDNotificationCenterHackery.h; sourceTree = ""; }; - 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NDNotificationCenterHackery.m; sourceTree = ""; }; 699B03442AB5FBA300E0D718 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 699DEBA12AB0573200115D22 /* NearDropShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = NearDropShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 699DEBA12AB0573200115D22 /* QuickDropShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = QuickDropShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 699DEBA52AB0573200115D22 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; 699DEBA82AB0573200115D22 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ShareViewController.xib; sourceTree = ""; }; 699DEBAA2AB0573200115D22 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -164,7 +160,7 @@ 69D2C33029E789AF00EC7E30 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = ""; }; 69D2C33729E78DF400EC7E30 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = Base; path = Base.lproj/Localizable.stringsdict; sourceTree = ""; }; 69D2C33929E78DFD00EC7E30 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ru; path = ru.lproj/Localizable.stringsdict; sourceTree = ""; }; - 69DA9A0E29E0BF5100A442DA /* NearDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NearDrop.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 69DA9A0E29E0BF5100A442DA /* QuickDrop.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuickDrop.app; sourceTree = BUILT_PRODUCTS_DIR; }; 69DA9A1129E0BF5100A442DA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 69DA9A1329E0BF5200A442DA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 69DA9A1829E0BF5200A442DA /* NearDrop.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NearDrop.entitlements; sourceTree = ""; }; @@ -210,10 +206,16 @@ E9C8C6D52CFF66650053474D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ro; path = ro.lproj/Localizable.stringsdict; sourceTree = ""; }; E9C8C6D62CFF66650053474D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = ""; }; EB4ACE3C2D345A0800A0AF4C /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + EB7CD1422D6FAEAF00CB0CB5 /* UserDefaultsKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKeys.swift; sourceTree = ""; }; + EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; }; EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeScreen.swift; sourceTree = ""; }; EBD2A2182D28619200BCB8E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedRootGroup section */ + EB7CD13B2D6F8B6500CB0CB5 /* IAP */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = IAP; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ 699DEB9E2AB0573200115D22 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -263,7 +265,6 @@ 691F53C92AC2599B0089FD92 /* Localizable.stringsdict */, 691F53C52AC2594E0089FD92 /* Localizable.strings */, 699DEBAA2AB0573200115D22 /* Info.plist */, - 18637D0F2AC2A25300AF8072 /* InfoPlist.strings */, 699DEBAB2AB0573200115D22 /* ShareExtension.entitlements */, ); path = ShareExtension; @@ -272,20 +273,20 @@ 69DA9A0529E0BF5100A442DA = { isa = PBXGroup; children = ( - 18637D0C2AC2A25300AF8072 /* NearDrop-InfoPlist.strings */, 69DA9A1029E0BF5100A442DA /* NearDrop */, 699DEBA22AB0573200115D22 /* ShareExtension */, 69DCF4822AB70D0600CBE2CC /* NearbyShare */, 698DFAEC29E353220064F247 /* Frameworks */, 69DA9A0F29E0BF5100A442DA /* Products */, + EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */, ); sourceTree = ""; }; 69DA9A0F29E0BF5100A442DA /* Products */ = { isa = PBXGroup; children = ( - 69DA9A0E29E0BF5100A442DA /* NearDrop.app */, - 699DEBA12AB0573200115D22 /* NearDropShareExtension.appex */, + 69DA9A0E29E0BF5100A442DA /* QuickDrop.app */, + 699DEBA12AB0573200115D22 /* QuickDropShareExtension.appex */, 69DCF4812AB70D0600CBE2CC /* libNearbyShare.dylib */, ); name = Products; @@ -297,13 +298,12 @@ EBD2A2182D28619200BCB8E2 /* Info.plist */, 69DA9A1129E0BF5100A442DA /* AppDelegate.swift */, EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */, + EB7CD1422D6FAEAF00CB0CB5 /* UserDefaultsKeys.swift */, + EB7CD13B2D6F8B6500CB0CB5 /* IAP */, 69DA9A1329E0BF5200A442DA /* Assets.xcassets */, 69D2C33629E78DF400EC7E30 /* Localizable.stringsdict */, 69D2C32B29E77F2200EC7E30 /* Localizable.strings */, - 698DFB0129E362140064F247 /* NDNotificationCenterHackery.h */, - 698DFB0229E362140064F247 /* NDNotificationCenterHackery.m */, 69DA9A1829E0BF5200A442DA /* NearDrop.entitlements */, - 698DFB0029E362140064F247 /* NearDrop-Bridging-Header.h */, 69D2C32E29E7898C00EC7E30 /* MainMenu.xib */, ); path = NearDrop; @@ -348,9 +348,9 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 699DEBA02AB0573200115D22 /* NearDropShareExtension */ = { + 699DEBA02AB0573200115D22 /* QuickDropShareExtension */ = { isa = PBXNativeTarget; - buildConfigurationList = 699DEBB12AB0573200115D22 /* Build configuration list for PBXNativeTarget "NearDropShareExtension" */; + buildConfigurationList = 699DEBB12AB0573200115D22 /* Build configuration list for PBXNativeTarget "QuickDropShareExtension" */; buildPhases = ( 699DEB9D2AB0573200115D22 /* Sources */, 699DEB9E2AB0573200115D22 /* Frameworks */, @@ -362,14 +362,14 @@ dependencies = ( 69DCF4A02AB8C9A500CBE2CC /* PBXTargetDependency */, ); - name = NearDropShareExtension; + name = QuickDropShareExtension; productName = ShareExtension; - productReference = 699DEBA12AB0573200115D22 /* NearDropShareExtension.appex */; + productReference = 699DEBA12AB0573200115D22 /* QuickDropShareExtension.appex */; productType = "com.apple.product-type.app-extension"; }; - 69DA9A0D29E0BF5100A442DA /* NearDrop */ = { + 69DA9A0D29E0BF5100A442DA /* QuickDrop */ = { isa = PBXNativeTarget; - buildConfigurationList = 69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "NearDrop" */; + buildConfigurationList = 69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "QuickDrop" */; buildPhases = ( 69DA9A0A29E0BF5100A442DA /* Sources */, 69DA9A0B29E0BF5100A442DA /* Frameworks */, @@ -384,11 +384,14 @@ 699DEBAD2AB0573200115D22 /* PBXTargetDependency */, 69DCF4972AB8BF7B00CBE2CC /* PBXTargetDependency */, ); - name = NearDrop; + fileSystemSynchronizedGroups = ( + EB7CD13B2D6F8B6500CB0CB5 /* IAP */, + ); + name = QuickDrop; packageProductDependencies = ( ); productName = NearDrop; - productReference = 69DA9A0E29E0BF5100A442DA /* NearDrop.app */; + productReference = 69DA9A0E29E0BF5100A442DA /* QuickDrop.app */; productType = "com.apple.product-type.application"; }; 69DCF4802AB70D0600CBE2CC /* NearbyShare */ = { @@ -434,7 +437,7 @@ }; }; }; - buildConfigurationList = 69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "NearDrop" */; + buildConfigurationList = 69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "QuickDrop" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -467,8 +470,8 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 69DA9A0D29E0BF5100A442DA /* NearDrop */, - 699DEBA02AB0573200115D22 /* NearDropShareExtension */, + 69DA9A0D29E0BF5100A442DA /* QuickDrop */, + 699DEBA02AB0573200115D22 /* QuickDropShareExtension */, 69DCF4802AB70D0600CBE2CC /* NearbyShare */, ); }; @@ -480,7 +483,6 @@ buildActionMask = 2147483647; files = ( 699B03452AB5FBA300E0D718 /* Assets.xcassets in Resources */, - 18637D112AC2A25300AF8072 /* InfoPlist.strings in Resources */, 691F53C72AC2594E0089FD92 /* Localizable.strings in Resources */, 691F53BC2ABB70840089FD92 /* DeviceListCell.xib in Resources */, 691F53CB2AC2599B0089FD92 /* Localizable.stringsdict in Resources */, @@ -495,7 +497,6 @@ 69DA9A1429E0BF5200A442DA /* Assets.xcassets in Resources */, 69D2C33829E78DF400EC7E30 /* Localizable.stringsdict in Resources */, 69D2C32D29E77F2200EC7E30 /* Localizable.strings in Resources */, - 18637D0E2AC2A25300AF8072 /* NearDrop-InfoPlist.strings in Resources */, 69D2C32F29E7898C00EC7E30 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -508,6 +509,7 @@ buildActionMask = 2147483647; files = ( 699DEBA62AB0573200115D22 /* ShareViewController.swift in Sources */, + EB7CD1462D6FB0E800CB0CB5 /* Logger.swift in Sources */, 691F53BB2ABB70840089FD92 /* DeviceListCell.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -517,8 +519,9 @@ buildActionMask = 2147483647; files = ( EBD2A2172D2860C100BCB8E2 /* WelcomeScreen.swift in Sources */, - 698DFB0329E362140064F247 /* NDNotificationCenterHackery.m in Sources */, + EB7CD1432D6FAEB400CB0CB5 /* UserDefaultsKeys.swift in Sources */, 69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */, + EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -533,6 +536,7 @@ 69DCF48E2AB70E8C00CBE2CC /* securegcm.pb.swift in Sources */, 691F53BE2ABF03820089FD92 /* OutboundNearbyConnection.swift in Sources */, 69DCF48C2AB70E8C00CBE2CC /* device_to_device_messages.pb.swift in Sources */, + EB7CD1472D6FB0E800CB0CB5 /* Logger.swift in Sources */, 69DCF4902AB70E9700CBE2CC /* InboundNearbyConnection.swift in Sources */, 69DCF48B2AB70E8C00CBE2CC /* ukey.pb.swift in Sources */, 69DCF48A2AB70E8C00CBE2CC /* wire_format.pb.swift in Sources */, @@ -545,7 +549,7 @@ /* Begin PBXTargetDependency section */ 699DEBAD2AB0573200115D22 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 699DEBA02AB0573200115D22 /* NearDropShareExtension */; + target = 699DEBA02AB0573200115D22 /* QuickDropShareExtension */; targetProxy = 699DEBAC2AB0573200115D22 /* PBXContainerItemProxy */; }; 69DCF4972AB8BF7B00CBE2CC /* PBXTargetDependency */ = { @@ -561,23 +565,6 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 18637D0C2AC2A25300AF8072 /* NearDrop-InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 18637D0D2AC2A25300AF8072 /* zh-Hans */, - ); - name = "NearDrop-InfoPlist.strings"; - path = NearDrop; - sourceTree = ""; - }; - 18637D0F2AC2A25300AF8072 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 18637D102AC2A25300AF8072 /* zh-Hans */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; 691F53C52AC2594E0089FD92 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( @@ -687,13 +674,13 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = "${SHARED_BUILD}"; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 92SDAWLN76; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ShareExtension/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = NearDrop; + INFOPLIST_KEY_CFBundleDisplayName = QuickDrop; INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -701,7 +688,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = "${SHARED_VERSION}"; PRODUCT_BUNDLE_IDENTIFIER = com.leonboettger.neardrop.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -716,13 +703,13 @@ CODE_SIGN_ENTITLEMENTS = ShareExtension/ShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = "${SHARED_BUILD}"; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 92SDAWLN76; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = ShareExtension/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = NearDrop; + INFOPLIST_KEY_CFBundleDisplayName = QuickDrop; INFOPLIST_KEY_NSHumanReadableCopyright = ""; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -730,7 +717,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = "${SHARED_VERSION}"; PRODUCT_BUNDLE_IDENTIFIER = com.leonboettger.neardrop.ShareExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -798,6 +785,8 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; + SHARED_BUILD = 7; + SHARED_VERSION = 1.2; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; @@ -855,6 +844,8 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; + SHARED_BUILD = 7; + SHARED_VERSION = 1.2; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; }; @@ -867,18 +858,19 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = "${SHARED_BUILD}"; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 92SDAWLN76; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = NearDrop/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = NearDrop; + INFOPLIST_KEY_CFBundleDisplayName = QuickDrop; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSUIElement = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "2025 Leon Böttger - Huge thanks to developers of NearDrop"; INFOPLIST_KEY_NSMainNibFile = MainMenu; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -886,11 +878,11 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = "${SHARED_VERSION}"; PRODUCT_BUNDLE_IDENTIFIER = com.leonboettger.neardrop; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; }; @@ -903,18 +895,19 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = NearDrop/NearDrop.entitlements; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = "${SHARED_BUILD}"; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 92SDAWLN76; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = NearDrop/Info.plist; - INFOPLIST_KEY_CFBundleDisplayName = NearDrop; + INFOPLIST_KEY_CFBundleDisplayName = QuickDrop; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities"; INFOPLIST_KEY_LSUIElement = YES; - INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INFOPLIST_KEY_NSHumanReadableCopyright = "2025 Leon Böttger - Huge thanks to developers of NearDrop"; INFOPLIST_KEY_NSMainNibFile = MainMenu; INFOPLIST_KEY_NSPrincipalClass = NSApplication; LD_RUNPATH_SEARCH_PATHS = ( @@ -922,11 +915,11 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 11.0; - MARKETING_VERSION = 1.1; + MARKETING_VERSION = "${SHARED_VERSION}"; PRODUCT_BUNDLE_IDENTIFIER = com.leonboettger.neardrop; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_OBJC_BRIDGING_HEADER = "NearDrop/NearDrop-Bridging-Header.h"; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_VERSION = 5.0; }; name = Release; @@ -968,7 +961,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 699DEBB12AB0573200115D22 /* Build configuration list for PBXNativeTarget "NearDropShareExtension" */ = { + 699DEBB12AB0573200115D22 /* Build configuration list for PBXNativeTarget "QuickDropShareExtension" */ = { isa = XCConfigurationList; buildConfigurations = ( 699DEBAF2AB0573200115D22 /* Debug */, @@ -977,7 +970,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "NearDrop" */ = { + 69DA9A0929E0BF5100A442DA /* Build configuration list for PBXProject "QuickDrop" */ = { isa = XCConfigurationList; buildConfigurations = ( 69DA9A1929E0BF5200A442DA /* Debug */, @@ -986,7 +979,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "NearDrop" */ = { + 69DA9A1B29E0BF5200A442DA /* Build configuration list for PBXNativeTarget "QuickDrop" */ = { isa = XCConfigurationList; buildConfigurations = ( 69DA9A1C29E0BF5200A442DA /* Debug */, diff --git a/NearDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/QuickDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from NearDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to QuickDrop.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/NearDrop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from NearDrop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/NearDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved similarity index 100% rename from NearDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved rename to QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved diff --git a/NearDrop.xcodeproj/xcshareddata/xcschemes/NearDrop.xcscheme b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDrop.xcscheme similarity index 80% rename from NearDrop.xcodeproj/xcshareddata/xcschemes/NearDrop.xcscheme rename to QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDrop.xcscheme index 15b53e2..3d12e57 100644 --- a/NearDrop.xcodeproj/xcshareddata/xcschemes/NearDrop.xcscheme +++ b/QuickDrop.xcodeproj/xcshareddata/xcschemes/QuickDrop.xcscheme @@ -4,7 +4,8 @@ version = "1.7"> + buildImplicitDependencies = "YES" + buildArchitectures = "Automatic"> + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> @@ -33,7 +34,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - language = "de" + language = "en" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -45,9 +46,9 @@ + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> @@ -62,9 +63,9 @@ + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> diff --git a/NearDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme b/QuickDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme similarity index 81% rename from NearDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme rename to QuickDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme index 6b0f96a..f6f66d9 100644 --- a/NearDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme +++ b/QuickDrop.xcodeproj/xcshareddata/xcschemes/ShareExtension.xcscheme @@ -16,9 +16,9 @@ + BuildableName = "QuickDropShareExtension.appex" + BlueprintName = "QuickDropShareExtension" + ReferencedContainer = "container:QuickDrop.xcodeproj"> + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> @@ -60,9 +60,9 @@ + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> @@ -79,9 +79,9 @@ + BuildableName = "QuickDrop.app" + BlueprintName = "QuickDrop" + ReferencedContainer = "container:QuickDrop.xcodeproj"> diff --git a/ShareExtension/Assets.xcassets/NearDropIcon.imageset/1024-1024.png b/ShareExtension/Assets.xcassets/QuickDropIcon.imageset/1024-1024.png similarity index 100% rename from ShareExtension/Assets.xcassets/NearDropIcon.imageset/1024-1024.png rename to ShareExtension/Assets.xcassets/QuickDropIcon.imageset/1024-1024.png diff --git a/ShareExtension/Assets.xcassets/NearDropIcon.imageset/Contents.json b/ShareExtension/Assets.xcassets/QuickDropIcon.imageset/Contents.json similarity index 100% rename from ShareExtension/Assets.xcassets/NearDropIcon.imageset/Contents.json rename to ShareExtension/Assets.xcassets/QuickDropIcon.imageset/Contents.json diff --git a/ShareExtension/Base.lproj/ShareViewController.xib b/ShareExtension/Base.lproj/ShareViewController.xib index 3e733f6..3bcd006 100644 --- a/ShareExtension/Base.lproj/ShareViewController.xib +++ b/ShareExtension/Base.lproj/ShareViewController.xib @@ -47,7 +47,7 @@ Gw - + @@ -55,11 +55,11 @@ Gw - + - - + + @@ -234,7 +234,7 @@ Gw - + @@ -259,6 +259,6 @@ Gw - + diff --git a/ShareExtension/ShareViewController.swift b/ShareExtension/ShareViewController.swift index 92a3c27..6df836c 100644 --- a/ShareExtension/ShareViewController.swift +++ b/ShareExtension/ShareViewController.swift @@ -127,7 +127,7 @@ class ShareViewController: NSViewController, ShareExtensionDelegate{ if url.isFileURL{ let isDirectory=UnsafeMutablePointer.allocate(capacity: 1) if FileManager.default.fileExists(atPath: url.path, isDirectory: isDirectory) && isDirectory.pointee.boolValue{ - print("Canceling share request because URL \(url) is a directory") + log("Canceling share request because URL \(url) is a directory") let cancelError = NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil) self.extensionContext!.cancelRequest(withError: cancelError) return diff --git a/ShareExtension/ar.lproj/ShareViewController.strings b/ShareExtension/ar.lproj/ShareViewController.strings index fc89940..273e97a 100644 --- a/ShareExtension/ar.lproj/ShareViewController.strings +++ b/ShareExtension/ar.lproj/ShareViewController.strings @@ -1,5 +1,5 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "إلغاء"; diff --git a/ShareExtension/de.lproj/Localizable.strings b/ShareExtension/de.lproj/Localizable.strings index 83ed9ee..aa6b78d 100644 Binary files a/ShareExtension/de.lproj/Localizable.strings and b/ShareExtension/de.lproj/Localizable.strings differ diff --git a/ShareExtension/ja.lproj/ShareViewController.strings b/ShareExtension/ja.lproj/ShareViewController.strings index d4ea40a..90c7336 100644 --- a/ShareExtension/ja.lproj/ShareViewController.strings +++ b/ShareExtension/ja.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "キャンセル"; diff --git a/ShareExtension/ko.lproj/ShareViewController.strings b/ShareExtension/ko.lproj/ShareViewController.strings index d093050..062b9ba 100644 --- a/ShareExtension/ko.lproj/ShareViewController.strings +++ b/ShareExtension/ko.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "취소"; diff --git a/ShareExtension/nl.lproj/ShareViewController.strings b/ShareExtension/nl.lproj/ShareViewController.strings index df2d7f8..f58fd08 100644 --- a/ShareExtension/nl.lproj/ShareViewController.strings +++ b/ShareExtension/nl.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "Annuleren"; diff --git a/ShareExtension/pt-PT.lproj/ShareViewController.strings b/ShareExtension/pt-PT.lproj/ShareViewController.strings index 7baba6f..99d451e 100644 --- a/ShareExtension/pt-PT.lproj/ShareViewController.strings +++ b/ShareExtension/pt-PT.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "Cancelar"; diff --git a/ShareExtension/ro.lproj/ShareViewController.strings b/ShareExtension/ro.lproj/ShareViewController.strings index 3fdcfce..b0faff8 100644 --- a/ShareExtension/ro.lproj/ShareViewController.strings +++ b/ShareExtension/ro.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "Anulare"; diff --git a/ShareExtension/ru.lproj/ShareViewController.strings b/ShareExtension/ru.lproj/ShareViewController.strings index bb56687..8d89c99 100644 --- a/ShareExtension/ru.lproj/ShareViewController.strings +++ b/ShareExtension/ru.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "Отменить"; diff --git a/ShareExtension/uk.lproj/ShareViewController.strings b/ShareExtension/uk.lproj/ShareViewController.strings index 9b1148a..fd7b0e4 100644 --- a/ShareExtension/uk.lproj/ShareViewController.strings +++ b/ShareExtension/uk.lproj/ShareViewController.strings @@ -1,6 +1,6 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "Скасувати"; diff --git a/ShareExtension/zh-Hans.lproj/InfoPlist.strings b/ShareExtension/zh-Hans.lproj/InfoPlist.strings deleted file mode 100644 index de34d11..0000000 --- a/ShareExtension/zh-Hans.lproj/InfoPlist.strings +++ /dev/null @@ -1,6 +0,0 @@ -/* Bundle display name */ -"CFBundleDisplayName" = "NearDrop 分享"; - -/* Bundle name */ -"CFBundleName" = "分享扩展"; - diff --git a/ShareExtension/zh-Hans.lproj/ShareViewController.strings b/ShareExtension/zh-Hans.lproj/ShareViewController.strings index 1a2520c..78b169f 100644 --- a/ShareExtension/zh-Hans.lproj/ShareViewController.strings +++ b/ShareExtension/zh-Hans.lproj/ShareViewController.strings @@ -1,5 +1,5 @@ -/* Class = "NSTextFieldCell"; title = "NearDrop"; ObjectID = "0xp-rC-2gr"; */ -"0xp-rC-2gr.title" = "NearDrop"; +/* Class = "NSTextFieldCell"; title = "QuickDrop"; ObjectID = "0xp-rC-2gr"; */ +"0xp-rC-2gr.title" = "QuickDrop"; /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "6Up-t3-mwm"; */ "6Up-t3-mwm.title" = "取消";