diff --git a/NearbyShare/Util/Zip.swift b/NearbyShare/Util/Zip.swift index 79ff9c7..c8e26c1 100644 --- a/NearbyShare/Util/Zip.swift +++ b/NearbyShare/Util/Zip.swift @@ -6,63 +6,43 @@ // import Foundation +import ZIPFoundation -class Zip { - - static func createAtTemporaryDirectory(zipFilename: String, zipExtension: String = "zip", fromDirectory directoryURL: URL) throws -> URL { - - let finalURL = FileManager.default.temporaryDirectory +final class Zip { + + static func createAtTemporaryDirectory( + zipFilename: String, + zipExtension: String = "zip", + fromDirectory directoryURL: URL + ) throws -> URL { + + guard directoryURL.isDirectory else { throw CreateZipError.urlNotADirectory(directoryURL) } + + let zipFinalURL = FileManager.default.temporaryDirectory .appendingPathComponent(zipFilename) .appendingPathExtension(zipExtension) - - return try createAt( - zipFinalURL: finalURL, - fromDirectory: directoryURL + + if FileManager.default.fileExists(atPath: zipFinalURL.path) { + try FileManager.default.removeItem(at: zipFinalURL) + } + + try FileManager.default.zipItem( + at: directoryURL, + to: zipFinalURL, + shouldKeepParent: true, + compressionMethod: .deflate ) - } - - static func createAt(zipFinalURL: URL, fromDirectory directoryURL: URL) throws -> URL { - - guard directoryURL.isDirectory else { - throw CreateZipError.urlNotADirectory(directoryURL) - } - - var fileManagerError: Swift.Error? - var coordinatorError: NSError? - let coordinator = NSFileCoordinator() - - coordinator.coordinate(readingItemAt: directoryURL, options: .forUploading, error: &coordinatorError) { zipCreatedURL in - do { - // clean if file exists - if FileManager.default.fileExists(atPath: zipFinalURL.path) { - try FileManager.default.removeItem(at: zipFinalURL) - } - - try FileManager.default.moveItem(at: zipCreatedURL, to: zipFinalURL) - - } catch { - fileManagerError = error - } - } - - if let error = coordinatorError ?? fileManagerError { - throw CreateZipError.failedToCreateZIP(error) - } - return zipFinalURL } - - enum CreateZipError: Swift.Error { + enum CreateZipError: Error { case urlNotADirectory(URL) - case failedToCreateZIP(Swift.Error) } } - -extension URL { +private extension URL { var isDirectory: Bool { - (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true + (try? resourceValues(forKeys: [.isDirectoryKey]))?.isDirectory == true } } diff --git a/QuickDrop.xcodeproj/project.pbxproj b/QuickDrop.xcodeproj/project.pbxproj index 1f1e5c0..0dfd013 100644 --- a/QuickDrop.xcodeproj/project.pbxproj +++ b/QuickDrop.xcodeproj/project.pbxproj @@ -51,6 +51,11 @@ EB4F9D222EC26C8100A74A0F /* EXIFUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB4F9D1E2EC26C7C00A74A0F /* EXIFUtils.swift */; }; EB4F9D252EC27CFB00A74A0F /* FileManager+DocumentsOpener.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB4F9D232EC27CF000A74A0F /* FileManager+DocumentsOpener.swift */; }; EB4F9D272EC27CFB00A74A0F /* FileManager+DocumentsOpener.swift in Sources */ = {isa = PBXBuildFile; fileRef = EB4F9D232EC27CF000A74A0F /* FileManager+DocumentsOpener.swift */; }; + EB53D8C42EF496AB004C95BA /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EB53D8C32EF496AB004C95BA /* ZIPFoundation */; }; + EB53D8C62EF496CA004C95BA /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EB53D8C52EF496CA004C95BA /* ZIPFoundation */; }; + EB53D8C82EF496D1004C95BA /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EB53D8C72EF496D1004C95BA /* ZIPFoundation */; }; + EB53D8CA2EF49703004C95BA /* BezelNotification in Frameworks */ = {isa = PBXBuildFile; productRef = EB53D8C92EF49703004C95BA /* BezelNotification */; }; + EB53D8CC2EF49707004C95BA /* ZIPFoundation in Frameworks */ = {isa = PBXBuildFile; productRef = EB53D8CB2EF49707004C95BA /* ZIPFoundation */; }; EB5C36932E34EBBD0052EFD7 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = EB5C36922E34EBBD0052EFD7 /* Localizable.xcstrings */; }; EB5C36942E34EBBD0052EFD7 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = EB5C36922E34EBBD0052EFD7 /* Localizable.xcstrings */; }; EB5C36E42E34EC0E0052EFD7 /* License.txt in Resources */ = {isa = PBXBuildFile; fileRef = EB5C36E32E34EC0E0052EFD7 /* License.txt */; }; @@ -395,8 +400,10 @@ files = ( EB5C37D82E377ACF0052EFD7 /* SwiftECC in Frameworks */, EBE5FF412EDB6F5D0019B380 /* LUI in Frameworks */, + EB53D8CA2EF49703004C95BA /* BezelNotification in Frameworks */, EB5C37D62E377ACF0052EFD7 /* SwiftProtobuf in Frameworks */, EB9925852E45EF0900357055 /* QRCode in Frameworks */, + EB53D8CC2EF49707004C95BA /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -409,6 +416,7 @@ EB5C37DC2E377AD60052EFD7 /* SwiftECC in Frameworks */, EB5C37DA2E377AD60052EFD7 /* SwiftProtobuf in Frameworks */, EBE5FF3F2EDB6F550019B380 /* LUI in Frameworks */, + EB53D8C42EF496AB004C95BA /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -421,6 +429,7 @@ EB886E582E4E66420052B7D9 /* LUI in Frameworks */, EB5C37EE2E377C3F0052EFD7 /* SwiftProtobuf in Frameworks */, EB9925892E45F13500357055 /* QRCode in Frameworks */, + EB53D8C62EF496CA004C95BA /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -433,6 +442,7 @@ EB950B652E52067D002D68FA /* LUI in Frameworks */, EB950B5F2E520671002D68FA /* SwiftProtobuf in Frameworks */, EB950B632E52067A002D68FA /* QRCode in Frameworks */, + EB53D8C82EF496D1004C95BA /* ZIPFoundation in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -733,6 +743,7 @@ EB5C37DB2E377AD60052EFD7 /* SwiftECC */, EB9925862E45F12F00357055 /* QRCode */, EBE5FF3E2EDB6F550019B380 /* LUI */, + EB53D8C32EF496AB004C95BA /* ZIPFoundation */, ); productName = NearDrop; productReference = 69DA9A0E29E0BF5100A442DA /* QuickDrop.app */; @@ -759,6 +770,7 @@ EB9925882E45F13500357055 /* QRCode */, EB886E572E4E66420052B7D9 /* LUI */, EBADEB8E2E8029750021B5E4 /* DeviceKit */, + EB53D8C52EF496CA004C95BA /* ZIPFoundation */, ); productName = QuickDropiOS; productReference = EB5C37E22E377C2E0052EFD7 /* QuickDropiOS.app */; @@ -783,6 +795,7 @@ EB950B622E52067A002D68FA /* QRCode */, EB950B642E52067D002D68FA /* LUI */, EBADEB902E802A830021B5E4 /* DeviceKit */, + EB53D8C72EF496D1004C95BA /* ZIPFoundation */, ); productName = iOSShareExtension; productReference = EB950B2D2E52027F002D68FA /* iOSShareExtension.appex */; @@ -845,6 +858,7 @@ EB9925832E45EF0900357055 /* XCRemoteSwiftPackageReference "qrcode" */, EB886E562E4E66420052B7D9 /* XCRemoteSwiftPackageReference "LUI" */, EBADEB8B2E8029420021B5E4 /* XCRemoteSwiftPackageReference "DeviceKit" */, + EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */, ); productRefGroup = 69DA9A0F29E0BF5100A442DA /* Products */; projectDirPath = ""; @@ -1311,7 +1325,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SHARED_BUILD = 97; - SHARED_VERSION = 2.9; + SHARED_VERSION = 2.9.1; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1374,7 +1388,7 @@ MTL_FAST_MATH = YES; SDKROOT = macosx; SHARED_BUILD = 97; - SHARED_VERSION = 2.9; + SHARED_VERSION = 2.9.1; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_EMIT_LOC_STRINGS = YES; @@ -1737,6 +1751,14 @@ minimumVersion = 2.1.0; }; }; + EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/weichsel/ZIPFoundation.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.9.20; + }; + }; EB886E562E4E66420052B7D9 /* XCRemoteSwiftPackageReference "LUI" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/leonboe1/LUI.git"; @@ -1769,6 +1791,31 @@ package = EB2F9BFC2DA05F48004010A2 /* XCRemoteSwiftPackageReference "BezelNotification" */; productName = BezelNotification; }; + EB53D8C32EF496AB004C95BA /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; + EB53D8C52EF496CA004C95BA /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; + EB53D8C72EF496D1004C95BA /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; + EB53D8C92EF49703004C95BA /* BezelNotification */ = { + isa = XCSwiftPackageProductDependency; + package = EB2F9BFC2DA05F48004010A2 /* XCRemoteSwiftPackageReference "BezelNotification" */; + productName = BezelNotification; + }; + EB53D8CB2EF49707004C95BA /* ZIPFoundation */ = { + isa = XCSwiftPackageProductDependency; + package = EB53D8C22EF496AB004C95BA /* XCRemoteSwiftPackageReference "ZIPFoundation" */; + productName = ZIPFoundation; + }; EB5C37D52E377ACF0052EFD7 /* SwiftProtobuf */ = { isa = XCSwiftPackageProductDependency; package = 69DA9A2429E189EF00A442DA /* XCRemoteSwiftPackageReference "swift-protobuf" */; diff --git a/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 9f7594f..a3241d6 100644 --- a/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/QuickDrop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "270e8bfd245fae589b12faf08b86042cbbe7c809d59c5b0b8b735c7fb3a8d4bd", + "originHash" : "85c9b997510f22b553d79f68fb6d51d149ac9324df643dbf1475023b39da33b3", "pins" : [ { "identity" : "applewatchscreensize", @@ -126,6 +126,15 @@ "branch" : "main", "revision" : "b10fc8a284abb9bd908d77243d2ba3b3d8ea6ebc" } + }, + { + "identity" : "zipfoundation", + "kind" : "remoteSourceControl", + "location" : "https://github.com/weichsel/ZIPFoundation.git", + "state" : { + "revision" : "22787ffb59de99e5dc1fbfe80b19c97a904ad48d", + "version" : "0.9.20" + } } ], "version" : 3 diff --git a/QuickDrop/Localizable.xcstrings b/QuickDrop/Localizable.xcstrings index a6e879f..62c3df2 100644 --- a/QuickDrop/Localizable.xcstrings +++ b/QuickDrop/Localizable.xcstrings @@ -10487,229 +10487,229 @@ "ar" : { "stringUnit" : { "state" : "translated", - "value" : "تم إيقاف الاتصال بواسطة هاتفك." + "value" : "تم إنهاء الاتصال من قبل جهازك الآخر." } }, "ca" : { "stringUnit" : { "state" : "translated", - "value" : "La connexió ha estat interrompuda pel teu telèfon." + "value" : "La connexió ha estat interrompuda per l'altre dispositiu." } }, "cs" : { "stringUnit" : { "state" : "translated", - "value" : "Připojení bylo ukončeno vaším telefonem." + "value" : "Připojení bylo přerušeno vaším druhým zařízením." } }, "da" : { "stringUnit" : { "state" : "translated", - "value" : "Forbindelsen blev afbrudt af din telefon." + "value" : "Forbindelsen blev afbrudt af din anden enhed." } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "Die Verbindung wurde von deinem Telefon abgebrochen." + "value" : "Die Verbindung wurde von deinem anderen Gerät abgebrochen." } }, "el" : { "stringUnit" : { "state" : "translated", - "value" : "Η σύνδεση διεκόπη από το τηλέφωνό σας." + "value" : "Η σύνδεση διακόπηκε από την άλλη συσκευή σας." } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "The connection was aborted by your phone." + "value" : "The connection was aborted by your other device." } }, "en-AU" : { "stringUnit" : { "state" : "translated", - "value" : "The connection was stopped by your phone." + "value" : "The connection was aborted by your other device." } }, "en-CA" : { "stringUnit" : { "state" : "translated", - "value" : "The connection was interrupted by your phone." + "value" : "The connection was aborted by your other device." } }, "en-GB" : { "stringUnit" : { "state" : "translated", - "value" : "The connection was aborted by your phone." + "value" : "The connection was aborted by your other device." } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "La conexión fue abortada por tu teléfono." + "value" : "La conexión fue interrumpida por tu otro dispositivo." } }, "es-419" : { "stringUnit" : { "state" : "translated", - "value" : "La conexión fue abortada por tu teléfono." + "value" : "La conexión fue abortada por tu otro dispositivo." } }, "fi" : { "stringUnit" : { "state" : "translated", - "value" : "Puhelimesi keskeytti yhteyden." + "value" : "Yhteys katkaistiin toisella laitteellasi." } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "La connexion a été interrompue par votre téléphone." + "value" : "La connexion a été interrompue par votre autre appareil." } }, "fr-CA" : { "stringUnit" : { "state" : "translated", - "value" : "La connexion a été interrompue par votre téléphone." + "value" : "La connexion a été interrompue par votre autre appareil." } }, "he" : { "stringUnit" : { "state" : "translated", - "value" : "החיבור הופסק על ידי הטלפון שלך." + "value" : "החיבור נותק על ידי המכשיר השני שלך." } }, "hi" : { "stringUnit" : { "state" : "translated", - "value" : "कनेक्शन आपके फोन द्वारा रद्द कर दिया गया।" + "value" : "कनेक्शन आपके दूसरे डिवाइस द्वारा समाप्त कर दिया गया था।" } }, "hr" : { "stringUnit" : { "state" : "translated", - "value" : "Veza je prekinuta od strane vašeg telefona." + "value" : "Vaš drugi uređaj je prekinuo vezu." } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "A kapcsolatot megszakította a telefonod." + "value" : "A másik eszköz szakította meg a kapcsolatot." } }, "id" : { "stringUnit" : { "state" : "translated", - "value" : "Koneksi dibatalkan oleh ponsel Anda." + "value" : "Koneksi terputus oleh perangkat Anda yang lain." } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "La connessione è stata interrotta dal tuo telefono." + "value" : "La connessione è stata interrotta dall'altro dispositivo." } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "接続はあなたの電話によって中断されました。" + "value" : "接続が他のデバイスによって中断されました。" } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "연결이 휴대폰에 의해 중단되었습니다." + "value" : "다른 기기에서 연결이 중단되었습니다." } }, "ms" : { "stringUnit" : { "state" : "translated", - "value" : "Sambungan telah dihentikan oleh telefon anda." + "value" : "Sambungan telah dibatalkan oleh peranti anda yang lain." } }, "nb" : { "stringUnit" : { "state" : "translated", - "value" : "Tilkoblingen ble avbrutt av telefonen din." + "value" : "Tilkoblingen ble avbrutt av den andre enheten din." } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "De verbinding is door uw telefoon afgebroken." + "value" : "De verbinding is afgebroken door je andere apparaat." } }, "pl" : { "stringUnit" : { "state" : "translated", - "value" : "Połączenie zostało przerwane przez telefon." + "value" : "Połączenie zostało przerwane przez inne urządzenie." } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "A conexão foi interrompida pelo seu telefone." + "value" : "A conexão foi abortada pelo seu outro dispositivo." } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "A ligação foi interrompida pelo seu telemóvel." + "value" : "A ligação foi interrompida pelo seu outro dispositivo." } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Conexiunea a fost întreruptă de telefonul dumneavoastră." + "value" : "Conexiunea a fost întreruptă de către celălalt dispozitiv." } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Соединение было прервано вашим телефоном." + "value" : "Соединение было прервано другим вашим устройством." } }, "sv" : { "stringUnit" : { "state" : "translated", - "value" : "Förbindelsen avbröts av din telefon." + "value" : "Anslutningen avbröts av din andra enhet." } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "การเชื่อมต่อล้มเลิกโดยโทรศัพท์ของคุณ" + "value" : "การเชื่อมต่อถูกยกเลิกโดยอุปกรณ์อีกเครื่องของคุณ" } }, "tr" : { "stringUnit" : { "state" : "translated", - "value" : "Bağlantı telefonunuz tarafından kesildi." + "value" : "Bağlantı diğer cihazınız tarafından sonlandırıldı." } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "З'єднання було перервано вашим телефоном." + "value" : "З'єднання було перервано вашим іншим пристроєм." } }, "vi" : { "stringUnit" : { "state" : "translated", - "value" : "Kết nối bị hủy bởi điện thoại của bạn." + "value" : "Kết nối đã bị thiết bị kia của bạn hủy." } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "连接被您的手机中断。" + "value" : "连接已被你的另一台设备中断。" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "連接已被您的手機中止。" + "value" : "連線已被您的其他裝置中止。" } } } @@ -10953,229 +10953,229 @@ "ar" : { "stringUnit" : { "state" : "translated", - "value" : "إذا تكرر هذا الأمر، يرجى إعادة تشغيل هاتفك أو محاولة تنزيل تطبيق QuickDrop للأندرويد من متجر Google Play." + "value" : "إذا تكرر ذلك، يرجى إعادة تشغيل جهازك الآخر أو محاولة تنزيل تطبيق QuickDrop للأندرويد من متجر Google Play." } }, "ca" : { "stringUnit" : { "state" : "translated", - "value" : "Si això passa repetidament, reinicia el telèfon o prova de descarregar l'app QuickDrop per a Android des de Google Play." + "value" : "Si això passa repetidament, reinicia l'altre dispositiu o prova de descarregar l'app QuickDrop per a Android des de Google Play." } }, "cs" : { "stringUnit" : { "state" : "translated", - "value" : "Pokud se to opakuje, restartujte prosím svůj telefon nebo zkuste stáhnout aplikaci QuickDrop pro Android z Google Play." + "value" : "Pokud se to opakuje, restartujte své druhé zařízení nebo zkuste stáhnout aplikaci QuickDrop pro Android z Google Play." } }, "da" : { "stringUnit" : { "state" : "translated", - "value" : "Hvis dette sker gentagne gange, så genstart venligst din telefon eller prøv at downloade QuickDrop Android-appen fra Google Play." + "value" : "Hvis dette sker gentagne gange, genstart venligst din anden enhed eller prøv at downloade QuickDrop Android-appen fra Google Play." } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "Wenn dies wiederholt passiert, starte bitte dein Handy neu oder lade die QuickDrop Android-App aus dem Google Play Store herunter." + "value" : "Wenn das wiederholt passiert, starte bitte dein anderes Gerät neu oder lade die QuickDrop Android-App aus dem Google Play Store herunter." } }, "el" : { "stringUnit" : { "state" : "translated", - "value" : "Αν αυτό συμβαίνει επανειλημμένα, επανεκκινήστε το τηλέφωνό σας ή δοκιμάστε να κατεβάσετε την εφαρμογή QuickDrop για Android από το Google Play." + "value" : "Αν αυτό συμβαίνει επαναλαμβανόμενα, παρακαλώ επανεκκινήστε τη συσκευή σας ή δοκιμάστε να κατεβάσετε την εφαρμογή QuickDrop για Android από το Google Play." } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "If this happens repeatedly, please restart your phone or try downloading the QuickDrop Android app from Google Play." + "value" : "If this happens repeatedly, please restart your other device or try downloading the QuickDrop Android app from Google Play." } }, "en-AU" : { "stringUnit" : { "state" : "translated", - "value" : "If this happens repeatedly, please restart your phone or try downloading the QuickDrop Android app from Google Play Store." + "value" : "If this happens repeatedly, please restart your other device or try downloading the QuickDrop Android app from Google Play." } }, "en-CA" : { "stringUnit" : { "state" : "translated", - "value" : "If this keeps happening, please restart your phone or try downloading the QuickDrop Android app from Google Play." + "value" : "If this happens repeatedly, please restart your other device or try downloading the QuickDrop Android app from Google Play." } }, "en-GB" : { "stringUnit" : { "state" : "translated", - "value" : "If this happens repeatedly, please restart your phone or try downloading the QuickDrop Android app from Google Play Store." + "value" : "If this happens repeatedly, please restart your other device or try downloading the QuickDrop Android app from Google Play." } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "Si esto ocurre repetidamente, reinicia tu teléfono o intenta descargar la app QuickDrop para Android desde Google Play." + "value" : "Si esto ocurre repetidamente, reinicia tu otro dispositivo o intenta descargar la aplicación QuickDrop para Android desde Google Play." } }, "es-419" : { "stringUnit" : { "state" : "translated", - "value" : "Si esto ocurre repetidamente, reinicia tu teléfono o intenta descargar la app QuickDrop para Android desde Google Play." + "value" : "Si esto ocurre repetidamente, por favor reinicia tu otro dispositivo o intenta descargar la app QuickDrop para Android desde Google Play." } }, "fi" : { "stringUnit" : { "state" : "translated", - "value" : "Jos tämä tapahtuu toistuvasti, käynnistä puhelin uudelleen tai kokeile ladata QuickDrop Android -sovellus Google Playsta." + "value" : "Jos tämä toistuu, käynnistä toinen laitteesi uudelleen tai kokeile ladata QuickDrop Android -sovellus Google Playsta." } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Si cela se produit à plusieurs reprises, veuillez redémarrer votre téléphone ou essayer de télécharger l'application QuickDrop pour Android depuis Google Play." + "value" : "Si cela se produit à plusieurs reprises, veuillez redémarrer votre autre appareil ou essayer de télécharger l'application QuickDrop pour Android depuis Google Play." } }, "fr-CA" : { "stringUnit" : { "state" : "translated", - "value" : "Si cela se produit à plusieurs reprises, veuillez redémarrer votre téléphone ou essayer de télécharger l'application QuickDrop pour Android depuis Google Play." + "value" : "Si cela se produit souvent, veuillez redémarrer votre autre appareil ou essayez de télécharger l’application QuickDrop pour Android sur Google Play." } }, "he" : { "stringUnit" : { "state" : "translated", - "value" : "אם זה קורה שוב ושוב, נא להפעיל את הטלפון מחדש או לנסות להוריד את אפליקציית QuickDrop לאנדרואיד מגוגל פליי." + "value" : "אם זה קורה שוב ושוב, נא הפעל מחדש את המכשיר השני או נסה להוריד את אפליקציית QuickDrop לאנדרואיד מ-Google Play." } }, "hi" : { "stringUnit" : { "state" : "translated", - "value" : "यदि ऐसा बार-बार होता है, तो कृपया अपने फोन को रीस्टार्ट करें या Google Play से QuickDrop Android ऐप डाउनलोड करने की कोशिश करें।" + "value" : "अगर यह बार-बार होता है, तो कृपया अपने दूसरे डिवाइस को पुनः प्रारंभ करें या Google Play से QuickDrop Android ऐप डाउनलोड करने का प्रयास करें।" } }, "hr" : { "stringUnit" : { "state" : "translated", - "value" : "Ako se ovo ponavlja, ponovno pokrenite svoj telefon ili pokušajte preuzeti QuickDrop Android aplikaciju s Google Playa." + "value" : "Ako se ovo ponavlja, ponovno pokrenite drugi uređaj ili pokušajte preuzeti QuickDrop Android aplikaciju s Google Playa." } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "Ha ez ismétlődően előfordul, indítsd újra a telefonodat, vagy próbáld meg letölteni a QuickDrop Android alkalmazást a Google Play-ről." + "value" : "Ha ez ismétlődően előfordul, indítsa újra a másik eszközt, vagy próbálja letölteni a QuickDrop Android alkalmazást a Google Play-ről." } }, "id" : { "stringUnit" : { "state" : "translated", - "value" : "Jika ini terjadi berulang kali, silakan mulai ulang ponsel Anda atau coba unduh aplikasi QuickDrop untuk Android dari Google Play." + "value" : "Jika ini terjadi berulang kali, silakan mulai ulang perangkat Anda yang lain atau coba unduh aplikasi QuickDrop Android dari Google Play." } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "Se questo accade ripetutamente, riavvia il telefono o prova a scaricare l'app QuickDrop per Android da Google Play." + "value" : "Se questo accade ripetutamente, riavvia il tuo altro dispositivo o prova a scaricare l'app QuickDrop per Android da Google Play." } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "この問題が繰り返し発生する場合は、スマートフォンを再起動するか、Google Play から QuickDrop Android アプリをダウンロードしてください。" + "value" : "この問題が繰り返し発生する場合は、他のデバイスを再起動するか、Google Play から QuickDrop Android アプリをダウンロードしてください。" } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "이 현상이 반복되면 휴대폰을 재시작하거나 Google Play에서 QuickDrop Android 앱을 다운로드해 보세요." + "value" : "이 문제가 반복된다면, 다른 기기를 재시작하거나 Google Play에서 QuickDrop Android 앱을 다운로드해보세요." } }, "ms" : { "stringUnit" : { "state" : "translated", - "value" : "Jika ini berlaku berulang kali, sila mulakan semula telefon anda atau cuba muat turun aplikasi QuickDrop Android dari Google Play." + "value" : "Jika ini berlaku berulang kali, sila mulakan semula peranti anda yang lain atau cuba muat turun aplikasi QuickDrop Android dari Google Play." } }, "nb" : { "stringUnit" : { "state" : "translated", - "value" : "Hvis dette skjer gjentatte ganger, start telefonen på nytt eller prøv å laste ned QuickDrop-appen for Android fra Google Play." + "value" : "Hvis dette skjer gjentatte ganger, start den andre enheten på nytt eller prøv å laste ned QuickDrop Android-appen fra Google Play." } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "Als dit herhaaldelijk gebeurt, start dan je telefoon opnieuw op of download de QuickDrop Android-app via Google Play." + "value" : "Als dit herhaaldelijk gebeurt, start dan je andere apparaat opnieuw op of download de QuickDrop Android-app via Google Play." } }, "pl" : { "stringUnit" : { "state" : "translated", - "value" : "Jeśli to się powtarza, uruchom ponownie telefon lub spróbuj pobrać aplikację QuickDrop na Androida z Google Play." + "value" : "Jeśli to się powtarza, uruchom ponownie inne urządzenie lub spróbuj pobrać aplikację QuickDrop na Androida ze Sklepu Google Play." } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Se isso acontecer repetidamente, reinicie seu telefone ou tente baixar o aplicativo QuickDrop para Android na Google Play." + "value" : "Se isso acontecer repetidamente, reinicie seu outro dispositivo ou tente baixar o app QuickDrop para Android na Google Play." } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Se isto acontecer repetidamente, reinicie o seu telemóvel ou tente instalar a aplicação QuickDrop para Android a partir da Google Play." + "value" : "Se isto acontecer repetidamente, reinicie o seu outro dispositivo ou tente descarregar a app QuickDrop para Android na Google Play." } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Dacă se întâmplă în mod repetat, repornește telefonul sau încearcă să descarci aplicația QuickDrop pentru Android din Google Play." + "value" : "Dacă se întâmplă frecvent, repornește celălalt dispozitiv sau încearcă să descarci aplicația QuickDrop pentru Android din Google Play." } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Если это происходит неоднократно, перезапустите телефон или попробуйте установить приложение QuickDrop для Android из Google Play." + "value" : "Если это происходит часто, перезагрузите ваше другое устройство или попробуйте скачать приложение QuickDrop для Android в Google Play." } }, "sv" : { "stringUnit" : { "state" : "translated", - "value" : "Om detta händer upprepade gånger, starta om din telefon eller ladda ner QuickDrop-appen för Android från Google Play." + "value" : "Om detta händer upprepade gånger, starta om din andra enhet eller ladda ner QuickDrop Android-appen från Google Play." } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "หากเกิดเหตุการณ์นี้ซ้ำ โปรดรีสตาร์ทโทรศัพท์หรือดาวน์โหลดแอป QuickDrop สำหรับ Android จาก Google Play" + "value" : "หากเกิดเหตุการณ์นี้บ่อยๆ กรุณารีสตาร์ทอุปกรณ์อีกเครื่องหรือดาวน์โหลดแอป QuickDrop สำหรับ Android จาก Google Play" } }, "tr" : { "stringUnit" : { "state" : "translated", - "value" : "Bu tekrar ederse, lütfen telefonunuzu yeniden başlatın veya QuickDrop Android uygulamasını Google Play'den indirmeyi deneyin." + "value" : "Bu durum tekrar ederse, lütfen diğer cihazınızı yeniden başlatın veya Google Play'den QuickDrop Android uygulamasını indirmeyi deneyin." } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "Якщо це трапляється повторно, перезавантажте телефон або спробуйте завантажити додаток QuickDrop для Android з Google Play." + "value" : "Якщо це трапляється часто, перезапустіть інший пристрій або спробуйте завантажити додаток QuickDrop для Android з Google Play." } }, "vi" : { "stringUnit" : { "state" : "translated", - "value" : "Nếu điều này xảy ra liên tục, vui lòng khởi động lại điện thoại hoặc thử tải ứng dụng QuickDrop cho Android từ Google Play." + "value" : "Nếu điều này xảy ra nhiều lần, vui lòng khởi động lại thiết bị kia hoặc thử tải ứng dụng QuickDrop cho Android từ Google Play." } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "如果此问题反复出现,请重启手机或尝试从 Google Play 下载 QuickDrop 安卓应用。" + "value" : "如果这种情况反复发生,请重启你的另一台设备,或尝试从 Google Play 下载 QuickDrop 安卓应用。" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "如果這種情況重複發生,請重啟您的手機,或嘗試從 Google Play 下載 QuickDrop Android 應用程式。" + "value" : "如果這種情況反覆發生,請重新啟動您的其他裝置,或嘗試從 Google Play 下載 QuickDrop Android 應用程式。" } } } @@ -27246,229 +27246,229 @@ "ar" : { "stringUnit" : { "state" : "translated", - "value" : "فشل في استقبال الملفات من %@" + "value" : "فشل الاتصال مع %@" } }, "ca" : { "stringUnit" : { "state" : "translated", - "value" : "No s'han pogut rebre arxius de %@" + "value" : "No s'ha pogut connectar a %@" } }, "cs" : { "stringUnit" : { "state" : "translated", - "value" : "Nepodařilo se obdržet soubory od %@" + "value" : "Připojení k %@ selhalo" } }, "da" : { "stringUnit" : { "state" : "translated", - "value" : "Mislykkedes at modtage filer fra %@" + "value" : "Forbindelsen til %@ mislykkedes" } }, "de" : { "stringUnit" : { "state" : "translated", - "value" : "Die Daten von %@ konnten nicht empfangen werden" + "value" : "Verbindung zu %@ fehlgeschlagen" } }, "el" : { "stringUnit" : { "state" : "translated", - "value" : "Αποτυχία λήψης αρχείων από %@" + "value" : "Η σύνδεση με το %@ απέτυχε" } }, "en" : { "stringUnit" : { "state" : "translated", - "value" : "Failed to receive files from %@" + "value" : "Connection to %@ failed" } }, "en-AU" : { "stringUnit" : { "state" : "translated", - "value" : "Failed to get files from %@" + "value" : "Connection to %@ failed" } }, "en-CA" : { "stringUnit" : { "state" : "translated", - "value" : "Failed to receive files from %@" + "value" : "Connection to %@ failed" } }, "en-GB" : { "stringUnit" : { "state" : "translated", - "value" : "Failed to receive files from %@" + "value" : "Connection to %@ failed" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "Error al recibir archivos de %@" + "value" : "La conexión con %@ falló" } }, "es-419" : { "stringUnit" : { "state" : "translated", - "value" : "Fallo al recibir archivos de %@" + "value" : "La conexión a %@ falló" } }, "fi" : { "stringUnit" : { "state" : "translated", - "value" : "Virhe tiedostojen vastaanottamisessa: %@" + "value" : "Yhteys laitteeseen %@ epäonnistui." } }, "fr" : { "stringUnit" : { "state" : "translated", - "value" : "Échec de la réception des fichiers de %@" + "value" : "La connexion à %@ a échoué" } }, "fr-CA" : { "stringUnit" : { "state" : "translated", - "value" : "Échec de la réception des fichiers de %@" + "value" : "La connexion à %@ a échoué" } }, "he" : { "stringUnit" : { "state" : "translated", - "value" : "נכשל בקבלת קבצים מ-%@" + "value" : "החיבור אל %@ נכשל" } }, "hi" : { "stringUnit" : { "state" : "translated", - "value" : "%@ से फ़ाइलें प्राप्त करने में विफल" + "value" : "%@ से कनेक्शन विफल हुआ" } }, "hr" : { "stringUnit" : { "state" : "translated", - "value" : "Neuspješno preuzimanje datoteka s %@" + "value" : "Veza s %@ nije uspjela" } }, "hu" : { "stringUnit" : { "state" : "translated", - "value" : "Nem sikerült %@-tól/től fájlokat fogadni" + "value" : "A(z) %@ kapcsolódás sikertelen" } }, "id" : { "stringUnit" : { "state" : "translated", - "value" : "Gagal menerima file dari %@" + "value" : "Koneksi ke %@ gagal" } }, "it" : { "stringUnit" : { "state" : "translated", - "value" : "Impossibile ricevere i file da %@" + "value" : "Connessione a %@ non riuscita" } }, "ja" : { "stringUnit" : { "state" : "translated", - "value" : "%@からのファイル受信に失敗しました。" + "value" : "%@ への接続に失敗しました" } }, "ko" : { "stringUnit" : { "state" : "translated", - "value" : "%@에서 전송한 Nearby Share가 실패했습니다." + "value" : "%@에 연결 실패" } }, "ms" : { "stringUnit" : { "state" : "translated", - "value" : "Gagal menerima fail daripada %@" + "value" : "Sambungan ke %@ gagal" } }, "nb" : { "stringUnit" : { "state" : "translated", - "value" : "Kunne ikke motta filer fra %@" + "value" : "Tilkobling til %@ mislyktes" } }, "nl" : { "stringUnit" : { "state" : "translated", - "value" : "Mislukt om bestanden te ontvangen van %@" + "value" : "Verbinding met %@ mislukt" } }, "pl" : { "stringUnit" : { "state" : "translated", - "value" : "Nie udało się odebrać plików od %@" + "value" : "Połączenie z %@ nie powiodło się" } }, "pt-BR" : { "stringUnit" : { "state" : "translated", - "value" : "Falha ao receber arquivos de %@" + "value" : "Conexão com %@ falhou" } }, "pt-PT" : { "stringUnit" : { "state" : "translated", - "value" : "Falha ao receber ficheiros de %@" + "value" : "A ligação a %@ falhou" } }, "ro" : { "stringUnit" : { "state" : "translated", - "value" : "Recepționarea fișierelor de la %@ a eșuat" + "value" : "Conectarea la %@ a eșuat" } }, "ru" : { "stringUnit" : { "state" : "translated", - "value" : "Не удалость принять файлы от %@" + "value" : "Не удалось подключиться к %@" } }, "sv" : { "stringUnit" : { "state" : "translated", - "value" : "Misslyckades att ta emot filer från %@" + "value" : "Anslutning till %@ misslyckades" } }, "th" : { "stringUnit" : { "state" : "translated", - "value" : "เกิดข้อผิดพลาดในการรับไฟล์จาก %@" + "value" : "การเชื่อมต่อกับ %@ ล้มเหลว" } }, "tr" : { "stringUnit" : { "state" : "translated", - "value" : "%@ dosyalarından dosyalar alınamadı." + "value" : "%@ ile bağlantı başarısız oldu" } }, "uk" : { "stringUnit" : { "state" : "translated", - "value" : "Не вдалося отримати файли від %@" + "value" : "Не вдалося підключитися до %@" } }, "vi" : { "stringUnit" : { "state" : "translated", - "value" : "Không nhận được tệp từ %@" + "value" : "Kết nối với %@ thất bại" } }, "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "无法从 %@ 接收文件" + "value" : "连接到 %@ 失败" } }, "zh-Hant" : { "stringUnit" : { "state" : "translated", - "value" : "無法從 %@ 接收檔案" + "value" : "連接 %@ 失敗" } } } diff --git a/QuickDrop/ViewModel/ReceiveModel.swift b/QuickDrop/ViewModel/ReceiveModel.swift index 32165c0..9ed0cb6 100644 --- a/QuickDrop/ViewModel/ReceiveModel.swift +++ b/QuickDrop/ViewModel/ReceiveModel.swift @@ -49,7 +49,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { AudioManager.playIncomingFileSound() #endif - let mainMessage = transfer.getDescription(deviceName: device.name ?? "Android", alreadyAccepted: false) + let mainMessage = transfer.getDescription(deviceName: device.name ?? "UnknownDevice".localized(), alreadyAccepted: false) let pinCodeMessage = transfer.getPinCodeMessage() let transferID = transfer.id @@ -111,7 +111,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { func obtainedUserConsentAutomatically(transfer: TransferMetadata, device: RemoteDeviceInfo) { - let mainMessage = transfer.getDescription(deviceName: device.name ?? "Android", alreadyAccepted: true) + let mainMessage = transfer.getDescription(deviceName: device.name ?? "UnknownDevice".localized(), alreadyAccepted: true) #if os(macOS) @@ -203,7 +203,7 @@ class ReceiveModel: ObservableObject, InboundAppDelegate { #endif controlPlusScreen(false) - ErrorAlertHandler.shared.showErrorAlert(for: device.name ?? "Android", error: error) + ErrorAlertHandler.shared.showErrorAlert(for: device.name ?? "UnknownDevice".localized(), error: error) } else { #if os(iOS) diff --git a/QuickDrop/ViewModel/SendModel.swift b/QuickDrop/ViewModel/SendModel.swift index 2c022ad..5d2218b 100644 --- a/QuickDrop/ViewModel/SendModel.swift +++ b/QuickDrop/ViewModel/SendModel.swift @@ -61,11 +61,10 @@ class SendModel: ObservableObject, OutboundAppDelegate { func connectionFailed(error: any Error) { - #if os(iOS) - errorVibration() - #endif - - ErrorAlertHandler.shared.showErrorAlert(for: selectedDevice?.name ?? "UnknownDevice".localized(), error: error) + if let name = selectedDevice?.name { + errorVibration() + ErrorAlertHandler.shared.showErrorAlert(for: name, error: error) + } progressValue = nil selectedDevice = nil @@ -126,9 +125,13 @@ class SendModel: ObservableObject, OutboundAppDelegate { else { progressValue = 0 - progressState = "Connecting".localized() + progressState = "Preparing".localized() selectedDevice = device - NearbyConnectionManager.shared.startOutgoingTransfer(deviceID: device.id!, delegate: self, urls: urls, textToSend: textToSend) + + runAfter(seconds: 0.3) { + NearbyConnectionManager.shared.startOutgoingTransfer(deviceID: device.id!, delegate: self, urls: self.urls, textToSend: self.textToSend) + self.progressState = "Connecting".localized() + } } } } diff --git a/QuickDropiOS/View/ContentView.swift b/QuickDropiOS/View/ContentView.swift index e41461d..a842cc5 100644 --- a/QuickDropiOS/View/ContentView.swift +++ b/QuickDropiOS/View/ContentView.swift @@ -284,7 +284,7 @@ struct DeviceButtonLabel: View { var body: some View { HStack(spacing: 12) { - let name = device.name ?? "Android" + let name = device.name ?? "UnknownDevice".localized() ZStack { Circle() diff --git a/Resources/License.txt b/Resources/License.txt index d674ba0..2c9530e 100644 --- a/Resources/License.txt +++ b/Resources/License.txt @@ -601,6 +601,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +ZIPFoundation +https://github.com/weichsel/ZIPFoundation +MIT License + +Copyright (c) 2017-2025 Thomas Zoechling (https://www.peakstep.com) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + SwiftECC https://github.com/leif-ibsen/SwiftECC Copyright (c) 2021 Leif Ibsen diff --git a/ShareExtension/ShareViewController.swift b/ShareExtension/ShareViewController.swift index 9dcbf62..4422045 100644 --- a/ShareExtension/ShareViewController.swift +++ b/ShareExtension/ShareViewController.swift @@ -252,27 +252,32 @@ class ShareViewController: NSViewController, OutboundAppDelegate { progressDeviceName?.stringValue = getDeviceName(device: device) progressDeviceIcon?.image = imageForDeviceType(type: device.type) progressProgressBar?.startAnimation(nil) - progressState?.stringValue = "Connecting".localized() + progressState?.stringValue = "Preparing".localized() chosenDevice = device NearbyConnectionManager.shared.stopDeviceDiscovery() - NearbyConnectionManager.shared.startOutgoingTransfer(deviceID: device.id!, delegate: self, urls: urls, textToSend: textToSend) - let timeoutAlert = DispatchWorkItem { - if !self.connectionEstablished { - AudioManager.playErrorSound() - let alert = NSAlert() - alert.alertStyle = .critical - - alert.messageText = "TimeoutTitle".localized() - alert.informativeText = "TimeoutDescription".localized() - alert.addButton(withTitle: "TimeoutButton".localized()) - - alert.beginSheetModal(for: self.view.window!) { _ in } + runAfter(seconds: 0.3) { + NearbyConnectionManager.shared.startOutgoingTransfer(deviceID: device.id!, delegate: self, urls: self.urls, textToSend: self.textToSend) + + self.progressState?.stringValue = "Connecting".localized() + + let timeoutAlert = DispatchWorkItem { + if !self.connectionEstablished { + AudioManager.playErrorSound() + let alert = NSAlert() + alert.alertStyle = .critical + + alert.messageText = "TimeoutTitle".localized() + alert.informativeText = "TimeoutDescription".localized() + alert.addButton(withTitle: "TimeoutButton".localized()) + + alert.beginSheetModal(for: self.view.window!) { _ in } + } } + + self.timeoutDispatchWorkItem = timeoutAlert + DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: timeoutAlert) } - - timeoutDispatchWorkItem = timeoutAlert - DispatchQueue.main.asyncAfter(deadline: .now() + 10.0, execute: timeoutAlert) } @@ -381,6 +386,6 @@ extension ShareViewController: NSCollectionViewDataSource { return name } - return "Android" + return "UnknownDevice".localized() } }