Polish the code
- Move somethings from view controller to the model "PasswordStore" - Simplify the logic of PasswordsViewController (especially about reloadTableView) - Mark many variables/methods private
This commit is contained in:
parent
95b3a7fcd3
commit
2b5c5cad97
3 changed files with 65 additions and 79 deletions
|
|
@ -25,13 +25,14 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
private var passwordsTableEntries: [PasswordsTableEntry] = []
|
private var passwordsTableEntries: [PasswordsTableEntry] = []
|
||||||
private var filteredPasswordsTableEntries: [PasswordsTableEntry] = []
|
private var filteredPasswordsTableEntries: [PasswordsTableEntry] = []
|
||||||
private var parentPasswordEntity: PasswordEntity? = nil
|
private var parentPasswordEntity: PasswordEntity? = nil
|
||||||
let passwordStore = PasswordStore.shared
|
private let passwordStore = PasswordStore.shared
|
||||||
|
|
||||||
private var tapTabBarTime: TimeInterval = 0
|
private var tapTabBarTime: TimeInterval = 0
|
||||||
|
|
||||||
var sections : [(index: Int, length :Int, title: String)] = Array()
|
private var sections : [(index: Int, length :Int, title: String)] = Array()
|
||||||
var searchActive : Bool = false
|
private var searchActive : Bool = false
|
||||||
lazy var searchController: UISearchController = {
|
|
||||||
|
private lazy var searchController: UISearchController = {
|
||||||
let uiSearchController = UISearchController(searchResultsController: nil)
|
let uiSearchController = UISearchController(searchResultsController: nil)
|
||||||
uiSearchController.searchResultsUpdater = self
|
uiSearchController.searchResultsUpdater = self
|
||||||
uiSearchController.dimsBackgroundDuringPresentation = false
|
uiSearchController.dimsBackgroundDuringPresentation = false
|
||||||
|
|
@ -40,22 +41,22 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
uiSearchController.searchBar.sizeToFit()
|
uiSearchController.searchBar.sizeToFit()
|
||||||
return uiSearchController
|
return uiSearchController
|
||||||
}()
|
}()
|
||||||
lazy var refreshControl: UIRefreshControl = {
|
private lazy var syncControl: UIRefreshControl = {
|
||||||
let refreshControl = UIRefreshControl()
|
let syncControl = UIRefreshControl()
|
||||||
refreshControl.addTarget(self, action: #selector(PasswordsViewController.handleRefresh(_:)), for: UIControlEvents.valueChanged)
|
syncControl.addTarget(self, action: #selector(handleRefresh(_:)), for: UIControlEvents.valueChanged)
|
||||||
return refreshControl
|
return syncControl
|
||||||
}()
|
}()
|
||||||
lazy var searchBarView: UIView = {
|
private lazy var searchBarView: UIView = {
|
||||||
let uiView = UIView(frame: CGRect(x: 0, y: 64, width: UIScreen.main.bounds.width, height: 44))
|
let uiView = UIView(frame: CGRect(x: 0, y: 64, width: self.view.bounds.width, height: 44))
|
||||||
uiView.addSubview(self.searchController.searchBar)
|
uiView.addSubview(self.searchController.searchBar)
|
||||||
return uiView
|
return uiView
|
||||||
}()
|
}()
|
||||||
lazy var backUIBarButtonItem: UIBarButtonItem = {
|
private lazy var backUIBarButtonItem: UIBarButtonItem = {
|
||||||
let backUIBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(self.backAction(_:)))
|
let backUIBarButtonItem = UIBarButtonItem(title: "Back", style: .plain, target: self, action: #selector(self.backAction(_:)))
|
||||||
return backUIBarButtonItem
|
return backUIBarButtonItem
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var transitionFromRight: CATransition = {
|
private lazy var transitionFromRight: CATransition = {
|
||||||
let transition = CATransition()
|
let transition = CATransition()
|
||||||
transition.type = kCATransitionPush
|
transition.type = kCATransitionPush
|
||||||
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
|
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
|
||||||
|
|
@ -65,7 +66,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
return transition
|
return transition
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var transitionFromLeft: CATransition = {
|
private lazy var transitionFromLeft: CATransition = {
|
||||||
let transition = CATransition()
|
let transition = CATransition()
|
||||||
transition.type = kCATransitionPush
|
transition.type = kCATransitionPush
|
||||||
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
|
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
|
||||||
|
|
@ -122,7 +123,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncPasswords() {
|
private func syncPasswords() {
|
||||||
SVProgressHUD.setDefaultMaskType(.black)
|
SVProgressHUD.setDefaultMaskType(.black)
|
||||||
SVProgressHUD.setDefaultStyle(.light)
|
SVProgressHUD.setDefaultStyle(.light)
|
||||||
SVProgressHUD.show(withStatus: "Sync Password Store")
|
SVProgressHUD.show(withStatus: "Sync Password Store")
|
||||||
|
|
@ -142,11 +143,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.passwordStore.updatePasswordEntityCoreData()
|
self.reloadTableView(parent: nil)
|
||||||
self.initPasswordsTableEntries(parent: nil)
|
|
||||||
self.reloadTableView(data: self.passwordsTableEntries)
|
|
||||||
self.passwordStore.setAllSynced()
|
|
||||||
self.setNavigationItemTitle()
|
|
||||||
Defaults[.lastUpdatedTime] = Date()
|
Defaults[.lastUpdatedTime] = Date()
|
||||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
Defaults[.gitRepositoryPasswordAttempts] = 0
|
||||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||||
|
|
@ -160,31 +157,27 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func addNotificationObservers() {
|
|
||||||
// reset the data table if some password (maybe another one) has been updated
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(PasswordsViewController.actOnPasswordStoreUpdatedNotification), name: .passwordStoreUpdated, object: nil)
|
|
||||||
|
|
||||||
// reset the data table if the disaply settings have been changed
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(actOnPasswordStoreUpdatedNotification), name: .passwordDisplaySettingChanged, object: nil)
|
|
||||||
|
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(PasswordsViewController.actOnSearchNotification), name: .passwordSearch, object: nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setNavigationItemTitle()
|
|
||||||
initPasswordsTableEntries(parent: nil)
|
|
||||||
addNotificationObservers()
|
|
||||||
generateSections(item: passwordsTableEntries)
|
|
||||||
tabBarController!.delegate = self
|
tabBarController!.delegate = self
|
||||||
tableView.delegate = self
|
tableView.delegate = self
|
||||||
tableView.dataSource = self
|
tableView.dataSource = self
|
||||||
definesPresentationContext = true
|
definesPresentationContext = true
|
||||||
view.addSubview(searchBarView)
|
view.addSubview(searchBarView)
|
||||||
tableView.insertSubview(refreshControl, at: 0)
|
tableView.insertSubview(syncControl, at: 0)
|
||||||
SVProgressHUD.setDefaultMaskType(.black)
|
SVProgressHUD.setDefaultMaskType(.black)
|
||||||
updateRefreshControlTitle()
|
|
||||||
tableView.register(UINib(nibName: "PasswordWithFolderTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordWithFolderTableViewCell")
|
tableView.register(UINib(nibName: "PasswordWithFolderTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordWithFolderTableViewCell")
|
||||||
|
|
||||||
|
// initialize the password table
|
||||||
|
reloadTableView(parent: nil)
|
||||||
|
|
||||||
|
// reset the data table if some password (maybe another one) has been updated
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(reloadTableView as (Void) -> Void), name: .passwordStoreUpdated, object: nil)
|
||||||
|
// reset the data table if the disaply settings have been changed
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(reloadTableView as (Void) -> Void), name: .passwordDisplaySettingChanged, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(actOnSearchNotification), name: .passwordSearch, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
|
@ -268,15 +261,13 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
} else {
|
} else {
|
||||||
tableView.deselectRow(at: indexPath, animated: true)
|
tableView.deselectRow(at: indexPath, animated: true)
|
||||||
searchController.isActive = false
|
searchController.isActive = false
|
||||||
initPasswordsTableEntries(parent: entry.passwordEntity)
|
reloadTableView(parent: entry.passwordEntity, anim: transitionFromRight)
|
||||||
reloadTableView(data: passwordsTableEntries, anim: transitionFromRight)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func backAction(_ sender: Any?) {
|
func backAction(_ sender: Any?) {
|
||||||
guard Defaults[.isShowFolderOn] else { return }
|
guard Defaults[.isShowFolderOn] else { return }
|
||||||
initPasswordsTableEntries(parent: parentPasswordEntity?.parent)
|
reloadTableView(parent: parentPasswordEntity?.parent, anim: transitionFromLeft)
|
||||||
reloadTableView(data: passwordsTableEntries, anim: transitionFromLeft)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func longPressAction(_ gesture: UILongPressGestureRecognizer) {
|
func longPressAction(_ gesture: UILongPressGestureRecognizer) {
|
||||||
|
|
@ -304,7 +295,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
copyToPasteboard(from: indexPath)
|
copyToPasteboard(from: indexPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyToPasteboard(from indexPath: IndexPath) {
|
private func copyToPasteboard(from indexPath: IndexPath) {
|
||||||
guard self.passwordStore.privateKey != nil else {
|
guard self.passwordStore.privateKey != nil else {
|
||||||
Utils.alert(title: "Cannot Copy Password", message: "PGP Key is not set. Please set your PGP Key first.", controller: self, completion: nil)
|
Utils.alert(title: "Cannot Copy Password", message: "PGP Key is not set. Please set your PGP Key first.", controller: self, completion: nil)
|
||||||
return
|
return
|
||||||
|
|
@ -330,7 +321,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptThenCopyPassword(passwordEntity: PasswordEntity, passphrase: String) {
|
private func decryptThenCopyPassword(passwordEntity: PasswordEntity, passphrase: String) {
|
||||||
SVProgressHUD.setDefaultMaskType(.black)
|
SVProgressHUD.setDefaultMaskType(.black)
|
||||||
SVProgressHUD.setDefaultStyle(.dark)
|
SVProgressHUD.setDefaultStyle(.dark)
|
||||||
SVProgressHUD.show(withStatus: "Decrypting")
|
SVProgressHUD.show(withStatus: "Decrypting")
|
||||||
|
|
@ -352,7 +343,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateSections(item: [PasswordsTableEntry]) {
|
private func generateSections(item: [PasswordsTableEntry]) {
|
||||||
sections.removeAll()
|
sections.removeAll()
|
||||||
guard item.count != 0 else {
|
guard item.count != 0 else {
|
||||||
return
|
return
|
||||||
|
|
@ -374,27 +365,6 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
sections.append(newSection)
|
sections.append(newSection)
|
||||||
}
|
}
|
||||||
|
|
||||||
func actOnPasswordStoreUpdatedNotification() {
|
|
||||||
initPasswordsTableEntries(parent: nil)
|
|
||||||
reloadTableView(data: passwordsTableEntries)
|
|
||||||
setNavigationItemTitle()
|
|
||||||
}
|
|
||||||
|
|
||||||
private func setNavigationItemTitle() {
|
|
||||||
var title = ""
|
|
||||||
if parentPasswordEntity != nil {
|
|
||||||
title = parentPasswordEntity!.name!
|
|
||||||
} else {
|
|
||||||
title = "Password Store"
|
|
||||||
}
|
|
||||||
let numberOfLocalCommits = self.passwordStore.numberOfLocalCommits()
|
|
||||||
if numberOfLocalCommits == 0 {
|
|
||||||
navigationItem.title = "\(title)"
|
|
||||||
} else {
|
|
||||||
navigationItem.title = "\(title) (\(numberOfLocalCommits))"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func actOnSearchNotification() {
|
func actOnSearchNotification() {
|
||||||
searchController.searchBar.becomeFirstResponder()
|
searchController.searchBar.becomeFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
@ -435,32 +405,47 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateRefreshControlTitle() {
|
private func reloadTableView(data: [PasswordsTableEntry], anim: CAAnimation? = nil) {
|
||||||
var atribbutedTitle = "Pull to Sync Password Store"
|
// set navigation item
|
||||||
atribbutedTitle = "Last Synced: \(Utils.getLastUpdatedTimeString())"
|
var numberOfLocalCommitsString = ""
|
||||||
refreshControl.attributedTitle = NSAttributedString(string: atribbutedTitle)
|
let numberOfLocalCommits = self.passwordStore.numberOfLocalCommits()
|
||||||
}
|
if numberOfLocalCommits > 0 {
|
||||||
|
numberOfLocalCommitsString = " (\(numberOfLocalCommits))"
|
||||||
func reloadTableView(data: [PasswordsTableEntry], anim: CAAnimation? = nil) {
|
}
|
||||||
|
|
||||||
if parentPasswordEntity != nil {
|
if parentPasswordEntity != nil {
|
||||||
|
navigationItem.title = "\(parentPasswordEntity!.name!)\(numberOfLocalCommitsString)"
|
||||||
navigationItem.leftBarButtonItem = backUIBarButtonItem
|
navigationItem.leftBarButtonItem = backUIBarButtonItem
|
||||||
} else {
|
} else {
|
||||||
|
navigationItem.title = "Password Store\(numberOfLocalCommitsString)"
|
||||||
navigationItem.leftBarButtonItem = nil
|
navigationItem.leftBarButtonItem = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set the password table
|
||||||
generateSections(item: data)
|
generateSections(item: data)
|
||||||
if anim != nil {
|
if anim != nil {
|
||||||
self.tableView.layer.add(anim!, forKey: "UITableViewReloadDataAnimationKey")
|
self.tableView.layer.add(anim!, forKey: "UITableViewReloadDataAnimationKey")
|
||||||
}
|
}
|
||||||
tableView.reloadData()
|
tableView.reloadData()
|
||||||
self.tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
self.tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
||||||
updateRefreshControlTitle()
|
|
||||||
setNavigationItemTitle()
|
// set the sync control title
|
||||||
|
let atribbutedTitle = "Last Synced: \(Utils.getLastUpdatedTimeString())"
|
||||||
|
syncControl.attributedTitle = NSAttributedString(string: atribbutedTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRefresh(_ refreshControl: UIRefreshControl) {
|
private func reloadTableView(parent: PasswordEntity?, anim: CAAnimation? = nil) {
|
||||||
|
initPasswordsTableEntries(parent: parent)
|
||||||
|
reloadTableView(data: passwordsTableEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reloadTableView() {
|
||||||
|
initPasswordsTableEntries(parent: nil)
|
||||||
|
reloadTableView(data: passwordsTableEntries)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRefresh(_ syncControl: UIRefreshControl) {
|
||||||
syncPasswords()
|
syncPasswords()
|
||||||
refreshControl.endRefreshing()
|
syncControl.endRefreshing()
|
||||||
}
|
}
|
||||||
|
|
||||||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,6 @@ class SettingsTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.passwordStore.updatePasswordEntityCoreData()
|
|
||||||
Defaults[.lastUpdatedTime] = Date()
|
Defaults[.lastUpdatedTime] = Date()
|
||||||
Defaults[.gitRepositoryURL] = URL(string: gitRepostiroyURL)
|
Defaults[.gitRepositoryURL] = URL(string: gitRepostiroyURL)
|
||||||
Defaults[.gitRepositoryUsername] = username
|
Defaults[.gitRepositoryUsername] = username
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,8 @@ class PasswordStore {
|
||||||
}
|
}
|
||||||
storeRepository = try GTRepository(url: storeURL)
|
storeRepository = try GTRepository(url: storeURL)
|
||||||
gitCredential = credential
|
gitCredential = credential
|
||||||
|
self.updatePasswordEntityCoreData()
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -298,12 +300,12 @@ class PasswordStore {
|
||||||
]
|
]
|
||||||
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||||
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
||||||
|
self.setAllSynced()
|
||||||
|
self.updatePasswordEntityCoreData()
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func updatePasswordEntityCoreData() {
|
||||||
|
|
||||||
func updatePasswordEntityCoreData() {
|
|
||||||
deleteCoreData(entityName: "PasswordEntity")
|
deleteCoreData(entityName: "PasswordEntity")
|
||||||
let fm = FileManager.default
|
let fm = FileManager.default
|
||||||
do {
|
do {
|
||||||
|
|
@ -657,10 +659,10 @@ class PasswordStore {
|
||||||
throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Cannot decide how to reset."])
|
throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Cannot decide how to reset."])
|
||||||
}
|
}
|
||||||
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
||||||
|
self.setAllSynced()
|
||||||
self.updatePasswordEntityCoreData()
|
self.updatePasswordEntityCoreData()
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
NotificationCenter.default.post(name: .passwordStoreChangeDiscarded, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreChangeDiscarded, object: nil)
|
||||||
self.setAllSynced()
|
|
||||||
return localCommits.count
|
return localCommits.count
|
||||||
} else {
|
} else {
|
||||||
return 0 // no new commit
|
return 0 // no new commit
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue