Skip to content

Commit

Permalink
scribe-org#378 keep db manager but remove references to rework + chan…
Browse files Browse the repository at this point in the history
…gelog
  • Loading branch information
andrewtavis authored and SaurabhJamadagni committed Apr 18, 2024
1 parent d0739a9 commit 055b578
Show file tree
Hide file tree
Showing 8 changed files with 1,098 additions and 664 deletions.
235 changes: 124 additions & 111 deletions CHANGELOG.md

Large diffs are not rendered by default.

1,101 changes: 617 additions & 484 deletions Keyboards/KeyboardsBase/KeyboardViewController.swift

Large diffs are not rendered by default.

158 changes: 158 additions & 0 deletions Keyboards/KeyboardsBase/LoadData.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**
* Function for loading in data to the keyboards.
*
* Copyright (C) 2023 Scribe
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import Foundation
import GRDB
import SwiftyJSON

/// Loads a JSON file that contains grammatical information into a dictionary.
///
/// - Parameters
/// - filename: the name of the JSON file to be loaded.
func loadJSON(filename fileName: String) -> JSON? {
guard let url = Bundle.main.url(forResource: fileName, withExtension: "json"),
let data = try? Data(contentsOf: url),
let jsonData = try? JSON(data: data)
else {
return nil
}
return jsonData
}

/// Makes a connection to the language database given the value for controllerLanguage.
func openDBQueue() -> DatabaseQueue {
let dbName = "\(String(describing: get_iso_code(keyboardLanguage: controllerLanguage).uppercased()))LanguageData"
guard let dbPath = Bundle.main.path(forResource: dbName, ofType: "sqlite") else {
fatalError("Failed to locate database file.")
}
do {
let dbQueue = try DatabaseQueue(path: dbPath)
return dbQueue
} catch {
fatalError("Failed to initialize DatabaseQueue: \(error)")
}
}

// Variable to be replaced with the result of openDBQueue.
var languageDB = try! DatabaseQueue()

/// Returns a row from the language database given a query and arguments.
///
/// - Parameters
/// - query: the query to run against the language database.
/// - outputCols: the columns from which the values should come.
/// - args: arguments to pass to `query`.
func queryDBRow(query: String, outputCols: [String], args: [String]) -> [String] {
var outputValues = [String]()
do {
try languageDB.read { db in
if let row = try Row.fetchOne(db, sql: query, arguments: StatementArguments(args)) {
for col in outputCols {
outputValues.append(row[col])
}
}
}
} catch let error as DatabaseError {
let errorMessage = error.message
let errorSQL = error.sql
let errorArguments = error.arguments
print(
"An error '\(String(describing: errorMessage))' occurred in the query: \(String(describing: errorSQL)) (\(String(describing: errorArguments)))"
)
} catch {}

if outputValues == [String]() {
// Append an empty string so that we can check for it and trigger commandState = .invalid.
outputValues.append("")
}

return outputValues
}

/// Writes a row of a language database table given a query and arguments.
///
/// - Parameters
/// - query: the query to run against the language database.
/// - args: arguments to pass to `query`.
func writeDBRow(query: String, args: StatementArguments) {
do {
try languageDB.write { db in
try db.execute(
sql: query,
arguments: args
)
}
} catch let error as DatabaseError {
let errorMessage = error.message
let errorSQL = error.sql
let errorArguments = error.arguments
print(
"An error '\(String(describing: errorMessage))' occurred in the query: \(String(describing: errorSQL)) (\(String(describing: errorArguments)))"
)
} catch {}
}

/// Returns the next three words in the `autocomplete_lexicon` that follow a given word.
///
/// - Parameters
/// - word: the word that autosuggestions should be returned for.
func queryAutocompletions(word: String) -> [String] {
var autocompletions = [String]()

let autocompletionsQuery = """
SELECT
word
FROM
autocomplete_lexicon
WHERE
LOWER(word) LIKE ?
ORDER BY
word COLLATE NOCASE ASC
LIMIT
3
"""
let patterns = ["\(word.lowercased())%"]

do {
let rows = try languageDB.read { db in
try Row.fetchAll(db, sql: autocompletionsQuery, arguments: StatementArguments(patterns))
}
for r in rows {
autocompletions.append(r["word"])
}
} catch let error as DatabaseError {
let errorMessage = error.message
let errorSQL = error.sql
let errorArguments = error.arguments
print(
"An error '\(String(describing: errorMessage))' occurred in the query: \(String(describing: errorSQL)) (\(String(describing: errorArguments)))"
)
} catch {}

if autocompletions == [String]() {
// Append an empty string so that we can check for it and trigger nothing being shown.
autocompletions.append("")
}

return autocompletions
}
61 changes: 44 additions & 17 deletions Keyboards/KeyboardsBase/ScribeFunctionality/Annotate.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
//
// Annotate.swift
//
// Functions and elements that control word annotations.
//
/**
* Functions and elements that control word annotations.
*
* Copyright (C) 2023 Scribe
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import UIKit

Expand Down Expand Up @@ -38,11 +51,17 @@ let prepAnnotationConversionDict = [
/// - wordToAnnotate: the word that an annotation should be created for.
/// - KVC: the keyboard view controller.
func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
let nounForm = LanguageDBManager.shared.queryNounForm(of: wordToAnnotate)[0]
prepAnnotationForm = LanguageDBManager.shared.queryPrepForm(of: wordToAnnotate)[0]
let nounGenderQuery = "SELECT * FROM nouns WHERE noun = ?"
let prepCaseQuery = "SELECT * FROM prepositions WHERE preposition = ?"
let nounGenderArgs = [wordToAnnotate]
let prepCaseArgs = [wordToAnnotate.lowercased()]
let outputCols = ["form"]

hasNounForm = nounForm != ""
hasPrepForm = prepAnnotationForm != ""
let nounForm = queryDBRow(query: nounGenderQuery, outputCols: outputCols, args: nounGenderArgs)[0]
prepAnnotationForm = queryDBRow(query: prepCaseQuery, outputCols: outputCols, args: prepCaseArgs)[0]

hasNounForm = !nounForm.isEmpty
hasPrepForm = !prepAnnotationForm.isEmpty

annotationsToAssign = [String]()
annotationBtns = [UIButton]()
Expand Down Expand Up @@ -71,7 +90,7 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
annotationBtn.styleSingleAnnotation(fullAnnotation: true)

let emojisToSelectFrom = "🥳🎉"
let emojis = String((0 ..< 3).map { _ in emojisToSelectFrom.randomElement()! })
let emojis = String((0 ..< 3).compactMap { _ in emojisToSelectFrom.randomElement() })
annotationBtn.setTitle(emojis, for: .normal)
KVC.view.addSubview(annotationBtn)
annotationBtns.append(annotationBtn)
Expand Down Expand Up @@ -169,7 +188,9 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
KVC.view.addSubview(annotationBtn)
annotationBtns.append(annotationBtn)
if nounFormToColorDict.keys.contains(annotationToDisplay) {
annotationColors.append(nounFormToColorDict[annotationsToAssign[i]]!)
if let annotationColor = nounFormToColorDict[annotationsToAssign[i]] {
annotationColors.append(annotationColor)
}
} else {
annotationColors.append(UITraitCollection.current.userInterfaceStyle == .light ? .black : .white)
}
Expand Down Expand Up @@ -208,7 +229,7 @@ func wordAnnotation(wordToAnnotate: String, KVC: KeyboardViewController) {
/// - KVC: the keyboard view controller.
func selectedWordAnnotation(KVC: KeyboardViewController) {
wordToCheck = proxy.selectedText ?? ""
if wordToCheck.count > 0 {
if !wordToCheck.isEmpty {
if !languagesWithCapitalizedNouns.contains(controllerLanguage) {
wordToCheck = wordToCheck.lowercased()
}
Expand Down Expand Up @@ -249,9 +270,13 @@ func typedWordAnnotation(KVC: KeyboardViewController) {
/// - index: the auto action key index that the annotation should be set for.
/// - KVC: the keyboard view controller.
func autoActionAnnotation(autoActionWord: String, index: Int, KVC: KeyboardViewController) {
let nounForm = LanguageDBManager.shared.queryNounForm(of: autoActionWord)[0]
let nounGenderQuery = "SELECT * FROM nouns WHERE noun = ?"
let nounGenderArgs = [autoActionWord]
let outputCols = ["form"]

let nounForm = queryDBRow(query: nounGenderQuery, outputCols: outputCols, args: nounGenderArgs)[0]

hasNounForm = nounForm != ""
hasNounForm = !nounForm.isEmpty

newAutoActionAnnotationsToAssign = [String]()
newAutoActionAnnotationBtns = [UIButton]()
Expand Down Expand Up @@ -331,9 +356,11 @@ func autoActionAnnotation(autoActionWord: String, index: Int, KVC: KeyboardViewC

KVC.view.addSubview(annotationBtn)
autoActionAnnotationBtns.append(annotationBtn)
newAutoActionAnnotationColors.append(
nounFormToColorDict[newAutoActionAnnotationsToAssign[i]]!.withAlphaComponent(0.75)
)
if let annotationColor = nounFormToColorDict[newAutoActionAnnotationsToAssign[i]] {
let colorWithAlpha = annotationColor.withAlphaComponent(0.75)
newAutoActionAnnotationColors.append(colorWithAlpha)
}

setBtn(
btn: annotationBtn,
color: newAutoActionAnnotationColors[i],
Expand Down
60 changes: 45 additions & 15 deletions Keyboards/KeyboardsBase/ScribeFunctionality/Conjugate.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
//
// Conjugation.swift
//
// Functions and elements that control the conjugation command.
//
/**
* Functions and elements that control the conjugation command.
*
* Copyright (C) 2023 Scribe
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import UIKit

Expand Down Expand Up @@ -47,9 +60,10 @@ let keyboardConjLabelDict: [String: Any] = [
func returnDeclension(keyPressed: UIButton) {
let wordPressed = keyPressed.titleLabel?.text ?? ""

let keyName = keyPressed.layer.value(
forKey: "original"
) as! String
var keyName = ""
if let originalKeyValue = keyPressed.layer.value(forKey: "original") as? String {
keyName = originalKeyValue
}

if !(wordPressed.contains("/") || wordPressed.contains("")) {
proxy.insertText(wordPressed + " ")
Expand Down Expand Up @@ -180,17 +194,28 @@ func returnDeclension(keyPressed: UIButton) {
/// - commandBar: the command bar into which an input was entered.
func triggerVerbConjugation(commandBar: UILabel) -> Bool {
// Cancel via a return press.
if commandBar.text! == conjugatePromptAndCursor || commandBar.text! == conjugatePromptAndPlaceholder {
if let commandBarText = commandBar.text,
commandBarText == conjugatePromptAndCursor || commandBarText == conjugatePromptAndCursor
{
return false
}
verbToConjugate = (commandBar.text!.substring(with: conjugatePrompt.count ..< (commandBar.text!.count) - 1))

if let commandBarText = commandBar.text {
let startIndex = commandBarText.index(commandBarText.startIndex, offsetBy: conjugatePrompt.count)
let endIndex = commandBarText.index(commandBarText.endIndex, offsetBy: -1)
verbToConjugate = String(commandBarText[startIndex ..< endIndex])
}
verbToConjugate = String(verbToConjugate.trailingSpacesTrimmed)

// Check to see if the input was uppercase to return an uppercase conjugation.
let firstLetter = verbToConjugate.substring(toIdx: 1)
inputWordIsCapitalized = firstLetter.isUppercase
verbToConjugate = verbToConjugate.lowercased()

let verbInTable = LanguageDBManager.shared.queryVerb(of: verbConjugated)[0]
let query = "SELECT * FROM verbs WHERE verb = ?"
let args = [verbToConjugate]
let outputCols = ["verb"]
let verbInTable = queryDBRow(query: query, outputCols: outputCols, args: args)[0]

return verbToConjugate == verbInTable
}
Expand All @@ -201,7 +226,6 @@ func triggerVerbConjugation(commandBar: UILabel) -> Bool {
/// - keyPressed: the button pressed as sender.
/// - requestedForm: the form that is triggered by the given key.
func returnConjugation(keyPressed: UIButton, requestedForm: String) {
let outputCols = [requestedForm]
if commandState == .selectCaseDeclension {
returnDeclension(keyPressed: keyPressed)
return
Expand All @@ -212,11 +236,14 @@ func returnConjugation(keyPressed: UIButton, requestedForm: String) {
if wordPressed == invalidCommandMsg {
proxy.insertText("")
} else if formsDisplayDimensions == .view3x2 {
wordToReturn = LanguageDBManager.shared.queryVerb(of: verbToConjugate, with: outputCols)[0]
let query = "SELECT * FROM verbs WHERE verb = ?"
let args = [verbToConjugate]
let outputCols = [requestedForm]
wordToReturn = queryDBRow(query: query, outputCols: outputCols, args: args)[0]
potentialWordsToReturn = wordToReturn.components(separatedBy: " ")

if inputWordIsCapitalized {
if controllerLanguage == "German" && potentialWordsToReturn.count == 2 {
if controllerLanguage == "German", potentialWordsToReturn.count == 2 {
// Don't return a space as well as we have a perfect verb and the cursor will be between.
proxy.insertText(wordToReturn.capitalize())
} else {
Expand All @@ -226,7 +253,10 @@ func returnConjugation(keyPressed: UIButton, requestedForm: String) {
proxy.insertText(wordToReturn + " ")
}
} else if formsDisplayDimensions == .view2x2 {
wordToReturn = LanguageDBManager.shared.queryVerb(of: verbToConjugate, with: outputCols)[0]
let query = "SELECT * FROM verbs WHERE verb = ?"
let args = [verbToConjugate]
let outputCols = [requestedForm]
wordToReturn = queryDBRow(query: query, outputCols: outputCols, args: args)[0]
potentialWordsToReturn = wordToReturn.components(separatedBy: " ")

if inputWordIsCapitalized {
Expand Down
Loading

0 comments on commit 055b578

Please sign in to comment.