diff --git a/Keyboards/DataManager/LanguageDBManager.swift b/Keyboards/DataManager/LanguageDBManager.swift index ad928099..b91be42f 100644 --- a/Keyboards/DataManager/LanguageDBManager.swift +++ b/Keyboards/DataManager/LanguageDBManager.swift @@ -14,7 +14,10 @@ class LanguageDBManager { private init(translate: Bool) { if translate { - database = openDBQueue("TranslationData") + database = openDownloadedDBQueue("TranslationData") + if database == nil { + database = openDBQueue("TranslationData") + } } else { database = openDownloadedDBQueue( "\(getControllerLanguageAbbr().uppercased())LanguageData" @@ -23,8 +26,10 @@ class LanguageDBManager { } /// Makes a connection to the language database given the value for controllerLanguage. - private func openDBQueue(_ dbName: String) -> DatabaseQueue { - let dbResourcePath = Bundle.main.path(forResource: dbName, ofType: "sqlite")! + private func openDBQueue(_ dbName: String) -> DatabaseQueue? { + guard let dbResourcePath = Bundle.main.path(forResource: dbName, ofType: "sqlite") else { + return nil + } let fileManager = FileManager.default do { let dbPath = @@ -42,7 +47,7 @@ class LanguageDBManager { return try DatabaseQueue(path: dbPath) } catch { print("An error occurred: UILexicon not available") - return try! DatabaseQueue(path: dbResourcePath) + return try? DatabaseQueue(path: dbResourcePath) } } diff --git a/Keyboards/KeyboardsBase/ScribeFunctionality/Translate.swift b/Keyboards/KeyboardsBase/ScribeFunctionality/Translate.swift index 8672e868..3a7a284c 100644 --- a/Keyboards/KeyboardsBase/ScribeFunctionality/Translate.swift +++ b/Keyboards/KeyboardsBase/ScribeFunctionality/Translate.swift @@ -32,16 +32,22 @@ func queryTranslation(commandBar: UILabel) { func queryWordToTranslate(queriedWordToTranslate: String) { wordToTranslate = String(queriedWordToTranslate.trailingSpacesTrimmed) + guard !wordToTranslate.isEmpty else { + commandState = .invalid + return + } + // Check to see if the input was uppercase to return an uppercase conjugation. inputWordIsCapitalized = wordToTranslate.substring(toIdx: 1).isUppercase - wordToReturn = - LanguageDBManager.translations.queryTranslation(of: wordToTranslate.lowercased())[0] - - if wordToReturn.isEmpty { - wordToReturn = LanguageDBManager.translations.queryTranslation(of: wordToTranslate)[0] - guard !wordToReturn.isEmpty - else { + let translations = LanguageDBManager.translations.queryTranslation(of: wordToTranslate.lowercased()) + if let firstTranslation = translations.first, !firstTranslation.isEmpty { + wordToReturn = firstTranslation + } else { + let fallbackTranslations = LanguageDBManager.translations.queryTranslation(of: wordToTranslate) + if let firstFallback = fallbackTranslations.first, !firstFallback.isEmpty { + wordToReturn = firstFallback + } else { commandState = .invalid return } diff --git a/Scribe.xcodeproj/project.pbxproj b/Scribe.xcodeproj/project.pbxproj index 6980936d..c1690429 100644 --- a/Scribe.xcodeproj/project.pbxproj +++ b/Scribe.xcodeproj/project.pbxproj @@ -228,6 +228,7 @@ D16151062E9DBDED00131732 /* IDLanguageData.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = D16150FB2E9DBDC500131732 /* IDLanguageData.sqlite */; }; D16151072E9DBDED00131732 /* IDLanguageData.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = D16150FB2E9DBDC500131732 /* IDLanguageData.sqlite */; }; D16151082E9DBDED00131732 /* IDLanguageData.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = D16150FB2E9DBDC500131732 /* IDLanguageData.sqlite */; }; + D1E385102C977FD200DCE538 /* TranslationData.sqlite in Resources */ = {isa = PBXBuildFile; fileRef = D1E3850F2C977FD100DCE538 /* TranslationData.sqlite */; }; D1671A67275A1E8700A7C118 /* Russian.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D1671A60275A1E8700A7C118 /* Russian.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; D1671A71275A1FA200A7C118 /* RUKeyboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D1671A70275A1FA200A7C118 /* RUKeyboardViewController.swift */; }; D1671A72275A1FC000A7C118 /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38DD94F022D6A40000FF8845 /* Extensions.swift */; }; @@ -1076,6 +1077,7 @@ D1608667270B6D3C00134D48 /* ESKeyboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ESKeyboardViewController.swift; sourceTree = ""; }; D1608669270B6D3C00134D48 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D16150FB2E9DBDC500131732 /* IDLanguageData.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = IDLanguageData.sqlite; sourceTree = ""; }; + D1E3850F2C977FD100DCE538 /* TranslationData.sqlite */ = {isa = PBXFileReference; lastKnownFileType = file; path = Data/TranslationData.sqlite; sourceTree = ""; }; D166FCF1275A197B0047E62B /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D1671A60275A1E8700A7C118 /* Russian.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = Russian.appex; sourceTree = BUILT_PRODUCTS_DIR; }; D1671A70275A1FA200A7C118 /* RUKeyboardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RUKeyboardViewController.swift; path = Keyboards/LanguageKeyboards/Russian/RUKeyboardViewController.swift; sourceTree = SOURCE_ROOT; }; @@ -1968,6 +1970,7 @@ EDC364682AE408F20001E456 /* InterfaceConstants.swift */, 19DC85F92C7772FC006E32FD /* KeyboardBuilder.swift */, 198369CB2C7980BA00C1B583 /* KeyboardProvider.swift */, + D1E3850F2C977FD100DCE538 /* TranslationData.sqlite */, E9B89DCD2F226757003E396F /* DataManager */, E98E73BF2F20D8C3005EEDA3 /* DataContracts */, ); @@ -2676,6 +2679,7 @@ E93179A42F03AE78002ED334 /* Localizable.xcstrings in Resources */, 38BD213922D5907F00C6795D /* AppScreen.storyboard in Resources */, 38BD213E22D5908100C6795D /* Assets.xcassets in Resources */, + D1E385102C977FD200DCE538 /* TranslationData.sqlite in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Scribe/AppDelegate.swift b/Scribe/AppDelegate.swift index e86a60b8..a5faf0a2 100644 --- a/Scribe/AppDelegate.swift +++ b/Scribe/AppDelegate.swift @@ -15,6 +15,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + copyTranslationDataToSharedContainer() initializeFontSize() // Override point for customization after application launch. if #available(iOS 13.0, *) { @@ -35,6 +36,38 @@ class AppDelegate: UIResponder, UIApplicationDelegate { return true } + private func copyTranslationDataToSharedContainer() { + let fileManager = FileManager.default + guard let containerURL = fileManager.containerURL(forSecurityApplicationGroupIdentifier: "group.be.scri.userDefaultsContainer") else { + return + } + + let destURL = containerURL.appendingPathComponent("TranslationData.sqlite") + guard let bundlePath = Bundle.main.path(forResource: "TranslationData", ofType: "sqlite") else { + return + } + + var shouldCopy = false + if !fileManager.fileExists(atPath: destURL.path) { + shouldCopy = true + } else { + // Check if the bundle database is newer. + if let bundleAttributes = try? fileManager.attributesOfItem(atPath: bundlePath), + let destAttributes = try? fileManager.attributesOfItem(atPath: destURL.path), + let bundleModDate = bundleAttributes[.modificationDate] as? Date, + let destModDate = destAttributes[.modificationDate] as? Date { + if bundleModDate > destModDate { + shouldCopy = true + try? fileManager.removeItem(at: destURL) + } + } + } + + if shouldCopy { + try? fileManager.copyItem(atPath: bundlePath, toPath: destURL.path) + } + } + func applicationWillResignActive(_: UIApplication) { /* Sent when the application is about to move from active to inactive state.