Self-maintained passcode lock
- No cancel button anywhere in the passcode lock yet - Poor UI
This commit is contained in:
parent
30ae08bed5
commit
da3c4f0bc0
10 changed files with 298 additions and 210 deletions
2
Cartfile
2
Cartfile
|
|
@ -1,8 +1,6 @@
|
|||
github "SVProgressHUD/SVProgressHUD"
|
||||
github "radex/SwiftyUserDefaults"
|
||||
github "libgit2/objective-git"
|
||||
# github "zahlz/SwiftPasscodeLock" "master"
|
||||
github "yishilin14/SwiftPasscodeLock" "app-extension-support"
|
||||
github "bitserf/FavIcon"
|
||||
github "kishikawakatsumi/KeychainAccess"
|
||||
github "mattrubin/OneTimePassword"
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@
|
|||
A26700371EEC475600176B8A /* passProcessor.js in Resources */ = {isa = PBXBuildFile; fileRef = A26700351EEC475600176B8A /* passProcessor.js */; };
|
||||
A2802BF91E70813A00879216 /* SliderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2802BF71E70813A00879216 /* SliderTableViewCell.swift */; };
|
||||
A2802BFA1E70813A00879216 /* SliderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = A2802BF81E70813A00879216 /* SliderTableViewCell.xib */; };
|
||||
A28C66651EF109D600A398A1 /* PasscodeLockConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28C66631EF109D600A398A1 /* PasscodeLockConfiguration.swift */; };
|
||||
A28C66661EF109D600A398A1 /* PasscodeLockRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28C66641EF109D600A398A1 /* PasscodeLockRepository.swift */; };
|
||||
A28C66681EF10EC900A398A1 /* PasscodeExtensionDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = A28C66671EF10EC900A398A1 /* PasscodeExtensionDisplay.swift */; };
|
||||
A2A61C131EEF90CB00CFE063 /* Base32.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A262A58C1E68749C006B0890 /* Base32.framework */; };
|
||||
A2A61C151EEF90CB00CFE063 /* KeychainAccess.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCA742D91E599ED400D54E16 /* KeychainAccess.framework */; };
|
||||
|
|
@ -39,6 +37,9 @@
|
|||
A2A61C201EEFABAD00CFE063 /* UtilsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2A61C1F1EEFABAD00CFE063 /* UtilsExtension.swift */; };
|
||||
A2A61C2C1EEFDF3300CFE063 /* ExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2A61C2B1EEFDF3300CFE063 /* ExtensionViewController.swift */; };
|
||||
A2A7813F1E97DBD9001311F5 /* QRScannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2A7813E1E97DBD9001311F5 /* QRScannerController.swift */; };
|
||||
A2C532BB201E5A9600DB9F53 /* PasscodeLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2C532BA201E5A9600DB9F53 /* PasscodeLock.swift */; };
|
||||
A2C532BE201E5AA100DB9F53 /* PasscodeLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2C532BC201E5AA000DB9F53 /* PasscodeLockViewController.swift */; };
|
||||
A2C532BF201E5AA100DB9F53 /* PasscodeLockPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2C532BD201E5AA100DB9F53 /* PasscodeLockPresenter.swift */; };
|
||||
A2F4E2141EED800F0011986E /* GitCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F4E2101EED800F0011986E /* GitCredential.swift */; };
|
||||
A2F4E2151EED800F0011986E /* Password.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F4E2111EED800F0011986E /* Password.swift */; };
|
||||
A2F4E2161EED800F0011986E /* PasswordEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F4E2121EED800F0011986E /* PasswordEntity.swift */; };
|
||||
|
|
@ -61,7 +62,6 @@
|
|||
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */; };
|
||||
DC13B1511E8640810097803F /* passTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC13B1501E8640810097803F /* passTests.swift */; };
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; };
|
||||
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; };
|
||||
DC3E64E61E656F11009A83DE /* CommitLogsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC3E64E51E656F11009A83DE /* CommitLogsTableViewController.swift */; };
|
||||
DC4914961E434301007FF592 /* LabelTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914941E434301007FF592 /* LabelTableViewCell.swift */; };
|
||||
DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */; };
|
||||
|
|
@ -191,8 +191,6 @@
|
|||
A26700351EEC475600176B8A /* passProcessor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = passProcessor.js; sourceTree = "<group>"; };
|
||||
A2802BF71E70813A00879216 /* SliderTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderTableViewCell.swift; sourceTree = "<group>"; };
|
||||
A2802BF81E70813A00879216 /* SliderTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SliderTableViewCell.xib; sourceTree = "<group>"; };
|
||||
A28C66631EF109D600A398A1 /* PasscodeLockConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasscodeLockConfiguration.swift; path = Models/PasscodeLockConfiguration.swift; sourceTree = "<group>"; };
|
||||
A28C66641EF109D600A398A1 /* PasscodeLockRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasscodeLockRepository.swift; path = Models/PasscodeLockRepository.swift; sourceTree = "<group>"; };
|
||||
A28C66671EF10EC900A398A1 /* PasscodeExtensionDisplay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeExtensionDisplay.swift; sourceTree = "<group>"; };
|
||||
A2A61C0C1EEF8DFE00CFE063 /* libPods-passExtension.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libPods-passExtension.a"; path = "../../Library/Developer/Xcode/DerivedData/pass-fwlmfsjroyvbfhdyqmglrwfhvjli/Build/Products/Debug-iphonesimulator/libPods-passExtension.a"; sourceTree = "<group>"; };
|
||||
A2A61C101EEF8E3500CFE063 /* libPods-passKit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libPods-passKit.a"; path = "Pods/../build/Debug-iphoneos/libPods-passKit.a"; sourceTree = "<group>"; };
|
||||
|
|
@ -200,6 +198,9 @@
|
|||
A2A61C2B1EEFDF3300CFE063 /* ExtensionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExtensionViewController.swift; sourceTree = "<group>"; };
|
||||
A2A7813E1E97DBD9001311F5 /* QRScannerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRScannerController.swift; sourceTree = "<group>"; };
|
||||
A2BC54C71EEE5669001FAFBD /* Objective-CBridgingHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Objective-CBridgingHeader.h"; sourceTree = "<group>"; };
|
||||
A2C532BA201E5A9600DB9F53 /* PasscodeLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasscodeLock.swift; path = Models/PasscodeLock.swift; sourceTree = "<group>"; };
|
||||
A2C532BC201E5AA000DB9F53 /* PasscodeLockViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasscodeLockViewController.swift; path = Controllers/PasscodeLockViewController.swift; sourceTree = "<group>"; };
|
||||
A2C532BD201E5AA100DB9F53 /* PasscodeLockPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasscodeLockPresenter.swift; path = Controllers/PasscodeLockPresenter.swift; sourceTree = "<group>"; };
|
||||
A2F4E2101EED800F0011986E /* GitCredential.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GitCredential.swift; path = Models/GitCredential.swift; sourceTree = "<group>"; };
|
||||
A2F4E2111EED800F0011986E /* Password.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Password.swift; path = Models/Password.swift; sourceTree = "<group>"; };
|
||||
A2F4E2121EED800F0011986E /* PasswordEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PasswordEntity.swift; path = Models/PasswordEntity.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -315,7 +316,6 @@
|
|||
files = (
|
||||
A260758D1EEC6F34005DB03E /* passKit.framework in Frameworks */,
|
||||
DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */,
|
||||
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */,
|
||||
18F19A67B0C07F13C17169E0 /* Pods_pass.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -344,11 +344,12 @@
|
|||
A26075791EEC6F34005DB03E /* passKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A2C532B9201DD07500DB9F53 /* Controllers */,
|
||||
A2F4E20F1EED7F0A0011986E /* Helpers */,
|
||||
A260757B1EEC6F34005DB03E /* Info.plist */,
|
||||
A2F4E20E1EED7F040011986E /* Models */,
|
||||
A26075A51EEC7125005DB03E /* pass.xcdatamodeld */,
|
||||
A2F4E20F1EED7F0A0011986E /* Helpers */,
|
||||
A260757A1EEC6F34005DB03E /* passKit.h */,
|
||||
A260757B1EEC6F34005DB03E /* Info.plist */,
|
||||
);
|
||||
path = passKit;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -376,11 +377,19 @@
|
|||
path = passExtension;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A2C532B9201DD07500DB9F53 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A2C532BD201E5AA100DB9F53 /* PasscodeLockPresenter.swift */,
|
||||
A2C532BC201E5AA000DB9F53 /* PasscodeLockViewController.swift */,
|
||||
);
|
||||
name = Controllers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A2F4E20E1EED7F040011986E /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A28C66631EF109D600A398A1 /* PasscodeLockConfiguration.swift */,
|
||||
A28C66641EF109D600A398A1 /* PasscodeLockRepository.swift */,
|
||||
A2C532BA201E5A9600DB9F53 /* PasscodeLock.swift */,
|
||||
A2F4E2101EED800F0011986E /* GitCredential.swift */,
|
||||
A2F4E2111EED800F0011986E /* Password.swift */,
|
||||
A2F4E2121EED800F0011986E /* PasswordEntity.swift */,
|
||||
|
|
@ -429,30 +438,30 @@
|
|||
DC19400C1E4B39400077E0A3 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DCD3C65D1EFB9BB400CBE842 /* SettingsSplitViewController.swift */,
|
||||
DC3E64E51E656F11009A83DE /* CommitLogsTableViewController.swift */,
|
||||
DC5F385A1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift */,
|
||||
DC037CB11E4CAB1700609409 /* AboutRepositoryTableViewController.swift */,
|
||||
DC962CDE1E4B62C10033B5D8 /* AboutTableViewController.swift */,
|
||||
DC037CB71E4DD1A500609409 /* AddPasswordTableViewController.swift */,
|
||||
DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */,
|
||||
DC037CA71E4B898100609409 /* BasicStaticTableViewController.swift */,
|
||||
DC3E64E51E656F11009A83DE /* CommitLogsTableViewController.swift */,
|
||||
DCFB77A61E502DF9008DE471 /* EditPasswordTableViewController.swift */,
|
||||
DC037CAF1E4CA51F00609409 /* GeneralSettingsTableViewController.swift */,
|
||||
A217ACE31E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift */,
|
||||
DCA049991E335CC800522E8F /* GitServerSettingTableViewController.swift */,
|
||||
DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */,
|
||||
DC037CA51E4B883900609409 /* OpenSourceComponentsTableViewController.swift */,
|
||||
A217ACE11E9AB17C00A1A6CF /* OTPScannerController.swift */,
|
||||
DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */,
|
||||
DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */,
|
||||
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */,
|
||||
DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */,
|
||||
DC5F385A1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift */,
|
||||
DCA0499B1E3362F400522E8F /* PGPKeySettingTableViewController.swift */,
|
||||
A2A7813E1E97DBD9001311F5 /* QRScannerController.swift */,
|
||||
DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */,
|
||||
DCD3C65D1EFB9BB400CBE842 /* SettingsSplitViewController.swift */,
|
||||
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
|
||||
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
|
||||
DC8963BF1E38EEB900828B09 /* SSHKeySettingTableViewController.swift */,
|
||||
DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */,
|
||||
A2A7813E1E97DBD9001311F5 /* QRScannerController.swift */,
|
||||
A217ACE11E9AB17C00A1A6CF /* OTPScannerController.swift */,
|
||||
A217ACE31E9BBBBD00A1A6CF /* GitConfigSettingTableViewController.swift */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -477,21 +486,21 @@
|
|||
DC19400F1E4B3A9E0077E0A3 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A2802BF71E70813A00879216 /* SliderTableViewCell.swift */,
|
||||
A2802BF81E70813A00879216 /* SliderTableViewCell.xib */,
|
||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
||||
DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */,
|
||||
DCFB779D1E4F40C7008DE471 /* FillPasswordTableViewCell.xib */,
|
||||
DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */,
|
||||
DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */,
|
||||
DC4914941E434301007FF592 /* LabelTableViewCell.swift */,
|
||||
DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */,
|
||||
DC037CB91E4DD47B00609409 /* TextFieldTableViewCell.swift */,
|
||||
DC037CBA1E4DD47B00609409 /* TextFieldTableViewCell.xib */,
|
||||
DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */,
|
||||
DCFB77A21E500D9C008DE471 /* PasswordDetailTitleTableViewCell.xib */,
|
||||
A2802BF71E70813A00879216 /* SliderTableViewCell.swift */,
|
||||
A2802BF81E70813A00879216 /* SliderTableViewCell.xib */,
|
||||
DC037CB91E4DD47B00609409 /* TextFieldTableViewCell.swift */,
|
||||
DC037CBA1E4DD47B00609409 /* TextFieldTableViewCell.xib */,
|
||||
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */,
|
||||
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */,
|
||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
||||
DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */,
|
||||
DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -984,7 +993,6 @@
|
|||
"$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/SwiftyUserDefaults.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/ObjectiveGit.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/PasscodeLock.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/FavIcon.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/KeychainAccess.framework",
|
||||
"$(SRCROOT)/Carthage/Build/iOS/OneTimePassword.framework",
|
||||
|
|
@ -1019,14 +1027,15 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A28C66661EF109D600A398A1 /* PasscodeLockRepository.swift in Sources */,
|
||||
A2C532BB201E5A9600DB9F53 /* PasscodeLock.swift in Sources */,
|
||||
A2F4E2151EED800F0011986E /* Password.swift in Sources */,
|
||||
A28C66651EF109D600A398A1 /* PasscodeLockConfiguration.swift in Sources */,
|
||||
A26075AD1EEC7125005DB03E /* pass.xcdatamodeld in Sources */,
|
||||
A2F4E21E1EED80160011986E /* AppError.swift in Sources */,
|
||||
A2F4E2171EED800F0011986E /* PasswordStore.swift in Sources */,
|
||||
A2F4E2211EED80160011986E /* NotificationNames.swift in Sources */,
|
||||
A2F4E2221EED80160011986E /* UITextFieldExtension.swift in Sources */,
|
||||
A2C532BF201E5AA100DB9F53 /* PasscodeLockPresenter.swift in Sources */,
|
||||
A2C532BE201E5AA100DB9F53 /* PasscodeLockViewController.swift in Sources */,
|
||||
A2F4E2201EED80160011986E /* Globals.swift in Sources */,
|
||||
A2F4E2231EED80160011986E /* Utils.swift in Sources */,
|
||||
A2F4E21F1EED80160011986E /* DefaultsKeys.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import UIKit
|
||||
import CoreData
|
||||
import PasscodeLock
|
||||
import SVProgressHUD
|
||||
import passKit
|
||||
|
||||
|
|
@ -21,7 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
}
|
||||
|
||||
lazy var passcodeLockPresenter: PasscodeLockPresenter = {
|
||||
let presenter = PasscodeLockPresenter(mainWindow: self.window, configuration: PasscodeLockConfiguration.shared)
|
||||
let presenter = PasscodeLockPresenter(mainWindow: self.window)
|
||||
return presenter
|
||||
}()
|
||||
|
||||
|
|
@ -92,7 +91,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
passcodeLockPresenter = PasscodeLockPresenter(mainWindow: self.window, configuration: PasscodeLockConfiguration.shared)
|
||||
passcodeLockPresenter.present(windowLevel: UIApplication.shared.windows.last?.windowLevel)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -195,29 +195,12 @@
|
|||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="touchIDTableViewCell" textLabel="H2E-hP-Gyf" style="IBUITableViewCellStyleDefault" id="wB7-Km-Oel">
|
||||
<rect key="frame" x="0.0" y="267" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wB7-Km-Oel" id="m90-X7-DbI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43.666666666666664"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Touch ID" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="H2E-hP-Gyf">
|
||||
<rect key="frame" x="20" y="0.0" width="374" height="43.666666666666664"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection id="6U8-ue-MhL">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="advancedTableViewCell" textLabel="MKj-d0-8q3" style="IBUITableViewCellStyleDefault" id="tQN-gu-iRe">
|
||||
<rect key="frame" x="0.0" y="347" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="303" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tQN-gu-iRe" id="Xs0-LN-r43">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
|
|
@ -241,7 +224,7 @@
|
|||
<tableViewSection id="T7L-rR-R9W">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="aboutTableViewCell" textLabel="oqz-Hr-RAl" style="IBUITableViewCellStyleDefault" id="osS-xk-WRP">
|
||||
<rect key="frame" x="0.0" y="427" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="383" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="osS-xk-WRP" id="G6j-ij-rNr">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
|
|
@ -273,7 +256,6 @@
|
|||
<outlet property="passcodeTableViewCell" destination="6Y0-mj-qhA" id="vkI-h5-GRo"/>
|
||||
<outlet property="passwordRepositoryTableViewCell" destination="2rc-ZW-XKd" id="aFq-K7-eIj"/>
|
||||
<outlet property="pgpKeyTableViewCell" destination="1ze-MS-Xbj" id="hXe-eD-0R4"/>
|
||||
<outlet property="touchIDTableViewCell" destination="wB7-Km-Oel" id="0fi-Sb-qMa"/>
|
||||
<segue destination="ZUt-x1-TJu" kind="showDetail" identifier="setPGPKeyByURLSegue" id="qRF-S1-bqF"/>
|
||||
<segue destination="ffY-rC-jhq" kind="showDetail" identifier="setPGPKeyByASCIISegue" id="mgi-Oe-i2X"/>
|
||||
</connections>
|
||||
|
|
|
|||
|
|
@ -9,25 +9,16 @@
|
|||
import UIKit
|
||||
import SVProgressHUD
|
||||
import CoreData
|
||||
import PasscodeLock
|
||||
import LocalAuthentication
|
||||
import passKit
|
||||
|
||||
class SettingsTableViewController: UITableViewController, UITabBarControllerDelegate {
|
||||
|
||||
lazy var touchIDSwitch: UISwitch = {
|
||||
let uiSwitch = UISwitch(frame: CGRect.zero)
|
||||
uiSwitch.onTintColor = Globals.blue
|
||||
uiSwitch.addTarget(self, action: #selector(touchIDSwitchAction), for: UIControlEvents.valueChanged)
|
||||
return uiSwitch
|
||||
}()
|
||||
|
||||
@IBOutlet weak var pgpKeyTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var touchIDTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var passcodeTableViewCell: UITableViewCell!
|
||||
@IBOutlet weak var passwordRepositoryTableViewCell: UITableViewCell!
|
||||
var setPasscodeLockAlert: UIAlertController?
|
||||
|
||||
let passwordStore = PasswordStore.shared
|
||||
var passcodeLockConfig = PasscodeLockConfiguration.shared
|
||||
var passcodeLock = PasscodeLock.shared
|
||||
|
||||
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
|
||||
navigationController?.popViewController(animated: true)
|
||||
|
|
@ -123,14 +114,6 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
// Security section, hide TouchID if the device doesn't support
|
||||
if section == 1 {
|
||||
if hasTouchID() {
|
||||
return 2
|
||||
} else {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return super.tableView(tableView, numberOfRowsInSection: section)
|
||||
}
|
||||
|
||||
|
|
@ -138,10 +121,9 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(SettingsTableViewController.actOnPasswordStoreErasedNotification), name: .passwordStoreErased, object: nil)
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = SharedDefaults[.gitURL]?.host
|
||||
touchIDTableViewCell.accessoryView = touchIDSwitch
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
setPasscodeLockTouchIDCells()
|
||||
setPasscodeLockCell()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
|
|
@ -149,38 +131,11 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
tabBarController!.delegate = self
|
||||
}
|
||||
|
||||
private func hasTouchID() -> Bool {
|
||||
let context = LAContext()
|
||||
var error: NSError?
|
||||
if context.canEvaluatePolicy(LAPolicy.deviceOwnerAuthenticationWithBiometrics, error: &error) {
|
||||
return true
|
||||
} else {
|
||||
switch error!.code {
|
||||
case LAError.Code.touchIDNotEnrolled.rawValue:
|
||||
return true
|
||||
case LAError.Code.passcodeNotSet.rawValue:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func isTouchIDEnabled() -> Bool {
|
||||
let context = LAContext()
|
||||
return context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
|
||||
}
|
||||
|
||||
private func setPasscodeLockTouchIDCells() {
|
||||
if passcodeLockConfig.repository.hasPasscode {
|
||||
private func setPasscodeLockCell() {
|
||||
if passcodeLock.hasPasscode {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "On"
|
||||
passcodeLockConfig.isTouchIDAllowed = SharedDefaults[.isTouchIDOn]
|
||||
touchIDSwitch.isOn = SharedDefaults[.isTouchIDOn]
|
||||
} else {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "Off"
|
||||
SharedDefaults[.isTouchIDOn] = false
|
||||
passcodeLockConfig.isTouchIDAllowed = SharedDefaults[.isTouchIDOn]
|
||||
touchIDSwitch.isOn = SharedDefaults[.isTouchIDOn]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -203,10 +158,10 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
@objc func actOnPasswordStoreErasedNotification() {
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
setPasscodeLockTouchIDCells()
|
||||
setPasscodeLockCell()
|
||||
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: passcodeLockConfig)
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
|
@ -221,22 +176,7 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
@objc func touchIDSwitchAction(uiSwitch: UISwitch) {
|
||||
if !passcodeLockConfig.repository.hasPasscode || !isTouchIDEnabled() {
|
||||
// switch off
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
|
||||
uiSwitch.isOn = SharedDefaults[.isTouchIDOn] // SharedDefaults[.isTouchIDOn] should be false
|
||||
Utils.alert(title: "Notice", message: "Please enable Touch ID of your phone and setup the passcode lock for Pass.", controller: self, completion: nil)
|
||||
}
|
||||
} else {
|
||||
SharedDefaults[.isTouchIDOn] = uiSwitch.isOn
|
||||
passcodeLockConfig.isTouchIDAllowed = SharedDefaults[.isTouchIDOn]
|
||||
}
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: passcodeLockConfig)
|
||||
}
|
||||
|
||||
|
||||
func showPGPKeyActionSheet() {
|
||||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
var urlActionTitle = "Download from URL"
|
||||
|
|
@ -314,21 +254,22 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
}
|
||||
|
||||
func showPasscodeActionSheet() {
|
||||
let passcodeChangeViewController = PasscodeLockViewController(state: .change, configuration: passcodeLockConfig)
|
||||
let passcodeRemoveViewController = PasscodeLockViewController(state: .remove, configuration: passcodeLockConfig)
|
||||
|
||||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let passcodeRemoveViewController = PasscodeLockViewController()
|
||||
|
||||
|
||||
let removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive) { [weak self] _ in
|
||||
passcodeRemoveViewController.successCallback = { _ in
|
||||
self?.setPasscodeLockTouchIDCells()
|
||||
passcodeRemoveViewController.successCallback = {
|
||||
self?.passcodeLock.delete()
|
||||
self?.setPasscodeLockCell()
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: (self?.passcodeLockConfig)!)
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window)
|
||||
}
|
||||
self?.present(passcodeRemoveViewController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let changePasscodeAction = UIAlertAction(title: "Change Passcode", style: .default) { [weak self] _ in
|
||||
self?.present(passcodeChangeViewController, animated: true, completion: nil)
|
||||
self?.setPasscodeLock()
|
||||
}
|
||||
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
|
||||
|
|
@ -339,12 +280,50 @@ class SettingsTableViewController: UITableViewController, UITabBarControllerDele
|
|||
optionMenu.popoverPresentationController?.sourceRect = passcodeTableViewCell.bounds
|
||||
self.present(optionMenu, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@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],
|
||||
let setPasscodeLockAlertTextFields1 = setPasscodeLockAlert.textFields?[1] {
|
||||
if sender == setPasscodeLockAlertTextFields0 || sender == setPasscodeLockAlertTextFields1 {
|
||||
// two passwords should be the same, and length >= 4
|
||||
let passcodeText = setPasscodeLockAlertTextFields0.text!
|
||||
let passcodeConfirmationText = setPasscodeLockAlertTextFields1.text!
|
||||
setPasscodeLockAlert.actions[0].isEnabled = passcodeText == passcodeConfirmationText && passcodeText.count >= 4
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setPasscodeLock() {
|
||||
let passcodeSetViewController = PasscodeLockViewController(state: .set, configuration: passcodeLockConfig)
|
||||
passcodeSetViewController.successCallback = { _ in
|
||||
self.setPasscodeLockTouchIDCells()
|
||||
// prepare the alert for setting the passcode
|
||||
setPasscodeLockAlert = UIAlertController(title: "Set passcode", message: "Fill in your passcode for Pass (at least 4 characters)", preferredStyle: .alert)
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in
|
||||
textField.placeholder = "Password"
|
||||
textField.isSecureTextEntry = true
|
||||
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControlEvents.editingChanged)
|
||||
})
|
||||
setPasscodeLockAlert?.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in
|
||||
textField.placeholder = "Password Confirmation"
|
||||
textField.isSecureTextEntry = true
|
||||
textField.addTarget(self, action: #selector(self.alertTextFieldDidChange(_:)), for: UIControlEvents.editingChanged)
|
||||
})
|
||||
|
||||
// save action
|
||||
let saveAction = UIAlertAction(title: "Save", style: .default) { (action:UIAlertAction) -> Void in
|
||||
let passcode: String = self.setPasscodeLockAlert!.textFields![0].text!
|
||||
self.passcodeLock.save(passcode: passcode)
|
||||
// refresh the passcode lock cell ("On")
|
||||
self.setPasscodeLockCell()
|
||||
}
|
||||
present(passcodeSetViewController, animated: true, completion: nil)
|
||||
saveAction.isEnabled = false // disable the Save button by default
|
||||
|
||||
// cancel action
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
|
||||
|
||||
// present
|
||||
setPasscodeLockAlert?.addAction(saveAction)
|
||||
setPasscodeLockAlert?.addAction(cancelAction)
|
||||
self.present(setPasscodeLockAlert!, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,46 +7,14 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import PasscodeLock
|
||||
import passKit
|
||||
|
||||
// add a cancel button in the passcode lock view
|
||||
struct CancelableEnterPasscodeState: PasscodeLockStateType {
|
||||
let title: String = "Enter passcode"
|
||||
let description: String = "Enter passcode"
|
||||
let isCancellableAction = true
|
||||
var isTouchIDAllowed = true
|
||||
mutating func accept(passcode: String, from lock: PasscodeLockType) {
|
||||
if lock.repository.check(passcode: passcode) {
|
||||
lock.delegate?.passcodeLockDidSucceed(lock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cancel means cancel the extension
|
||||
class PasscodeLockViewControllerForExtension: PasscodeLockViewController {
|
||||
var originalExtensionContest: NSExtensionContext?
|
||||
public convenience init(extensionContext: NSExtensionContext?, state: PasscodeLockStateType, configuration: PasscodeLockConfigurationType, animateOnDismiss: Bool = true) {
|
||||
self.init(state: state, configuration: configuration, animateOnDismiss: animateOnDismiss)
|
||||
originalExtensionContest = extensionContext
|
||||
}
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
cancelButton?.removeTarget(nil, action: nil, for: .allEvents)
|
||||
cancelButton?.addTarget(self, action: #selector(cancelExtension), for: .touchUpInside)
|
||||
}
|
||||
@objc func cancelExtension() {
|
||||
originalExtensionContest?.completeRequest(returningItems: [], completionHandler: nil)
|
||||
}
|
||||
}
|
||||
|
||||
class PasscodeExtensionDisplay {
|
||||
private var isPasscodePresented = false
|
||||
private let passcodeLockVC: PasscodeLockViewControllerForExtension
|
||||
private let passcodeLockVC: PasscodeLockViewController
|
||||
|
||||
init(extensionContext: NSExtensionContext?) {
|
||||
let cancelableEnter = CancelableEnterPasscodeState()
|
||||
passcodeLockVC = PasscodeLockViewControllerForExtension(extensionContext: extensionContext, state: cancelableEnter, configuration: PasscodeLockConfiguration.shared)
|
||||
passcodeLockVC = PasscodeLockViewController()
|
||||
passcodeLockVC.dismissCompletionCallback = { [weak self] in
|
||||
self?.dismiss()
|
||||
}
|
||||
|
|
@ -54,7 +22,7 @@ class PasscodeExtensionDisplay {
|
|||
|
||||
// present the passcode lock view if passcode is set and the view controller is not presented
|
||||
func presentPasscodeLockIfNeeded(_ extensionVC: ExtensionViewController) {
|
||||
guard PasscodeLockConfiguration.shared.repository.hasPasscode && !isPasscodePresented == true else {
|
||||
guard PasscodeLock.shared.hasPasscode && !isPasscodePresented == true else {
|
||||
return
|
||||
}
|
||||
isPasscodePresented = true
|
||||
|
|
|
|||
59
passKit/Controllers/PasscodeLockPresenter.swift
Normal file
59
passKit/Controllers/PasscodeLockPresenter.swift
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// PasscodeLockPresenter.swift
|
||||
// PasscodeLock
|
||||
//
|
||||
// Created by Yanko Dimitrov on 8/29/15.
|
||||
// Copyright © 2015 Yanko Dimitrov. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
open class PasscodeLockPresenter {
|
||||
|
||||
fileprivate var mainWindow: UIWindow?
|
||||
|
||||
fileprivate lazy var passcodeLockWindow = UIWindow(frame: UIScreen.main.bounds)
|
||||
|
||||
open var isPasscodePresented = false
|
||||
open let passcodeLockVC: PasscodeLockViewController
|
||||
|
||||
public init(mainWindow window: UIWindow?, viewController: PasscodeLockViewController) {
|
||||
mainWindow = window
|
||||
passcodeLockVC = viewController
|
||||
}
|
||||
|
||||
public convenience init(mainWindow window: UIWindow?) {
|
||||
let passcodeLockVC = PasscodeLockViewController()
|
||||
self.init(mainWindow: window, viewController: passcodeLockVC)
|
||||
}
|
||||
|
||||
open func present(windowLevel: CGFloat?) {
|
||||
guard PasscodeLock.shared.hasPasscode else { return }
|
||||
guard !isPasscodePresented else { return }
|
||||
|
||||
isPasscodePresented = true
|
||||
|
||||
mainWindow?.endEditing(true)
|
||||
moveWindowsToFront(windowLevel: windowLevel)
|
||||
passcodeLockWindow.isHidden = false
|
||||
|
||||
let userDismissCompletionCallback = passcodeLockVC.dismissCompletionCallback
|
||||
passcodeLockVC.dismissCompletionCallback = { [weak self] in
|
||||
userDismissCompletionCallback?()
|
||||
self?.dismiss()
|
||||
}
|
||||
passcodeLockWindow.rootViewController = passcodeLockVC
|
||||
}
|
||||
|
||||
open func dismiss() {
|
||||
isPasscodePresented = false
|
||||
passcodeLockWindow.isHidden = true
|
||||
passcodeLockWindow.rootViewController = nil
|
||||
}
|
||||
|
||||
fileprivate func moveWindowsToFront(windowLevel: CGFloat?) {
|
||||
let windowLevel = windowLevel ?? UIWindowLevelNormal
|
||||
let maxWinLevel = max(windowLevel, UIWindowLevelNormal)
|
||||
passcodeLockWindow.windowLevel = maxWinLevel + 1
|
||||
}
|
||||
}
|
||||
125
passKit/Controllers/PasscodeLockViewController.swift
Normal file
125
passKit/Controllers/PasscodeLockViewController.swift
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
//
|
||||
// PasscodeLockViewController.swift
|
||||
// PasscodeLock
|
||||
//
|
||||
// Created by Yanko Dimitrov on 8/28/15.
|
||||
// Copyright © 2015 Yanko Dimitrov. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import LocalAuthentication
|
||||
|
||||
open class PasscodeLockViewController: UIViewController {
|
||||
|
||||
open var dismissCompletionCallback: (()->Void)?
|
||||
open var successCallback: (()->Void)?
|
||||
open var cancelCallback: (()->Void)?
|
||||
lazy var enterPasscodeAlert: UIAlertController = {
|
||||
let enterPasscodeAlert = UIAlertController(title: "Authenticate Pass", message: "Unlock with passcode for Pass", preferredStyle: .alert)
|
||||
|
||||
enterPasscodeAlert.addTextField(configurationHandler: {(_ textField: UITextField) -> Void in
|
||||
textField.placeholder = "passcode"
|
||||
textField.isSecureTextEntry = true
|
||||
textField.addTarget(self, action: #selector(self.passcodeTextFieldDidChange(_:)), for: UIControlEvents.editingChanged)
|
||||
textField.clearButtonMode = UITextFieldViewMode.whileEditing
|
||||
textField.becomeFirstResponder()
|
||||
})
|
||||
|
||||
let myContext = LAContext()
|
||||
var authError: NSError?
|
||||
if #available(iOS 8.0, macOS 10.12.1, *) {
|
||||
if myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
|
||||
var biometryType = "Touch ID"
|
||||
if #available(iOS 11.0, *) {
|
||||
if myContext.biometryType == LABiometryType.faceID {
|
||||
biometryType = "Face ID"
|
||||
}
|
||||
}
|
||||
let bioAction = UIAlertAction(title: "Use " + biometryType, style: .default) { (action:UIAlertAction) -> Void in
|
||||
self.authenticate()
|
||||
}
|
||||
enterPasscodeAlert.addAction(bioAction)
|
||||
}
|
||||
}
|
||||
|
||||
return enterPasscodeAlert
|
||||
}()
|
||||
|
||||
open override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.view.backgroundColor = UIColor.white
|
||||
}
|
||||
|
||||
open override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
authenticate()
|
||||
}
|
||||
|
||||
internal func dismissPasscodeLock(completionHandler: (() -> Void)? = nil) {
|
||||
// clean up the textfield
|
||||
enterPasscodeAlert.textFields?[0].text = ""
|
||||
if presentingViewController?.presentedViewController == self {
|
||||
// if presented as modal
|
||||
dismiss(animated: true, completion: { [weak self] in
|
||||
self?.dismissCompletionCallback?()
|
||||
completionHandler?()
|
||||
})
|
||||
// if pushed in a navigation controller
|
||||
} else {
|
||||
_ = navigationController?.popViewController(animated: true)
|
||||
dismissCompletionCallback?()
|
||||
completionHandler?()
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - PasscodeLockDelegate
|
||||
|
||||
open func passcodeLockDidSucceed() {
|
||||
dismissPasscodeLock(completionHandler: successCallback)
|
||||
}
|
||||
|
||||
open func passcodeLockDidCancel() {
|
||||
dismissPasscodeLock(completionHandler: cancelCallback)
|
||||
}
|
||||
|
||||
public func authenticate() {
|
||||
print(enterPasscodeAlert.isBeingPresented)
|
||||
|
||||
let myContext = LAContext()
|
||||
let myLocalizedReasonString = "Authentication is needed to access Pass."
|
||||
var authError: NSError?
|
||||
|
||||
if #available(iOS 8.0, *) {
|
||||
if myContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &authError) {
|
||||
myContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString) { success, evaluateError in
|
||||
if success {
|
||||
DispatchQueue.main.async {
|
||||
// user authenticated successfully, take appropriate action
|
||||
self.passcodeLockDidSucceed()
|
||||
}
|
||||
} else {
|
||||
// User did not authenticate successfully
|
||||
self.showPasswordAlert()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// could not evaluate policy; look at authError and present an appropriate message to user
|
||||
self.showPasswordAlert()
|
||||
}
|
||||
} else {
|
||||
// fallback on earlier versions
|
||||
self.showPasswordAlert()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func passcodeTextFieldDidChange(_ sender: UITextField) {
|
||||
// check whether the passcode is correct
|
||||
if PasscodeLock.shared.check(passcode: sender.text ?? "") {
|
||||
self.passcodeLockDidSucceed()
|
||||
}
|
||||
}
|
||||
|
||||
func showPasswordAlert() {
|
||||
self.present(enterPasscodeAlert, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,24 @@
|
|||
//
|
||||
// PasscodeRepository.swift
|
||||
// pass
|
||||
// PasscodeLock.swift
|
||||
// PassKit
|
||||
//
|
||||
// Created by Mingshen Sun on 7/2/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
// Created by Yishi Lin on 28/1/2018.
|
||||
// Copyright © 2017 Yishi Lin. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PasscodeLock
|
||||
import LocalAuthentication
|
||||
|
||||
public class PasscodeLockRepository: PasscodeRepositoryType {
|
||||
private let passcodeKey = "passcode.lock.passcode"
|
||||
open class PasscodeLock {
|
||||
public static let shared = PasscodeLock()
|
||||
|
||||
public var hasPasscode: Bool {
|
||||
|
||||
if passcode != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
fileprivate let passcodeKey = "passcode.lock.passcode"
|
||||
fileprivate var passcode: String? {
|
||||
return SharedDefaults[.passcodeKey]
|
||||
}
|
||||
|
||||
private var passcode: String? {
|
||||
return SharedDefaults[.passcodeKey]
|
||||
public var hasPasscode: Bool {
|
||||
return passcode != nil
|
||||
}
|
||||
|
||||
public func save(passcode: String) {
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
//
|
||||
// PasscodeLockConfiguration.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 7/2/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import PasscodeLock
|
||||
|
||||
public class PasscodeLockConfiguration: PasscodeLockConfigurationType {
|
||||
|
||||
public static let shared = PasscodeLockConfiguration()
|
||||
|
||||
public let repository: PasscodeRepositoryType
|
||||
public let passcodeLength = 4
|
||||
public var isTouchIDAllowed = SharedDefaults[.isTouchIDOn]
|
||||
|
||||
public let shouldRequestTouchIDImmediately = true
|
||||
public let maximumInccorectPasscodeAttempts = 3
|
||||
|
||||
init() {
|
||||
self.repository = PasscodeLockRepository()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue