spiegel-keyman/oem/firstvoices/ios/FirstVoices/KeyboardTableController.swift

155 lines
5.3 KiB
Swift

/*
* KeyboardTableController.swift
* FirstVoices app
*
* License: MIT
*
* Copyright © 2022 FirstVoices.
*
* Created by Shawn Schantz on 2022-01-13.
*
* The main screen of the app containing the list (UITableView) of FirstVoices keyboards.
* From here, users can tap on a keyboard which will cause it to transition to a detail page for that keyboard, or
* they can tap on the info icon for a keyboard which will load the help web page for the keyboard in the browser.
*
*/
import UIKit
let keymanHelpSite: String = "https://help.keyman.com/keyboard/"
/*
* define protocol so that KeyboardDetailController can send message to update state of checkmark in keyboard list
*/
protocol RefreshKeyboardCheckmark {
func refreshCheckmark()
}
class KeyboardTableController: UIViewController, RefreshKeyboardCheckmark {
var settingsRepo = KeyboardSettingsRepository.shared
/*
* mark the row to be reloaded after return segue -- it can be reloaded immediately
* when the state changes because it is outside the view hierachy until the user
* navigates back
*/
func refreshCheckmark() {
self.rowToReload = self.selectedKeyboardIndex
}
@IBOutlet weak var tableView: UITableView!
var selectedKeyboardIndex: IndexPath = IndexPath(row: 0, section: 0)
private var _keyboardList: FVRegionList!
private var keyboardList: FVRegionList {
get {
if _keyboardList == nil {
_keyboardList = FVRegionStorage.load()
}
return _keyboardList!
}
}
private var rowToReload: IndexPath? = nil
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController!.isNavigationBarHidden = false
navigationController?.setToolbarHidden(true, animated: false)
}
/*
* Needed to override to add the checkmark to the keyboard that has just been made active. Cannot call reloadRows before the view appears because it causes layout.
*/
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if(rowToReload != nil) {
let rows: [IndexPath] = [rowToReload!]
self.tableView.reloadRows(at: rows, with: UITableView.RowAnimation.none)
self.rowToReload = nil;
}
}
/*
* Segue to keyboard details screen.
* Before the segue, call the details view controller and pass the state of the keyboard and
* a reference to self to be called back to update the row if the state changes.
*/
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "keyboardDetails" {
let detailsController = segue.destination as! KeyboardDetailController
let indexPath = self.tableView.indexPathForSelectedRow
let keyboards = (self.keyboardList[indexPath!.section]).keyboards
let keyboard = keyboards[indexPath!.row]
if let keyboardState: KeyboardState = settingsRepo.loadKeyboardState(keyboardId: keyboard.id) {
detailsController.configure(delegate: self, keyboard: keyboardState)
} else {
print("Could not find keyboard \(keyboard.id) in available keyboards list.")
}
}
}
// TODO: stop using deprecated openURL method when we upgrade to iOS 10 or later
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
let keyboards: FVKeyboardList = (self.keyboardList[indexPath.section]).keyboards
let keyboard: FVKeyboard = keyboards[indexPath.row]
let helpUrl: URL = URL.init(string: "\(keymanHelpSite)\(keyboard.id)")!
UIApplication.shared.openURL(helpUrl)
}
func reportFatalError(message: String) {
let alertController = UIAlertController(title: title, message: message,
preferredStyle: UIAlertController.Style.alert)
alertController.addAction(UIAlertAction(title: "OK",
style: UIAlertAction.Style.cancel,
handler: nil))
self.present(alertController, animated: true, completion: nil)
print(message)
// TODO: send the error message + call stack through to us
// some reporting mechanism
}
}
extension KeyboardTableController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return self.keyboardList.count
}
func tableView(_ tableView: UITableView,
titleForHeaderInSection section: Int) -> String? {
return self.keyboardList[section].name
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedKeyboardIndex = indexPath
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.keyboardList[section].keyboards.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let keyboards = (self.keyboardList[indexPath.section]).keyboards
let keyboard = keyboards[indexPath.row]
let keyboardState = settingsRepo.loadKeyboardState(keyboardId: keyboard.id)
let cell = tableView.dequeueReusableCell(withIdentifier: "KeyboardCell")
cell!.textLabel!.text = keyboardState?.name
cell!.imageView?.isHidden = !keyboardState!.isActive
return cell!
}
}