Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Keyboards/DataManager/DataContract.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct DeclensionSection: Codable {
let declensionForms: [Int: DeclensionNode]?
}

struct DeclensionNode: Codable {
class DeclensionNode: Codable {
let label: String?
let value: String?
let displayValue: String?
Expand Down
96 changes: 96 additions & 0 deletions Keyboards/KeyboardsBase/KeyboardViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,100 @@ class KeyboardViewController: UIInputViewController {
pluralKey.isHidden = state
}

// MARK: Download Data Button

/// A button shown above the keyboard when no language data has been downloaded.
var downloadDataBtn: UIButton?

/// Checks whether language data has been downloaded for the current keyboard language.
func hasLanguageData() -> Bool {
let langAbbr = getControllerLanguageAbbr()
guard !langAbbr.isEmpty,
let containerURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: "group.be.scri.userDefaultsContainer"
) else {
return true // default to true to avoid showing the button unnecessarily
}
let dbPath = containerURL.appendingPathComponent("\(langAbbr.uppercased())LanguageData.sqlite").path
return FileManager.default.fileExists(atPath: dbPath)
}

/// Opens the Scribe app via the responder chain so the user can download language data.
@objc func openScribeApp() {
guard let url = URL(string: "scribe://") else { return }
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
application.open(url)
return
}
responder = responder?.next
}
}

/// Shows or hides the download data button based on whether language data is available.
func conditionallyShowDownloadDataBtn() {
// Only show the download button in idle state (not during commands).
guard commandState == .idle else {
downloadDataBtn?.isHidden = true
return
}
if hasLanguageData() {
downloadDataBtn?.isHidden = true
} else {
showDownloadDataBtn()
}
}

/// Creates and displays the download data button above the keyboard.
func showDownloadDataBtn() {
// Remove any existing button first.
downloadDataBtn?.removeFromSuperview()

let btn = UIButton(type: .system)
btn.translatesAutoresizingMaskIntoConstraints = false
btn.backgroundColor = scribeCTAColor
btn.setTitleColor(.white, for: .normal)
btn.setTitle(downloadDataMsg, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.layer.cornerRadius = commandKeyCornerRadius
btn.layer.masksToBounds = true

// Add a download icon on the left side.
let iconConfig = UIImage.SymbolConfiguration(pointSize: 14, weight: .medium)
btn.setImage(UIImage(systemName: "arrow.down.circle.fill", withConfiguration: iconConfig), for: .normal)
btn.tintColor = .white
if #available(iOS 15.0, *) {
var config = UIButton.Configuration.plain()
config.baseForegroundColor = .white
config.image = UIImage(systemName: "arrow.down.circle.fill", withConfiguration: iconConfig)
config.imagePadding = 8
config.imagePlacement = .leading
config.title = downloadDataMsg
config.attributedTitle = AttributedString(
downloadDataMsg,
attributes: AttributeContainer([.font: UIFont.systemFont(ofSize: 16, weight: .medium)])
)
btn.configuration = config
btn.backgroundColor = scribeCTAColor
} else {
btn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 8)
btn.contentEdgeInsets = UIEdgeInsets(top: 8, left: 12, bottom: 8, right: 12)
}

btn.addTarget(self, action: #selector(openScribeApp), for: .touchUpInside)

view.addSubview(btn)
downloadDataBtn = btn

NSLayoutConstraint.activate([
btn.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8),
btn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -8),
btn.topAnchor.constraint(equalTo: view.topAnchor, constant: 4),
btn.heightAnchor.constraint(equalToConstant: scribeKey.frame.height > 0 ? scribeKey.frame.height : 36)
])
}

/// Logic to create notification tooltip.
func createInformationStateDatasource(text: NSMutableAttributedString, backgroundColor: UIColor)
-> ToolTipViewDatasource {
Expand Down Expand Up @@ -1714,6 +1808,7 @@ class KeyboardViewController: UIInputViewController {
deactivateBtn(btn: padEmojiKey2)

setInformationState()
downloadDataBtn?.isHidden = true
return // return to skip normal keyboard setup
}

Expand Down Expand Up @@ -1835,6 +1930,7 @@ class KeyboardViewController: UIInputViewController {
}

setKeyPadding()
conditionallyShowDownloadDataBtn()
}

func setCommaAndPeriodKeysConditionally() {
Expand Down
9 changes: 7 additions & 2 deletions Keyboards/KeyboardsBase/NavigationStructure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@
import Foundation

/// Represents a single option in the navigation.
enum NavigationNode {
indirect enum NavigationNode {
case nextLevel(NavigationLevel, displayValue: String?) // navigate deeper, with optional display value
case finalValue(String) // terminal node, insert this text
}

/// Represents a level in the navigation hierarchy.
struct NavigationLevel {
class NavigationLevel {
let title: String // title for command bar
let options: [(label: String, node: NavigationNode)] // buttons to display

init(title: String, options: [(label: String, node: NavigationNode)]) {
self.title = title
self.options = options
}
}

/// Builds navigation trees for conjugations and declensions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,8 @@ var pluralPromptAndCursor = ""
var pluralPromptAndPlaceholder = ""
var pluralPromptAndColorPlaceholder = NSMutableAttributedString()
var alreadyPluralMsg = ""

// MARK: Download Data Variables

/// The message shown on the download data button when no language data has been downloaded.
var downloadDataMsg = "Please download language data"
Original file line number Diff line number Diff line change
Expand Up @@ -294,4 +294,5 @@ func setENKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Already plural"
downloadDataMsg = "Please download language data"
}
Original file line number Diff line number Diff line change
Expand Up @@ -293,4 +293,5 @@ func setFRKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Déjà pluriel"
downloadDataMsg = "Veuillez télécharger les données linguistiques"
}
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,5 @@ func setDEKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Schon Plural"
downloadDataMsg = "Bitte Sprachdaten herunterladen"
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,5 @@ func setHEKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "כבר בצורת רבים"
downloadDataMsg = "אנא הורד נתוני שפה"
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,5 @@ func setIDKeyboardLayout() {
textForAttribute: translatePlaceholder,
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
downloadDataMsg = "Unduh data bahasa"
}
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,5 @@ func setITKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Già plurale"
downloadDataMsg = "Scarica i dati della lingua"
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,4 +300,5 @@ func setNBKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Allerede flertall"
downloadDataMsg = "Last ned språkdata"
}
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,5 @@ func setPTKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Já plural"
downloadDataMsg = "Por favor baixe os dados do idioma"
}
Original file line number Diff line number Diff line change
Expand Up @@ -269,4 +269,5 @@ func setRUKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Уже во множ-ом"
downloadDataMsg = "Загрузите языковые данные"
}
Original file line number Diff line number Diff line change
Expand Up @@ -353,4 +353,5 @@ func setESKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Ya en plural"
downloadDataMsg = "Por favor descarga los datos del idioma"
}
Original file line number Diff line number Diff line change
Expand Up @@ -349,4 +349,5 @@ func setSVKeyboardLayout() {
withColor: UIColor(cgColor: commandBarPlaceholderColorCG)
)
alreadyPluralMsg = "Redan plural"
downloadDataMsg = "Ladda ner språkdata"
}
9 changes: 9 additions & 0 deletions Scribe/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
*/
}

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
// Handle scribe:// URL scheme to navigate to the download data screen.
if url.scheme == "scribe" {
NotificationCenter.default.post(name: NSNotification.Name("NavigateToDownloadScreen"), object: nil)
return true
}
return false
}

func applicationDidBecomeActive(_: UIApplication) {
/*
Restart any tasks that were paused (or not yet started) while the application was inactive.
Expand Down
11 changes: 11 additions & 0 deletions Scribe/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,16 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>scribe</string>
</array>
<key>CFBundleURLName</key>
<string>be.scri.scribe</string>
</dict>
</array>
</dict>
</plist>
Loading