mirror of
https://github.com/leonboe1/QuickDrop.git
synced 2026-11-11 02:51:11 +00:00
Add option to choose save directory & automatically accept files
This commit is contained in:
1 parent
164d351c4d
commit
ea324ea7d8
26 files changed
+436
-77
No files matched your search
+68
-21
@@ -13,7 +13,7 @@ import StoreKit
|
||||
import AudioToolbox
|
||||
|
||||
@main
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate, MainAppDelegate{
|
||||
private var statusItem: NSStatusItem?
|
||||
private var activeIncomingTransfers: [String : TransferInfo] = [:]
|
||||
|
||||
@@ -85,6 +85,8 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UNUserNotificationCenter.current().delegate=self
|
||||
}
|
||||
|
||||
|
||||
@@ -149,6 +151,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
return UserDefaults.standard.bool(forKey: UserDefaultsKeys.plusVersion.rawValue)
|
||||
}
|
||||
|
||||
|
||||
func transmissionCount() -> Int {
|
||||
return UserDefaults.standard.integer(forKey: UserDefaultsKeys.transmissionCount.rawValue)
|
||||
}
|
||||
@@ -161,12 +164,14 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@objc func getSupport() {
|
||||
if let url = URL(string: "mailto:quickdrop@leonboettger.com?subject=QuickDrop") {
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Action for "Privacy Policy" menu item
|
||||
@objc func openPrivacyPolicy() {
|
||||
if let url = URL(string: "http://leonboettger.com/privacy") {
|
||||
@@ -174,20 +179,31 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
|
||||
statusItem?.isVisible=true
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
public func userNotificationCenter(_ center: UNUserNotificationCenter,
|
||||
willPresent notification: UNNotification,
|
||||
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.sound, .banner])
|
||||
}
|
||||
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
|
||||
iapManager?.stopObserving()
|
||||
}
|
||||
|
||||
|
||||
func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
public func continueTransmission(accept: Bool, transferID: String) {
|
||||
NearbyConnectionManager.shared.submitUserConsent(transferID: transferID, accept: accept)
|
||||
|
||||
@@ -196,17 +212,17 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func obtainUserConsent(for transfer: TransferMetadata, from device: RemoteDeviceInfo) {
|
||||
self.activeIncomingTransfers[transfer.id] = TransferInfo(device: device, transfer: transfer)
|
||||
|
||||
AudioManager.playSound()
|
||||
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .informational
|
||||
let acceptAutomatically = UserDefaults.standard.bool(forKey: UserDefaultsKeys.automaticallyAcceptFiles.rawValue)
|
||||
|
||||
let fileStr: String
|
||||
|
||||
if let textTitle = transfer.textDescription{
|
||||
if let textTitle = transfer.textDescription {
|
||||
fileStr = textTitle
|
||||
} else if transfer.files.count == 1 {
|
||||
fileStr = transfer.files[0].name
|
||||
@@ -214,34 +230,65 @@ class AppDelegate: NSObject, NSApplicationDelegate, MainAppDelegate{
|
||||
fileStr = String.localizedStringWithFormat(NSLocalizedString("NFiles", value: "%d files", comment: ""), transfer.files.count)
|
||||
}
|
||||
|
||||
let mainMessage = String(format: NSLocalizedString("DeviceSendingFiles", value: "%1$@ is sending you %2$@", comment: ""), arguments: [device.name, fileStr])
|
||||
let mainMessage = String(format: (acceptAutomatically ? "DeviceCurrentlySendingFiles" : "DeviceSendingFiles").localized(), 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 acceptAutomatically {
|
||||
pressAcceptButton(transferID: transfer.id)
|
||||
|
||||
if !isPlusVersion() && transmissionCount() > 0 {
|
||||
self.openPlusScreen {
|
||||
self.continueTransmission(accept: self.isPlusVersion(), transferID: transferID)
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, err in
|
||||
if granted {
|
||||
log("User granted notification permissions")
|
||||
|
||||
let notificationContent = UNMutableNotificationContent()
|
||||
notificationContent.title = "QuickDrop"
|
||||
notificationContent.body = mainMessage
|
||||
notificationContent.sound = nil
|
||||
let notificationId = UUID().uuidString
|
||||
|
||||
let notificationReq = UNNotificationRequest(identifier: notificationId, content: notificationContent, trigger: nil)
|
||||
UNUserNotificationCenter.current().add(notificationReq)
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [notificationId])
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
continueTransmission(accept: true, transferID: transferID)
|
||||
}
|
||||
else {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .informational
|
||||
|
||||
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 {
|
||||
pressAcceptButton(transferID: transferID)
|
||||
} else if result == .alertSecondButtonReturn {
|
||||
continueTransmission(accept: false, transferID: transferID)
|
||||
}
|
||||
|
||||
} else if result == .alertSecondButtonReturn {
|
||||
|
||||
continueTransmission(accept: false, transferID: transferID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func pressAcceptButton(transferID: String) {
|
||||
if !isPlusVersion() && transmissionCount() > 0 {
|
||||
self.openPlusScreen {
|
||||
self.continueTransmission(accept: self.isPlusVersion(), transferID: transferID)
|
||||
}
|
||||
}
|
||||
else {
|
||||
continueTransmission(accept: true, transferID: transferID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func incomingTransfer(id: String, didFinishWith error: Error?) {
|
||||
guard let transfer = self.activeIncomingTransfers[id] else { return }
|
||||
if let error = error {
|
||||
|
||||
@@ -52,7 +52,16 @@
|
||||
|
||||
"PrivacyPolicy" = "Privacy Policy";
|
||||
|
||||
"UserManual" = "User Manual";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ is sending you %2$@";
|
||||
"UserManual" = "User Manual & Settings";
|
||||
"Settings" = "Settings";
|
||||
"AutomaticallyAcceptFiles" = "Automatically Accept Incoming Files";
|
||||
"AutomaticallyAcceptFilesFooter" = "Enabling this setting is only recommended in your private network. Anyone on the same network can send files to your device without your consent.";
|
||||
|
||||
"SaveFilesTo" = "Save Incoming Files To:";
|
||||
"SaveFilesLocation" = "Incomping Files Location";
|
||||
"SaveFilesToButton" = "Select…";
|
||||
"DownloadsFolder" = "Downloads";
|
||||
|
||||
"SendFiles" = "Send Files";
|
||||
"ReceiveFiles" = "Receive Files";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// SettingsView.swift
|
||||
// QuickDrop
|
||||
//
|
||||
// Created by Leon Böttger on 24.03.25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AppKit
|
||||
|
||||
struct SettingsView: View {
|
||||
@AppStorage(UserDefaultsKeys.automaticallyAcceptFiles.rawValue) private var automaticallyAcceptFiles = false
|
||||
@AppStorage(UserDefaultsKeys.saveFolderBookmark.rawValue) private var saveFolderPath: Data = Data()
|
||||
|
||||
var body: some View {
|
||||
|
||||
LargeAppIconView(title: "Settings") {
|
||||
Form {
|
||||
Toggle("AutomaticallyAcceptFiles", isOn: $automaticallyAcceptFiles)
|
||||
.padding(.top, 10)
|
||||
|
||||
Text("AutomaticallyAcceptFilesFooter")
|
||||
.font(.footnote)
|
||||
.foregroundColor(.red)
|
||||
.padding(.top, 5)
|
||||
|
||||
Divider()
|
||||
.padding(.vertical, 10)
|
||||
|
||||
HStack {
|
||||
Text("SaveFilesTo")
|
||||
Spacer()
|
||||
Text(getSavedFolderPath() ?? "DownloadsFolder".localized())
|
||||
.foregroundColor(saveFolderPath.isEmpty ? .gray : .primary)
|
||||
Button("SaveFilesToButton") {
|
||||
selectFolder()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getSavedFolderPath() -> String? {
|
||||
if !saveFolderPath.isEmpty {
|
||||
var isStale = false
|
||||
do {
|
||||
let url = try URL(resolvingBookmarkData: saveFolderPath, options: [], relativeTo: nil, bookmarkDataIsStale: &isStale)
|
||||
return url.lastPathComponent // Returns the folder path as a string
|
||||
} catch {
|
||||
print("Failed to resolve bookmark: \(error)")
|
||||
}
|
||||
}
|
||||
return nil // No saved folder
|
||||
}
|
||||
|
||||
private func selectFolder() {
|
||||
let panel = NSOpenPanel()
|
||||
panel.title = "SaveFilesLocation".localized()
|
||||
panel.canChooseFiles = false
|
||||
panel.canChooseDirectories = true
|
||||
panel.allowsMultipleSelection = false
|
||||
|
||||
if panel.runModal() == .OK, let url = panel.urls.first {
|
||||
do {
|
||||
print("Selected folder: \(url)")
|
||||
|
||||
let bookmarkData = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
|
||||
|
||||
print(bookmarkData)
|
||||
|
||||
UserDefaults.standard.set(bookmarkData, forKey: UserDefaultsKeys.saveFolderBookmark.rawValue)
|
||||
} catch {
|
||||
print("Failed to save security-scoped bookmark: \(error)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SettingsView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
SettingsView()
|
||||
.frame(width: 800, height: 500)
|
||||
}
|
||||
}
|
||||
+38
-21
@@ -21,28 +21,9 @@ struct TutorialView: View {
|
||||
@AppStorage(UserDefaultsKeys.plusVersion.rawValue) var isPlusVersion = false
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
|
||||
|
||||
LargeAppIconView(title: title) {
|
||||
VStack {
|
||||
Image("AppIconHighRes")
|
||||
.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(title.localized())
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
Text(text.localized())
|
||||
.multilineTextAlignment(.center)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
@@ -90,6 +71,42 @@ struct TutorialView: View {
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct LargeAppIconView<Content: View>: View {
|
||||
|
||||
let title: String
|
||||
let bottomView: () -> Content
|
||||
@State var taps = 0
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
|
||||
VStack {
|
||||
Image("AppIconHighRes")
|
||||
.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(title.localized())
|
||||
.font(.largeTitle)
|
||||
.padding()
|
||||
|
||||
bottomView()
|
||||
}
|
||||
.frame(maxWidth: 500)
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
@@ -12,4 +12,6 @@ enum UserDefaultsKeys: String, CaseIterable {
|
||||
case appLaunchedBefore = "ShowedWelcomeScreen"
|
||||
case plusVersion = "isPlusVersion"
|
||||
case transmissionCount = "reviewRequestCountKey"
|
||||
case automaticallyAcceptFiles = "automaticallyAcceptFiles"
|
||||
case saveFolderBookmark = "saveFolderBookmark"
|
||||
}
|
||||
@@ -20,21 +20,24 @@ struct WelcomeScreen: View {
|
||||
|
||||
HStack(spacing: 0) {
|
||||
List(selection: $selection) {
|
||||
ForEach(Tabs.allCases, id: \.self) { tab in
|
||||
ForEach(Tabs.allCases.filter({$0 != .settings}), id: \.self) { tab in
|
||||
Label(tab.title, systemImage: tab.systemImage)
|
||||
// .font(.system(size: 13))
|
||||
.tag(tab)
|
||||
.frame(height: 30)
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Label(Tabs.settings.title, systemImage: Tabs.settings.systemImage)
|
||||
.tag(Tabs.settings)
|
||||
.frame(height: 30)
|
||||
}
|
||||
.frame(width: 220)
|
||||
.listStyle(SidebarListStyle())
|
||||
|
||||
Divider()
|
||||
.opacity(colorScheme == .light ? 1 : 0)
|
||||
// .overlay(
|
||||
// Color.black.opacity(colorScheme == .dark ? 1 : 0)
|
||||
// )
|
||||
.edgesIgnoringSafeArea(.vertical)
|
||||
|
||||
ZStack {
|
||||
@@ -47,8 +50,11 @@ struct WelcomeScreen: View {
|
||||
case .send:
|
||||
TutorialView(title: "SendFiles", text: "SendFilesDescription", showsLicense: false, openIAP: openIAP)
|
||||
|
||||
default:
|
||||
case .troubleshooting:
|
||||
TutorialView(title: "Troubleshooting", text: "TroubleshootingDescription", showsLicense: false, openIAP: openIAP)
|
||||
|
||||
default:
|
||||
SettingsView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,6 +67,7 @@ enum Tabs: CaseIterable {
|
||||
case receive
|
||||
case send
|
||||
case troubleshooting
|
||||
case settings
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
@@ -70,17 +77,21 @@ enum Tabs: CaseIterable {
|
||||
return "SendFiles".localized()
|
||||
case .troubleshooting:
|
||||
return "DeviceNotShown".localized()
|
||||
case .settings:
|
||||
return "Settings".localized()
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .receive:
|
||||
return "tray.and.arrow.down.fill"
|
||||
return "tray.and.arrow.down"
|
||||
case .send:
|
||||
return "tray.and.arrow.up.fill"
|
||||
return "tray.and.arrow.up"
|
||||
case .troubleshooting:
|
||||
return "exclamationmark.triangle.fill"
|
||||
return "exclamationmark.triangle"
|
||||
case .settings:
|
||||
return "gear"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "التطبيقات الموصى بها";
|
||||
"GetSupport" = "الدعم";
|
||||
"PrivacyPolicy" = "سياسة الخصوصية";
|
||||
"UserManual" = "دليل المستخدم";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ يرسل لك %2$@";
|
||||
"UserManual" = "دليل المستخدم والإعدادات";
|
||||
"Settings" = "الإعدادات";
|
||||
"AutomaticallyAcceptFiles" = "قبول الملفات الواردة تلقائيًا";
|
||||
"AutomaticallyAcceptFilesFooter" = "يُوصى بتمكين هذا الإعداد فقط في شبكتك الخاصة. يمكن لأي شخص على نفس الشبكة إرسال الملفات إلى جهازك دون موافقتك.";
|
||||
|
||||
"SaveFilesTo" = "حفظ الملفات الواردة في:";
|
||||
"SaveFilesLocation" = "موقع الملفات الواردة";
|
||||
"SaveFilesToButton" = "تحديد…";
|
||||
"DownloadsFolder" = "التنزيلات";
|
||||
"SendFiles" = "إرسال الملفات";
|
||||
"ReceiveFiles" = "استقبال الملفات";
|
||||
"DeviceNotShown" = "الجهاز غير ظاهر؟";
|
||||
|
||||
@@ -45,7 +45,16 @@
|
||||
|
||||
"PrivacyPolicy" = "Datenschutzerklärung";
|
||||
|
||||
"UserManual" = "Benutzerhandbuch";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ sendet dir %2$@";
|
||||
"UserManual" = "Benutzerhandbuch & Einstellungen";
|
||||
"Settings" = "Einstellungen";
|
||||
"AutomaticallyAcceptFiles" = "Eingehende Dateien automatisch akzeptieren";
|
||||
"AutomaticallyAcceptFilesFooter" = "Diese Einstellung wird nur in privaten Netzwerken empfohlen. Jede Person im selben Netzwerk kann ohne deine Zustimmung Dateien an diesen Mac senden.";
|
||||
|
||||
"SaveFilesTo" = "Eingehende Dateien speichern in:";
|
||||
"SaveFilesLocation" = "Speicherort der eingehenden Dateien";
|
||||
"SaveFilesToButton" = "Auswählen…";
|
||||
"DownloadsFolder" = "Downloads";
|
||||
|
||||
"SendFiles" = "Dateien senden";
|
||||
"ReceiveFiles" = "Dateien empfangen";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Apps recomendadas";
|
||||
"GetSupport" = "Soporte";
|
||||
"PrivacyPolicy" = "Política de privacidad";
|
||||
"UserManual" = "Manual de usuario";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ te está enviando %2$@";
|
||||
"UserManual" = "Manual de usuario y Configuración";
|
||||
"Settings" = "Configuración";
|
||||
"AutomaticallyAcceptFiles" = "Aceptar automáticamente archivos entrantes";
|
||||
"AutomaticallyAcceptFilesFooter" = "Se recomienda habilitar esta opción solo en su red privada. Cualquier persona en la misma red puede enviar archivos a su dispositivo sin su consentimiento.";
|
||||
|
||||
"SaveFilesTo" = "Guardar archivos entrantes en:";
|
||||
"SaveFilesLocation" = "Ubicación de archivos entrantes";
|
||||
"SaveFilesToButton" = "Seleccionar…";
|
||||
"DownloadsFolder" = "Descargas";
|
||||
"SendFiles" = "Enviar archivos";
|
||||
"ReceiveFiles" = "Recibir archivos";
|
||||
"DeviceNotShown" = "¿Dispositivo no mostrado?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Applications recommandées";
|
||||
"GetSupport" = "Support";
|
||||
"PrivacyPolicy" = "Politique de confidentialité";
|
||||
"UserManual" = "Manuel d'utilisateur";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ vous envoie %2$@";
|
||||
"UserManual" = "Manuel d'utilisation et Paramètres";
|
||||
"Settings" = "Paramètres";
|
||||
"AutomaticallyAcceptFiles" = "Accepter automatiquement les fichiers entrants";
|
||||
"AutomaticallyAcceptFilesFooter" = "L'activation de ce paramètre est recommandée uniquement sur votre réseau privé. Toute personne sur le même réseau peut envoyer des fichiers sur votre appareil sans votre consentement.";
|
||||
|
||||
"SaveFilesTo" = "Enregistrer les fichiers reçus dans :";
|
||||
"SaveFilesLocation" = "Emplacement des fichiers reçus";
|
||||
"SaveFilesToButton" = "Sélectionner…";
|
||||
"DownloadsFolder" = "Téléchargements";
|
||||
"SendFiles" = "Envoyer des fichiers";
|
||||
"ReceiveFiles" = "Recevoir des fichiers";
|
||||
"DeviceNotShown" = "Appareil non affiché?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Ajánlott alkalmazások";
|
||||
"GetSupport" = "Támogatás";
|
||||
"PrivacyPolicy" = "Adatvédelmi irányelvek";
|
||||
"UserManual" = "Felhasználói kézikönyv";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ éppen küldi neked: %2$@";
|
||||
"UserManual" = "Felhasználói kézikönyv és Beállítások";
|
||||
"Settings" = "Beállítások";
|
||||
"AutomaticallyAcceptFiles" = "Bejövő fájlok automatikus elfogadása";
|
||||
"AutomaticallyAcceptFilesFooter" = "Ennek a beállításnak az engedélyezése csak a saját privát hálózatán ajánlott. Bárki a hálózaton belül fájlokat küldhet az eszközére az ön beleegyezése nélkül.";
|
||||
|
||||
"SaveFilesTo" = "Bejövő fájlok mentése ide:";
|
||||
"SaveFilesLocation" = "Bejövő fájlok helye";
|
||||
"SaveFilesToButton" = "Kiválasztás…";
|
||||
"DownloadsFolder" = "Letöltések";
|
||||
"SendFiles" = "Fájlok küldése";
|
||||
"ReceiveFiles" = "Fájlok fogadása";
|
||||
"DeviceNotShown" = "Az eszköz nem látható?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "App consigliate";
|
||||
"GetSupport" = "Supporto";
|
||||
"PrivacyPolicy" = "Informativa sulla privacy";
|
||||
"UserManual" = "Manuale utente";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ ti sta inviando %2$@";
|
||||
"UserManual" = "Manuale utente e Impostazioni";
|
||||
"Settings" = "Impostazioni";
|
||||
"AutomaticallyAcceptFiles" = "Accetta automaticamente i file in arrivo";
|
||||
"AutomaticallyAcceptFilesFooter" = "L'abilitazione di questa impostazione è consigliata solo nella tua rete privata. Chiunque nella stessa rete può inviare file al tuo dispositivo senza il tuo consenso.";
|
||||
|
||||
"SaveFilesTo" = "Salva i file ricevuti in:";
|
||||
"SaveFilesLocation" = "Posizione dei file ricevuti";
|
||||
"SaveFilesToButton" = "Seleziona…";
|
||||
"DownloadsFolder" = "Download";
|
||||
"SendFiles" = "Invia file";
|
||||
"ReceiveFiles" = "Ricevi file";
|
||||
"DeviceNotShown" = "Dispositivo non mostrato?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "おすすめアプリ";
|
||||
"GetSupport" = "サポート";
|
||||
"PrivacyPolicy" = "プライバシーポリシー";
|
||||
"UserManual" = "ユーザーマニュアル";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ が %2$@ を送信中";
|
||||
"UserManual" = "ユーザーマニュアルと設定";
|
||||
"Settings" = "設定";
|
||||
"AutomaticallyAcceptFiles" = "受信ファイルを自動的に受け入れる";
|
||||
"AutomaticallyAcceptFilesFooter" = "この設定はプライベートネットワークでのみ有効にすることを推奨します。同じネットワーク上の誰でも、あなたの許可なしにファイルを送信できる可能性があります。";
|
||||
|
||||
"SaveFilesTo" = "受信ファイルの保存先:";
|
||||
"SaveFilesLocation" = "受信ファイルの保存場所";
|
||||
"SaveFilesToButton" = "選択…";
|
||||
"DownloadsFolder" = "ダウンロード";
|
||||
"SendFiles" = "ファイルを送信";
|
||||
"ReceiveFiles" = "ファイルを受信";
|
||||
"DeviceNotShown" = "デバイスが表示されない?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "추천 앱";
|
||||
"GetSupport" = "지원";
|
||||
"PrivacyPolicy" = "개인정보 처리방침";
|
||||
"UserManual" = "사용자 매뉴얼";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@이(가) %2$@을(를) 보내는 중입니다";
|
||||
"UserManual" = "사용자 매뉴얼 및 설정";
|
||||
"Settings" = "설정";
|
||||
"AutomaticallyAcceptFiles" = "수신 파일 자동 수락";
|
||||
"AutomaticallyAcceptFilesFooter" = "이 설정은 개인 네트워크에서만 활성화하는 것이 좋습니다. 같은 네트워크에 있는 누구나 사용자의 동의 없이 파일을 보낼 수 있습니다.";
|
||||
|
||||
"SaveFilesTo" = "수신 파일 저장 위치:";
|
||||
"SaveFilesLocation" = "수신 파일 위치";
|
||||
"SaveFilesToButton" = "선택…";
|
||||
"DownloadsFolder" = "다운로드";
|
||||
"SendFiles" = "파일 보내기";
|
||||
"ReceiveFiles" = "파일 받기";
|
||||
"DeviceNotShown" = "장치가 표시되지 않음?";
|
||||
|
||||
@@ -44,7 +44,16 @@
|
||||
"GetSupport" = "Ondersteuning";
|
||||
"PrivacyPolicy" = "Privacybeleid";
|
||||
|
||||
"UserManual" = "Gebruikershandleiding";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ stuurt je %2$@";
|
||||
"UserManual" = "Gebruikershandleiding en Instellingen";
|
||||
"Settings" = "Instellingen";
|
||||
"AutomaticallyAcceptFiles" = "Inkomende bestanden automatisch accepteren";
|
||||
"AutomaticallyAcceptFilesFooter" = "Het inschakelen van deze instelling wordt alleen aanbevolen in uw privé-netwerk. Iedereen in hetzelfde netwerk kan bestanden naar uw apparaat sturen zonder uw toestemming.";
|
||||
|
||||
"SaveFilesTo" = "Opslaan inkomende bestanden in:";
|
||||
"SaveFilesLocation" = "Locatie van inkomende bestanden";
|
||||
"SaveFilesToButton" = "Selecteren…";
|
||||
"DownloadsFolder" = "Downloads";
|
||||
"SendFiles" = "Bestanden verzenden";
|
||||
"ReceiveFiles" = "Bestanden ontvangen";
|
||||
"DeviceNotShown" = "Apparaat niet weergegeven?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Apps recomendados";
|
||||
"GetSupport" = "Suporte";
|
||||
"PrivacyPolicy" = "Política de Privacidade";
|
||||
"UserManual" = "Manual do Usuário";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ está enviando %2$@ para você";
|
||||
"UserManual" = "Manual do Usuário e Configurações";
|
||||
"Settings" = "Configurações";
|
||||
"AutomaticallyAcceptFiles" = "Aceitar automaticamente arquivos recebidos";
|
||||
"AutomaticallyAcceptFilesFooter" = "Ativar esta configuração é recomendado apenas na sua rede privada. Qualquer pessoa na mesma rede pode enviar arquivos para o seu dispositivo sem o seu consentimento.";
|
||||
|
||||
"SaveFilesTo" = "Salvar arquivos recebidos em:";
|
||||
"SaveFilesLocation" = "Localização dos arquivos recebidos";
|
||||
"SaveFilesToButton" = "Selecionar…";
|
||||
"DownloadsFolder" = "Downloads";
|
||||
"SendFiles" = "Enviar arquivos";
|
||||
"ReceiveFiles" = "Receber arquivos";
|
||||
"DeviceNotShown" = "Dispositivo não mostrado?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Aplicativos recomendados";
|
||||
"GetSupport" = "Suporte";
|
||||
"PrivacyPolicy" = "Política de privacidade";
|
||||
"UserManual" = "Manual do usuário";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ está a enviar-te %2$@";
|
||||
"UserManual" = "Manual do Utilizador e Definições";
|
||||
"Settings" = "Definições";
|
||||
"AutomaticallyAcceptFiles" = "Aceitar automaticamente ficheiros recebidos";
|
||||
"AutomaticallyAcceptFilesFooter" = "Ativar esta definição é recomendado apenas na sua rede privada. Qualquer pessoa na mesma rede pode enviar ficheiros para o seu dispositivo sem o seu consentimento.";
|
||||
|
||||
"SaveFilesTo" = "Guardar ficheiros recebidos em:";
|
||||
"SaveFilesLocation" = "Localização dos ficheiros recebidos";
|
||||
"SaveFilesToButton" = "Selecionar…";
|
||||
"DownloadsFolder" = "Transferências";
|
||||
"SendFiles" = "Enviar ficheiros";
|
||||
"ReceiveFiles" = "Receber ficheiros";
|
||||
"DeviceNotShown" = "Dispositivo não mostrado?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Aplicații recomandate";
|
||||
"GetSupport" = "Suport";
|
||||
"PrivacyPolicy" = "Politica de confidențialitate";
|
||||
"UserManual" = "Manualul utilizatorului";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ îți trimite %2$@";
|
||||
"UserManual" = "Manual utilizator & Setări";
|
||||
"Settings" = "Setări";
|
||||
"AutomaticallyAcceptFiles" = "Acceptă automat fișierele primite";
|
||||
"AutomaticallyAcceptFilesFooter" = "Activarea acestei opțiuni este recomandată doar în rețeaua privată. Oricine din aceeași rețea poate trimite fișiere către dispozitivul dvs. fără consimțământ.";
|
||||
|
||||
"SaveFilesTo" = "Salvează fișierele primite în:";
|
||||
"SaveFilesLocation" = "Locația fișierelor primite";
|
||||
"SaveFilesToButton" = "Selectează…";
|
||||
"DownloadsFolder" = "Descărcări";
|
||||
"SendFiles" = "Trimite fișiere";
|
||||
"ReceiveFiles" = "Primește fișiere";
|
||||
"DeviceNotShown" = "Dispozitivul nu este afișat?";
|
||||
|
||||
@@ -45,7 +45,16 @@
|
||||
|
||||
"PrivacyPolicy" = "Политика конфиденциальности";
|
||||
|
||||
"UserManual" = "Руководство пользователя";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ отправляет вам %2$@";
|
||||
"UserManual" = "Руководство пользователя и Настройки";
|
||||
"Settings" = "Настройки";
|
||||
"AutomaticallyAcceptFiles" = "Автоматически принимать входящие файлы";
|
||||
"AutomaticallyAcceptFilesFooter" = "Включение этой настройки рекомендуется только в вашей частной сети. Любой пользователь в той же сети может отправлять файлы на ваше устройство без вашего согласия.";
|
||||
|
||||
"SaveFilesTo" = "Сохранять входящие файлы в:";
|
||||
"SaveFilesLocation" = "Местоположение входящих файлов";
|
||||
"SaveFilesToButton" = "Выбрать…";
|
||||
"DownloadsFolder" = "Загрузки";
|
||||
"SendFiles" = "Отправить файлы";
|
||||
"ReceiveFiles" = "Получить файлы";
|
||||
"DeviceNotShown" = "Устройство не отображается?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "แอปแนะนำ";
|
||||
"GetSupport" = "การสนับสนุน";
|
||||
"PrivacyPolicy" = "นโยบายความเป็นส่วนตัว";
|
||||
"UserManual" = "คู่มือการใช้งาน";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ กำลังส่ง %2$@ ให้คุณ";
|
||||
"UserManual" = "คู่มือผู้ใช้และการตั้งค่า";
|
||||
"Settings" = "การตั้งค่า";
|
||||
"AutomaticallyAcceptFiles" = "ยอมรับไฟล์ขาเข้าโดยอัตโนมัติ";
|
||||
"AutomaticallyAcceptFilesFooter" = "แนะนำให้เปิดใช้งานการตั้งค่านี้เฉพาะในเครือข่ายส่วนตัวของคุณเท่านั้น ใครก็ตามที่อยู่ในเครือข่ายเดียวกันสามารถส่งไฟล์ไปยังอุปกรณ์ของคุณได้โดยไม่ต้องได้รับอนุญาต";
|
||||
|
||||
"SaveFilesTo" = "บันทึกไฟล์ขาเข้าไปที่:";
|
||||
"SaveFilesLocation" = "ตำแหน่งไฟล์ขาเข้า";
|
||||
"SaveFilesToButton" = "เลือก…";
|
||||
"DownloadsFolder" = "ดาวน์โหลด";
|
||||
"SendFiles" = "ส่งไฟล์";
|
||||
"ReceiveFiles" = "รับไฟล์";
|
||||
"DeviceNotShown" = "อุปกรณ์ไม่แสดง?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "Рекомендовані додатки";
|
||||
"GetSupport" = "Підтримка";
|
||||
"PrivacyPolicy" = "Політика конфіденційності";
|
||||
"UserManual" = "Посібник користувача";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ надсилає вам %2$@";
|
||||
"UserManual" = "Керівництво користувача та налаштування";
|
||||
"Settings" = "Налаштування";
|
||||
"AutomaticallyAcceptFiles" = "Автоматично приймати вхідні файли";
|
||||
"AutomaticallyAcceptFilesFooter" = "Увімкнення цього параметра рекомендується лише у вашій приватній мережі. Будь-хто в тій самій мережі може надсилати файли на ваш пристрій без вашої згоди.";
|
||||
|
||||
"SaveFilesTo" = "Зберігати вхідні файли у:";
|
||||
"SaveFilesLocation" = "Розташування вхідних файлів";
|
||||
"SaveFilesToButton" = "Вибрати…";
|
||||
"DownloadsFolder" = "Завантаження";
|
||||
"SendFiles" = "Надіслати файли";
|
||||
"ReceiveFiles" = "Отримати файли";
|
||||
"DeviceNotShown" = "Пристрій не відображається?";
|
||||
|
||||
@@ -43,7 +43,16 @@
|
||||
"RecommendedApps" = "推荐应用";
|
||||
"GetSupport" = "支持";
|
||||
"PrivacyPolicy" = "隐私政策";
|
||||
"UserManual" = "用户手册";
|
||||
"DeviceCurrentlySendingFiles" = "%1$@ 正在向你发送 %2$@";
|
||||
"UserManual" = "用户手册与设置";
|
||||
"Settings" = "设置";
|
||||
"AutomaticallyAcceptFiles" = "自动接受传入文件";
|
||||
"AutomaticallyAcceptFilesFooter" = "仅建议在您的私人网络中启用此设置。同一网络中的任何人都可以在未经您同意的情况下向您的设备发送文件。";
|
||||
|
||||
"SaveFilesTo" = "保存传入文件到:";
|
||||
"SaveFilesLocation" = "传入文件位置";
|
||||
"SaveFilesToButton" = "选择…";
|
||||
"DownloadsFolder" = "下载";
|
||||
"SendFiles" = "发送文件";
|
||||
"ReceiveFiles" = "接收文件";
|
||||
"DeviceNotShown" = "设备未显示?";
|
||||
|
||||
@@ -22,6 +22,7 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
private var cipherCommitment:Data?
|
||||
|
||||
private var textPayloadID:Int64=0
|
||||
private var securityScopeUrl: URL?
|
||||
|
||||
enum State{
|
||||
case initial, receivedConnectionRequest, sentUkeyServerInit, receivedUkeyClientFinish, sentConnectionResponse, sentPairedKeyResult, receivedPairedKeyResult, waitingForUserConsent, receivingFiles, disconnected
|
||||
@@ -32,6 +33,7 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
}
|
||||
|
||||
override func handleConnectionClosure() {
|
||||
|
||||
super.handleConnectionClosure()
|
||||
currentState = .disconnected
|
||||
do{
|
||||
@@ -41,6 +43,11 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.connectionWasTerminated(connection: self, error: self.lastError)
|
||||
|
||||
if let url = self.securityScopeUrl {
|
||||
log("Stopped accessing security scoped resource.")
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +287,7 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
currentState = .receivedPairedKeyResult
|
||||
}
|
||||
|
||||
private func makeFileDestinationURL(_ initialDest:URL) -> URL{
|
||||
private func makeFileDestinationURL(_ initialDest:URL) -> URL {
|
||||
var dest=initialDest
|
||||
if FileManager.default.fileExists(atPath: dest.path){
|
||||
var counter=1
|
||||
@@ -302,14 +309,18 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
private func processIntroductionFrame(_ frame:Sharing_Nearby_Frame) throws{
|
||||
guard frame.hasV1, frame.v1.hasIntroduction else { throw NearbyError.requiredFieldMissing("shareNearbyFrame.v1.introduction") }
|
||||
currentState = .waitingForUserConsent
|
||||
|
||||
if frame.v1.introduction.fileMetadata.count>0 && frame.v1.introduction.textMetadata.isEmpty{
|
||||
let downloadsDirectory=(try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)).resolvingSymlinksInPath()
|
||||
for file in frame.v1.introduction.fileMetadata{
|
||||
let dest=makeFileDestinationURL(downloadsDirectory.appendingPathComponent(file.name))
|
||||
let info=InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
|
||||
|
||||
let saveDirectory = getSaveDirectory()
|
||||
|
||||
for file in frame.v1.introduction.fileMetadata {
|
||||
|
||||
let dest = makeFileDestinationURL(saveDirectory.appendingPathComponent(file.name))
|
||||
let info = InternalFileInfo(meta: FileMetadata(name: file.name, size: file.size, mimeType: file.mimeType),
|
||||
payloadID: file.payloadID,
|
||||
destinationURL: dest)
|
||||
transferredFiles[file.payloadID]=info
|
||||
transferredFiles[file.payloadID] = info
|
||||
}
|
||||
let metadata=TransferMetadata(files: transferredFiles.map({$0.value.meta}), id: id, pinCode: pinCode)
|
||||
DispatchQueue.main.async {
|
||||
@@ -324,10 +335,12 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
self.delegate?.obtainUserConsent(for: metadata, from: self.remoteDeviceInfo!, connection: self)
|
||||
}
|
||||
}else if case .text=meta.type{
|
||||
let downloadsDirectory=(try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true)).resolvingSymlinksInPath()
|
||||
|
||||
let saveDirectory = getSaveDirectory()
|
||||
|
||||
let dateFormatter=DateFormatter()
|
||||
dateFormatter.dateFormat="yyyy-MM-dd HH.mm.ss"
|
||||
let dest=makeFileDestinationURL(downloadsDirectory.appendingPathComponent("\(dateFormatter.string(from: Date())).txt"))
|
||||
let dest=makeFileDestinationURL(saveDirectory.appendingPathComponent("\(dateFormatter.string(from: Date())).txt"))
|
||||
let info=InternalFileInfo(meta: FileMetadata(name: dest.lastPathComponent, size: meta.size, mimeType: "text/plain"),
|
||||
payloadID: meta.payloadID,
|
||||
destinationURL: dest)
|
||||
@@ -342,6 +355,32 @@ class InboundNearbyConnection: NearbyConnection{
|
||||
rejectTransfer(with: .unsupportedAttachmentType)
|
||||
}
|
||||
}
|
||||
|
||||
private func getSaveDirectory() -> URL {
|
||||
if let bookmarkData = UserDefaults.standard.data(forKey: UserDefaultsKeys.saveFolderBookmark.rawValue) {
|
||||
var isStale = false
|
||||
do {
|
||||
let url = try URL(resolvingBookmarkData: bookmarkData, options: .withSecurityScope, relativeTo: nil, bookmarkDataIsStale: &isStale)
|
||||
if !isStale {
|
||||
if url.startAccessingSecurityScopedResource() {
|
||||
self.securityScopeUrl = url
|
||||
return url
|
||||
}
|
||||
} else {
|
||||
print("Bookmark is stale, using default downloads folder.")
|
||||
}
|
||||
|
||||
} catch {
|
||||
print("Failed to resolve bookmark: \(error), using default downloads folder.")
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
return try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: true).resolvingSymlinksInPath()
|
||||
} catch {
|
||||
fatalError("Failed to get downloads directory: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
func submitUserConsent(accepted:Bool){
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
69DCF49E2AB8C9A500CBE2CC /* libNearbyShare.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 69DCF4812AB70D0600CBE2CC /* libNearbyShare.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
EB3643602D73A2A2009CDFF8 /* AudioManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB36435F2D73A29F009CDFF8 /* AudioManager.swift */; };
|
||||
EB3643622D73A2CA009CDFF8 /* timeIsNow.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = EB3643612D73A2CA009CDFF8 /* timeIsNow.mp3 */; };
|
||||
EB6F62D72D91F4AF00534EC2 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */; };
|
||||
EB6F62DE2D932B4800534EC2 /* UserDefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB7CD1422D6FAEAF00CB0CB5 /* UserDefaultsKeys.swift */; };
|
||||
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 */; };
|
||||
@@ -196,6 +198,7 @@
|
||||
E9C8C6D42CFF66650053474D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||
EB36435F2D73A29F009CDFF8 /* AudioManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioManager.swift; sourceTree = "<group>"; };
|
||||
EB3643612D73A2CA009CDFF8 /* timeIsNow.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = timeIsNow.mp3; sourceTree = "<group>"; };
|
||||
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
|
||||
EB7CD1422D6FAEAF00CB0CB5 /* UserDefaultsKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaultsKeys.swift; sourceTree = "<group>"; };
|
||||
EB7CD1442D6FB0C100CB0CB5 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = "<group>"; };
|
||||
EB7F540F2D78E6DD00989564 /* Sidebar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sidebar.swift; sourceTree = "<group>"; };
|
||||
@@ -304,6 +307,7 @@
|
||||
EBD2A2162D2860BE00BCB8E2 /* WelcomeScreen.swift */,
|
||||
EB7F54112D78E95C00989564 /* TutorialView.swift */,
|
||||
EB7F54132D78E9E400989564 /* LicenseWindow.swift */,
|
||||
EB6F62D62D91F4AC00534EC2 /* SettingsView.swift */,
|
||||
EB36435F2D73A29F009CDFF8 /* AudioManager.swift */,
|
||||
EB96ED8E2D7F8103004B3FF1 /* Localized.swift */,
|
||||
EB7F540F2D78E6DD00989564 /* Sidebar.swift */,
|
||||
@@ -538,6 +542,7 @@
|
||||
EB7CD1432D6FAEB400CB0CB5 /* UserDefaultsKeys.swift in Sources */,
|
||||
69DA9A1229E0BF5100A442DA /* AppDelegate.swift in Sources */,
|
||||
EB7F54102D78E6DF00989564 /* Sidebar.swift in Sources */,
|
||||
EB6F62D72D91F4AF00534EC2 /* SettingsView.swift in Sources */,
|
||||
EB7F54122D78E96000989564 /* TutorialView.swift in Sources */,
|
||||
EB96ED8F2D7F8105004B3FF1 /* Localized.swift in Sources */,
|
||||
EB7CD1452D6FB0C300CB0CB5 /* Logger.swift in Sources */,
|
||||
@@ -550,6 +555,7 @@
|
||||
files = (
|
||||
69DCF48D2AB70E8C00CBE2CC /* offline_wire_formats.pb.swift in Sources */,
|
||||
69DCF48F2AB70E8C00CBE2CC /* securemessage.pb.swift in Sources */,
|
||||
EB6F62DE2D932B4800534EC2 /* UserDefaultsKeys.swift in Sources */,
|
||||
69DCF4912AB70E9700CBE2CC /* NearbyConnection.swift in Sources */,
|
||||
69DCF4922AB70E9700CBE2CC /* NearbyConnectionManager.swift in Sources */,
|
||||
69DCF48E2AB70E8C00CBE2CC /* securegcm.pb.swift in Sources */,
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = "en"
|
||||
language = "de"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
Reference in new issue
Block a user