Format code with SwiftFormat automatically in every build
This commit is contained in:
parent
f167ab7549
commit
7f9f0e43b2
100 changed files with 1124 additions and 1063 deletions
|
|
@ -6,11 +6,10 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
||||
|
||||
private static let VALUE_NOT_AVAILABLE = "ValueNotAvailable".localize()
|
||||
|
||||
private var needRefresh = false
|
||||
|
|
@ -18,6 +17,7 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
let indicator = UIActivityIndicatorView(style: .gray)
|
||||
return indicator
|
||||
}()
|
||||
|
||||
private let passwordStore = PasswordStore.shared
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
|
@ -41,10 +41,9 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
}
|
||||
|
||||
private func setTableData() {
|
||||
|
||||
// clear current contents (if any)
|
||||
self.tableData.removeAll(keepingCapacity: true)
|
||||
self.tableView.reloadData()
|
||||
tableData.removeAll(keepingCapacity: true)
|
||||
tableView.reloadData()
|
||||
indicator.startAnimating()
|
||||
|
||||
// reload the table
|
||||
|
|
@ -67,8 +66,7 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "LocalCommits".localize(), .detailText: localCommits],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "LastSynced".localize(), .detailText: lastSynced],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Commits".localize(), .detailText: commits],
|
||||
[.title: "CommitLogs".localize(), .action: "segue", .link: "showCommitLogsSegue"],
|
||||
],
|
||||
[.title: "CommitLogs".localize(), .action: "segue", .link: "showCommitLogsSegue"]],
|
||||
]
|
||||
strongSelf.indicator.stopAnimating()
|
||||
strongSelf.tableView.reloadData()
|
||||
|
|
@ -79,15 +77,15 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
private func numberOfPasswordsString() -> String {
|
||||
let formatter = NumberFormatter()
|
||||
formatter.numberStyle = NumberFormatter.Style.decimal
|
||||
return formatter.string(from: NSNumber(value: self.passwordStore.numberOfPasswords)) ?? ""
|
||||
return formatter.string(from: NSNumber(value: passwordStore.numberOfPasswords)) ?? ""
|
||||
}
|
||||
|
||||
private func sizeOfRepositoryString() -> String {
|
||||
return ByteCountFormatter.string(fromByteCount: Int64(self.passwordStore.sizeOfRepositoryByteCount), countStyle: ByteCountFormatter.CountStyle.file)
|
||||
ByteCountFormatter.string(fromByteCount: Int64(passwordStore.sizeOfRepositoryByteCount), countStyle: ByteCountFormatter.CountStyle.file)
|
||||
}
|
||||
|
||||
private func lastSyncedTimeString() -> String {
|
||||
guard let date = self.passwordStore.lastSyncedTime else {
|
||||
guard let date = passwordStore.lastSyncedTime else {
|
||||
return "SyncAgain?".localize()
|
||||
}
|
||||
let formatter = DateFormatter()
|
||||
|
|
@ -103,7 +101,8 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
return AboutRepositoryTableViewController.VALUE_NOT_AVAILABLE
|
||||
}
|
||||
|
||||
@objc func setNeedRefresh() {
|
||||
@objc
|
||||
func setNeedRefresh() {
|
||||
needRefresh = true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,17 +9,16 @@
|
|||
import UIKit
|
||||
|
||||
class AboutTableViewController: BasicStaticTableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
tableData = [
|
||||
// section 0
|
||||
[[.title: "Website".localize(), .action: "link", .link: "https://github.com/mssun/pass-ios.git"],
|
||||
[.title: "Help".localize(), .action: "link", .link: "https://github.com/mssun/passforios/wiki"],
|
||||
[.title: "ContactDeveloper".localize(), .action: "link", .link: "mailto:developer@passforios.mssun.me?subject=Pass%20for%20iOS"],],
|
||||
[.title: "ContactDeveloper".localize(), .action: "link", .link: "mailto:developer@passforios.mssun.me?subject=Pass%20for%20iOS"]],
|
||||
|
||||
// section 1,
|
||||
[[.title: "OpenSourceComponents".localize(), .action: "segue", .link: "showOpenSourceComponentsSegue"],
|
||||
[.title: "SpecialThanks".localize(), .action: "segue", .link: "showSpecialThanksSegue"],],
|
||||
[.title: "SpecialThanks".localize(), .action: "segue", .link: "showSpecialThanksSegue"]],
|
||||
]
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
|
@ -39,11 +38,10 @@ class AboutTableViewController: BasicStaticTableViewController {
|
|||
return nil
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if section == 1 {
|
||||
return "Acknowledgements".localize().uppercased()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class AddPasswordTableViewController: PasswordEditorTableViewController {
|
||||
var defaultDirPrefix = ""
|
||||
|
|
@ -17,7 +17,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController {
|
|||
tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix
|
||||
}
|
||||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender _: Any?) -> Bool {
|
||||
if identifier == "saveAddPasswordSegue" {
|
||||
// check PGP key
|
||||
guard PGPAgent.shared.isPrepared else {
|
||||
|
|
|
|||
|
|
@ -6,16 +6,15 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
class AdvancedSettingsTableViewController: UITableViewController {
|
||||
|
||||
@IBOutlet weak var encryptInASCIIArmoredTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var gitSignatureTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var eraseDataTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var discardChangesTableViewCell: UITableViewCell!
|
||||
@IBOutlet var encryptInASCIIArmoredTableViewCell: UITableViewCell!
|
||||
@IBOutlet var gitSignatureTableViewCell: UITableViewCell!
|
||||
@IBOutlet var eraseDataTableViewCell: UITableViewCell!
|
||||
@IBOutlet var discardChangesTableViewCell: UITableViewCell!
|
||||
let passwordStore = PasswordStore.shared
|
||||
|
||||
let encryptInASCIIArmoredSwitch: UISwitch = {
|
||||
|
|
@ -37,10 +36,10 @@ class AdvancedSettingsTableViewController: UITableViewController {
|
|||
private func setGitSignatureText() {
|
||||
let gitSignatureName = passwordStore.gitSignatureForNow?.name ?? ""
|
||||
let gitSignatureEmail = passwordStore.gitSignatureForNow?.email ?? ""
|
||||
self.gitSignatureTableViewCell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
|
||||
self.gitSignatureTableViewCell.detailTextLabel?.text = "\(gitSignatureName) <\(gitSignatureEmail)>"
|
||||
if Defaults.gitSignatureName == nil && Defaults.gitSignatureEmail == nil {
|
||||
self.gitSignatureTableViewCell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
gitSignatureTableViewCell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
|
||||
gitSignatureTableViewCell.detailTextLabel?.text = "\(gitSignatureName) <\(gitSignatureEmail)>"
|
||||
if Defaults.gitSignatureName == nil, Defaults.gitSignatureEmail == nil {
|
||||
gitSignatureTableViewCell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
gitSignatureTableViewCell.detailTextLabel?.text = "NotSet".localize()
|
||||
}
|
||||
}
|
||||
|
|
@ -49,7 +48,7 @@ class AdvancedSettingsTableViewController: UITableViewController {
|
|||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
if tableView.cellForRow(at: indexPath) == eraseDataTableViewCell {
|
||||
let alert = UIAlertController(title: "ErasePasswordStoreData?".localize(), message: "EraseExplanation.".localize(), preferredStyle: UIAlertController.Style.alert)
|
||||
alert.addAction(UIAlertAction(title: "ErasePasswordStoreData".localize(), style: UIAlertAction.Style.destructive, handler: {[unowned self] (action) -> Void in
|
||||
alert.addAction(UIAlertAction(title: "ErasePasswordStoreData".localize(), style: UIAlertAction.Style.destructive, handler: { [unowned self] (_) -> Void in
|
||||
SVProgressHUD.show(withStatus: "Erasing...".localize())
|
||||
self.passwordStore.erase()
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
|
|
@ -57,10 +56,10 @@ class AdvancedSettingsTableViewController: UITableViewController {
|
|||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
}))
|
||||
alert.addAction(UIAlertAction.dismiss())
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
} else if tableView.cellForRow(at: indexPath) == discardChangesTableViewCell {
|
||||
let alert = UIAlertController(title: "DiscardAllLocalChanges?".localize(), message: "DiscardExplanation.".localize(), preferredStyle: UIAlertController.Style.alert)
|
||||
alert.addAction(UIAlertAction(title: "DiscardAllLocalChanges".localize(), style: UIAlertAction.Style.destructive, handler: {[unowned self] (action) -> Void in
|
||||
alert.addAction(UIAlertAction(title: "DiscardAllLocalChanges".localize(), style: UIAlertAction.Style.destructive, handler: { [unowned self] (_) -> Void in
|
||||
SVProgressHUD.show(withStatus: "Resetting...".localize())
|
||||
do {
|
||||
let numberDiscarded = try self.passwordStore.reset()
|
||||
|
|
@ -73,15 +72,17 @@ class AdvancedSettingsTableViewController: UITableViewController {
|
|||
|
||||
}))
|
||||
alert.addAction(UIAlertAction.dismiss())
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func encryptInASCIIArmoredAction(_ sender: Any?) {
|
||||
@objc
|
||||
func encryptInASCIIArmoredAction(_: Any?) {
|
||||
Defaults.encryptInArmored = encryptInASCIIArmoredSwitch.isOn
|
||||
}
|
||||
|
||||
@IBAction func saveGitConfigSetting(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
func saveGitConfigSetting(segue: UIStoryboardSegue) {
|
||||
if let controller = segue.source as? GitConfigSettingsTableViewController {
|
||||
if let gitSignatureName = controller.nameTextField.text,
|
||||
let gitSignatureEmail = controller.emailTextField.text {
|
||||
|
|
@ -91,5 +92,4 @@ class AdvancedSettingsTableViewController: UITableViewController {
|
|||
setGitSignatureText()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import MessageUI
|
||||
import passKit
|
||||
|
||||
import SafariServices
|
||||
import UIKit
|
||||
|
||||
enum CellDataType {
|
||||
case link, segue, empty, detail
|
||||
|
|
@ -25,7 +24,7 @@ enum CellDataKey {
|
|||
}
|
||||
|
||||
class BasicStaticTableViewController: UITableViewController, MFMailComposeViewControllerDelegate {
|
||||
var tableData = [[Dictionary<CellDataKey, Any>]]()
|
||||
var tableData = [[[CellDataKey: Any]]]()
|
||||
var navigationItemTitle: String?
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
|
@ -35,12 +34,12 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
}
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return tableData.count
|
||||
override func numberOfSections(in _: UITableView) -> Int {
|
||||
tableData.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return tableData[section].count
|
||||
override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
tableData[section].count
|
||||
}
|
||||
|
||||
override func didReceiveMemoryWarning() {
|
||||
|
|
@ -48,8 +47,7 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
||||
override func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cellData = tableData[indexPath.section][indexPath.row]
|
||||
let cellDataStyle = cellData[CellDataKey.style] as? CellDataStyle
|
||||
var cell: UITableViewCell?
|
||||
|
|
@ -76,7 +74,7 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
return cell ?? UITableViewCell()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||
override func tableView(_: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||
let cellData = tableData[indexPath.section][indexPath.row]
|
||||
let selector = cellData[CellDataKey.detailDisclosureAction] as? Selector
|
||||
perform(selector, with: cellData[CellDataKey.detailDisclosureData])
|
||||
|
|
@ -108,7 +106,7 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
}
|
||||
case "http", "https":
|
||||
let svc = SFSafariViewController(url: URL(string: link)!, entersReaderIfAvailable: false)
|
||||
self.present(svc, animated: true, completion: nil)
|
||||
present(svc, animated: true, completion: nil)
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
@ -123,10 +121,10 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
mailVC.setToRecipients(recipients)
|
||||
mailVC.setSubject(subject)
|
||||
mailVC.setMessageBody("", isHTML: false)
|
||||
self.present(mailVC, animated: true, completion: nil)
|
||||
present(mailVC, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith _: MFMailComposeResult, error _: Error?) {
|
||||
controller.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import ObjectiveGit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class CommitLogsTableViewController: UITableViewController {
|
||||
var commits: [GTCommit] = []
|
||||
|
|
@ -18,12 +18,12 @@ class CommitLogsTableViewController: UITableViewController {
|
|||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(updateCommitLogs), name: .passwordStoreUpdated, object: nil)
|
||||
commits = getCommitLogs()
|
||||
self.tableView.estimatedRowHeight = 50
|
||||
self.tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.estimatedRowHeight = 50
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return commits.count
|
||||
override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
|
||||
commits.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
|
@ -42,7 +42,8 @@ class CommitLogsTableViewController: UITableViewController {
|
|||
return cell
|
||||
}
|
||||
|
||||
@objc func updateCommitLogs() {
|
||||
@objc
|
||||
func updateCommitLogs() {
|
||||
commits = getCommitLogs()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class EditPasswordTableViewController: PasswordEditorTableViewController {
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender _: Any?) -> Bool {
|
||||
if identifier == "saveEditPasswordSegue" {
|
||||
// check name
|
||||
guard checkName() else {
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
||||
let passwordStore = PasswordStore.shared
|
||||
|
|
@ -67,37 +67,35 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
|||
override func viewDidLoad() {
|
||||
tableData = [
|
||||
// section 0
|
||||
[[.title: "AboutRepository".localize(), .action: "segue", .link: "showAboutRepositorySegue"],],
|
||||
[[.title: "AboutRepository".localize(), .action: "segue", .link: "showAboutRepositorySegue"]],
|
||||
|
||||
// section 1
|
||||
[
|
||||
[.title: "RememberPgpKeyPassphrase".localize(), .action: "none",],
|
||||
[.title: "RememberGitCredentialPassphrase".localize(), .action: "none",],
|
||||
[.title: "RememberPgpKeyPassphrase".localize(), .action: "none"],
|
||||
[.title: "RememberGitCredentialPassphrase".localize(), .action: "none"],
|
||||
],
|
||||
|
||||
|
||||
// section 2
|
||||
[
|
||||
[.title: "ShowFolders".localize(), .action: "none",],
|
||||
[.title: "HidePasswordImages".localize(), .action: "none",],
|
||||
[.title: "HideUnknownFields".localize(), .action: "none",],
|
||||
[.title: "HideOtpFields".localize(), .action: "none",],
|
||||
[.title: "ShowFolders".localize(), .action: "none"],
|
||||
[.title: "HidePasswordImages".localize(), .action: "none"],
|
||||
[.title: "HideUnknownFields".localize(), .action: "none"],
|
||||
[.title: "HideOtpFields".localize(), .action: "none"],
|
||||
],
|
||||
|
||||
]
|
||||
super.viewDidLoad()
|
||||
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = super.tableView(tableView, cellForRowAt: indexPath)
|
||||
let cell = super.tableView(tableView, cellForRowAt: indexPath)
|
||||
switch cell.textLabel!.text! {
|
||||
case "HideUnknownFields".localize():
|
||||
cell.accessoryType = .none
|
||||
let detailButton = UIButton(type: .detailDisclosure)
|
||||
hideUnknownSwitch.frame = CGRect(x: detailButton.bounds.width+10, y: 0, width: hideUnknownSwitch.bounds.width, height: hideUnknownSwitch.bounds.height)
|
||||
hideUnknownSwitch.frame = CGRect(x: detailButton.bounds.width + 10, y: 0, width: hideUnknownSwitch.bounds.width, height: hideUnknownSwitch.bounds.height)
|
||||
detailButton.frame = CGRect(x: 0, y: 5, width: detailButton.bounds.width, height: detailButton.bounds.height)
|
||||
detailButton.addTarget(self, action: #selector(GeneralSettingsTableViewController.tapHideUnknownSwitchDetailButton(_:)), for: UIControl.Event.touchDown)
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hideUnknownSwitch.bounds.width+10, height: hideUnknownSwitch.bounds.height))
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hideUnknownSwitch.bounds.width + 10, height: hideUnknownSwitch.bounds.height))
|
||||
accessoryView.addSubview(detailButton)
|
||||
accessoryView.addSubview(hideUnknownSwitch)
|
||||
cell.accessoryView = accessoryView
|
||||
|
|
@ -106,10 +104,10 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
|||
case "HideOtpFields".localize():
|
||||
cell.accessoryType = .none
|
||||
let detailButton = UIButton(type: .detailDisclosure)
|
||||
hideOTPSwitch.frame = CGRect(x: detailButton.bounds.width+10, y: 0, width: hideOTPSwitch.bounds.width, height: hideOTPSwitch.bounds.height)
|
||||
hideOTPSwitch.frame = CGRect(x: detailButton.bounds.width + 10, y: 0, width: hideOTPSwitch.bounds.width, height: hideOTPSwitch.bounds.height)
|
||||
detailButton.frame = CGRect(x: 0, y: 5, width: detailButton.bounds.width, height: detailButton.bounds.height)
|
||||
detailButton.addTarget(self, action: #selector(GeneralSettingsTableViewController.tapHideOTPSwitchDetailButton(_:)), for: UIControl.Event.touchDown)
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hideOTPSwitch.bounds.width+10, height: hideOTPSwitch.bounds.height))
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hideOTPSwitch.bounds.width + 10, height: hideOTPSwitch.bounds.height))
|
||||
accessoryView.addSubview(detailButton)
|
||||
accessoryView.addSubview(hideOTPSwitch)
|
||||
cell.accessoryView = accessoryView
|
||||
|
|
@ -130,10 +128,10 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
|||
case "HidePasswordImages".localize():
|
||||
cell.accessoryType = .none
|
||||
let detailButton = UIButton(type: .detailDisclosure)
|
||||
hidePasswordImagesSwitch.frame = CGRect(x: detailButton.bounds.width+10, y: 0, width: hidePasswordImagesSwitch.bounds.width, height: hidePasswordImagesSwitch.bounds.height)
|
||||
hidePasswordImagesSwitch.frame = CGRect(x: detailButton.bounds.width + 10, y: 0, width: hidePasswordImagesSwitch.bounds.width, height: hidePasswordImagesSwitch.bounds.height)
|
||||
detailButton.frame = CGRect(x: 0, y: 5, width: detailButton.bounds.width, height: detailButton.bounds.height)
|
||||
detailButton.addTarget(self, action: #selector(GeneralSettingsTableViewController.tapHidePasswordImagesSwitchDetailButton(_:)), for: UIControl.Event.touchDown)
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hidePasswordImagesSwitch.bounds.width+10, height: hidePasswordImagesSwitch.bounds.height))
|
||||
let accessoryView = UIView(frame: CGRect(x: 0, y: 0, width: detailButton.bounds.width + hidePasswordImagesSwitch.bounds.width + 10, height: hidePasswordImagesSwitch.bounds.height))
|
||||
accessoryView.addSubview(detailButton)
|
||||
accessoryView.addSubview(hidePasswordImagesSwitch)
|
||||
cell.accessoryView = accessoryView
|
||||
|
|
@ -144,43 +142,50 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
|||
return cell
|
||||
}
|
||||
|
||||
@objc func tapHideUnknownSwitchDetailButton(_ sender: Any?) {
|
||||
@objc
|
||||
func tapHideUnknownSwitchDetailButton(_: Any?) {
|
||||
let alertMessage = "HideUnknownFieldsExplanation.".localize()
|
||||
let alertTitle = "HideUnknownFields".localize()
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
||||
}
|
||||
|
||||
@objc func tapHideOTPSwitchDetailButton(_ sender: Any?) {
|
||||
@objc
|
||||
func tapHideOTPSwitchDetailButton(_: Any?) {
|
||||
let keywordsString = Constants.OTP_KEYWORDS.joined(separator: ", ")
|
||||
let alertMessage = "HideOtpFieldsExplanation.".localize(keywordsString)
|
||||
let alertTitle = "HideOtpFields".localize()
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
||||
}
|
||||
|
||||
@objc func tapHidePasswordImagesSwitchDetailButton(_ sender: Any?) {
|
||||
@objc
|
||||
func tapHidePasswordImagesSwitchDetailButton(_: Any?) {
|
||||
let alertMessage = "HidePasswordImagesExplanation.".localize()
|
||||
let alertTitle = "HidePasswordImages".localize()
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
||||
}
|
||||
|
||||
@objc func hideUnknownSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func hideUnknownSwitchAction(_: Any?) {
|
||||
Defaults.isHideUnknownOn = hideUnknownSwitch.isOn
|
||||
NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil)
|
||||
}
|
||||
|
||||
@objc func hideOTPSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func hideOTPSwitchAction(_: Any?) {
|
||||
Defaults.isHideOTPOn = hideOTPSwitch.isOn
|
||||
NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil)
|
||||
}
|
||||
|
||||
@objc func rememberPGPPassphraseSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func rememberPGPPassphraseSwitchAction(_: Any?) {
|
||||
Defaults.isRememberPGPPassphraseOn = rememberPGPPassphraseSwitch.isOn
|
||||
if rememberPGPPassphraseSwitch.isOn == false {
|
||||
AppKeychain.shared.removeAllContent(withPrefix: Globals.pgpKeyPassphrase)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func rememberGitCredentialPassphraseSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func rememberGitCredentialPassphraseSwitchAction(_: Any?) {
|
||||
Defaults.isRememberGitCredentialPassphraseOn = rememberGitCredentialPassphraseSwitch.isOn
|
||||
if rememberGitCredentialPassphraseSwitch.isOn == false {
|
||||
passwordStore.gitSSHPrivateKeyPassphrase = nil
|
||||
|
|
@ -188,14 +193,15 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@objc func showFolderSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func showFolderSwitchAction(_: Any?) {
|
||||
Defaults.isShowFolderOn = showFolderSwitch.isOn
|
||||
NotificationCenter.default.post(name: .passwordDisplaySettingChanged, object: nil)
|
||||
}
|
||||
|
||||
@objc func hidePasswordImagesSwitchAction(_ sender: Any?) {
|
||||
@objc
|
||||
func hidePasswordImagesSwitchAction(_: Any?) {
|
||||
Defaults.isHidePasswordImagesOn = hidePasswordImagesSwitch.isOn
|
||||
NotificationCenter.default.post(name: .passwordDetailDisplaySettingChanged, object: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
// Copyright © 2017 Yishi Lin. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class GitConfigSettingsTableViewController: UITableViewController {
|
||||
let passwordStore = PasswordStore.shared
|
||||
|
||||
@IBOutlet weak var nameTextField: UITextField!
|
||||
@IBOutlet weak var emailTextField: UITextField!
|
||||
@IBOutlet var nameTextField: UITextField!
|
||||
@IBOutlet var emailTextField: UITextField!
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
|
@ -26,7 +26,7 @@ class GitConfigSettingsTableViewController: UITableViewController {
|
|||
emailTextField.text = Defaults.gitSignatureEmail
|
||||
}
|
||||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender _: Any?) -> Bool {
|
||||
if identifier == "saveGitConfigSettingSegue" {
|
||||
let name = nameTextField.text!.isEmpty ? Globals.gitSignatureDefaultName : nameTextField.text!
|
||||
let email = emailTextField.text!.isEmpty ? Globals.gitSignatureDefaultEmail : nameTextField.text!
|
||||
|
|
@ -38,4 +38,3 @@ class GitConfigSettingsTableViewController: UITableViewController {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,21 +6,20 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
class GitRepositorySettingsTableViewController: UITableViewController {
|
||||
// MARK: - View Outlet
|
||||
|
||||
@IBOutlet weak var gitURLTextField: UITextField!
|
||||
@IBOutlet weak var usernameTextField: UITextField!
|
||||
@IBOutlet weak var branchNameTextField: UITextField!
|
||||
@IBOutlet weak var authSSHKeyCell: UITableViewCell!
|
||||
@IBOutlet weak var authPasswordCell: UITableViewCell!
|
||||
@IBOutlet weak var gitURLCell: UITableViewCell!
|
||||
@IBOutlet weak var gitRepositoryURLTabelViewCell: UITableViewCell!
|
||||
@IBOutlet var gitURLTextField: UITextField!
|
||||
@IBOutlet var usernameTextField: UITextField!
|
||||
@IBOutlet var branchNameTextField: UITextField!
|
||||
@IBOutlet var authSSHKeyCell: UITableViewCell!
|
||||
@IBOutlet var authPasswordCell: UITableViewCell!
|
||||
@IBOutlet var gitURLCell: UITableViewCell!
|
||||
@IBOutlet var gitRepositoryURLTabelViewCell: UITableViewCell!
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
|
|
@ -33,27 +32,29 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
updateAuthenticationMethodCheckView(for: newValue)
|
||||
}
|
||||
}
|
||||
|
||||
private var gitUrl: URL {
|
||||
get { Defaults.gitURL }
|
||||
set { Defaults.gitURL = newValue }
|
||||
}
|
||||
|
||||
private var gitBranchName: String {
|
||||
get { Defaults.gitBranchName }
|
||||
set { Defaults.gitBranchName = newValue }
|
||||
}
|
||||
|
||||
private var gitUsername: String {
|
||||
get { Defaults.gitUsername }
|
||||
set { Defaults.gitUsername = newValue }
|
||||
}
|
||||
|
||||
private var gitCredential: GitCredential {
|
||||
get {
|
||||
switch Defaults.gitAuthenticationMethod {
|
||||
case .password:
|
||||
return GitCredential(credential: .http(userName: Defaults.gitUsername))
|
||||
case .key:
|
||||
let privateKey: String = AppKeychain.shared.get(for: SshKey.PRIVATE.getKeychainKey()) ?? ""
|
||||
return GitCredential(credential: .ssh(userName: Defaults.gitUsername, privateKey: privateKey))
|
||||
}
|
||||
switch Defaults.gitAuthenticationMethod {
|
||||
case .password:
|
||||
return GitCredential(credential: .http(userName: Defaults.gitUsername))
|
||||
case .key:
|
||||
let privateKey: String = AppKeychain.shared.get(for: SshKey.PRIVATE.getKeychainKey()) ?? ""
|
||||
return GitCredential(credential: .ssh(userName: Defaults.gitUsername, privateKey: privateKey))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,9 +62,9 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
gitURLTextField.text = self.gitUrl.absoluteString
|
||||
usernameTextField.text = self.gitUsername
|
||||
branchNameTextField.text = self.gitBranchName
|
||||
gitURLTextField.text = gitUrl.absoluteString
|
||||
usernameTextField.text = gitUsername
|
||||
branchNameTextField.text = gitBranchName
|
||||
sshLabel = authSSHKeyCell.subviews[0].subviews[0] as? UILabel
|
||||
authSSHKeyCell.accessoryType = .detailButton
|
||||
}
|
||||
|
|
@ -94,7 +95,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
if cell == authPasswordCell {
|
||||
self.gitAuthenticationMethod = .password
|
||||
gitAuthenticationMethod = .password
|
||||
} else if cell == authSSHKeyCell {
|
||||
if !AppKeychain.shared.contains(key: SshKey.PRIVATE.getKeychainKey()) {
|
||||
Utils.alert(title: "CannotSelectSshKey".localize(), message: "PleaseSetupSshKeyFirst.".localize(), controller: self)
|
||||
|
|
@ -108,7 +109,8 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
|
||||
// MARK: - Segue Handlers
|
||||
|
||||
@IBAction func save(_ sender: Any) {
|
||||
@IBAction
|
||||
func save(_: Any) {
|
||||
guard let gitURLTextFieldText = gitURLTextField.text, let gitURL = URL(string: gitURLTextFieldText.trimmed) else {
|
||||
Utils.alert(title: "CannotSave".localize(), message: "SetGitRepositoryUrl".localize(), controller: self)
|
||||
return
|
||||
|
|
@ -137,9 +139,9 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
self.gitUrl = gitURL
|
||||
self.gitBranchName = branchName.trimmed
|
||||
self.gitUsername = (gitURL.user ?? usernameTextField.text ?? "git").trimmed
|
||||
gitUrl = gitURL
|
||||
gitBranchName = branchName.trimmed
|
||||
gitUsername = (gitURL.user ?? usernameTextField.text ?? "git").trimmed
|
||||
|
||||
if passwordStore.repositoryExists() {
|
||||
let overwriteAlert: UIAlertController = {
|
||||
|
|
@ -150,7 +152,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
alert.addAction(UIAlertAction.cancel())
|
||||
return alert
|
||||
}()
|
||||
self.present(overwriteAlert, animated: true)
|
||||
present(overwriteAlert, animated: true)
|
||||
} else {
|
||||
cloneAndSegueIfSuccess()
|
||||
}
|
||||
|
|
@ -159,15 +161,15 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
private func cloneAndSegueIfSuccess() {
|
||||
// Remember git credential password/passphrase temporarily, ask whether users want this after a successful clone.
|
||||
Defaults.isRememberGitCredentialPassphraseOn = true
|
||||
DispatchQueue.global(qos: .userInitiated).async() {
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
do {
|
||||
let transferProgressBlock: (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void = { (git_transfer_progress, _) in
|
||||
let transferProgressBlock: (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void = { git_transfer_progress, _ in
|
||||
let gitTransferProgress = git_transfer_progress.pointee
|
||||
let progress = Float(gitTransferProgress.received_objects) / Float(gitTransferProgress.total_objects)
|
||||
SVProgressHUD.showProgress(progress, status: "Cloning Remote Repository")
|
||||
}
|
||||
|
||||
let checkoutProgressBlock: (String, UInt, UInt) -> Void = { (_, completedSteps, totalSteps) in
|
||||
let checkoutProgressBlock: (String, UInt, UInt) -> Void = { _, completedSteps, totalSteps in
|
||||
let progress = Float(completedSteps) / Float(totalSteps)
|
||||
SVProgressHUD.showProgress(progress, status: "CheckingOutBranch".localize(self.gitBranchName))
|
||||
}
|
||||
|
|
@ -179,7 +181,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
transferProgressBlock: transferProgressBlock,
|
||||
checkoutProgressBlock: checkoutProgressBlock)
|
||||
|
||||
SVProgressHUD.dismiss() {
|
||||
SVProgressHUD.dismiss {
|
||||
let savePassphraseAlert: UIAlertController = {
|
||||
let alert = UIAlertController(title: "Done".localize(), message: "WantToSaveGitCredential?".localize(), preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction(title: "No".localize(), style: .default) { _ in
|
||||
|
|
@ -188,7 +190,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
self.passwordStore.gitSSHPrivateKeyPassphrase = nil
|
||||
self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self)
|
||||
})
|
||||
alert.addAction(UIAlertAction(title: "Yes".localize(), style: .destructive) {_ in
|
||||
alert.addAction(UIAlertAction(title: "Yes".localize(), style: .destructive) { _ in
|
||||
Defaults.isRememberGitCredentialPassphraseOn = true
|
||||
self.performSegue(withIdentifier: "saveGitServerSettingSegue", sender: self)
|
||||
})
|
||||
|
|
@ -199,7 +201,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
} catch {
|
||||
SVProgressHUD.dismiss() {
|
||||
SVProgressHUD.dismiss {
|
||||
let error = error as NSError
|
||||
var message = error.localizedDescription
|
||||
if let underlyingError = error.userInfo[NSUnderlyingErrorKey] as? NSError {
|
||||
|
|
@ -213,7 +215,8 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction func importSSHKey(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
func importSSHKey(segue: UIStoryboardSegue) {
|
||||
guard let sourceController = segue.source as? KeyImporter, sourceController.isReadyToUse() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -278,7 +281,7 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
}
|
||||
|
||||
private func requestCredentialPassword(credential: GitCredential.Credential, lastPassword: String?) -> String? {
|
||||
return requestGitCredentialPassword(credential: credential, lastPassword: lastPassword, controller: self)
|
||||
requestGitCredentialPassword(credential: credential, lastPassword: lastPassword, controller: self)
|
||||
}
|
||||
|
||||
private func updateAuthenticationMethodCheckView(for method: GitAuthenticationMethod) {
|
||||
|
|
@ -297,21 +300,20 @@ class GitRepositorySettingsTableViewController: UITableViewController {
|
|||
|
||||
private func showGitURLFormatHelp() {
|
||||
let message = """
|
||||
https://example.com[:port]/project.git
|
||||
ssh://[user@]server[:port]/project.git
|
||||
[user@]server:project.git (no scheme)
|
||||
"""
|
||||
https://example.com[:port]/project.git
|
||||
ssh://[user@]server[:port]/project.git
|
||||
[user@]server:project.git (no scheme)
|
||||
"""
|
||||
Utils.alert(title: "Git URL Format", message: message, controller: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension GitRepositorySettingsTableViewController: KeyImporter {
|
||||
|
||||
static let keySource = KeySource.itunes
|
||||
static let label = "ITunesFileSharing".localize()
|
||||
|
||||
func isReadyToUse() -> Bool {
|
||||
return KeyFileManager.PrivateSsh.doesKeyFileExist()
|
||||
KeyFileManager.PrivateSsh.doesKeyFileExist()
|
||||
}
|
||||
|
||||
func importKeys() throws {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@
|
|||
import passKit
|
||||
|
||||
protocol KeyImporter {
|
||||
|
||||
static var keySource: KeySource { get }
|
||||
|
||||
static var label: String { get }
|
||||
|
|
@ -24,9 +23,8 @@ protocol KeyImporter {
|
|||
}
|
||||
|
||||
extension KeyImporter {
|
||||
|
||||
static var isCurrentKeySource: Bool {
|
||||
return Defaults.gitSSHKeySource == Self.keySource
|
||||
Defaults.gitSSHKeySource == Self.keySource
|
||||
}
|
||||
|
||||
static var menuLabel: String {
|
||||
|
|
|
|||
|
|
@ -6,11 +6,10 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import UIKit
|
||||
|
||||
class OpenSourceComponentsTableViewController: BasicStaticTableViewController {
|
||||
|
||||
private static let openSourceComponents = [
|
||||
["FavIcon",
|
||||
"https://github.com/bitserf/FavIcon",
|
||||
|
|
@ -48,12 +47,13 @@ class OpenSourceComponentsTableViewController: BasicStaticTableViewController {
|
|||
.link: item[1],
|
||||
.accessoryType: UITableViewCell.AccessoryType.detailDisclosureButton,
|
||||
.detailDisclosureAction: #selector(actOnDetailDisclosureButton(_:)),
|
||||
.detailDisclosureData: item[2]
|
||||
.detailDisclosureData: item[2],
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
@objc func actOnDetailDisclosureButton(_ sender: Any?) {
|
||||
@objc
|
||||
func actOnDetailDisclosureButton(_ sender: Any?) {
|
||||
if let link = sender as? String, let url = URL(string: link) {
|
||||
let svc = SFSafariViewController(url: url, entersReaderIfAvailable: false)
|
||||
present(svc, animated: true)
|
||||
|
|
|
|||
|
|
@ -6,15 +6,14 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController, UITextViewDelegate, QRScannerControllerDelegate {
|
||||
|
||||
@IBOutlet weak var armorPublicKeyTextView: UITextView!
|
||||
@IBOutlet weak var armorPrivateKeyTextView: UITextView!
|
||||
@IBOutlet weak var scanPublicKeyCell: UITableViewCell!
|
||||
@IBOutlet weak var scanPrivateKeyCell: UITableViewCell!
|
||||
@IBOutlet var armorPublicKeyTextView: UITextView!
|
||||
@IBOutlet var armorPrivateKeyTextView: UITextView!
|
||||
@IBOutlet var scanPublicKeyCell: UITableViewCell!
|
||||
@IBOutlet var scanPrivateKeyCell: UITableViewCell!
|
||||
|
||||
var armorPublicKey: String?
|
||||
var armorPrivateKey: String?
|
||||
|
|
@ -23,45 +22,47 @@ class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
enum KeyType {
|
||||
case publicKey, privateKey
|
||||
}
|
||||
|
||||
var keyType = KeyType.publicKey
|
||||
var segments = [String]()
|
||||
var message = ""
|
||||
|
||||
func reset(keytype: KeyType) {
|
||||
self.keyType = keytype
|
||||
self.segments.removeAll()
|
||||
keyType = keytype
|
||||
segments.removeAll()
|
||||
message = "LookingForStartingFrame.".localize()
|
||||
}
|
||||
|
||||
func addSegment(segment: String) -> (accept: Bool, message: String) {
|
||||
let keyTypeStr = self.keyType == .publicKey ? "Public" : "Private"
|
||||
let theOtherKeyTypeStr = self.keyType == .publicKey ? "Private" : "Public"
|
||||
|
||||
let keyTypeStr = keyType == .publicKey ? "Public" : "Private"
|
||||
let theOtherKeyTypeStr = keyType == .publicKey ? "Private" : "Public"
|
||||
|
||||
// Skip duplicated segments.
|
||||
guard segment != self.segments.last else {
|
||||
return (accept: false, message: self.message)
|
||||
guard segment != segments.last else {
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
|
||||
// Check whether we have found the first block.
|
||||
guard !self.segments.isEmpty || segment.contains("-----BEGIN PGP \(keyTypeStr.uppercased()) KEY BLOCK-----") else {
|
||||
guard !segments.isEmpty || segment.contains("-----BEGIN PGP \(keyTypeStr.uppercased()) KEY BLOCK-----") else {
|
||||
// Check whether we are scanning the wrong key type.
|
||||
if segment.contains("-----BEGIN PGP \(theOtherKeyTypeStr.uppercased()) KEY BLOCK-----") {
|
||||
self.message = "Scan\(keyTypeStr)Key.".localize()
|
||||
message = "Scan\(keyTypeStr)Key.".localize()
|
||||
}
|
||||
return (accept: false, message: self.message)
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
|
||||
|
||||
// Update the list of scanned segment and return.
|
||||
self.segments.append(segment)
|
||||
segments.append(segment)
|
||||
if segment.contains("-----END PGP \(keyTypeStr.uppercased()) KEY BLOCK-----") {
|
||||
self.message = "Done".localize()
|
||||
return (accept: true, message: self.message)
|
||||
message = "Done".localize()
|
||||
return (accept: true, message: message)
|
||||
} else {
|
||||
self.message = "ScannedQrCodes(%d)".localize(self.segments.count)
|
||||
return (accept: false, message: self.message)
|
||||
message = "ScannedQrCodes(%d)".localize(segments.count)
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scanned = ScannedPGPKey()
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
|
@ -76,13 +77,14 @@ class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
scanPrivateKeyCell?.accessoryType = .disclosureIndicator
|
||||
}
|
||||
|
||||
@IBAction func save(_ sender: Any) {
|
||||
@IBAction
|
||||
func save(_: Any) {
|
||||
armorPublicKey = armorPublicKeyTextView.text
|
||||
armorPrivateKey = armorPrivateKeyTextView.text
|
||||
self.saveImportedKeys()
|
||||
saveImportedKeys()
|
||||
}
|
||||
|
||||
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
func textView(_: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
|
||||
if text == UIPasteboard.general.string {
|
||||
// user pastes something, do the copy here again and clear the pasteboard in 45s
|
||||
SecurePasteboard.shared.copy(textToCopy: text)
|
||||
|
|
@ -94,21 +96,23 @@ class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
let selectedCell = tableView.cellForRow(at: indexPath)
|
||||
if selectedCell == scanPublicKeyCell {
|
||||
scanned.reset(keytype: ScannedPGPKey.KeyType.publicKey)
|
||||
self.performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
} else if selectedCell == scanPrivateKeyCell {
|
||||
scanned.reset(keytype: ScannedPGPKey.KeyType.privateKey)
|
||||
self.performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
|
||||
func checkScannedOutput(line: String) -> (accept: Bool, message: String) {
|
||||
return scanned.addSegment(segment: line)
|
||||
}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
func handleScannedOutput(line: String) {
|
||||
|
||||
func handleScannedOutput(line _: String) {
|
||||
let key = scanned.segments.joined(separator: "")
|
||||
switch scanned.keyType {
|
||||
case .publicKey:
|
||||
|
|
@ -118,7 +122,7 @@ class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
}
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
override func prepare(for segue: UIStoryboardSegue, sender _: Any?) {
|
||||
if segue.identifier == "showPGPScannerSegue" {
|
||||
if let navController = segue.destination as? UINavigationController {
|
||||
if let viewController = navController.topViewController as? QRScannerController {
|
||||
|
|
@ -132,7 +136,6 @@ class PGPKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
}
|
||||
|
||||
extension PGPKeyArmorImportTableViewController: PGPKeyImporter {
|
||||
|
||||
static let keySource = KeySource.armor
|
||||
static let label = "AsciiArmorEncryptedKey".localize()
|
||||
|
||||
|
|
|
|||
|
|
@ -9,18 +9,18 @@
|
|||
import passKit
|
||||
|
||||
class PGPKeyFileImportTableViewController: AutoCellHeightUITableViewController {
|
||||
@IBOutlet var pgpPublicKeyFile: UITableViewCell!
|
||||
@IBOutlet var pgpPrivateKeyFile: UITableViewCell!
|
||||
|
||||
@IBOutlet weak var pgpPublicKeyFile: UITableViewCell!
|
||||
@IBOutlet weak var pgpPrivateKeyFile: UITableViewCell!
|
||||
|
||||
private var publicKey: String? = nil
|
||||
private var privateKey: String? = nil
|
||||
private var publicKey: String?
|
||||
private var privateKey: String?
|
||||
|
||||
private enum KeyType { case none, `private`, `public` }
|
||||
private var currentlyPicking = KeyType.none
|
||||
|
||||
@IBAction func save(_ sender: Any) {
|
||||
self.saveImportedKeys()
|
||||
@IBAction
|
||||
func save(_: Any) {
|
||||
saveImportedKeys()
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
|
@ -43,7 +43,6 @@ class PGPKeyFileImportTableViewController: AutoCellHeightUITableViewController {
|
|||
}
|
||||
|
||||
extension PGPKeyFileImportTableViewController: UIDocumentPickerDelegate {
|
||||
|
||||
func documentPicker(_: UIDocumentPickerViewController, didPickDocumentsAt url: [URL]) {
|
||||
guard let url = url.first else {
|
||||
return
|
||||
|
|
@ -78,12 +77,11 @@ extension PGPKeyFileImportTableViewController: UIDocumentPickerDelegate {
|
|||
}
|
||||
|
||||
extension PGPKeyFileImportTableViewController: PGPKeyImporter {
|
||||
|
||||
static let keySource = KeySource.file
|
||||
static let label = "LoadFromFiles".localize()
|
||||
|
||||
func isReadyToUse() -> Bool {
|
||||
return validate(key: publicKey) && validate(key: privateKey)
|
||||
validate(key: publicKey) && validate(key: privateKey)
|
||||
}
|
||||
|
||||
func importKeys() throws {
|
||||
|
|
|
|||
|
|
@ -9,19 +9,15 @@
|
|||
import passKit
|
||||
|
||||
protocol PGPKeyImporter: KeyImporter {
|
||||
|
||||
func doAfterImport()
|
||||
|
||||
func saveImportedKeys()
|
||||
}
|
||||
|
||||
extension PGPKeyImporter {
|
||||
|
||||
static var isCurrentKeySource: Bool {
|
||||
return Defaults.pgpKeySource == Self.keySource
|
||||
Defaults.pgpKeySource == Self.keySource
|
||||
}
|
||||
|
||||
func doAfterImport() {
|
||||
|
||||
}
|
||||
func doAfterImport() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,13 +6,12 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class PGPKeyUrlImportTableViewController: AutoCellHeightUITableViewController {
|
||||
|
||||
@IBOutlet weak var pgpPublicKeyURLTextField: UITextField!
|
||||
@IBOutlet weak var pgpPrivateKeyURLTextField: UITextField!
|
||||
@IBOutlet var pgpPublicKeyURLTextField: UITextField!
|
||||
@IBOutlet var pgpPrivateKeyURLTextField: UITextField!
|
||||
|
||||
var pgpPrivateKeyURL: URL?
|
||||
var pgpPublicKeyURL: URL?
|
||||
|
|
@ -22,31 +21,31 @@ class PGPKeyUrlImportTableViewController: AutoCellHeightUITableViewController {
|
|||
pgpPublicKeyURLTextField.text = Defaults.pgpPublicKeyURL?.absoluteString
|
||||
pgpPrivateKeyURLTextField.text = Defaults.pgpPrivateKeyURL?.absoluteString
|
||||
}
|
||||
|
||||
@IBAction func save(_ sender: Any) {
|
||||
|
||||
@IBAction
|
||||
func save(_: Any) {
|
||||
guard let publicKeyURLText = pgpPublicKeyURLTextField.text,
|
||||
let publicKeyURL = URL(string: publicKeyURLText),
|
||||
let privateKeyURLText = pgpPrivateKeyURLTextField.text,
|
||||
let privateKeyURL = URL(string: privateKeyURLText) else {
|
||||
Utils.alert(title: "CannotSavePgpKey".localize(), message: "SetPgpKeyUrlsFirst.".localize(), controller: self)
|
||||
return
|
||||
Utils.alert(title: "CannotSavePgpKey".localize(), message: "SetPgpKeyUrlsFirst.".localize(), controller: self)
|
||||
return
|
||||
}
|
||||
if privateKeyURL.scheme?.lowercased() == "http" || publicKeyURL.scheme?.lowercased() == "http" {
|
||||
Utils.alert(title: "HttpNotSecure".localize(), message: "ReallyUseHttp.".localize(), controller: self)
|
||||
}
|
||||
pgpPrivateKeyURL = privateKeyURL
|
||||
pgpPublicKeyURL = publicKeyURL
|
||||
self.saveImportedKeys()
|
||||
saveImportedKeys()
|
||||
}
|
||||
}
|
||||
|
||||
extension PGPKeyUrlImportTableViewController: PGPKeyImporter {
|
||||
|
||||
static let keySource = KeySource.url
|
||||
static let label = "DownloadFromUrl".localize()
|
||||
|
||||
func isReadyToUse() -> Bool {
|
||||
return validate(pgpKeyUrl: pgpPublicKeyURLTextField.text ?? "")
|
||||
validate(pgpKeyUrl: pgpPublicKeyURLTextField.text ?? "")
|
||||
&& validate(pgpKeyUrl: pgpPrivateKeyURLTextField.text ?? "")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import FavIcon
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
class PasswordDetailTableViewController: UITableViewController, UIGestureRecognizerDelegate {
|
||||
var passwordEntity: PasswordEntity?
|
||||
private var password: Password?
|
||||
private var passwordImage: UIImage?
|
||||
private var oneTimePasswordIndexPath : IndexPath?
|
||||
private var oneTimePasswordIndexPath: IndexPath?
|
||||
private var shouldPopCurrentView = false
|
||||
private let passwordStore = PasswordStore.shared
|
||||
private let keychain = AppKeychain.shared
|
||||
|
|
@ -52,7 +52,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
tableView.addGestureRecognizer(tapGesture)
|
||||
tapGesture.delegate = self
|
||||
|
||||
tableView.contentInset = UIEdgeInsets.init(top: -36, left: 0, bottom: 44, right: 0);
|
||||
tableView.contentInset = UIEdgeInsets(top: -36, left: 0, bottom: 44, right: 0)
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.estimatedRowHeight = 52
|
||||
|
||||
|
|
@ -66,8 +66,8 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
let image = UIImage(data: imageData as Data)
|
||||
passwordImage = image
|
||||
}
|
||||
self.decryptThenShowPassword()
|
||||
self.setupOneTimePasswordAutoRefresh()
|
||||
decryptThenShowPassword()
|
||||
setupOneTimePasswordAutoRefresh()
|
||||
|
||||
// pop the current view because this password might be "discarded"
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(setShouldPopCurrentView), name: .passwordStoreChangeDiscarded, object: nil)
|
||||
|
|
@ -78,16 +78,17 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
if self.shouldPopCurrentView {
|
||||
if shouldPopCurrentView {
|
||||
let alert = UIAlertController(title: "Notice".localize(), message: "PreviousChangesDiscarded.".localize(), preferredStyle: UIAlertController.Style.alert)
|
||||
alert.addAction(UIAlertAction.okAndPopView(controller: self))
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func decryptThenShowPassword(keyID: String? = nil) {
|
||||
@objc
|
||||
private func decryptThenShowPassword(keyID: String? = nil) {
|
||||
guard let passwordEntity = passwordEntity else {
|
||||
Utils.alert(title: "CannotShowPassword".localize(), message: "PasswordDoesNotExist".localize(), controller: self, handler: {(UIAlertAction) -> Void in
|
||||
Utils.alert(title: "CannotShowPassword".localize(), message: "PasswordDoesNotExist".localize(), controller: self, handler: { (_) -> Void in
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
})
|
||||
return
|
||||
|
|
@ -98,7 +99,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
let requestPGPKeyPassphrase = Utils.createRequestPGPKeyPassphraseHandler(controller: self)
|
||||
self.password = try self.passwordStore.decrypt(passwordEntity: passwordEntity, keyID: keyID, requestPGPKeyPassphrase: requestPGPKeyPassphrase)
|
||||
self.showPassword()
|
||||
} catch AppError.PgpPrivateKeyNotFound(let key) {
|
||||
} catch let AppError.PgpPrivateKeyNotFound(key) {
|
||||
DispatchQueue.main.async {
|
||||
// alert: cancel or try again
|
||||
let alert = UIAlertController(title: "CannotShowPassword".localize(), message: AppError.PgpPrivateKeyNotFound(keyID: key).localizedDescription, preferredStyle: .alert)
|
||||
|
|
@ -115,7 +116,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
// alert: cancel or try again
|
||||
let alert = UIAlertController(title: "CannotShowPassword".localize(), message: error.localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction.cancelAndPopView(controller: self))
|
||||
alert.addAction(UIAlertAction(title: "TryAgain".localize(), style: .default) {_ in
|
||||
alert.addAction(UIAlertAction(title: "TryAgain".localize(), style: .default) { _ in
|
||||
self.decryptThenShowPassword()
|
||||
})
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
|
|
@ -141,14 +142,14 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
|
||||
private func setupOneTimePasswordAutoRefresh() {
|
||||
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {
|
||||
[weak self] timer in
|
||||
[weak self] _ in
|
||||
// bail out of the timer code if the object has been freed
|
||||
guard let strongSelf = self,
|
||||
let otpType = strongSelf.password?.otpType,
|
||||
otpType != .none,
|
||||
let indexPath = strongSelf.oneTimePasswordIndexPath,
|
||||
let cell = strongSelf.tableView.cellForRow(at: indexPath) as? LabelTableViewCell else {
|
||||
return
|
||||
return
|
||||
}
|
||||
switch otpType {
|
||||
case .totp:
|
||||
|
|
@ -163,64 +164,67 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
}
|
||||
|
||||
@objc private func pressEdit(_ sender: Any?) {
|
||||
@objc
|
||||
private func pressEdit(_: Any?) {
|
||||
performSegue(withIdentifier: "editPasswordSegue", sender: self)
|
||||
}
|
||||
|
||||
@objc private func setShouldPopCurrentView() {
|
||||
self.shouldPopCurrentView = true
|
||||
@objc
|
||||
private func setShouldPopCurrentView() {
|
||||
shouldPopCurrentView = true
|
||||
}
|
||||
|
||||
@IBAction private func cancelEditPassword(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
private func cancelEditPassword(segue _: UIStoryboardSegue) {}
|
||||
|
||||
}
|
||||
|
||||
@IBAction private func saveEditPassword(segue: UIStoryboardSegue) {
|
||||
if self.password!.changed != 0 {
|
||||
self.saveEditPassword(password: self.password!)
|
||||
@IBAction
|
||||
private func saveEditPassword(segue _: UIStoryboardSegue) {
|
||||
if password!.changed != 0 {
|
||||
saveEditPassword(password: password!)
|
||||
}
|
||||
}
|
||||
|
||||
private func saveEditPassword(password: Password, keyID: String? = nil) {
|
||||
SVProgressHUD.show(withStatus: "Saving".localize())
|
||||
do {
|
||||
self.passwordEntity = try self.passwordStore.edit(passwordEntity: self.passwordEntity!, password: password, keyID: keyID)
|
||||
self.setTableData()
|
||||
self.tableView.reloadData()
|
||||
passwordEntity = try passwordStore.edit(passwordEntity: passwordEntity!, password: password, keyID: keyID)
|
||||
setTableData()
|
||||
tableView.reloadData()
|
||||
SVProgressHUD.showSuccess(withStatus: "Success".localize())
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
} catch AppError.PgpPublicKeyNotFound(let key) {
|
||||
DispatchQueue.main.async {
|
||||
// alert: cancel or select keys
|
||||
SVProgressHUD.dismiss()
|
||||
let alert = UIAlertController(title: "Cannot Edit Password", message: AppError.PgpPublicKeyNotFound(keyID: key).localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction.cancelAndPopView(controller: self))
|
||||
let selectKey = UIAlertAction.selectKey(controller: self) { action in
|
||||
self.saveEditPassword(password: password, keyID: action.title)
|
||||
}
|
||||
alert.addAction(selectKey)
|
||||
} catch let AppError.PgpPublicKeyNotFound(key) {
|
||||
DispatchQueue.main.async {
|
||||
// alert: cancel or select keys
|
||||
SVProgressHUD.dismiss()
|
||||
let alert = UIAlertController(title: "Cannot Edit Password", message: AppError.PgpPublicKeyNotFound(keyID: key).localizedDescription, preferredStyle: .alert)
|
||||
alert.addAction(UIAlertAction.cancelAndPopView(controller: self))
|
||||
let selectKey = UIAlertAction.selectKey(controller: self) { action in
|
||||
self.saveEditPassword(password: password, keyID: action.title)
|
||||
}
|
||||
alert.addAction(selectKey)
|
||||
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
Utils.alert(title: "Error".localize(), message: error.localizedDescription, controller: self, completion: nil)
|
||||
}
|
||||
}
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
return
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
Utils.alert(title: "Error".localize(), message: error.localizedDescription, controller: self, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func deletePassword(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
private func deletePassword(segue _: UIStoryboardSegue) {
|
||||
do {
|
||||
try passwordStore.delete(passwordEntity: passwordEntity!)
|
||||
} catch {
|
||||
Utils.alert(title: "Error".localize(), message: error.localizedDescription, controller: self, completion: nil)
|
||||
}
|
||||
let _ = navigationController?.popViewController(animated: true)
|
||||
_ = navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
private func setTableData() {
|
||||
self.tableData = Array<TableSection>()
|
||||
tableData = [TableSection]()
|
||||
|
||||
// name section
|
||||
var section = TableSection(type: .name)
|
||||
|
|
@ -239,7 +243,6 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
section.item.append(Constants.PASSWORD_KEYWORD => password.password)
|
||||
tableData.append(section)
|
||||
|
||||
|
||||
// addition section
|
||||
|
||||
// show one time password
|
||||
|
|
@ -254,7 +257,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
|
||||
// show additional information
|
||||
let filteredAdditionKeys = password.getFilteredAdditions()
|
||||
if filteredAdditionKeys.count > 0 {
|
||||
if !filteredAdditionKeys.isEmpty {
|
||||
section = TableSection(type: .addition, header: "Additions".localize())
|
||||
section.item.append(contentsOf: filteredAdditionKeys)
|
||||
tableData.append(section)
|
||||
|
|
@ -264,10 +267,9 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
section = TableSection(type: .misc)
|
||||
section.item.append(AdditionField(title: "ShowRaw".localize()))
|
||||
tableData.append(section)
|
||||
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
override func prepare(for segue: UIStoryboardSegue, sender _: Any?) {
|
||||
if segue.identifier == "editPasswordSegue" {
|
||||
if let controller = segue.destination as? UINavigationController {
|
||||
if let editController = controller.viewControllers.first as? EditPasswordTableViewController {
|
||||
|
|
@ -288,9 +290,9 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
if urlString.lowercased().hasPrefix("http://") {
|
||||
// try to replace http url to https url
|
||||
newUrlString = urlString.replacingOccurrences(of: "http://",
|
||||
with: "https://",
|
||||
options: .caseInsensitive,
|
||||
range: urlString.range(of: "http://"))
|
||||
with: "https://",
|
||||
options: .caseInsensitive,
|
||||
range: urlString.range(of: "http://"))
|
||||
} else if urlString.lowercased().hasPrefix("https://") {
|
||||
// do nothing here
|
||||
} else {
|
||||
|
|
@ -311,11 +313,12 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
}
|
||||
|
||||
@objc private func tapMenu(recognizer: UITapGestureRecognizer) {
|
||||
@objc
|
||||
private func tapMenu(recognizer: UITapGestureRecognizer) {
|
||||
if recognizer.state == UIGestureRecognizer.State.ended {
|
||||
let tapLocation = recognizer.location(in: self.tableView)
|
||||
if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
|
||||
if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? LabelTableViewCell {
|
||||
let tapLocation = recognizer.location(in: tableView)
|
||||
if let tapIndexPath = tableView.indexPathForRow(at: tapLocation) {
|
||||
if let tappedCell = tableView.cellForRow(at: tapIndexPath) as? LabelTableViewCell {
|
||||
tappedCell.becomeFirstResponder()
|
||||
let menuController = UIMenuController.shared
|
||||
let revealItem = UIMenuItem(title: "Reveal".localize(), action: #selector(LabelTableViewCell.revealPassword(_:)))
|
||||
|
|
@ -330,22 +333,22 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
func gestureRecognizer(_: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
if touch.view!.isKind(of: UIButton.classForCoder()) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@IBAction func back(segue:UIStoryboardSegue) {
|
||||
}
|
||||
@IBAction
|
||||
func back(segue _: UIStoryboardSegue) {}
|
||||
|
||||
func getNextHOTP() {
|
||||
guard password != nil, passwordEntity != nil, password?.otpType == .hotp else {
|
||||
DispatchQueue.main.async {
|
||||
Utils.alert(title: "Error".localize(), message: "GetNextPasswordOfNonHotp.".localize(), controller: self, completion: nil)
|
||||
}
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
// copy HOTP to pasteboard (will update counter)
|
||||
|
|
@ -356,7 +359,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
// commit the change of HOTP counter
|
||||
if password!.changed != 0 {
|
||||
do {
|
||||
self.passwordEntity = try self.passwordStore.edit(passwordEntity: self.passwordEntity!, password: self.password!)
|
||||
passwordEntity = try passwordStore.edit(passwordEntity: passwordEntity!, password: password!)
|
||||
SVProgressHUD.showSuccess(withStatus: "PasswordCopied".localize() | "CounterUpdated".localize())
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
} catch {
|
||||
|
|
@ -384,19 +387,19 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
return from
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return tableData.count
|
||||
override func numberOfSections(in _: UITableView) -> Int {
|
||||
tableData.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return tableData[section].item.count
|
||||
override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
tableData[section].item.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let sectionIndex = indexPath.section
|
||||
let rowIndex = indexPath.row
|
||||
let tableDataItem = tableData[sectionIndex].item[rowIndex]
|
||||
switch(tableData[sectionIndex].type) {
|
||||
switch tableData[sectionIndex].type {
|
||||
case .name:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordDetailTitleTableViewCell", for: indexPath) as! PasswordDetailTitleTableViewCell
|
||||
if !Defaults.isHidePasswordImagesOn {
|
||||
|
|
@ -453,8 +456,8 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
detailTextLabel.text = "HiddenFields(%d)".localize(numberOfHiddenFields)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return tableData[section].header
|
||||
override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
tableData[section].header
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
|
|
@ -464,7 +467,7 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
footerLabel.numberOfLines = 0
|
||||
footerLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
|
||||
footerLabel.textColor = UIColor.gray
|
||||
let dateString = self.passwordStore.getLatestUpdateInfo(filename: password!.url.path)
|
||||
let dateString = passwordStore.getLatestUpdateInfo(filename: password!.url.path)
|
||||
footerLabel.text = "LastUpdated".localize(dateString)
|
||||
view.addSubview(footerLabel)
|
||||
return view
|
||||
|
|
@ -472,15 +475,15 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
return nil
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
|
||||
override func tableView(_: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender _: Any?) {
|
||||
if action == #selector(copy(_:)) {
|
||||
SecurePasteboard.shared.copy(textToCopy: tableData[indexPath.section].item[indexPath.row].content)
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
|
||||
override func tableView(_: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender _: Any?) -> Bool {
|
||||
let section = tableData[indexPath.section]
|
||||
switch(section.type) {
|
||||
switch section.type {
|
||||
case .main, .addition:
|
||||
return action == #selector(UIResponderStandardEditActions.copy(_:))
|
||||
default:
|
||||
|
|
@ -488,8 +491,8 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
|
||||
return true
|
||||
override func tableView(_: UITableView, shouldShowMenuForRowAt _: IndexPath) -> Bool {
|
||||
true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SafariServices
|
||||
import OneTimePassword
|
||||
import passKit
|
||||
import SafariServices
|
||||
import UIKit
|
||||
|
||||
enum PasswordEditorCellType: Equatable {
|
||||
case nameCell
|
||||
|
|
@ -30,18 +30,16 @@ enum PasswordEditorCellKey {
|
|||
}
|
||||
|
||||
protocol PasswordSettingSliderTableViewCellDelegate {
|
||||
|
||||
func generateAndCopyPassword()
|
||||
}
|
||||
|
||||
class PasswordEditorTableViewController: UITableViewController {
|
||||
|
||||
var tableData = [[Dictionary<PasswordEditorCellKey, Any>]]()
|
||||
var tableData = [[[PasswordEditorCellKey: Any]]]()
|
||||
var password: Password?
|
||||
|
||||
private var navigationItemTitle: String?
|
||||
|
||||
private var sectionHeaderTitles = ["Name".localize(), "Password".localize(), "Additions".localize(),""].map {$0.uppercased()}
|
||||
private var sectionHeaderTitles = ["Name".localize(), "Password".localize(), "Additions".localize(), ""].map { $0.uppercased() }
|
||||
private var sectionFooterTitles = ["", "", "UseKeyValueFormat.".localize(), ""]
|
||||
private let nameSection = 0
|
||||
private let passwordSection = 1
|
||||
|
|
@ -86,7 +84,7 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
passwordFlavorCell?.textLabel?.text = "PasswordGeneratorFlavor".localize()
|
||||
passwordFlavorCell?.selectionStyle = .none
|
||||
|
||||
let passwordFlavorSelector = UISegmentedControl(items: PasswordGeneratorFlavor.allCases.map { $0.localized })
|
||||
let passwordFlavorSelector = UISegmentedControl(items: PasswordGeneratorFlavor.allCases.map(\.localized))
|
||||
passwordFlavorSelector.selectedSegmentIndex = PasswordGeneratorFlavor.allCases.firstIndex(of: passwordGenerator.flavor)!
|
||||
passwordFlavorSelector.addTarget(self, action: #selector(flavorChanged), for: .valueChanged)
|
||||
passwordFlavorCell?.accessoryView = passwordFlavorSelector
|
||||
|
|
@ -126,11 +124,11 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
],
|
||||
[
|
||||
[.type: PasswordEditorCellType.scanQRCodeCell],
|
||||
]
|
||||
],
|
||||
]
|
||||
|
||||
if self.password != nil {
|
||||
tableData[additionsSection+1].append([.type: PasswordEditorCellType.deletePasswordCell])
|
||||
|
||||
if password != nil {
|
||||
tableData[additionsSection + 1].append([.type: PasswordEditorCellType.deletePasswordCell])
|
||||
}
|
||||
updateTableData(withRespectTo: passwordGenerator.flavor)
|
||||
}
|
||||
|
|
@ -206,11 +204,11 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
return 44
|
||||
override func tableView(_: UITableView, heightForHeaderInSection _: Int) -> CGFloat {
|
||||
44
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
override func tableView(_: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
switch tableData[indexPath.section][indexPath.row][PasswordEditorCellKey.type] as! PasswordEditorCellType {
|
||||
case .passwordLengthCell, .passwordGroupsCell:
|
||||
return 42
|
||||
|
|
@ -221,11 +219,11 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return tableData.count
|
||||
override func numberOfSections(in _: UITableView) -> Int {
|
||||
tableData.count
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if section == passwordSection, hidePasswordSettings {
|
||||
// hide the password section, only the password should be shown
|
||||
return 1
|
||||
|
|
@ -234,27 +232,27 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return sectionHeaderTitles[section]
|
||||
override func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
sectionHeaderTitles[section]
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
return sectionFooterTitles[section]
|
||||
override func tableView(_: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
sectionFooterTitles[section]
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let selectedCell = tableView.cellForRow(at: indexPath)
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
|
||||
|
||||
if selectedCell == deletePasswordCell {
|
||||
let alert = UIAlertController(title: "DeletePassword?".localize(), message: nil, preferredStyle: UIAlertController.Style.alert)
|
||||
alert.addAction(UIAlertAction(title: "Delete".localize(), style: UIAlertAction.Style.destructive, handler: {[unowned self] (action) -> Void in
|
||||
alert.addAction(UIAlertAction(title: "Delete".localize(), style: UIAlertAction.Style.destructive, handler: { [unowned self] (_) -> Void in
|
||||
self.performSegue(withIdentifier: "deletePasswordSegue", sender: self)
|
||||
}))
|
||||
alert.addAction(UIAlertAction.cancel())
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
} else if selectedCell == scanQRCodeCell {
|
||||
self.performSegue(withIdentifier: "showQRScannerSegue", sender: self)
|
||||
performSegue(withIdentifier: "showQRScannerSegue", sender: self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,11 +274,12 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
private func isPasswordDelimiterCellData(data: Dictionary<PasswordEditorCellKey, Any>) -> Bool {
|
||||
return (data[.type] as? PasswordEditorCellType) == .some(.passwordGroupsCell)
|
||||
private func isPasswordDelimiterCellData(data: [PasswordEditorCellKey: Any]) -> Bool {
|
||||
(data[.type] as? PasswordEditorCellType) == .some(.passwordGroupsCell)
|
||||
}
|
||||
|
||||
@objc func flavorChanged(_ sender: UISegmentedControl) {
|
||||
@objc
|
||||
func flavorChanged(_ sender: UISegmentedControl) {
|
||||
let flavor = PasswordGeneratorFlavor.allCases[sender.selectedSegmentIndex]
|
||||
guard passwordGenerator.flavor != flavor else {
|
||||
return
|
||||
|
|
@ -327,7 +326,7 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
additionsCell?.setContent(content: additionsString)
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
override func prepare(for segue: UIStoryboardSegue, sender _: Any?) {
|
||||
if segue.identifier == "showQRScannerSegue" {
|
||||
if let navController = segue.destination as? UINavigationController {
|
||||
if let viewController = navController.topViewController as? QRScannerController {
|
||||
|
|
@ -362,8 +361,8 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
// the name field should be a valid url
|
||||
guard let path = name.stringByAddingPercentEncodingForRFC3986(),
|
||||
var passwordURL = URL(string: path) else {
|
||||
Utils.alert(title: "CannotSave".localize(), message: "PasswordNameInvalid.".localize(), controller: self, completion: nil)
|
||||
return false
|
||||
Utils.alert(title: "CannotSave".localize(), message: "PasswordNameInvalid.".localize(), controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
|
||||
// check whether we can parse the filename (be consistent with PasswordStore::addPasswordEntities)
|
||||
|
|
@ -382,20 +381,20 @@ class PasswordEditorTableViewController: UITableViewController {
|
|||
}
|
||||
|
||||
// MARK: - FillPasswordTableViewCellDelegate
|
||||
extension PasswordEditorTableViewController: FillPasswordTableViewCellDelegate {
|
||||
|
||||
extension PasswordEditorTableViewController: FillPasswordTableViewCellDelegate {
|
||||
// generate password, copy to pasteboard, and set the cell
|
||||
// check whether the current password looks like an OTP field
|
||||
func generateAndCopyPassword() {
|
||||
if let currentPassword = fillPasswordCell?.getContent(), Constants.isOtpRelated(line: currentPassword) {
|
||||
let alert = UIAlertController(title: "Overwrite?".localize(), message: "OverwriteOtpConfiguration?".localize(), preferredStyle: UIAlertController.Style.alert)
|
||||
alert.addAction(UIAlertAction(title: "Yes".localize(), style: UIAlertAction.Style.destructive, handler: {_ in
|
||||
alert.addAction(UIAlertAction(title: "Yes".localize(), style: UIAlertAction.Style.destructive, handler: { _ in
|
||||
self.generateAndCopyPasswordNoOtpCheck()
|
||||
}))
|
||||
alert.addAction(UIAlertAction.cancel())
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
} else {
|
||||
self.generateAndCopyPasswordNoOtpCheck()
|
||||
generateAndCopyPasswordNoOtpCheck()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -407,11 +406,12 @@ extension PasswordEditorTableViewController: FillPasswordTableViewCellDelegate {
|
|||
}
|
||||
|
||||
// MARK: - PasswordSettingSliderTableViewCellDelegate
|
||||
|
||||
extension PasswordEditorTableViewController: PasswordSettingSliderTableViewCellDelegate {}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate
|
||||
extension PasswordEditorTableViewController: QRScannerControllerDelegate {
|
||||
|
||||
extension PasswordEditorTableViewController: QRScannerControllerDelegate {
|
||||
func checkScannedOutput(line: String) -> (accept: Bool, message: String) {
|
||||
if let url = URL(string: line), let _ = Token(url: url) {
|
||||
return (accept: true, message: "ValidTokenUrl".localize())
|
||||
|
|
@ -426,31 +426,31 @@ extension PasswordEditorTableViewController: QRScannerControllerDelegate {
|
|||
}
|
||||
|
||||
// MARK: - SFSafariViewControllerDelegate
|
||||
extension PasswordEditorTableViewController: SFSafariViewControllerDelegate {
|
||||
|
||||
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
|
||||
let copiedLinesSplit = UIPasteboard.general.string?.components(separatedBy: CharacterSet.whitespacesAndNewlines).filter({ !$0.isEmpty })
|
||||
extension PasswordEditorTableViewController: SFSafariViewControllerDelegate {
|
||||
func safariViewControllerDidFinish(_: SFSafariViewController) {
|
||||
let copiedLinesSplit = UIPasteboard.general.string?.components(separatedBy: CharacterSet.whitespacesAndNewlines).filter { !$0.isEmpty }
|
||||
if copiedLinesSplit?.count ?? 0 > 0 {
|
||||
let generatedPassword = copiedLinesSplit![0]
|
||||
let alert = UIAlertController(title: "WannaUseIt?".localize(), message: "", preferredStyle: UIAlertController.Style.alert)
|
||||
let message = NSMutableAttributedString(string: "\("SeemsLikeYouHaveCopiedSomething.".localize()) \("FirstStringIs:".localize())\n")
|
||||
message.append(Utils.attributedPassword(plainPassword: generatedPassword))
|
||||
alert.setValue(message, forKey: "attributedMessage")
|
||||
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: {[unowned self] (action) -> Void in
|
||||
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertAction.Style.default, handler: { [unowned self] (_) -> Void in
|
||||
// update tableData so to make sure reloadData() works correctly
|
||||
self.tableData[self.passwordSection][0][PasswordEditorCellKey.content] = generatedPassword
|
||||
// update cell manually, no need to call reloadData()
|
||||
self.fillPasswordCell?.setContent(content: generatedPassword)
|
||||
}))
|
||||
alert.addAction(UIAlertAction.cancel())
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UITextFieldDelegate
|
||||
extension PasswordEditorTableViewController: UITextFieldDelegate {
|
||||
|
||||
extension PasswordEditorTableViewController: UITextFieldDelegate {
|
||||
// update tableData so to make sure reloadData() works correctly
|
||||
func textFieldDidEndEditing(_ textField: UITextField) {
|
||||
if textField == nameCell?.contentTextField {
|
||||
|
|
@ -471,8 +471,8 @@ extension PasswordEditorTableViewController: UITextFieldDelegate {
|
|||
}
|
||||
|
||||
// MARK: - UITextViewDelegate
|
||||
extension PasswordEditorTableViewController: UITextViewDelegate {
|
||||
|
||||
extension PasswordEditorTableViewController: UITextViewDelegate {
|
||||
// update tableData so to make sure reloadData() works correctly
|
||||
func textViewDidEndEditing(_ textView: UITextView) {
|
||||
if textView == additionsCell?.contentTextView {
|
||||
|
|
|
|||
|
|
@ -6,16 +6,16 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
fileprivate let hideSectionHeaderThreshold = 6 // hide section header if passwords count is less than the threshold
|
||||
private let hideSectionHeaderThreshold = 6 // hide section header if passwords count is less than the threshold
|
||||
|
||||
class PasswordsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITabBarControllerDelegate, UISearchBarDelegate {
|
||||
private var passwordsTableEntries: [PasswordTableEntry] = []
|
||||
private var passwordsTableAllEntries: [PasswordTableEntry] = []
|
||||
private var parentPasswordEntity: PasswordEntity? = nil
|
||||
private var parentPasswordEntity: PasswordEntity?
|
||||
private let passwordStore = PasswordStore.shared
|
||||
private let keychain = AppKeychain.shared
|
||||
|
||||
|
|
@ -30,14 +30,12 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
private var gitCredential: GitCredential {
|
||||
get {
|
||||
switch Defaults.gitAuthenticationMethod {
|
||||
case .password:
|
||||
return GitCredential(credential: .http(userName: Defaults.gitUsername))
|
||||
case .key:
|
||||
let privateKey: String = AppKeychain.shared.get(for: SshKey.PRIVATE.getKeychainKey()) ?? ""
|
||||
return GitCredential(credential: .ssh(userName: Defaults.gitUsername, privateKey: privateKey))
|
||||
}
|
||||
switch Defaults.gitAuthenticationMethod {
|
||||
case .password:
|
||||
return GitCredential(credential: .http(userName: Defaults.gitUsername))
|
||||
case .key:
|
||||
let privateKey: String = AppKeychain.shared.get(for: SshKey.PRIVATE.getKeychainKey()) ?? ""
|
||||
return GitCredential(credential: .ssh(userName: Defaults.gitUsername, privateKey: privateKey))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,11 +47,13 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
uiSearchController.searchBar.sizeToFit()
|
||||
return uiSearchController
|
||||
}()
|
||||
|
||||
private lazy var syncControl: UIRefreshControl = {
|
||||
let syncControl = UIRefreshControl()
|
||||
syncControl.addTarget(self, action: #selector(handleRefresh(_:)), for: UIControl.Event.valueChanged)
|
||||
return syncControl
|
||||
}()
|
||||
|
||||
private lazy var searchBarView: UIView? = {
|
||||
guard #available(iOS 11, *) else {
|
||||
let uiView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.bounds.width, height: 44))
|
||||
|
|
@ -62,6 +62,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
return nil
|
||||
}()
|
||||
|
||||
private lazy var backUIBarButtonItem: UIBarButtonItem = {
|
||||
let backUIButton = UIButton(type: .system)
|
||||
if #available(iOS 13.0, *) {
|
||||
|
|
@ -116,28 +117,29 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
return transition
|
||||
}()
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
@IBOutlet var tableView: UITableView!
|
||||
|
||||
private func initPasswordsTableEntries(parent: PasswordEntity?) {
|
||||
let passwordAllEntities = self.passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
||||
let passwordAllEntities = passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
||||
passwordsTableAllEntries = passwordAllEntities.compactMap {
|
||||
PasswordTableEntry($0)
|
||||
}
|
||||
|
||||
|
||||
let passwordEntities = Defaults.isShowFolderOn ?
|
||||
self.passwordStore.fetchPasswordEntityCoreData(parent: parent) :
|
||||
passwordStore.fetchPasswordEntityCoreData(parent: parent) :
|
||||
passwordAllEntities
|
||||
passwordsTableEntries = passwordEntities.compactMap {
|
||||
PasswordTableEntry($0)
|
||||
}
|
||||
|
||||
|
||||
parentPasswordEntity = parent
|
||||
}
|
||||
|
||||
@IBAction func cancelAddPassword(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
func cancelAddPassword(segue _: UIStoryboardSegue) {}
|
||||
|
||||
}
|
||||
@IBAction func saveAddPassword(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
func saveAddPassword(segue: UIStoryboardSegue) {
|
||||
if let controller = segue.source as? AddPasswordTableViewController {
|
||||
addPassword(password: controller.password!)
|
||||
}
|
||||
|
|
@ -149,13 +151,13 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
SVProgressHUD.show(withStatus: "Saving".localize())
|
||||
DispatchQueue.global(qos: .userInitiated).async {
|
||||
do {
|
||||
let _ = try self.passwordStore.add(password: password, keyID: keyID)
|
||||
_ = try self.passwordStore.add(password: password, keyID: keyID)
|
||||
DispatchQueue.main.async {
|
||||
// will trigger reloadTableView() by a notification
|
||||
SVProgressHUD.showSuccess(withStatus: "Done".localize())
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
}
|
||||
} catch AppError.PgpPublicKeyNotFound(let key) {
|
||||
} catch let AppError.PgpPublicKeyNotFound(key) {
|
||||
DispatchQueue.main.async {
|
||||
// alert: cancel or select keys
|
||||
SVProgressHUD.dismiss()
|
||||
|
|
@ -190,15 +192,15 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
|
||||
DispatchQueue.global(qos: .userInitiated).async { [unowned self] in
|
||||
do {
|
||||
try self.passwordStore.pullRepository(credential: self.gitCredential, requestCredentialPassword: self.requestCredentialPassword, progressBlock: {(git_transfer_progress, stop) in
|
||||
try self.passwordStore.pullRepository(credential: self.gitCredential, requestCredentialPassword: self.requestCredentialPassword, progressBlock: { git_transfer_progress, _ in
|
||||
DispatchQueue.main.async {
|
||||
SVProgressHUD.showProgress(Float(git_transfer_progress.pointee.received_objects)/Float(git_transfer_progress.pointee.total_objects), status: "PullingFromRemoteRepository".localize())
|
||||
SVProgressHUD.showProgress(Float(git_transfer_progress.pointee.received_objects) / Float(git_transfer_progress.pointee.total_objects), status: "PullingFromRemoteRepository".localize())
|
||||
}
|
||||
})
|
||||
if self.passwordStore.numberOfLocalCommits > 0 {
|
||||
try self.passwordStore.pushRepository(credential: self.gitCredential, requestCredentialPassword: self.requestCredentialPassword, transferProgressBlock: {(current, total, bytes, stop) in
|
||||
try self.passwordStore.pushRepository(credential: self.gitCredential, requestCredentialPassword: self.requestCredentialPassword, transferProgressBlock: { current, total, _, _ in
|
||||
DispatchQueue.main.async {
|
||||
SVProgressHUD.showProgress(Float(current)/Float(total), status: "PushingToRemoteRepository".localize())
|
||||
SVProgressHUD.showProgress(Float(current) / Float(total), status: "PushingToRemoteRepository".localize())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -232,7 +234,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
super.viewDidAppear(animated)
|
||||
|
||||
if Defaults.isShowFolderOn {
|
||||
searchController.searchBar.scopeButtonTitles = SearchBarScope.allCases.map { $0.localizedName }
|
||||
searchController.searchBar.scopeButtonTitles = SearchBarScope.allCases.map(\.localizedName)
|
||||
} else {
|
||||
searchController.searchBar.scopeButtonTitles = nil
|
||||
}
|
||||
|
|
@ -251,7 +253,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
navigationItem.hidesSearchBarWhenScrolling = false
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
tableView.contentInset = UIEdgeInsets.init(top: 44, left: 0, bottom: 0, right: 0)
|
||||
tableView.contentInset = UIEdgeInsets(top: 44, left: 0, bottom: 0, right: 0)
|
||||
view.addSubview(searchBarView!)
|
||||
}
|
||||
navigationItem.title = "PasswordStore".localize()
|
||||
|
|
@ -272,16 +274,17 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
NotificationCenter.default.addObserver(self, selector: #selector(actOnReloadTableViewRelatedNotification), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
|
||||
// listen to the swipe back guesture
|
||||
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(self.respondToSwipeGesture))
|
||||
let swipeRight = UISwipeGestureRecognizer(target: self, action: #selector(respondToSwipeGesture))
|
||||
swipeRight.direction = UISwipeGestureRecognizer.Direction.right
|
||||
self.view.addGestureRecognizer(swipeRight)
|
||||
view.addGestureRecognizer(swipeRight)
|
||||
}
|
||||
|
||||
@objc func didTapNavigationBar(_ sender: UITapGestureRecognizer) {
|
||||
let location = sender.location(in: self.navigationController?.navigationBar)
|
||||
let hitView = self.navigationController?.navigationBar.hitTest(location, with: nil)
|
||||
@objc
|
||||
func didTapNavigationBar(_ sender: UITapGestureRecognizer) {
|
||||
let location = sender.location(in: navigationController?.navigationBar)
|
||||
let hitView = navigationController?.navigationBar.hitTest(location, with: nil)
|
||||
guard !(hitView is UIControl) else { return }
|
||||
guard (passwordStore.numberOfLocalCommits != 0) else { return }
|
||||
guard passwordStore.numberOfLocalCommits != 0 else { return }
|
||||
|
||||
let ac = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let allAction = UIAlertAction(title: "All Passwords", style: .default) { _ in
|
||||
|
|
@ -289,7 +292,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
let unsyncedAction = UIAlertAction(title: "Unsynced Passwords", style: .default) { _ in
|
||||
let filteredPasswordsTableEntries = self.passwordsTableEntries.filter { entry in
|
||||
return !entry.synced
|
||||
!entry.synced
|
||||
}
|
||||
self.reloadTableView(data: filteredPasswordsTableEntries, label: .unsynced)
|
||||
}
|
||||
|
|
@ -299,7 +302,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
ac.addAction(unsyncedAction)
|
||||
ac.addAction(cancelAction)
|
||||
|
||||
self.present(ac, animated: true, completion: nil)
|
||||
present(ac, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
|
@ -310,7 +313,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
// Add gesture recognizer to the navigation bar when the view is about to appear
|
||||
self.navigationController?.navigationBar.addGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
navigationController?.navigationBar.addGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
|
||||
// This allows controlls in the navigation bar to continue receiving touches
|
||||
tapNavigationBarGestureRecognizer.cancelsTouchesInView = false
|
||||
|
|
@ -318,9 +321,9 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
tableView.refreshControl = passwordStore.repositoryExists() ? syncControl : nil
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
override func viewWillDisappear(_: Bool) {
|
||||
// Remove gesture recognizer from navigation bar when view is about to disappear
|
||||
self.navigationController?.navigationBar.removeGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
navigationController?.navigationBar.removeGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
|
|
@ -332,12 +335,12 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
}
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return sections.count
|
||||
func numberOfSections(in _: UITableView) -> Int {
|
||||
sections.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return sections[section].entries.count
|
||||
func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
sections[section].entries.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
|
@ -372,7 +375,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
private func getPasswordEntry(by indexPath: IndexPath) -> PasswordTableEntry {
|
||||
return sections[indexPath.section].entries[indexPath.row]
|
||||
sections[indexPath.section].entries[indexPath.row]
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
|
@ -390,16 +393,18 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
}
|
||||
|
||||
@objc func respondToSwipeGesture(gesture: UIGestureRecognizer) {
|
||||
@objc
|
||||
func respondToSwipeGesture(gesture: UIGestureRecognizer) {
|
||||
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
|
||||
// swipe right -> swipe back
|
||||
if swipeGesture.direction == .right && parentPasswordEntity != nil {
|
||||
self.backAction(nil)
|
||||
if swipeGesture.direction == .right, parentPasswordEntity != nil {
|
||||
backAction(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc func backAction(_ sender: Any?) {
|
||||
@objc
|
||||
func backAction(_: Any?) {
|
||||
guard Defaults.isShowFolderOn else { return }
|
||||
var anim: CATransition? = transitionFromLeft
|
||||
if parentPasswordEntity == nil {
|
||||
|
|
@ -408,13 +413,15 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
reloadTableView(parent: parentPasswordEntity?.parent, anim: anim)
|
||||
}
|
||||
|
||||
@objc func addPasswordAction(_ sender: Any?) {
|
||||
@objc
|
||||
func addPasswordAction(_: Any?) {
|
||||
if shouldPerformSegue(withIdentifier: "addPasswordSegue", sender: self) {
|
||||
performSegue(withIdentifier: "addPasswordSegue", sender: self)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func longPressAction(_ gesture: UILongPressGestureRecognizer) {
|
||||
@objc
|
||||
func longPressAction(_ gesture: UILongPressGestureRecognizer) {
|
||||
if gesture.state == UIGestureRecognizer.State.began {
|
||||
let touchPoint = gesture.location(in: tableView)
|
||||
if let indexPath = tableView.indexPathForRow(at: touchPoint) {
|
||||
|
|
@ -424,31 +431,31 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
private func hideSectionHeader() -> Bool {
|
||||
if passwordsTableEntries.count < hideSectionHeaderThreshold || self.searchController.isActive {
|
||||
if passwordsTableEntries.count < hideSectionHeaderThreshold || searchController.isActive {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
func tableView(_: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if hideSectionHeader() {
|
||||
return nil
|
||||
}
|
||||
return sections[section].title
|
||||
}
|
||||
|
||||
func sectionIndexTitles(for tableView: UITableView) -> [String]? {
|
||||
func sectionIndexTitles(for _: UITableView) -> [String]? {
|
||||
if hideSectionHeader() {
|
||||
return nil
|
||||
}
|
||||
return sections.map { $0.title }
|
||||
return sections.map(\.title)
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
|
||||
return index
|
||||
func tableView(_: UITableView, sectionForSectionIndexTitle _: String, at index: Int) -> Int {
|
||||
index
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||
func tableView(_: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||
decryptThenCopyPassword(from: indexPath)
|
||||
}
|
||||
|
||||
|
|
@ -460,7 +467,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
let passwordEntity = getPasswordEntry(by: indexPath).passwordEntity
|
||||
UIImpactFeedbackGenerator(style: .medium).impactOccurred()
|
||||
SVProgressHUD.dismiss()
|
||||
self.decryptPassword(passwordEntity: passwordEntity)
|
||||
decryptPassword(passwordEntity: passwordEntity)
|
||||
}
|
||||
|
||||
private func decryptPassword(passwordEntity: PasswordEntity, keyID: String? = nil) {
|
||||
|
|
@ -476,7 +483,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
SVProgressHUD.showSuccess(withStatus: "PasswordCopiedToPasteboard.".localize())
|
||||
SVProgressHUD.dismiss(withDelay: 0.6)
|
||||
}
|
||||
} catch AppError.PgpPrivateKeyNotFound(let key) {
|
||||
} catch let AppError.PgpPrivateKeyNotFound(key) {
|
||||
DispatchQueue.main.async {
|
||||
// alert: cancel or try again
|
||||
let alert = UIAlertController(title: "CannotShowPassword".localize(), message: AppError.PgpPrivateKeyNotFound(keyID: key).localizedDescription, preferredStyle: .alert)
|
||||
|
|
@ -488,7 +495,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
|
||||
self.present(alert, animated: true)
|
||||
}
|
||||
} catch {
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
Utils.alert(title: "CannotCopyPassword".localize(), message: error.localizedDescription, controller: self)
|
||||
}
|
||||
|
|
@ -496,14 +503,13 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private func generateSections(item: [PasswordTableEntry]) {
|
||||
let collation = UILocalizedIndexedCollation.current()
|
||||
let sectionTitles = collation.sectionIndexTitles
|
||||
var newSections = [(title: String, entries: [PasswordTableEntry])]()
|
||||
|
||||
// initialize all sections
|
||||
for i in 0..<sectionTitles.count {
|
||||
for i in 0 ..< sectionTitles.count {
|
||||
newSections.append((title: sectionTitles[i], entries: [PasswordTableEntry]()))
|
||||
}
|
||||
|
||||
|
|
@ -514,21 +520,21 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
// sort each list and set sectionTitles
|
||||
for i in 0..<sectionTitles.count {
|
||||
for i in 0 ..< sectionTitles.count {
|
||||
let entriesToSort = newSections[i].entries
|
||||
let sortedEntries = collation.sortedArray(from: entriesToSort, collationStringSelector: #selector(getter: PasswordTableEntry.title))
|
||||
newSections[i].entries = sortedEntries as! [PasswordTableEntry]
|
||||
}
|
||||
|
||||
// only keep non-empty sections
|
||||
sections = newSections.filter {$0.entries.count > 0}
|
||||
sections = newSections.filter { !$0.entries.isEmpty }
|
||||
}
|
||||
|
||||
@objc func actOnSearchNotification() {
|
||||
@objc
|
||||
func actOnSearchNotification() {
|
||||
searchController.searchBar.becomeFirstResponder()
|
||||
}
|
||||
|
||||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if identifier == "showPasswordDetail" {
|
||||
guard PGPAgent.shared.isPrepared else {
|
||||
|
|
@ -540,7 +546,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
return false
|
||||
}
|
||||
} else if identifier == "addPasswordSegue" {
|
||||
guard PGPAgent.shared.isPrepared && self.passwordStore.storeRepository != nil else {
|
||||
guard PGPAgent.shared.isPrepared && passwordStore.storeRepository != nil else {
|
||||
Utils.alert(title: "CannotAddPassword".localize(), message: "MakeSurePgpAndGitProperlySet.".localize(), controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
|
|
@ -551,7 +557,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if segue.identifier == "showPasswordDetail" {
|
||||
if let viewController = segue.destination as? PasswordDetailTableViewController {
|
||||
let selectedIndexPath = self.tableView.indexPath(for: sender as! UITableViewCell)!
|
||||
let selectedIndexPath = tableView.indexPath(for: sender as! UITableViewCell)!
|
||||
let passwordEntity = getPasswordEntry(by: selectedIndexPath).passwordEntity
|
||||
viewController.passwordEntity = passwordEntity
|
||||
}
|
||||
|
|
@ -568,8 +574,8 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
|
||||
func filterContentForSearchText(searchText: String, scope: SearchBarScope = .all) {
|
||||
var entries: [PasswordTableEntry] = scope == .all ? passwordsTableAllEntries : passwordsTableEntries
|
||||
if searchController.isActive && searchController.searchBar.text != "" {
|
||||
entries = entries.filter {$0.match(searchText)}
|
||||
if searchController.isActive, searchController.searchBar.text != "" {
|
||||
entries = entries.filter { $0.match(searchText) }
|
||||
}
|
||||
reloadTableView(data: entries)
|
||||
}
|
||||
|
|
@ -587,7 +593,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
if #available(iOS 11, *) {
|
||||
navigationController?.navigationBar.prefersLargeTitles = false
|
||||
}
|
||||
self.navigationController?.navigationBar.removeGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
navigationController?.navigationBar.removeGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
} else {
|
||||
navigationItem.leftBarButtonItem = nil
|
||||
switch label {
|
||||
|
|
@ -599,17 +605,17 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
if #available(iOS 11, *) {
|
||||
navigationController?.navigationBar.prefersLargeTitles = true
|
||||
}
|
||||
self.navigationController?.navigationBar.addGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
navigationController?.navigationBar.addGestureRecognizer(tapNavigationBarGestureRecognizer)
|
||||
}
|
||||
navigationItem.rightBarButtonItem = addPasswordUIBarButtonItem
|
||||
|
||||
// set the password table
|
||||
generateSections(item: data)
|
||||
if anim != nil {
|
||||
self.tableView.layer.add(anim!, forKey: "UITableViewReloadDataAnimationKey")
|
||||
tableView.layer.add(anim!, forKey: "UITableViewReloadDataAnimationKey")
|
||||
}
|
||||
tableView.reloadData()
|
||||
self.tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
||||
tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
||||
|
||||
// set the sync control title
|
||||
let atribbutedTitle = "LastSynced".localize() + ": \(lastSyncedTimeString())"
|
||||
|
|
@ -617,7 +623,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
private func lastSyncedTimeString() -> String {
|
||||
guard let date = self.passwordStore.lastSyncedTime else {
|
||||
guard let date = passwordStore.lastSyncedTime else {
|
||||
return "SyncAgain?".localize()
|
||||
}
|
||||
let formatter = DateFormatter()
|
||||
|
|
@ -631,7 +637,8 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
reloadTableView(data: passwordsTableEntries, label: label, anim: anim)
|
||||
}
|
||||
|
||||
@objc func actOnReloadTableViewRelatedNotification() {
|
||||
@objc
|
||||
func actOnReloadTableViewRelatedNotification() {
|
||||
DispatchQueue.main.async { [weak weakSelf = self] in
|
||||
guard let strongSelf = weakSelf else { return }
|
||||
// Reset selectedScopeButtonIndex to make sure the correct reloadTableView
|
||||
|
|
@ -641,36 +648,37 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
}
|
||||
|
||||
@objc func handleRefresh(_ syncControl: UIRefreshControl) {
|
||||
@objc
|
||||
func handleRefresh(_: UIRefreshControl) {
|
||||
syncPasswords()
|
||||
}
|
||||
|
||||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
||||
if viewController == self.navigationController {
|
||||
func tabBarController(_: UITabBarController, didSelect viewController: UIViewController) {
|
||||
if viewController == navigationController {
|
||||
let currentTime = Date().timeIntervalSince1970
|
||||
let duration = currentTime - self.tapTabBarTime
|
||||
self.tapTabBarTime = currentTime
|
||||
let duration = currentTime - tapTabBarTime
|
||||
tapTabBarTime = currentTime
|
||||
if duration < 0.35 {
|
||||
let topIndexPath = IndexPath(row: 0, section: 0)
|
||||
if tableView.numberOfSections > 0 {
|
||||
tableView.scrollToRow(at: topIndexPath, at: .bottom, animated: true)
|
||||
}
|
||||
self.tapTabBarTime = 0
|
||||
if tableView.numberOfSections > 0 {
|
||||
tableView.scrollToRow(at: topIndexPath, at: .bottom, animated: true)
|
||||
}
|
||||
tapTabBarTime = 0
|
||||
return
|
||||
}
|
||||
backAction(self)
|
||||
}
|
||||
}
|
||||
|
||||
func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
|
||||
func searchBar(_: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) {
|
||||
// update the default search scope
|
||||
Defaults.searchDefault = SearchBarScope(rawValue: selectedScope)
|
||||
updateSearchResults(for: searchController)
|
||||
}
|
||||
|
||||
func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool {
|
||||
func searchBarShouldBeginEditing(_: UISearchBar) -> Bool {
|
||||
// set the default search scope to "all"
|
||||
if Defaults.isShowFolderOn && Defaults.searchDefault == .all {
|
||||
if Defaults.isShowFolderOn, Defaults.searchDefault == .all {
|
||||
searchController.searchBar.selectedScopeButtonIndex = SearchBarScope.all.rawValue
|
||||
} else {
|
||||
searchController.searchBar.selectedScopeButtonIndex = SearchBarScope.current.rawValue
|
||||
|
|
@ -678,7 +686,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
return true
|
||||
}
|
||||
|
||||
func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
|
||||
func searchBarShouldEndEditing(_: UISearchBar) -> Bool {
|
||||
// set the default search scope to "current"
|
||||
searchController.searchBar.selectedScopeButtonIndex = SearchBarScope.current.rawValue
|
||||
updateSearchResults(for: searchController)
|
||||
|
|
@ -686,13 +694,11 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
|
||||
private func requestCredentialPassword(credential: GitCredential.Credential, lastPassword: String?) -> String? {
|
||||
return requestGitCredentialPassword(credential: credential, lastPassword: lastPassword, controller: self)
|
||||
requestGitCredentialPassword(credential: credential, lastPassword: lastPassword, controller: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension PasswordsViewController: UISearchResultsUpdating {
|
||||
|
||||
func updateSearchResults(for searchController: UISearchController) {
|
||||
let scope = SearchBarScope(rawValue: searchController.searchBar.selectedScopeButtonIndex) ?? .all
|
||||
filterContentForSearchText(searchText: searchController.searchBar.text!, scope: scope)
|
||||
|
|
@ -700,8 +706,7 @@ extension PasswordsViewController: UISearchResultsUpdating {
|
|||
}
|
||||
|
||||
extension PasswordsViewController: CAAnimationDelegate {
|
||||
|
||||
func animationDidStart(_ anim: CAAnimation) {
|
||||
func animationDidStart(_: CAAnimation) {
|
||||
view.window?.backgroundColor = Colors.systemBackground
|
||||
view.layer.backgroundColor = Colors.systemBackground.cgColor
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
// Copyright © 2017 Yishi Lin. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AVFoundation
|
||||
import OneTimePassword
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
protocol QRScannerControllerDelegate {
|
||||
func checkScannedOutput(line: String) -> (accept: Bool, message: String)
|
||||
|
|
@ -18,8 +18,7 @@ protocol QRScannerControllerDelegate {
|
|||
}
|
||||
|
||||
class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
|
||||
|
||||
@IBOutlet weak var scannerOutput: UILabel!
|
||||
@IBOutlet var scannerOutput: UILabel!
|
||||
|
||||
var captureSession: AVCaptureSession?
|
||||
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
|
||||
|
|
@ -93,15 +92,12 @@ class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDeleg
|
|||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
|
||||
// MARK: - AVCaptureMetadataOutputObjectsDelegate Methods
|
||||
|
||||
func metadataOutput(_ captureOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
|
||||
|
||||
func metadataOutput(_: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from _: AVCaptureConnection) {
|
||||
if let metadataObj = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
|
||||
supportedCodeTypes.contains(metadataObj.type),
|
||||
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj) {
|
||||
|
||||
// draw a bounds on the found QR code
|
||||
qrCodeFrameView?.frame = barCodeObject.bounds
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class RawPasswordViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var rawPasswordTextView: UITextView!
|
||||
@IBOutlet var rawPasswordTextView: UITextView!
|
||||
var password: Password?
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
|
|
|||
|
|
@ -6,13 +6,12 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import passKit
|
||||
import UIKit
|
||||
|
||||
class SSHKeyArmorImportTableViewController: AutoCellHeightUITableViewController, UITextViewDelegate, QRScannerControllerDelegate {
|
||||
|
||||
@IBOutlet weak var armorPrivateKeyTextView: UITextView!
|
||||
@IBOutlet weak var scanPrivateKeyCell: UITableViewCell!
|
||||
@IBOutlet var armorPrivateKeyTextView: UITextView!
|
||||
@IBOutlet var scanPrivateKeyCell: UITableViewCell!
|
||||
|
||||
var gitSSHPrivateKeyPassphrase: String?
|
||||
var armorPrivateKey: String?
|
||||
|
|
@ -22,32 +21,33 @@ class SSHKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
var message = ""
|
||||
|
||||
func reset() {
|
||||
self.segments.removeAll()
|
||||
segments.removeAll()
|
||||
message = "LookingForStartingFrame.".localize()
|
||||
}
|
||||
|
||||
func addSegment(segment: String) -> (accept: Bool, message: String) {
|
||||
// Skip duplicated segments.
|
||||
guard segment != self.segments.last else {
|
||||
return (accept: false, message: self.message)
|
||||
guard segment != segments.last else {
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
|
||||
|
||||
// Check whether we have found the first block.
|
||||
guard !self.segments.isEmpty || segment.contains("-----BEGIN") else {
|
||||
return (accept: false, message: self.message)
|
||||
guard !segments.isEmpty || segment.contains("-----BEGIN") else {
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
|
||||
|
||||
// Update the list of scanned segment and return.
|
||||
self.segments.append(segment)
|
||||
segments.append(segment)
|
||||
if segment.range(of: "-----END.*KEY-----", options: .regularExpression, range: nil, locale: nil) != nil {
|
||||
self.message = "Done".localize()
|
||||
return (accept: true, message: self.message)
|
||||
message = "Done".localize()
|
||||
return (accept: true, message: message)
|
||||
} else {
|
||||
self.message = "ScannedQrCodes(%d)".localize(self.segments.count)
|
||||
return (accept: false, message: self.message)
|
||||
message = "ScannedQrCodes(%d)".localize(segments.count)
|
||||
return (accept: false, message: message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scanned = ScannedSSHKey()
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
|
@ -59,12 +59,13 @@ class SSHKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
scanPrivateKeyCell?.accessoryType = .disclosureIndicator
|
||||
}
|
||||
|
||||
@IBAction func doneButtonTapped(_ sender: Any) {
|
||||
@IBAction
|
||||
func doneButtonTapped(_: Any) {
|
||||
armorPrivateKey = armorPrivateKeyTextView.text
|
||||
performSegue(withIdentifier: "importSSHKeySegue", sender: self)
|
||||
}
|
||||
|
||||
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
|
||||
func textView(_: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
|
||||
if text == UIPasteboard.general.string {
|
||||
// user pastes something, do the copy here again and clear the pasteboard in 45s
|
||||
SecurePasteboard.shared.copy(textToCopy: text)
|
||||
|
|
@ -76,23 +77,24 @@ class SSHKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
let selectedCell = tableView.cellForRow(at: indexPath)
|
||||
if selectedCell == scanPrivateKeyCell {
|
||||
scanned.reset()
|
||||
self.performSegue(withIdentifier: "showSSHScannerSegue", sender: self)
|
||||
performSegue(withIdentifier: "showSSHScannerSegue", sender: self)
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
|
||||
func checkScannedOutput(line: String) -> (accept: Bool, message: String) {
|
||||
return scanned.addSegment(segment: line)
|
||||
}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
func handleScannedOutput(line: String) {
|
||||
|
||||
func handleScannedOutput(line _: String) {
|
||||
armorPrivateKeyTextView.text = scanned.segments.joined(separator: "")
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
override func prepare(for segue: UIStoryboardSegue, sender _: Any?) {
|
||||
if segue.identifier == "showSSHScannerSegue" {
|
||||
if let navController = segue.destination as? UINavigationController {
|
||||
if let viewController = navController.topViewController as? QRScannerController {
|
||||
|
|
@ -104,13 +106,11 @@ class SSHKeyArmorImportTableViewController: AutoCellHeightUITableViewController,
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction private func cancelSSHScanner(segue: UIStoryboardSegue) {
|
||||
|
||||
}
|
||||
@IBAction
|
||||
private func cancelSSHScanner(segue _: UIStoryboardSegue) {}
|
||||
}
|
||||
|
||||
extension SSHKeyArmorImportTableViewController: KeyImporter {
|
||||
|
||||
static let keySource = KeySource.armor
|
||||
static let label = "AsciiArmorEncryptedKey".localize()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,12 @@ import passKit
|
|||
import SVProgressHUD
|
||||
|
||||
class SSHKeyFileImportTableViewController: AutoCellHeightUITableViewController {
|
||||
@IBOutlet var sshPrivateKeyFile: UITableViewCell!
|
||||
|
||||
@IBOutlet weak var sshPrivateKeyFile: UITableViewCell!
|
||||
private var privateKey: String?
|
||||
|
||||
private var privateKey: String? = nil
|
||||
|
||||
@IBAction func doneButtonTapped(_ sender: Any) {
|
||||
@IBAction
|
||||
func doneButtonTapped(_: Any) {
|
||||
performSegue(withIdentifier: "importSSHKeySegue", sender: self)
|
||||
}
|
||||
|
||||
|
|
@ -35,7 +35,6 @@ class SSHKeyFileImportTableViewController: AutoCellHeightUITableViewController {
|
|||
}
|
||||
|
||||
extension SSHKeyFileImportTableViewController: UIDocumentPickerDelegate {
|
||||
|
||||
func documentPicker(_: UIDocumentPickerViewController, didPickDocumentsAt url: [URL]) {
|
||||
guard let url = url.first else {
|
||||
return
|
||||
|
|
@ -61,7 +60,6 @@ extension SSHKeyFileImportTableViewController: UIDocumentPickerDelegate {
|
|||
}
|
||||
|
||||
extension SSHKeyFileImportTableViewController: KeyImporter {
|
||||
|
||||
static let keySource = KeySource.file
|
||||
static let label = "LoadFromFiles".localize()
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,11 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
|
||||
class SSHKeyUrlImportTableViewController: AutoCellHeightUITableViewController {
|
||||
|
||||
@IBOutlet weak var privateKeyURLTextField: UITextField!
|
||||
@IBOutlet var privateKeyURLTextField: UITextField!
|
||||
|
||||
var sshPrivateKeyURL: URL?
|
||||
|
||||
|
|
@ -20,11 +19,12 @@ class SSHKeyUrlImportTableViewController: AutoCellHeightUITableViewController {
|
|||
privateKeyURLTextField.text = Defaults.gitSSHPrivateKeyURL?.absoluteString
|
||||
}
|
||||
|
||||
@IBAction func doneButtonTapped(_ sender: UIButton) {
|
||||
@IBAction
|
||||
func doneButtonTapped(_: UIButton) {
|
||||
guard let text = privateKeyURLTextField.text,
|
||||
let privateKeyURL = URL(string: text) else {
|
||||
Utils.alert(title: "CannotSave".localize(), message: "SetPrivateKeyUrl.".localize(), controller: self)
|
||||
return
|
||||
Utils.alert(title: "CannotSave".localize(), message: "SetPrivateKeyUrl.".localize(), controller: self)
|
||||
return
|
||||
}
|
||||
|
||||
if privateKeyURL.scheme?.lowercased() == "http" {
|
||||
|
|
@ -41,7 +41,6 @@ class SSHKeyUrlImportTableViewController: AutoCellHeightUITableViewController {
|
|||
}
|
||||
|
||||
extension SSHKeyUrlImportTableViewController: KeyImporter {
|
||||
|
||||
static let keySource = KeySource.url
|
||||
static let label = "DownloadFromUrl".localize()
|
||||
|
||||
|
|
|
|||
|
|
@ -10,15 +10,16 @@ import UIKit
|
|||
|
||||
class SettingsSplitViewController: UISplitViewController, UISplitViewControllerDelegate {
|
||||
override func viewDidLoad() {
|
||||
self.delegate = self
|
||||
self.preferredDisplayMode = .allVisible
|
||||
delegate = self
|
||||
preferredDisplayMode = .allVisible
|
||||
}
|
||||
|
||||
func splitViewController(
|
||||
_ splitViewController: UISplitViewController,
|
||||
collapseSecondary secondaryViewController: UIViewController,
|
||||
onto primaryViewController: UIViewController) -> Bool {
|
||||
_: UISplitViewController,
|
||||
collapseSecondary _: UIViewController,
|
||||
onto _: UIViewController
|
||||
) -> Bool {
|
||||
// Return true to prevent UIKit from applying its default behavior
|
||||
return true
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,26 +6,27 @@
|
|||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SVProgressHUD
|
||||
import CoreData
|
||||
import passKit
|
||||
import SVProgressHUD
|
||||
import UIKit
|
||||
|
||||
class SettingsTableViewController: UITableViewController, UITabBarControllerDelegate {
|
||||
@IBOutlet weak var pgpKeyTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var passcodeTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var passwordRepositoryTableViewCell: UITableViewCell!
|
||||
@IBOutlet var pgpKeyTableViewCell: UITableViewCell!
|
||||
@IBOutlet var passcodeTableViewCell: UITableViewCell!
|
||||
@IBOutlet var passwordRepositoryTableViewCell: UITableViewCell!
|
||||
var setPasscodeLockAlert: UIAlertController?
|
||||
|
||||
let passwordStore = PasswordStore.shared
|
||||
let keychain = AppKeychain.shared
|
||||
var passcodeLock = PasscodeLock.shared
|
||||
|
||||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
||||
func tabBarController(_: UITabBarController, didSelect _: UIViewController) {
|
||||
navigationController?.popViewController(animated: true)
|
||||
}
|
||||
|
||||
@IBAction func savePGPKey(segue: UIStoryboardSegue) {
|
||||
@IBAction
|
||||
func savePGPKey(segue: UIStoryboardSegue) {
|
||||
guard let sourceController = segue.source as? PGPKeyImporter, sourceController.isReadyToUse() else {
|
||||
return
|
||||
}
|
||||
|
|
@ -58,19 +59,20 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
}
|
||||
}
|
||||
|
||||
@IBAction func saveGitServerSetting(segue: UIStoryboardSegue) {
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
|
||||
@IBAction
|
||||
func saveGitServerSetting(segue _: UIStoryboardSegue) {
|
||||
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(SettingsTableViewController.actOnPasswordStoreErasedNotification), name: .passwordStoreErased, object: nil)
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
|
||||
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults.gitURL.host
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasscodeLockCell()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
override func viewWillAppear(_: Bool) {
|
||||
super.viewWillAppear(true)
|
||||
tabBarController!.delegate = self
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
|
|
@ -78,9 +80,9 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
|
||||
private func setPasscodeLockCell() {
|
||||
if passcodeLock.hasPasscode {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "On".localize()
|
||||
passcodeTableViewCell.detailTextLabel?.text = "On".localize()
|
||||
} else {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "Off".localize()
|
||||
passcodeTableViewCell.detailTextLabel?.text = "Off".localize()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +109,8 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
passwordRepositoryTableViewCell.detailTextLabel?.text = host
|
||||
}
|
||||
|
||||
@objc func actOnPasswordStoreErasedNotification() {
|
||||
@objc
|
||||
func actOnPasswordStoreErasedNotification() {
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
setPasscodeLockCell()
|
||||
|
|
@ -180,9 +183,8 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let passcodeRemoveViewController = PasscodeLockViewController()
|
||||
|
||||
|
||||
let removePasscodeAction = UIAlertAction(title: "RemovePasscode".localize(), style: .destructive) { [weak self] _ in
|
||||
passcodeRemoveViewController.successCallback = {
|
||||
passcodeRemoveViewController.successCallback = {
|
||||
self?.passcodeLock.delete()
|
||||
self?.setPasscodeLockCell()
|
||||
}
|
||||
|
|
@ -198,10 +200,11 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
optionMenu.addAction(UIAlertAction.cancel())
|
||||
optionMenu.popoverPresentationController?.sourceView = passcodeTableViewCell
|
||||
optionMenu.popoverPresentationController?.sourceRect = passcodeTableViewCell.bounds
|
||||
self.present(optionMenu, animated: true, completion: nil)
|
||||
present(optionMenu, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@objc func alertTextFieldDidChange(_ sender: UITextField) {
|
||||
@objc
|
||||
func alertTextFieldDidChange(_ sender: UITextField) {
|
||||
// check whether we should enable the Save button in setPasscodeLockAlert
|
||||
if let setPasscodeLockAlert = self.setPasscodeLockAlert,
|
||||
let setPasscodeLockAlertTextFields0 = setPasscodeLockAlert.textFields?[0],
|
||||
|
|
@ -218,25 +221,25 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
func setPasscodeLock() {
|
||||
// prepare the alert for setting the passcode
|
||||
setPasscodeLockAlert = UIAlertController(title: "SetPasscode".localize(), message: "FillInAppPasscode.".localize(), preferredStyle: .alert)
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: { (_ textField: UITextField) -> Void in
|
||||
textField.placeholder = "Passcode".localize()
|
||||
textField.isSecureTextEntry = true
|
||||
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
|
||||
})
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: { (_ textField: UITextField) -> Void in
|
||||
textField.placeholder = "PasswordConfirmation".localize()
|
||||
textField.isSecureTextEntry = true
|
||||
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControl.Event.editingChanged)
|
||||
})
|
||||
|
||||
// save action
|
||||
let saveAction = UIAlertAction(title: "Save".localize(), style: .default) { (action:UIAlertAction) -> Void in
|
||||
let saveAction = UIAlertAction(title: "Save".localize(), style: .default) { (_: UIAlertAction) -> Void in
|
||||
let passcode: String = self.setPasscodeLockAlert!.textFields![0].text!
|
||||
self.passcodeLock.save(passcode: passcode)
|
||||
// refresh the passcode lock cell ("On")
|
||||
self.setPasscodeLockCell()
|
||||
}
|
||||
saveAction.isEnabled = false // disable the Save button by default
|
||||
saveAction.isEnabled = false // disable the Save button by default
|
||||
|
||||
// cancel action
|
||||
let cancelAction = UIAlertAction.cancel()
|
||||
|
|
@ -244,17 +247,16 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
// present
|
||||
setPasscodeLockAlert?.addAction(saveAction)
|
||||
setPasscodeLockAlert?.addAction(cancelAction)
|
||||
self.present(setPasscodeLockAlert!, animated: true, completion: nil)
|
||||
present(setPasscodeLockAlert!, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension SettingsTableViewController: PGPKeyImporter {
|
||||
|
||||
static let keySource = KeySource.itunes
|
||||
static let label = "ITunesFileSharing".localize()
|
||||
|
||||
func isReadyToUse() -> Bool {
|
||||
return KeyFileManager.PublicPgp.doesKeyFileExist() && KeyFileManager.PrivatePgp.doesKeyFileExist()
|
||||
KeyFileManager.PublicPgp.doesKeyFileExist() && KeyFileManager.PrivatePgp.doesKeyFileExist()
|
||||
}
|
||||
|
||||
func importKeys() throws {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class SpecialThanksTableViewController: BasicStaticTableViewController {
|
|||
"https://icons8.com"],
|
||||
["FlatIcon",
|
||||
"https://www.flaticon.com"],
|
||||
]
|
||||
]
|
||||
|
||||
override func viewDidLoad() {
|
||||
tableData.append([])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue