diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 9daa812..b202f31 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -26,7 +26,7 @@ 30697C2A21F63C5A0064FCAC /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2321F63C580064FCAC /* NotificationNames.swift */; }; 30697C2B21F63C5A0064FCAC /* Globals.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2421F63C590064FCAC /* Globals.swift */; }; 30697C2C21F63C5A0064FCAC /* FileManagerExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2521F63C590064FCAC /* FileManagerExtension.swift */; }; - 30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavour.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */; }; + 30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */; }; 30697C2E21F63C5A0064FCAC /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2721F63C590064FCAC /* Utils.swift */; }; 30697C2F21F63C5A0064FCAC /* DefaultsKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2821F63C590064FCAC /* DefaultsKeys.swift */; }; 30697C3021F63C5A0064FCAC /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30697C2921F63C590064FCAC /* AppError.swift */; }; @@ -249,7 +249,7 @@ 30697C2321F63C580064FCAC /* NotificationNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationNames.swift; sourceTree = ""; }; 30697C2421F63C590064FCAC /* Globals.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Globals.swift; sourceTree = ""; }; 30697C2521F63C590064FCAC /* FileManagerExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileManagerExtension.swift; sourceTree = ""; }; - 30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGeneratorFlavour.swift; sourceTree = ""; }; + 30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordGeneratorFlavor.swift; sourceTree = ""; }; 30697C2721F63C590064FCAC /* Utils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 30697C2821F63C590064FCAC /* DefaultsKeys.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultsKeys.swift; sourceTree = ""; }; 30697C2921F63C590064FCAC /* AppError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = ""; }; @@ -678,7 +678,7 @@ 3032327322C7F710009EBD9C /* KeyFileManager.swift */, 30BAC8CC22E3BB9700438475 /* KeyStore.swift */, 30697C2321F63C580064FCAC /* NotificationNames.swift */, - 30697C2621F63C590064FCAC /* PasswordGeneratorFlavour.swift */, + 30697C2621F63C590064FCAC /* PasswordGeneratorFlavor.swift */, 302202EE222F14E400555236 /* SearchBarScope.swift */, 30697C2721F63C590064FCAC /* Utils.swift */, ); @@ -1305,7 +1305,7 @@ 30697C2B21F63C5A0064FCAC /* Globals.swift in Sources */, 30697C4821F63CAB0064FCAC /* PasswordStore.swift in Sources */, A26075AD1EEC7125005DB03E /* pass.xcdatamodeld in Sources */, - 30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavour.swift in Sources */, + 30697C2D21F63C5A0064FCAC /* PasswordGeneratorFlavor.swift in Sources */, 308C273A2279F9CB0016D0E2 /* SearchBarScope.swift in Sources */, 30697C2F21F63C5A0064FCAC /* DefaultsKeys.swift in Sources */, 30A1D2A821B2D53200E2D1F7 /* PasswordChange.swift in Sources */, diff --git a/pass/Base.lproj/Main.storyboard b/pass/Base.lproj/Main.storyboard index de1ea7d..2ed6e88 100644 --- a/pass/Base.lproj/Main.storyboard +++ b/pass/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -809,7 +809,7 @@ - + @@ -1968,6 +1968,6 @@ Secret Question 1: What is your childhood best friend's most bizarre superhero f - + diff --git a/pass/Controllers/AddPasswordTableViewController.swift b/pass/Controllers/AddPasswordTableViewController.swift index bae6b2e..75d770a 100644 --- a/pass/Controllers/AddPasswordTableViewController.swift +++ b/pass/Controllers/AddPasswordTableViewController.swift @@ -10,22 +10,11 @@ import UIKit import passKit class AddPasswordTableViewController: PasswordEditorTableViewController { - let passwordStore = PasswordStore.shared var defaultDirPrefix = "" override func viewDidLoad() { - tableData = [ - [[.type: PasswordEditorCellType.nameCell, .title: "name"]], - [[.type: PasswordEditorCellType.fillPasswordCell, .title: "password"]], - [[.type: PasswordEditorCellType.additionsCell, .title: "additions"]], - [[.type: PasswordEditorCellType.scanQRCodeCell]] - ] - if PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor) == .RANDOM { - tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"]) - } - tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell]) - tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix super.viewDidLoad() + tableData[0][0][PasswordEditorCellKey.content] = defaultDirPrefix } override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { @@ -39,7 +28,7 @@ class AddPasswordTableViewController: PasswordEditorTableViewController { } // check name - guard checkName() == true else { + guard checkName() else { return false } } diff --git a/pass/Controllers/EditPasswordTableViewController.swift b/pass/Controllers/EditPasswordTableViewController.swift index 32b2132..107f1df 100644 --- a/pass/Controllers/EditPasswordTableViewController.swift +++ b/pass/Controllers/EditPasswordTableViewController.swift @@ -10,25 +10,10 @@ import UIKit import passKit class EditPasswordTableViewController: PasswordEditorTableViewController { - override func viewDidLoad() { - tableData = [ - [[.type: PasswordEditorCellType.nameCell, .title: "Name".localize(), .content: password!.namePath]], - [[.type: PasswordEditorCellType.fillPasswordCell, .title: "Password".localize(), .content: password!.password]], - [[.type: PasswordEditorCellType.additionsCell, .title: "Additions".localize(), .content: password!.additionsPlainText]], - [[.type: PasswordEditorCellType.scanQRCodeCell], - [.type: PasswordEditorCellType.deletePasswordCell]] - ] - if PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor) == .RANDOM { - tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"]) - } - tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell]) - super.viewDidLoad() - } - override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { if identifier == "saveEditPasswordSegue" { // check name - guard checkName() == true else { + guard checkName() else { return false } } diff --git a/pass/Controllers/GeneralSettingsTableViewController.swift b/pass/Controllers/GeneralSettingsTableViewController.swift index 8d2cca3..de1d0e5 100644 --- a/pass/Controllers/GeneralSettingsTableViewController.swift +++ b/pass/Controllers/GeneralSettingsTableViewController.swift @@ -144,7 +144,7 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { hidePasswordImagesSwitch.isOn = Defaults.isHidePasswordImagesOn case "PasswordGeneratorFlavor".localize(): cell.accessoryType = .disclosureIndicator - cell.detailTextLabel?.text = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).name + cell.detailTextLabel?.text = Defaults.passwordGeneratorFlavor.localized default: break } return cell @@ -161,31 +161,26 @@ class GeneralSettingsTableViewController: BasicStaticTableViewController { func showPasswordGeneratorFlavorActionSheet(sourceCell: UITableViewCell) { let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) - var randomFlavorActionTitle = "" - var appleFlavorActionTitle = "" - if Defaults.passwordGeneratorFlavor == PasswordGeneratorFlavour.RANDOM.rawValue { - randomFlavorActionTitle = "✓ " + "RandomString".localize() - appleFlavorActionTitle = "ApplesKeychainStyle".localize() - } else { - randomFlavorActionTitle = "RandomString".localize() - appleFlavorActionTitle = "✓ " + "ApplesKeychainStyle".localize() - } - let randomFlavorAction = UIAlertAction(title: randomFlavorActionTitle, style: .default) { _ in - Defaults.passwordGeneratorFlavor = PasswordGeneratorFlavour.RANDOM.rawValue - sourceCell.detailTextLabel?.text = PasswordGeneratorFlavour.RANDOM.name - } - let appleFlavorAction = UIAlertAction(title: appleFlavorActionTitle, style: .default) { _ in - Defaults.passwordGeneratorFlavor = PasswordGeneratorFlavour.APPLE.rawValue - sourceCell.detailTextLabel?.text = PasswordGeneratorFlavour.APPLE.name + PasswordGeneratorFlavor.allCases.forEach { flavor in + let actionTitlePrefix = Defaults.passwordGeneratorFlavor + var actionTitle = flavor.longNameLocalized + if Defaults.passwordGeneratorFlavor == flavor { + actionTitle = "✓ " + actionTitle + } + let action = UIAlertAction(title: actionTitle, style: .default) { _ in + Defaults.passwordGeneratorFlavor = flavor + sourceCell.detailTextLabel?.text = Defaults.passwordGeneratorFlavor.localized + } + optionMenu.addAction(action) } let cancelAction = UIAlertAction(title: "Cancel".localize(), style: .cancel, handler: nil) - optionMenu.addAction(randomFlavorAction) - optionMenu.addAction(appleFlavorAction) optionMenu.addAction(cancelAction) + optionMenu.popoverPresentationController?.sourceView = sourceCell optionMenu.popoverPresentationController?.sourceRect = sourceCell.bounds + self.present(optionMenu, animated: true, completion: nil) } diff --git a/pass/Controllers/PasswordEditorTableViewController.swift b/pass/Controllers/PasswordEditorTableViewController.swift index 9ab75fb..0f02028 100644 --- a/pass/Controllers/PasswordEditorTableViewController.swift +++ b/pass/Controllers/PasswordEditorTableViewController.swift @@ -89,9 +89,22 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 48 - self.tableView.sectionFooterHeight = UITableView.automaticDimension; - self.tableView.estimatedSectionFooterHeight = 0; + self.tableView.sectionFooterHeight = UITableView.automaticDimension + self.tableView.estimatedSectionFooterHeight = 0 + + tableData = [ + [[.type: PasswordEditorCellType.nameCell, .title: "Name".localize(), .content: password?.namePath ?? ""]], + [[.type: PasswordEditorCellType.fillPasswordCell, .title: "Password".localize(), .content: password?.password ?? ""]], + [[.type: PasswordEditorCellType.additionsCell, .title: "Additions".localize(), .content: password?.additionsPlainText ?? ""]], + [[.type: PasswordEditorCellType.scanQRCodeCell], + [.type: PasswordEditorCellType.deletePasswordCell]] + ] + if Defaults.passwordGeneratorFlavor == .random { + tableData[1].append([.type: PasswordEditorCellType.passwordLengthCell, .title: "passwordlength"]) + } + tableData[1].append([.type: PasswordEditorCellType.memorablePasswordGeneratorCell]) } + override func viewDidLayoutSubviews() { additionsCell?.contentTextView.setContentOffset(.zero, animated: false) } @@ -116,7 +129,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl return fillPasswordCell! case .passwordLengthCell: passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell - let lengthSetting = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).defaultLength + let lengthSetting = Defaults.passwordGeneratorFlavor.defaultLength let minimumLength = lengthSetting.min let maximumLength = lengthSetting.max var defaultLength = lengthSetting.def @@ -215,7 +228,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl showPasswordSettings() let length = passwordLengthCell?.roundedValue ?? 0 - let plainPassword = PasswordGeneratorFlavour.from(Defaults.passwordGeneratorFlavor).generatePassword(length: length) + let plainPassword = Defaults.passwordGeneratorFlavor.generate(length: length) // update tableData so to make sure reloadData() works correctly tableData[passwordSection][0][PasswordEditorCellKey.content] = plainPassword diff --git a/passKit/Helpers/DefaultsKeys.swift b/passKit/Helpers/DefaultsKeys.swift index 202212f..3f6ab56 100644 --- a/passKit/Helpers/DefaultsKeys.swift +++ b/passKit/Helpers/DefaultsKeys.swift @@ -19,6 +19,8 @@ public enum GitAuthenticationMethod: String, DefaultsSerializable { case password, key } +extension PasswordGeneratorFlavor: DefaultsSerializable {} + public extension DefaultsKeys { var pgpKeySource: DefaultsKey { .init("pgpKeySource") } var pgpPublicKeyURL: DefaultsKey { .init("pgpPublicKeyURL") } @@ -50,7 +52,7 @@ public extension DefaultsKeys { var isShowFolderOn: DefaultsKey { .init("isShowFolderOn", defaultValue: true) } var isHidePasswordImagesOn: DefaultsKey { .init("isHidePasswordImagesOn", defaultValue: false) } var searchDefault: DefaultsKey { .init("searchDefault", defaultValue: .all) } - var passwordGeneratorFlavor: DefaultsKey { .init("passwordGeneratorFlavor", defaultValue: "Apple") } + var passwordGeneratorFlavor: DefaultsKey { .init("passwordGeneratorFlavor", defaultValue: .apple) } var encryptInArmored: DefaultsKey { .init("encryptInArmored", defaultValue: false) } } diff --git a/passKit/Helpers/PasswordGeneratorFlavor.swift b/passKit/Helpers/PasswordGeneratorFlavor.swift new file mode 100644 index 0000000..1f50299 --- /dev/null +++ b/passKit/Helpers/PasswordGeneratorFlavor.swift @@ -0,0 +1,52 @@ +// +// PasswordGeneratorFlavour.swift +// passKit +// +// Created by Danny Moesch on 28.11.18. +// Copyright © 2018 Bob Sun. All rights reserved. +// + +import KeychainAccess + +public enum PasswordGeneratorFlavor: String { + case apple = "Apple" + case random = "Random" + + public var localized: String { + return rawValue.localize() + } + + public var longNameLocalized: String { + switch self { + case .apple: + return "ApplesKeychainStyle".localize() + case .random: + return "RandomString".localize() + } + } + + public var defaultLength: (min: Int, max: Int, def: Int) { + switch self { + case .apple: + return (15, 15, 15) + case .random: + return (4, 64, 16) + } + } + + public func generate(length: Int) -> String { + switch self { + case .apple: + return Keychain.generatePassword() + case .random: + return PasswordGeneratorFlavor.generateRandom(length: length) + } + } + + private static func generateRandom(length: Int) -> String { + let chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*_+-=" + return String((0.. PasswordGeneratorFlavour { - return PasswordGeneratorFlavour(rawValue: option) ?? PasswordGeneratorFlavour.RANDOM - } - - public var name: String { - return rawValue.localize() - } - - public var defaultLength: (min: Int, max: Int, def: Int) { - switch self { - case .APPLE: - return (15, 15, 15) - default: - return (4, 64, 16) - } - } - - public func generatePassword(length: Int) -> String { - switch self { - case .APPLE: - return Keychain.generatePassword() - default: - return PasswordGeneratorFlavour.randomString(length: length) - } - } - - private static func randomString(length: Int) -> String { - return String((0..