Merge branch 'release/0.2.6'
This commit is contained in:
commit
c19d6469ea
15 changed files with 597 additions and 331 deletions
|
|
@ -59,6 +59,8 @@
|
|||
DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */; };
|
||||
DCC441521E8F6C06008A90C4 /* RawPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */; };
|
||||
DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */; };
|
||||
DCD9AD131EB678500093499A /* GitCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD9AD121EB678500093499A /* GitCredential.swift */; };
|
||||
DCD9AD151EB6829A0093499A /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCD9AD141EB6829A0093499A /* AppError.swift */; };
|
||||
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */; };
|
||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */; };
|
||||
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */; };
|
||||
|
|
@ -142,6 +144,8 @@
|
|||
DCC408C91E30BA1300F29B0E /* pass.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = pass.xcdatamodel; sourceTree = "<group>"; };
|
||||
DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawPasswordViewController.swift; sourceTree = "<group>"; };
|
||||
DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitSSHKeyArmorSettingTableViewController.swift; sourceTree = "<group>"; };
|
||||
DCD9AD121EB678500093499A /* GitCredential.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GitCredential.swift; path = pass/Controllers/GitCredential.swift; sourceTree = SOURCE_ROOT; };
|
||||
DCD9AD141EB6829A0093499A /* AppError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = "<group>"; };
|
||||
DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LabelTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordDetailTitleTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleTextFieldTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -238,6 +242,7 @@
|
|||
DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */,
|
||||
DC193FFF1E49E1A60077E0A3 /* PasscodeLockConfiguration.swift */,
|
||||
DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */,
|
||||
DCD9AD121EB678500093499A /* GitCredential.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -302,6 +307,7 @@
|
|||
children = (
|
||||
DC917BE21E2E8231000FDF54 /* Info.plist */,
|
||||
DC917BD61E2E8231000FDF54 /* AppDelegate.swift */,
|
||||
DCD9AD141EB6829A0093499A /* AppError.swift */,
|
||||
DC19400D1E4B3A340077E0A3 /* Models */,
|
||||
DC19400C1E4B39400077E0A3 /* Controllers */,
|
||||
DC19400F1E4B3A9E0077E0A3 /* Views */,
|
||||
|
|
@ -526,6 +532,7 @@
|
|||
files = (
|
||||
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */,
|
||||
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */,
|
||||
DCD9AD151EB6829A0093499A /* AppError.swift in Sources */,
|
||||
DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */,
|
||||
DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */,
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
||||
|
|
@ -545,6 +552,7 @@
|
|||
DC4914991E434600007FF592 /* PasswordDetailTableViewController.swift in Sources */,
|
||||
DC962CDF1E4B62C10033B5D8 /* AboutTableViewController.swift in Sources */,
|
||||
DC5734AE1E439AD400D09270 /* PasswordsViewController.swift in Sources */,
|
||||
DCD9AD131EB678500093499A /* GitCredential.swift in Sources */,
|
||||
DC3E64E61E656F11009A83DE /* CommitLogsTableViewController.swift in Sources */,
|
||||
DC037CAA1E4B8EAE00609409 /* SpecialThanksTableViewController.swift in Sources */,
|
||||
DC037CA61E4B883900609409 /* OpenSourceComponentsTableViewController.swift in Sources */,
|
||||
|
|
|
|||
40
pass/AppError.swift
Normal file
40
pass/AppError.swift
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// AppError.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 30/4/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum AppError: Error {
|
||||
case RepositoryNotSetError
|
||||
case RepositoryRemoteMasterNotFoundError
|
||||
case KeyImportError
|
||||
case PasswordDuplicatedError
|
||||
case GitResetError
|
||||
case PGPPublicKeyNotExistError
|
||||
case UnknownError
|
||||
}
|
||||
|
||||
extension AppError: LocalizedError {
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
case .RepositoryNotSetError:
|
||||
return "Git repository is not set."
|
||||
case .RepositoryRemoteMasterNotFoundError:
|
||||
return "Cannot find remote branch origin/master."
|
||||
case .KeyImportError:
|
||||
return "Cannot import the key."
|
||||
case .PasswordDuplicatedError:
|
||||
return "Cannot add the password: password duplicated."
|
||||
case .GitResetError:
|
||||
return "Cannot identify the latest synced commit."
|
||||
case .PGPPublicKeyNotExistError:
|
||||
return "PGP public key doesn't exist."
|
||||
case .UnknownError:
|
||||
return "Unknown error."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16F60a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="YoR-iB-XAd">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="YoR-iB-XAd">
|
||||
<device id="retina5_5" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
|
|
@ -31,18 +31,18 @@
|
|||
<rect key="frame" x="0.0" y="28" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="bEm-K1-de5" id="kV8-N2-jWc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Eu3-i0-M5v">
|
||||
<rect key="frame" x="15" y="11.999999999999998" width="33.333333333333336" height="20.333333333333332"/>
|
||||
<rect key="frame" x="15" y="11" width="34" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="jms-aX-6FT">
|
||||
<rect key="frame" x="335" y="11.999999999999998" width="44" height="20.333333333333332"/>
|
||||
<rect key="frame" x="335" y="11" width="44" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||
|
|
@ -89,11 +89,11 @@
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="55g-T3-9ak" id="dKn-cO-EJa">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="General" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dOt-Rj-vWD">
|
||||
<rect key="frame" x="20" y="0.0" width="356" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="364" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
|
|
@ -109,18 +109,18 @@
|
|||
<rect key="frame" x="0.0" y="79" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="2rc-ZW-XKd" id="CpT-zb-QEP">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Password Repository" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="gWn-ib-STb">
|
||||
<rect key="frame" x="20" y="11.999999999999998" width="160.33333333333334" height="20.333333333333332"/>
|
||||
<rect key="frame" x="15" y="11" width="161" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Not Set" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Myq-fV-riz">
|
||||
<rect key="frame" x="318.33333333333331" y="11.999999999999998" width="57.666666666666664" height="20.333333333333332"/>
|
||||
<rect key="frame" x="321" y="11" width="58" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -136,18 +136,18 @@
|
|||
<rect key="frame" x="0.0" y="123" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="1ze-MS-Xbj" id="W7U-oL-hOh">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="PGP Key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RR9-xr-9ko">
|
||||
<rect key="frame" x="20" y="11.999999999999998" width="66" height="20.333333333333332"/>
|
||||
<rect key="frame" x="15" y="11" width="66" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Not Set" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="7lc-Vh-G9W">
|
||||
<rect key="frame" x="318.33333333333331" y="11.999999999999998" width="57.666666666666664" height="20.333333333333332"/>
|
||||
<rect key="frame" x="321" y="11" width="58" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.55686274509803924" green="0.55686274509803924" blue="0.57647058823529407" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -161,21 +161,21 @@
|
|||
<tableViewSection headerTitle="SECURITY" id="Cx7-e4-wCO">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="passcodeTableViewCell" textLabel="RaZ-6t-0CU" detailTextLabel="HXb-ZX-HUv" style="IBUITableViewCellStyleValue1" id="6Y0-mj-qhA">
|
||||
<rect key="frame" x="0.0" y="223" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="224" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="6Y0-mj-qhA" id="qlv-tQ-Xmc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Passcode Lock" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RaZ-6t-0CU">
|
||||
<rect key="frame" x="20" y="11.999999999999998" width="115" height="20.333333333333332"/>
|
||||
<rect key="frame" x="15" y="11" width="115" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Off" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HXb-ZX-HUv">
|
||||
<rect key="frame" x="351.66666666666669" y="11.999999999999998" width="24.333333333333332" height="20.333333333333332"/>
|
||||
<rect key="frame" x="354" y="11" width="25" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -185,14 +185,14 @@
|
|||
</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"/>
|
||||
<rect key="frame" x="0.0" y="268" 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"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Touch ID" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="H2E-hP-Gyf">
|
||||
<rect key="frame" x="20" y="0.0" width="379" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="384" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
|
|
@ -206,14 +206,14 @@
|
|||
<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="348" 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"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Advanced" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="MKj-d0-8q3">
|
||||
<rect key="frame" x="20" y="0.0" width="356" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="364" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -230,14 +230,14 @@
|
|||
<tableViewSection id="T7L-rR-R9W">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="aboutTableViewCell" textLabel="oqz-Hr-RAl" imageView="Fgk-EG-6cx" 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="428" 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"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="About" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="oqz-Hr-RAl">
|
||||
<rect key="frame" x="20" y="0.0" width="356" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="364" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -288,23 +288,23 @@
|
|||
<rect key="frame" x="0.0" y="28" width="414" height="54"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="OfB-1N-1Am" id="fh0-au-C6q">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="53.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="53"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="201" contentMode="left" verticalHuggingPriority="251" preservesSuperviewLayoutMargins="YES" text="2017/04/04" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GLC-qL-55P">
|
||||
<rect key="frame" x="87.333333333333343" y="10.999999999999998" width="311.66666666666663" height="14.33333333333333"/>
|
||||
<rect key="frame" x="88" y="11" width="311" height="15"/>
|
||||
<fontDescription key="fontDescription" name=".AppleSystemUIFont" family=".AppleSystemUIFont" pointSize="12"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="202" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" preservesSuperviewLayoutMargins="YES" text="Edit password for baidu.com using Pass for iOS." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="L1p-Dm-Mnh">
|
||||
<rect key="frame" x="15" y="28.666666666666671" width="384" height="14.333333333333329"/>
|
||||
<rect key="frame" x="15" y="29" width="384" height="14"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="200" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" preservesSuperviewLayoutMargins="YES" text="Bob Sun" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8Dc-U9-AVf">
|
||||
<rect key="frame" x="15" y="11.000000000000002" width="62.333333333333329" height="14.66666666666667"/>
|
||||
<rect key="frame" x="15" y="11" width="63" height="15"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
|
@ -348,10 +348,10 @@
|
|||
<tableViewSection headerTitle="Git Repository URL" id="pbe-W6-w4V">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="gitRepositoryURLTabelViewCell" rowHeight="52" id="FRr-pf-aPO">
|
||||
<rect key="frame" x="0.0" y="55.5" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="56" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="FRr-pf-aPO" id="60A-PS-qGe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Git Repository URL" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="EVT-VU-sCi">
|
||||
|
|
@ -378,10 +378,10 @@
|
|||
<tableViewSection headerTitle="Username" id="fRu-A2-SCk">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" reuseIdentifier="usernameTableVIewCell" rowHeight="52" id="tnj-5U-kMB">
|
||||
<rect key="frame" x="0.0" y="163.5" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="165" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="tnj-5U-kMB" id="f0c-pI-MSJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Username" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="TMg-Gk-7nG">
|
||||
|
|
@ -407,10 +407,10 @@
|
|||
<tableViewSection headerTitle="Authentication Method" id="h0N-tI-shZ">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="2" indentationWidth="0.0" shouldIndentWhileEditing="NO" id="KrP-nb-haa">
|
||||
<rect key="frame" x="0.0" y="271.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="274" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KrP-nb-haa" id="1uB-oE-kfI">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LfQ-Af-j2O">
|
||||
|
|
@ -420,7 +420,7 @@
|
|||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="1001" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✓" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Scc-5J-bu1">
|
||||
<rect key="frame" x="23" y="11.666666666666668" width="15.666666666666664" height="21.333333333333332"/>
|
||||
<rect key="frame" x="23" y="11" width="16" height="22"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
|
@ -438,10 +438,10 @@
|
|||
<inset key="separatorInset" minX="62" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" accessoryType="detailButton" hidesAccessoryWhenEditing="NO" indentationLevel="2" indentationWidth="0.0" shouldIndentWhileEditing="NO" id="Qmt-bo-CuJ">
|
||||
<rect key="frame" x="0.0" y="315.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="318" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Qmt-bo-CuJ" id="p3u-8b-h3U">
|
||||
<rect key="frame" x="0.0" y="0.0" width="367" height="44"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="367" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="SSH Key" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ezz-76-a53">
|
||||
|
|
@ -451,7 +451,7 @@
|
|||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="1001" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="✓" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wbx-rk-i8H">
|
||||
<rect key="frame" x="23" y="10.666666666666664" width="16.666666666666664" height="22"/>
|
||||
<rect key="frame" x="23" y="11" width="16" height="22"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
|
@ -519,7 +519,7 @@
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="BYZ-9g-xZy" id="Zfn-rK-sN1">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public Key URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dWi-eh-7Eq">
|
||||
|
|
@ -553,7 +553,7 @@
|
|||
<rect key="frame" x="0.0" y="87" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vpk-J8-j7t" id="1td-qT-6ts">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Private Key URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Qht-RC-Yeg">
|
||||
|
|
@ -916,7 +916,7 @@ Phone Support PIN #: 84719</string>
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Jy1-4S-Lvf" id="tJE-ww-okf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Public Key URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Oys-xP-ZrB">
|
||||
|
|
@ -950,7 +950,7 @@ Phone Support PIN #: 84719</string>
|
|||
<rect key="frame" x="0.0" y="87" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="MA5-lE-8dT" id="pTv-Wj-psC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Private Key URL" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C2w-dd-roS">
|
||||
|
|
@ -1056,14 +1056,14 @@ Phone Support PIN #: 84719</string>
|
|||
<tableViewSection headerTitle="GPG Configuration" id="ugP-R2-9M7">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="Jwg-mt-woS" style="IBUITableViewCellStyleDefault" id="tHt-Ro-0HF" userLabel="Encrypt in ASCII-Armored">
|
||||
<rect key="frame" x="0.0" y="55.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="56" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tHt-Ro-0HF" id="Epj-ei-NtS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Encrypt in ASCII-Armored" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Jwg-mt-woS">
|
||||
<rect key="frame" x="20" y="0.0" width="379" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="384" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
|
|
@ -1077,21 +1077,21 @@ Phone Support PIN #: 84719</string>
|
|||
<tableViewSection headerTitle="Git Configuration" id="ihT-OG-HTv">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="87a-xY-AbR" detailTextLabel="2qr-d7-0SK" style="IBUITableViewCellStyleValue1" id="SVj-jD-qPT" userLabel="Git Signature">
|
||||
<rect key="frame" x="0.0" y="155.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="157" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="SVj-jD-qPT" id="HaO-5w-qZt">
|
||||
<rect key="frame" x="0.0" y="0.0" width="376" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Git Signature" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="87a-xY-AbR">
|
||||
<rect key="frame" x="20.000000000000007" y="11.999999999999998" width="99.666666666666671" height="20.333333333333332"/>
|
||||
<rect key="frame" x="15" y="11" width="100" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Not Set" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2qr-d7-0SK">
|
||||
<rect key="frame" x="318.33333333333331" y="11.999999999999998" width="57.666666666666664" height="20.333333333333332"/>
|
||||
<rect key="frame" x="321" y="11" width="58" height="21"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -1108,14 +1108,14 @@ Phone Support PIN #: 84719</string>
|
|||
<tableViewSection headerTitle="PasswordStore Data" id="aVR-FE-jMg">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="zrl-v3-fxg" style="IBUITableViewCellStyleDefault" id="Jm8-B5-wKx" userLabel="Discard Changes Table View Cell">
|
||||
<rect key="frame" x="0.0" y="255.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="258" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Jm8-B5-wKx" id="tjS-Q6-y2M">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Discard All Local Changes" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="zrl-v3-fxg">
|
||||
<rect key="frame" x="20" y="0.0" width="379" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="384" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.50196081400000003" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -1125,14 +1125,14 @@ Phone Support PIN #: 84719</string>
|
|||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" textLabel="K2K-Bx-g7Z" style="IBUITableViewCellStyleDefault" id="NI1-Kd-hyH">
|
||||
<rect key="frame" x="0.0" y="299.5" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="302" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="NI1-Kd-hyH" id="yLe-T2-TWF">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43.666666666666664"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Erase All Password Store Data" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="K2K-Bx-g7Z">
|
||||
<rect key="frame" x="20" y="0.0" width="379" height="43.666666666666664"/>
|
||||
<rect key="frame" x="15" y="0.0" width="384" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="0.50196081400000003" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
|
@ -1265,7 +1265,7 @@ Phone Support PIN #: 84719</string>
|
|||
<scene sceneID="Jmv-A6-Wr1">
|
||||
<objects>
|
||||
<tableViewController id="1gA-jh-frD" customClass="PGPKeyArmorSettingTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="1" id="WYj-Sf-Cyc">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="1" sectionFooterHeight="1" id="WYj-Sf-Cyc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
|
|
@ -1276,18 +1276,18 @@ Phone Support PIN #: 84719</string>
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="170"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Pv0-ev-stj" id="ywz-II-W1g">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="169.66666666666666"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ASCII-Armor Keys" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="M32-yr-IfE">
|
||||
<rect key="frame" x="20.000000000000007" y="17" width="121.66666666666667" height="17"/>
|
||||
<rect key="frame" x="15" y="17" width="122" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" usesAttributedText="YES" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="sMx-qd-MTJ">
|
||||
<rect key="frame" x="20" y="34" width="363.66666666666669" height="119"/>
|
||||
<rect key="frame" x="15" y="34" width="384" height="119"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment>
|
||||
|
|
@ -1337,14 +1337,14 @@ Cgo
|
|||
<tableViewSection headerTitle="ASCII-Armor Encrypted Public Key" id="MZz-mp-v5N">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="pgpKeyURLTableViewCell" rowHeight="160" id="Lom-iT-l16">
|
||||
<rect key="frame" x="0.0" y="244" width="414" height="160"/>
|
||||
<rect key="frame" x="0.0" y="245" width="414" height="160"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Lom-iT-l16" id="eya-Tv-r0q">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyB-oI-1fS">
|
||||
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
|
||||
<rect key="frame" x="15" y="8" width="391" height="144"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
|
|
@ -1362,19 +1362,27 @@ Cgo
|
|||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="F0i-XE-PGt" userLabel="scanQRCodeCell">
|
||||
<rect key="frame" x="0.0" y="405" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="F0i-XE-PGt" id="xO8-yL-W9a">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="ASCII-ARMOR ENCRYPTED PRIVATE KEY" id="0RP-Jn-j5G">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="pgpKeyURLTableViewCell" rowHeight="160" id="J8U-ev-FRQ">
|
||||
<rect key="frame" x="0.0" y="443" width="414" height="160"/>
|
||||
<rect key="frame" x="0.0" y="489" width="414" height="160"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="J8U-ev-FRQ" id="eb0-vb-Fcc">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lrQ-Ln-ZOv">
|
||||
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
|
||||
<rect key="frame" x="15" y="8" width="391" height="143"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
|
|
@ -1392,6 +1400,14 @@ Cgo
|
|||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="b0Z-rW-sAE" userLabel="scanQRCodeCell">
|
||||
<rect key="frame" x="0.0" y="649" width="414" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="b0Z-rW-sAE" id="UZX-pP-UWB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
|
|
@ -1415,7 +1431,10 @@ Cgo
|
|||
<connections>
|
||||
<outlet property="armorPrivateKeyTextView" destination="lrQ-Ln-ZOv" id="13E-xA-FHB"/>
|
||||
<outlet property="armorPublicKeyTextView" destination="oyB-oI-1fS" id="pX6-9c-Z78"/>
|
||||
<outlet property="scanPrivateKeyCell" destination="b0Z-rW-sAE" id="cKx-fK-Ik1"/>
|
||||
<outlet property="scanPublicKeyCell" destination="F0i-XE-PGt" id="kLX-N9-E4U"/>
|
||||
<segue destination="Ul9-vk-jhw" kind="unwind" identifier="savePGPKeySegue" unwindAction="savePGPKeyWithSegue:" id="Eof-7g-AlY"/>
|
||||
<segue destination="LZE-gF-IcM" kind="show" identifier="showPGPScannerSegue" id="5iZ-y9-FCH"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="2Wn-7D-LLj" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
|
|
@ -1474,18 +1493,18 @@ Cgo
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="170"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EMz-nP-2Om" id="XW5-mL-PRC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="169.66666666666666"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="169"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="ASCII-Armor Keys" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="i78-t7-fP9">
|
||||
<rect key="frame" x="20.000000000000007" y="37" width="121.66666666666667" height="17"/>
|
||||
<rect key="frame" x="15" y="36" width="122" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" name="HelveticaNeue-Bold" family="Helvetica Neue" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" usesAttributedText="YES" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Oit-sd-wa5">
|
||||
<rect key="frame" x="20" y="53.999999999999993" width="344" height="79.333333333333329"/>
|
||||
<rect key="frame" x="15" y="53" width="344" height="80"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment>
|
||||
|
|
@ -1518,14 +1537,14 @@ Cgo
|
|||
<tableViewSection headerTitle="ASCII-Armor Encrypted Public Key" id="w4D-Mh-0pP">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="pgpKeyURLTableViewCell" rowHeight="160" id="3po-uS-Nch">
|
||||
<rect key="frame" x="0.0" y="244" width="414" height="160"/>
|
||||
<rect key="frame" x="0.0" y="245" width="414" height="160"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3po-uS-Nch" id="pet-if-EHU">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Y9t-DD-6uH">
|
||||
<rect key="frame" x="15" y="8" width="391" height="143.66666666666666"/>
|
||||
<rect key="frame" x="15" y="8" width="391" height="144"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
|
|
@ -1545,14 +1564,14 @@ Cgo
|
|||
<tableViewSection headerTitle="ASCII-ARMOR ENCRYPTED PRIVATE KEY" id="sxk-Yb-Y3x">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="pgpKeyURLTableViewCell" rowHeight="160" id="nmc-vy-Ab5">
|
||||
<rect key="frame" x="0.0" y="443" width="414" height="160"/>
|
||||
<rect key="frame" x="0.0" y="445" width="414" height="160"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="nmc-vy-Ab5" id="TQD-GC-YOY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="23o-MP-wQY">
|
||||
<rect key="frame" x="15" y="8" width="391" height="144"/>
|
||||
<rect key="frame" x="15" y="8" width="391" height="143"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
|
|
@ -1606,7 +1625,7 @@ Cgo
|
|||
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4Bh-1D-w5T" id="mIL-ig-tbp">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hlb-Zh-ega">
|
||||
|
|
@ -1639,7 +1658,7 @@ Cgo
|
|||
<rect key="frame" x="0.0" y="87" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="JRY-pY-XtS" id="KrQ-Ih-dk8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Email" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="m25-Qy-XwU">
|
||||
|
|
@ -1716,12 +1735,58 @@ Cgo
|
|||
</objects>
|
||||
<point key="canvasLocation" x="4967" y="5333"/>
|
||||
</scene>
|
||||
<!--Scanner-->
|
||||
<scene sceneID="7j1-Qg-pUZ">
|
||||
<objects>
|
||||
<viewController id="LZE-gF-IcM" customClass="QRScannerController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="6mM-FW-piL"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="53A-gx-tky"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="CA8-A9-019">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="scanner output" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="U8O-Md-w8e">
|
||||
<rect key="frame" x="50" y="562" width="314" height="45"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="0.5" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="45" id="q3X-BT-aK8"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="U8O-Md-w8e" secondAttribute="trailing" constant="30" id="Sok-Wi-SXQ"/>
|
||||
<constraint firstItem="U8O-Md-w8e" firstAttribute="leading" secondItem="CA8-A9-019" secondAttribute="leadingMargin" constant="30" id="opY-C9-XIS"/>
|
||||
<constraint firstItem="53A-gx-tky" firstAttribute="top" secondItem="U8O-Md-w8e" secondAttribute="bottom" constant="80" id="tzL-K0-lE7"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" title="Scanner" id="JIs-3z-Tmr">
|
||||
<barButtonItem key="leftBarButtonItem" systemItem="cancel" id="yma-o8-xRu">
|
||||
<connections>
|
||||
<segue destination="0F8-Zv-c2C" kind="unwind" unwindAction="cancelPGPScannerWithSegue:" id="q14-fu-3N4"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="scannerOutput" destination="U8O-Md-w8e" id="JTW-9y-mr6"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="I2W-rx-CxX" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="0F8-Zv-c2C" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6122" y="4302"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Lock" width="25" height="25"/>
|
||||
<image name="Settings" width="25" height="25"/>
|
||||
</resources>
|
||||
<inferredMetricsTieBreakers>
|
||||
<segue reference="UfP-k3-XeR"/>
|
||||
<segue reference="yyD-4H-pLE"/>
|
||||
</inferredMetricsTieBreakers>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -98,6 +98,12 @@ class BasicStaticTableViewController: UITableViewController, MFMailComposeViewCo
|
|||
let subject = urlComponents.queryItems![0].value ?? ""
|
||||
if MFMailComposeViewController.canSendMail() {
|
||||
sendEmail(toRecipients: [urlComponents.path], subject: subject)
|
||||
} else {
|
||||
let email = urlComponents.path
|
||||
let alertTitle = "Cannot open Mail App"
|
||||
let alertMessage = "Email copied: \(email)"
|
||||
Utils.copyToPasteboard(textToCopy: email)
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self, completion: nil)
|
||||
}
|
||||
case "http", "https":
|
||||
let svc = SFSafariViewController(url: URL(string: link)!, entersReaderIfAvailable: false)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class CommitLogsTableViewController: UITableViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(updateCommitLogs), name: .passwordStoreUpdated, object: nil)
|
||||
commits = passwordStore.getRecentCommits(count: 20)
|
||||
commits = getCommitLogs()
|
||||
self.tableView.estimatedRowHeight = 50
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension
|
||||
}
|
||||
|
|
@ -41,8 +41,17 @@ class CommitLogsTableViewController: UITableViewController {
|
|||
return cell
|
||||
}
|
||||
|
||||
func updateCommitLogs () {
|
||||
commits = passwordStore.getRecentCommits(count: 20)
|
||||
func updateCommitLogs() {
|
||||
commits = getCommitLogs()
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
private func getCommitLogs() -> [GTCommit] {
|
||||
do {
|
||||
return try passwordStore.getRecentCommits(count: 20)
|
||||
} catch {
|
||||
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
107
pass/Controllers/GitCredential.swift
Normal file
107
pass/Controllers/GitCredential.swift
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
//
|
||||
// GitCredential.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 30/4/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
import SwiftyUserDefaults
|
||||
import ObjectiveGit
|
||||
import SVProgressHUD
|
||||
|
||||
struct GitCredential {
|
||||
var credential: Credential
|
||||
|
||||
enum Credential {
|
||||
case http(userName: String, controller: UIViewController)
|
||||
case ssh(userName: String, publicKeyFile: URL, privateKeyFile: URL, controller: UIViewController)
|
||||
}
|
||||
|
||||
init(credential: Credential) {
|
||||
self.credential = credential
|
||||
}
|
||||
|
||||
func credentialProvider() throws -> GTCredentialProvider {
|
||||
var attempts = 0
|
||||
var lastPassword: String? = nil
|
||||
return GTCredentialProvider { (_, _, _) -> (GTCredential?) in
|
||||
var credential: GTCredential? = nil
|
||||
|
||||
switch self.credential {
|
||||
case let .http(userName, controller):
|
||||
var newPassword = Utils.getPasswordFromKeychain(name: "gitPassword")
|
||||
if newPassword == nil || attempts != 0 {
|
||||
if let requestedPassword = self.requestGitPassword(controller, lastPassword) {
|
||||
newPassword = requestedPassword
|
||||
Utils.addPasswordToKeychain(name: "gitPassword", password: newPassword)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
attempts += 1
|
||||
lastPassword = newPassword
|
||||
credential = try? GTCredential(userName: userName, password: newPassword!)
|
||||
case let .ssh(userName, publicKeyFile, privateKeyFile, controller):
|
||||
var newPassword = Utils.getPasswordFromKeychain(name: "gitSSHKeyPassphrase")
|
||||
if newPassword == nil || attempts != 0 {
|
||||
if let requestedPassword = self.requestGitPassword(controller, lastPassword) {
|
||||
newPassword = requestedPassword
|
||||
Utils.addPasswordToKeychain(name: "gitSSHKeyPassphrase", password: newPassword)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
attempts += 1
|
||||
lastPassword = newPassword
|
||||
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword!)
|
||||
}
|
||||
return credential
|
||||
}
|
||||
}
|
||||
|
||||
func delete() {
|
||||
switch credential {
|
||||
case .http:
|
||||
Utils.removeKeychain(name: "gitPassword")
|
||||
case .ssh:
|
||||
Utils.removeKeychain(name: "gitSSHKeyPassphrase")
|
||||
}
|
||||
}
|
||||
|
||||
private func requestGitPassword(_ controller: UIViewController, _ lastPassword: String?) -> String? {
|
||||
let sem = DispatchSemaphore(value: 0)
|
||||
var password: String?
|
||||
var message = ""
|
||||
switch credential {
|
||||
case .http:
|
||||
message = "Please fill in the password of your Git account."
|
||||
case .ssh:
|
||||
message = "Please fill in the password of your SSH key."
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
SVProgressHUD.dismiss()
|
||||
let alert = UIAlertController(title: "Password", message: message, preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = lastPassword ?? ""
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||
password = alert.textFields!.first!.text
|
||||
sem.signal()
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
|
||||
password = nil
|
||||
sem.signal()
|
||||
})
|
||||
controller.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let _ = sem.wait(timeout: .distantFuture)
|
||||
return password
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
let passwordStore = PasswordStore.shared
|
||||
var sshLabel: UILabel? = nil
|
||||
|
||||
var authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||
var authenticationMethod = Defaults[.gitAuthenticationMethod] ?? "Password"
|
||||
|
||||
private func checkAuthenticationMethod(method: String) {
|
||||
let passwordCheckView = authPasswordCell.viewWithTag(1001)!
|
||||
|
|
@ -41,9 +41,9 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
// Grey out ssh option if ssh_key and ssh_key.pub are not present
|
||||
sshLabel = authSSHKeyCell.subviews[0].subviews[0] as? UILabel
|
||||
sshLabel!.isEnabled = gitSSHKeyExists()
|
||||
|
||||
if let sshLabel = sshLabel {
|
||||
sshLabel.isEnabled = gitSSHKeyExists()
|
||||
}
|
||||
}
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
|
@ -51,9 +51,8 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
gitURLTextField.text = url.absoluteString
|
||||
}
|
||||
usernameTextField.text = Defaults[.gitUsername]
|
||||
authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||
|
||||
checkAuthenticationMethod(method: authenticationMethod!)
|
||||
sshLabel = authSSHKeyCell.subviews[0].subviews[0] as? UILabel
|
||||
checkAuthenticationMethod(method: authenticationMethod)
|
||||
authSSHKeyCell.accessoryType = .detailButton
|
||||
}
|
||||
|
||||
|
|
@ -80,10 +79,6 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
Utils.alert(title: "Cannot Save", message: "Git Server is not set.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
guard authenticationMethod != nil else {
|
||||
Utils.alert(title: "Cannot Save", message: "Authentication method is not set.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
@ -101,7 +96,7 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
authenticationMethod = "SSH Key"
|
||||
}
|
||||
}
|
||||
checkAuthenticationMethod(method: authenticationMethod!)
|
||||
checkAuthenticationMethod(method: authenticationMethod)
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
|
|
@ -163,7 +158,10 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
let deleteAction = UIAlertAction(title: "Remove Git SSH Keys", style: .destructive) { _ in
|
||||
Utils.removeGitSSHKeys()
|
||||
Defaults[.gitSSHKeySource] = nil
|
||||
self.sshLabel!.isEnabled = false
|
||||
if let sshLabel = self.sshLabel {
|
||||
sshLabel.isEnabled = false
|
||||
self.checkAuthenticationMethod(method: "Password")
|
||||
}
|
||||
}
|
||||
optionMenu.addAction(deleteAction)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,19 +9,102 @@
|
|||
import UIKit
|
||||
import SwiftyUserDefaults
|
||||
|
||||
class PGPKeyArmorSettingTableViewController: UITableViewController, UITextViewDelegate {
|
||||
class PGPKeyArmorSettingTableViewController: UITableViewController, UITextViewDelegate, QRScannerControllerDelegate {
|
||||
@IBOutlet weak var armorPublicKeyTextView: UITextView!
|
||||
@IBOutlet weak var armorPrivateKeyTextView: UITextView!
|
||||
@IBOutlet weak var scanPublicKeyCell: UITableViewCell!
|
||||
@IBOutlet weak var scanPrivateKeyCell: UITableViewCell!
|
||||
|
||||
var pgpPassphrase: String?
|
||||
let passwordStore = PasswordStore.shared
|
||||
|
||||
private var recentPastedText = ""
|
||||
|
||||
class ScannedPGPKey {
|
||||
static let maxNumberOfGif = 100
|
||||
enum KeyType {
|
||||
case publicKey, privateKey
|
||||
}
|
||||
var keyType = KeyType.publicKey
|
||||
var numberOfSegments = 0
|
||||
var previousSegment = ""
|
||||
var key = ""
|
||||
var message = ""
|
||||
var hasStarted = false
|
||||
var isDone = false
|
||||
|
||||
func reset(keytype: KeyType) {
|
||||
self.keyType = keytype
|
||||
numberOfSegments = 0
|
||||
previousSegment = ""
|
||||
key = ""
|
||||
message = "Looking for the starting frame."
|
||||
hasStarted = false
|
||||
isDone = false
|
||||
}
|
||||
|
||||
func addSegment(segment: String) {
|
||||
// skip duplicated segments
|
||||
guard segment != previousSegment else {
|
||||
return
|
||||
}
|
||||
previousSegment = segment
|
||||
|
||||
// check whether we have found the first block
|
||||
if hasStarted == false {
|
||||
let findPublic = segment.contains("-----BEGIN PGP PUBLIC KEY BLOCK-----")
|
||||
let findPrivate = segment.contains("-----BEGIN PGP PRIVATE KEY BLOCK-----")
|
||||
switch keyType {
|
||||
case .publicKey:
|
||||
if findPrivate {
|
||||
message = "Please scan public key."
|
||||
}
|
||||
hasStarted = findPublic
|
||||
case .privateKey:
|
||||
if findPublic {
|
||||
message = "Please scan private key."
|
||||
}
|
||||
hasStarted = findPrivate
|
||||
}
|
||||
}
|
||||
guard hasStarted == true else {
|
||||
return
|
||||
}
|
||||
|
||||
// check the number of segments
|
||||
numberOfSegments = numberOfSegments + 1
|
||||
guard numberOfSegments <= ScannedPGPKey.maxNumberOfGif else {
|
||||
key = "Too many QR codes"
|
||||
return
|
||||
}
|
||||
|
||||
// update full text and check whether we are done
|
||||
key.append(segment)
|
||||
if key.contains("-----END PGP PUBLIC KEY BLOCK-----") || key.contains("-----END PGP PRIVATE KEY BLOCK-----") {
|
||||
isDone = true
|
||||
}
|
||||
|
||||
// update message
|
||||
message = "\(numberOfSegments) scanned QR codes."
|
||||
}
|
||||
}
|
||||
var scanned = ScannedPGPKey()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
armorPublicKeyTextView.text = Defaults[.pgpPublicKeyArmor]
|
||||
armorPrivateKeyTextView.text = Defaults[.pgpPrivateKeyArmor]
|
||||
pgpPassphrase = passwordStore.pgpKeyPassphrase
|
||||
|
||||
scanPublicKeyCell?.textLabel?.text = "Scan Public Key QR Codes"
|
||||
scanPublicKeyCell?.textLabel?.textColor = Globals.blue
|
||||
scanPublicKeyCell?.selectionStyle = .default
|
||||
scanPublicKeyCell?.accessoryType = .disclosureIndicator
|
||||
|
||||
scanPrivateKeyCell?.textLabel?.text = "Scan Private Key QR Codes"
|
||||
scanPrivateKeyCell?.textLabel?.textColor = Globals.blue
|
||||
scanPrivateKeyCell?.selectionStyle = .default
|
||||
scanPrivateKeyCell?.accessoryType = .disclosureIndicator
|
||||
}
|
||||
|
||||
private func createSavePassphraseAndSegueAlert() -> UIAlertController {
|
||||
|
|
@ -79,4 +162,53 @@ class PGPKeyArmorSettingTableViewController: UITableViewController, UITextViewDe
|
|||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let selectedCell = tableView.cellForRow(at: indexPath)
|
||||
if selectedCell == scanPublicKeyCell {
|
||||
scanned.reset(keytype: ScannedPGPKey.KeyType.publicKey)
|
||||
self.performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
} else if selectedCell == scanPrivateKeyCell {
|
||||
scanned.reset(keytype: ScannedPGPKey.KeyType.privateKey)
|
||||
self.performSegue(withIdentifier: "showPGPScannerSegue", sender: self)
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
func checkScannedOutput(line: String) -> (accept: Bool, message: String) {
|
||||
scanned.addSegment(segment: line)
|
||||
if scanned.isDone {
|
||||
return (accept: true, message: "Done")
|
||||
} else {
|
||||
return (accept: false, message: scanned.message)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - QRScannerControllerDelegate Methods
|
||||
func handleScannedOutput(line: String) {
|
||||
switch scanned.keyType {
|
||||
case .publicKey:
|
||||
armorPublicKeyTextView.text = scanned.key
|
||||
case .privateKey:
|
||||
armorPrivateKeyTextView.text = scanned.key
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
viewController.delegate = self
|
||||
}
|
||||
} else if let viewController = segue.destination as? QRScannerController {
|
||||
viewController.delegate = self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@IBAction private func cancelPGPScanner(segue: UIStoryboardSegue) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,22 +39,26 @@ class PGPKeySettingTableViewController: UITableViewController {
|
|||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if identifier == "savePGPKeySegue" {
|
||||
guard let pgpPublicKeyURL = URL(string: pgpPublicKeyURLTextField.text!) else {
|
||||
Utils.alert(title: "Cannot Save", message: "Please set Public Key URL first.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
guard let pgpPrivateKeyURL = URL(string: pgpPrivateKeyURLTextField.text!) else {
|
||||
Utils.alert(title: "Cannot Save", message: "Please set Private Key URL first.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
guard pgpPublicKeyURL.scheme! == "https", pgpPrivateKeyURL.scheme! == "https" else {
|
||||
Utils.alert(title: "Cannot Save Settings", message: "HTTP connection is not supported.", controller: self, completion: nil)
|
||||
guard validatePGPKeyURL(input: pgpPublicKeyURLTextField.text) == true,
|
||||
validatePGPKeyURL(input: pgpPrivateKeyURLTextField.text) == true else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private func validatePGPKeyURL(input: String?) -> Bool {
|
||||
guard let path = input, let url = URL(string: path) else {
|
||||
Utils.alert(title: "Cannot Save PGP Key", message: "Please set PGP Key URL first.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
guard let scheme = url.scheme, scheme == "https", scheme == "https" else {
|
||||
Utils.alert(title: "Cannot Save PGP Key", message: "HTTP connection is not supported.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@IBAction func save(_ sender: Any) {
|
||||
let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your PGP secret key.", preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
self.password = try self.passwordStore.decrypt(passwordEntity: self.passwordEntity!, requestPGPKeyPassphrase: self.requestPGPKeyPassphrase)
|
||||
} catch {
|
||||
DispatchQueue.main.async {
|
||||
// remove the wrong passphrase so that users could enter it next time
|
||||
self.passwordStore.pgpKeyPassphrase = nil
|
||||
let alert = UIAlertController(title: "Cannot Show Password", message: error.localizedDescription, preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {(UIAlertAction) -> Void in
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
|
|
|
|||
|
|
@ -355,9 +355,15 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
textField.text = ""
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
// hide it so that alert is on the top of the view
|
||||
SVProgressHUD.dismiss()
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
let _ = sem.wait(timeout: DispatchTime.distantFuture)
|
||||
DispatchQueue.main.async {
|
||||
// bring back
|
||||
SVProgressHUD.show(withStatus: "Decrypting")
|
||||
}
|
||||
if Defaults[.isRememberPassphraseOn] {
|
||||
self.passwordStore.pgpKeyPassphrase = passphrase
|
||||
}
|
||||
|
|
@ -380,7 +386,9 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
} catch {
|
||||
print(error)
|
||||
DispatchQueue.main.async {
|
||||
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
|
||||
// remove the wrong passphrase so that users could enter it next time
|
||||
self.passwordStore.pgpKeyPassphrase = nil
|
||||
Utils.alert(title: "Cannot Copy Password", message: error.localizedDescription, controller: self, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,17 +156,19 @@ class SettingsTableViewController: UITableViewController {
|
|||
touchIDTableViewCell.accessoryView = touchIDSwitch
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
setTouchIDSwitch()
|
||||
setPasscodeLockRepositoryTableViewCellDetailText()
|
||||
setPasscodeLockTouchIDCells()
|
||||
}
|
||||
|
||||
private func setPasscodeLockRepositoryTableViewCellDetailText() {
|
||||
private func setPasscodeLockTouchIDCells() {
|
||||
if PasscodeLockRepository().hasPasscode {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "On"
|
||||
Globals.passcodeConfiguration.isTouchIDAllowed = true
|
||||
touchIDSwitch.isOn = Defaults[.isTouchIDOn]
|
||||
} else {
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "Off"
|
||||
touchIDSwitch.isEnabled = false
|
||||
Globals.passcodeConfiguration.isTouchIDAllowed = false
|
||||
Defaults[.isTouchIDOn] = false
|
||||
touchIDSwitch.isOn = Defaults[.isTouchIDOn]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -186,19 +188,10 @@ class SettingsTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
|
||||
private func setTouchIDSwitch() {
|
||||
if Defaults[.isTouchIDOn] {
|
||||
touchIDSwitch.isOn = true
|
||||
} else {
|
||||
touchIDSwitch.isOn = false
|
||||
}
|
||||
}
|
||||
|
||||
func actOnPasswordStoreErasedNotification() {
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
setTouchIDSwitch()
|
||||
setPasscodeLockRepositoryTableViewCellDetailText()
|
||||
setPasscodeLockTouchIDCells()
|
||||
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: Globals.passcodeConfiguration)
|
||||
|
|
@ -222,12 +215,12 @@ class SettingsTableViewController: UITableViewController {
|
|||
}
|
||||
|
||||
func touchIDSwitchAction(uiSwitch: UISwitch) {
|
||||
if uiSwitch.isOn {
|
||||
Defaults[.isTouchIDOn] = true
|
||||
Globals.passcodeConfiguration.isTouchIDAllowed = true
|
||||
if !Globals.passcodeConfiguration.isTouchIDAllowed {
|
||||
// switch off
|
||||
uiSwitch.isOn = Defaults[.isTouchIDOn] // false
|
||||
Utils.alert(title: "Notice", message: "Please set the passcode lock first.", controller: self, completion: nil)
|
||||
} else {
|
||||
Defaults[.isTouchIDOn] = false
|
||||
Globals.passcodeConfiguration.isTouchIDAllowed = false
|
||||
Defaults[.isTouchIDOn] = uiSwitch.isOn
|
||||
}
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: Globals.passcodeConfiguration)
|
||||
|
|
@ -335,8 +328,7 @@ class SettingsTableViewController: UITableViewController {
|
|||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
let removePasscodeAction = UIAlertAction(title: "Remove Passcode", style: .destructive) { [weak self] _ in
|
||||
passcodeRemoveViewController.successCallback = { _ in
|
||||
self?.passcodeTableViewCell.detailTextLabel?.text = "Off"
|
||||
self?.touchIDSwitch.isEnabled = false
|
||||
self?.setPasscodeLockTouchIDCells()
|
||||
let appDelegate = UIApplication.shared.delegate as! AppDelegate
|
||||
appDelegate.passcodeLockPresenter = PasscodeLockPresenter(mainWindow: appDelegate.window, configuration: Globals.passcodeConfiguration)
|
||||
}
|
||||
|
|
@ -359,8 +351,7 @@ class SettingsTableViewController: UITableViewController {
|
|||
func setPasscodeLock() {
|
||||
let passcodeSetViewController = PasscodeLockViewController(state: .set, configuration: Globals.passcodeConfiguration)
|
||||
passcodeSetViewController.successCallback = { _ in
|
||||
self.passcodeTableViewCell.detailTextLabel?.text = "On"
|
||||
self.touchIDSwitch.isEnabled = true
|
||||
self.setPasscodeLockTouchIDCells()
|
||||
}
|
||||
present(passcodeSetViewController, animated: true, completion: nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.2.5</string>
|
||||
<string>0.2.6</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
|
|
|||
|
|
@ -13,99 +13,6 @@ import SwiftyUserDefaults
|
|||
import ObjectiveGit
|
||||
import SVProgressHUD
|
||||
|
||||
struct GitCredential {
|
||||
var credential: Credential
|
||||
|
||||
enum Credential {
|
||||
case http(userName: String, controller: UIViewController)
|
||||
case ssh(userName: String, publicKeyFile: URL, privateKeyFile: URL, controller: UIViewController)
|
||||
}
|
||||
|
||||
init(credential: Credential) {
|
||||
self.credential = credential
|
||||
}
|
||||
|
||||
func credentialProvider() throws -> GTCredentialProvider {
|
||||
var attempts = 0
|
||||
var lastPassword: String? = nil
|
||||
return GTCredentialProvider { (_, _, _) -> (GTCredential?) in
|
||||
var credential: GTCredential? = nil
|
||||
|
||||
switch self.credential {
|
||||
case let .http(userName, controller):
|
||||
var newPassword = Utils.getPasswordFromKeychain(name: "gitPassword")
|
||||
if newPassword == nil || attempts != 0 {
|
||||
if let requestedPassword = self.requestGitPassword(controller, lastPassword) {
|
||||
newPassword = requestedPassword
|
||||
Utils.addPasswordToKeychain(name: "gitPassword", password: newPassword)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
attempts += 1
|
||||
lastPassword = newPassword
|
||||
credential = try? GTCredential(userName: userName, password: newPassword!)
|
||||
case let .ssh(userName, publicKeyFile, privateKeyFile, controller):
|
||||
var newPassword = Utils.getPasswordFromKeychain(name: "gitSSHKeyPassphrase")
|
||||
if newPassword == nil || attempts != 0 {
|
||||
if let requestedPassword = self.requestGitPassword(controller, lastPassword) {
|
||||
newPassword = requestedPassword
|
||||
Utils.addPasswordToKeychain(name: "gitSSHKeyPassphrase", password: newPassword)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
attempts += 1
|
||||
lastPassword = newPassword
|
||||
credential = try? GTCredential(userName: userName, publicKeyURL: publicKeyFile, privateKeyURL: privateKeyFile, passphrase: newPassword!)
|
||||
}
|
||||
return credential
|
||||
}
|
||||
}
|
||||
|
||||
func delete() {
|
||||
switch credential {
|
||||
case .http:
|
||||
Utils.removeKeychain(name: "gitPassword")
|
||||
case .ssh:
|
||||
Utils.removeKeychain(name: "gitSSHKeyPassphrase")
|
||||
}
|
||||
}
|
||||
|
||||
private func requestGitPassword(_ controller: UIViewController, _ lastPassword: String?) -> String? {
|
||||
let sem = DispatchSemaphore(value: 0)
|
||||
var password: String?
|
||||
var message = ""
|
||||
switch credential {
|
||||
case .http:
|
||||
message = "Please fill in the password of your Git account."
|
||||
case .ssh:
|
||||
message = "Please fill in the password of your SSH key."
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
SVProgressHUD.dismiss()
|
||||
let alert = UIAlertController(title: "Password", message: message, preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = lastPassword ?? ""
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||
password = alert.textFields!.first!.text
|
||||
sem.signal()
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
|
||||
password = nil
|
||||
sem.signal()
|
||||
})
|
||||
controller.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let _ = sem.wait(timeout: .distantFuture)
|
||||
return password
|
||||
}
|
||||
}
|
||||
|
||||
class PasswordStore {
|
||||
static let shared = PasswordStore()
|
||||
let storeURL = URL(fileURLWithPath: "\(Globals.repositoryPath)")
|
||||
|
|
@ -223,16 +130,16 @@ class PasswordStore {
|
|||
let keyPath = Globals.pgpPublicKeyPath
|
||||
self.publicKey = importKey(from: keyPath)
|
||||
if self.publicKey == nil {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 2, userInfo: [NSLocalizedDescriptionKey: "Cannot import the public PGP key."])
|
||||
throw AppError.KeyImportError
|
||||
}
|
||||
case .secret:
|
||||
let keyPath = Globals.pgpPrivateKeyPath
|
||||
self.privateKey = importKey(from: keyPath)
|
||||
if self.privateKey == nil {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 2, userInfo: [NSLocalizedDescriptionKey: "Cannot import the private PGP key."])
|
||||
throw AppError.KeyImportError
|
||||
}
|
||||
default:
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 2, userInfo: [NSLocalizedDescriptionKey: "Cannot import key: unknown PGP key type."])
|
||||
throw AppError.UnknownError
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -329,9 +236,7 @@ class PasswordStore {
|
|||
Utils.removeFileIfExists(at: tempStoreURL)
|
||||
do {
|
||||
let credentialProvider = try credential.credentialProvider()
|
||||
let options: [String: Any] = [
|
||||
GTRepositoryCloneOptionsCredentialProvider: credentialProvider,
|
||||
]
|
||||
let options = [GTRepositoryCloneOptionsCredentialProvider: credentialProvider]
|
||||
storeRepository = try GTRepository.clone(from: remoteRepoURL, toWorkingDirectory: tempStoreURL, options: options, transferProgressBlock:transferProgressBlock)
|
||||
let fm = FileManager.default
|
||||
if fm.fileExists(atPath: storeURL.path) {
|
||||
|
|
@ -352,16 +257,14 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
func pullRepository(credential: GitCredential, transferProgressBlock: @escaping (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
|
||||
if storeRepository == nil {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Git Repository is not set."])
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
do {
|
||||
let credentialProvider = try credential.credentialProvider()
|
||||
let options: [String: Any] = [
|
||||
GTRepositoryRemoteOptionsCredentialProvider: credentialProvider
|
||||
]
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||
try storeRepository!.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
||||
let options = [GTRepositoryRemoteOptionsCredentialProvider: credentialProvider]
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository)
|
||||
try storeRepository.pull(storeRepository.currentBranch(), from: remote, withOptions: options, progress: transferProgressBlock)
|
||||
} catch {
|
||||
credential.delete()
|
||||
throw(error)
|
||||
|
|
@ -429,21 +332,18 @@ class PasswordStore {
|
|||
}
|
||||
}
|
||||
|
||||
func getRecentCommits(count: Int) -> [GTCommit] {
|
||||
guard storeRepository != nil else {
|
||||
func getRecentCommits(count: Int) throws -> [GTCommit] {
|
||||
guard let storeRepository = storeRepository else {
|
||||
return []
|
||||
}
|
||||
var commits = [GTCommit]()
|
||||
do {
|
||||
let enumerator = try GTEnumerator(repository: storeRepository!)
|
||||
try enumerator.pushSHA(storeRepository!.headReference().targetOID.sha!)
|
||||
for _ in 0 ..< count {
|
||||
let commit = try enumerator.nextObject(withSuccess: nil)
|
||||
commits.append(commit)
|
||||
}
|
||||
} catch {
|
||||
print(error)
|
||||
return commits
|
||||
let enumerator = try GTEnumerator(repository: storeRepository)
|
||||
if let sha = try storeRepository.headReference().targetOID.sha {
|
||||
try enumerator.pushSHA(sha)
|
||||
}
|
||||
for _ in 0 ..< count {
|
||||
let commit = try enumerator.nextObject(withSuccess: nil)
|
||||
commits.append(commit)
|
||||
}
|
||||
return commits
|
||||
}
|
||||
|
|
@ -464,7 +364,6 @@ class PasswordStore {
|
|||
do {
|
||||
if !withDir {
|
||||
passwordEntityFetch.predicate = NSPredicate(format: "isDir = false")
|
||||
|
||||
}
|
||||
let fetchedPasswordEntities = try context.fetch(passwordEntityFetch) as! [PasswordEntity]
|
||||
return fetchedPasswordEntities.sorted { $0.name!.caseInsensitiveCompare($1.name!) == .orderedAscending }
|
||||
|
|
@ -511,11 +410,14 @@ class PasswordStore {
|
|||
|
||||
|
||||
func getLatestUpdateInfo(filename: String) -> String {
|
||||
guard let blameHunks = try? storeRepository?.blame(withFile: filename, options: nil).hunks,
|
||||
let latestCommitTime = blameHunks?.map({
|
||||
guard let storeRepository = storeRepository else {
|
||||
return "Unknown"
|
||||
}
|
||||
guard let blameHunks = try? storeRepository.blame(withFile: filename, options: nil).hunks,
|
||||
let latestCommitTime = blameHunks.map({
|
||||
$0.finalSignature?.time?.timeIntervalSince1970 ?? 0
|
||||
}).max() else {
|
||||
return "unknown"
|
||||
return "Unknown"
|
||||
}
|
||||
let lastCommitDate = Date(timeIntervalSince1970: latestCommitTime)
|
||||
let currentDate = Date()
|
||||
|
|
@ -528,7 +430,7 @@ class PasswordStore {
|
|||
dateComponentsFormatter.unitsStyle = .full
|
||||
dateComponentsFormatter.maximumUnitCount = 2
|
||||
dateComponentsFormatter.includesApproximationPhrase = true
|
||||
autoFormattedDifference = (dateComponentsFormatter.string(from: diffDate)?.appending(" ago"))!
|
||||
autoFormattedDifference = dateComponentsFormatter.string(from: diffDate)!.appending(" ago")
|
||||
}
|
||||
return autoFormattedDifference
|
||||
}
|
||||
|
|
@ -537,21 +439,23 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
private func gitAdd(path: String) throws {
|
||||
if let repo = storeRepository {
|
||||
try repo.index().addFile(path)
|
||||
try repo.index().write()
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
try storeRepository.index().addFile(path)
|
||||
try storeRepository.index().write()
|
||||
}
|
||||
|
||||
private func gitRm(path: String) throws {
|
||||
if let repo = storeRepository {
|
||||
if FileManager.default.fileExists(atPath: storeURL.appendingPathComponent(path).path) {
|
||||
try FileManager.default.removeItem(at: storeURL.appendingPathComponent(path))
|
||||
}
|
||||
try repo.index().removeFile(path)
|
||||
try repo.index().write()
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
|
||||
let url = storeURL.appendingPathComponent(path)
|
||||
if FileManager.default.fileExists(atPath: url.path) {
|
||||
try FileManager.default.removeItem(at: url)
|
||||
}
|
||||
try storeRepository.index().removeFile(path)
|
||||
try storeRepository.index().write()
|
||||
}
|
||||
|
||||
private func deleteDirectoryTree(at url: URL) throws {
|
||||
|
|
@ -571,54 +475,52 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
private func gitMv(from: String, to: String) throws {
|
||||
let fromURL = storeURL.appendingPathComponent(from)
|
||||
let toURL = storeURL.appendingPathComponent(to)
|
||||
let fm = FileManager.default
|
||||
do {
|
||||
guard fm.fileExists(atPath: storeURL.appendingPathComponent(from).path) else {
|
||||
print("\(from) not exist")
|
||||
return
|
||||
}
|
||||
try fm.moveItem(at: storeURL.appendingPathComponent(from), to: storeURL.appendingPathComponent(to))
|
||||
} catch {
|
||||
print(error)
|
||||
guard fm.fileExists(atPath: fromURL.path) else {
|
||||
print("\(from) not exist")
|
||||
return
|
||||
}
|
||||
try fm.moveItem(at: fromURL, to: toURL)
|
||||
try gitAdd(path: to)
|
||||
try gitRm(path: from)
|
||||
}
|
||||
|
||||
private func gitCommit(message: String) throws -> GTCommit? {
|
||||
if let repo = storeRepository {
|
||||
let newTree = try repo.index().writeTree()
|
||||
let headReference = try repo.headReference()
|
||||
let commitEnum = try GTEnumerator(repository: repo)
|
||||
try commitEnum.pushSHA(headReference.targetOID.sha!)
|
||||
let parent = commitEnum.nextObject() as! GTCommit
|
||||
let signature = gitSignatureForNow
|
||||
let commit = try repo.createCommit(with: newTree, message: message, author: signature, committer: signature, parents: [parent], updatingReferenceNamed: headReference.name)
|
||||
return commit
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
return nil
|
||||
let newTree = try storeRepository.index().writeTree()
|
||||
let headReference = try storeRepository.headReference()
|
||||
let commitEnum = try GTEnumerator(repository: storeRepository)
|
||||
try commitEnum.pushSHA(headReference.targetOID.sha!)
|
||||
let parent = commitEnum.nextObject() as! GTCommit
|
||||
let signature = gitSignatureForNow
|
||||
let commit = try storeRepository.createCommit(with: newTree, message: message, author: signature, committer: signature, parents: [parent], updatingReferenceNamed: headReference.name)
|
||||
return commit
|
||||
}
|
||||
|
||||
private func getLocalBranch(withName branchName: String) -> GTBranch? {
|
||||
do {
|
||||
let reference = GTBranch.localNamePrefix().appending(branchName)
|
||||
let branches = try storeRepository!.branches(withPrefix: reference)
|
||||
return branches[0]
|
||||
} catch {
|
||||
print(error)
|
||||
private func getLocalBranch(withName branchName: String) throws -> GTBranch? {
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
return nil
|
||||
let reference = GTBranch.localNamePrefix().appending(branchName)
|
||||
let branches = try storeRepository.branches(withPrefix: reference)
|
||||
return branches.first
|
||||
}
|
||||
|
||||
func pushRepository(credential: GitCredential, transferProgressBlock: @escaping (UInt32, UInt32, Int, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
do {
|
||||
let credentialProvider = try credential.credentialProvider()
|
||||
let options: [String: Any] = [
|
||||
GTRepositoryRemoteOptionsCredentialProvider: credentialProvider,
|
||||
]
|
||||
let masterBranch = getLocalBranch(withName: "master")!
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||
try storeRepository?.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock)
|
||||
let options = [GTRepositoryRemoteOptionsCredentialProvider: credentialProvider]
|
||||
if let masterBranch = try getLocalBranch(withName: "master") {
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository)
|
||||
try storeRepository.push(masterBranch, to: remote, withOptions: options, progress: transferProgressBlock)
|
||||
}
|
||||
} catch {
|
||||
credential.delete()
|
||||
throw(error)
|
||||
|
|
@ -627,7 +529,7 @@ class PasswordStore {
|
|||
|
||||
private func addPasswordEntities(password: Password) throws -> PasswordEntity? {
|
||||
guard !passwordExisted(password: password) else {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 2, userInfo: [NSLocalizedDescriptionKey: "Cannot add password: password duplicated."])
|
||||
throw AppError.PasswordDuplicatedError
|
||||
}
|
||||
|
||||
var passwordURL = password.url!
|
||||
|
|
@ -726,7 +628,6 @@ class PasswordStore {
|
|||
|
||||
private func deletePasswordEntities(passwordEntity: PasswordEntity) throws {
|
||||
var current: PasswordEntity? = passwordEntity
|
||||
print(passwordEntity.path!)
|
||||
while current != nil && (current!.children!.count == 0 || !current!.isDir) {
|
||||
let parent = current!.parent
|
||||
self.context.delete(current!)
|
||||
|
|
@ -761,13 +662,13 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
func updateImage(passwordEntity: PasswordEntity, image: Data?) {
|
||||
if image == nil {
|
||||
guard let image = image else {
|
||||
return
|
||||
}
|
||||
let privateMOC = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
|
||||
privateMOC.parent = context
|
||||
privateMOC.perform {
|
||||
passwordEntity.image = NSData(data: image!)
|
||||
passwordEntity.image = NSData(data: image)
|
||||
do {
|
||||
try privateMOC.save()
|
||||
self.context.performAndWait {
|
||||
|
|
@ -796,7 +697,6 @@ class PasswordStore {
|
|||
|
||||
Utils.removeAllKeychain()
|
||||
|
||||
|
||||
deleteCoreData(entityName: "PasswordEntity")
|
||||
|
||||
Defaults.removeAll()
|
||||
|
|
@ -808,6 +708,9 @@ class PasswordStore {
|
|||
|
||||
// return the number of discarded commits
|
||||
func reset() throws -> Int {
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
// get a list of local commits
|
||||
if let localCommits = try getLocalCommits(),
|
||||
localCommits.count > 0 {
|
||||
|
|
@ -815,9 +718,9 @@ class PasswordStore {
|
|||
guard let firstLocalCommit = localCommits.last,
|
||||
firstLocalCommit.parents.count == 1,
|
||||
let newHead = firstLocalCommit.parents.first else {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Cannot decide how to reset."])
|
||||
throw AppError.GitResetError
|
||||
}
|
||||
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
||||
try storeRepository.reset(to: newHead, resetType: .hard)
|
||||
self.setAllSynced()
|
||||
self.updatePasswordEntityCoreData()
|
||||
|
||||
|
|
@ -843,24 +746,28 @@ class PasswordStore {
|
|||
}
|
||||
|
||||
private func getLocalCommits() throws -> [GTCommit]? {
|
||||
// get the remote origin/master branch
|
||||
guard let remoteBranches = try storeRepository?.remoteBranches(),
|
||||
let index = remoteBranches.index(where: { $0.shortName == "master" })
|
||||
else {
|
||||
throw NSError(domain: "me.mssun.pass.error", code: 1, userInfo: [NSLocalizedDescriptionKey: "Cannot find remote branch origin/master."])
|
||||
guard let storeRepository = storeRepository else {
|
||||
throw AppError.RepositoryNotSetError
|
||||
}
|
||||
// get the remote origin/master branch
|
||||
guard let index = try storeRepository.remoteBranches().index(where: { $0.shortName == "master" }) else {
|
||||
throw AppError.RepositoryRemoteMasterNotFoundError
|
||||
}
|
||||
let remoteMasterBranch = try storeRepository.remoteBranches()[index]
|
||||
|
||||
// check oid before calling localCommitsRelative
|
||||
guard remoteMasterBranch.oid != nil else {
|
||||
throw AppError.RepositoryRemoteMasterNotFoundError
|
||||
}
|
||||
let remoteMasterBranch = remoteBranches[index]
|
||||
//print("remoteMasterBranch \(remoteMasterBranch)")
|
||||
|
||||
// get a list of local commits
|
||||
return try storeRepository?.localCommitsRelative(toRemoteBranch: remoteMasterBranch)
|
||||
return try storeRepository.localCommitsRelative(toRemoteBranch: remoteMasterBranch)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func decrypt(passwordEntity: PasswordEntity, requestPGPKeyPassphrase: () -> String) throws -> Password? {
|
||||
var password: Password?
|
||||
let encryptedDataPath = URL(fileURLWithPath: "\(Globals.repositoryPath)/\(passwordEntity.path!)")
|
||||
let encryptedDataPath = storeURL.appendingPathComponent(passwordEntity.path!)
|
||||
let encryptedData = try Data(contentsOf: encryptedDataPath)
|
||||
var passphrase = self.pgpKeyPassphrase
|
||||
if passphrase == nil {
|
||||
|
|
@ -869,14 +776,15 @@ class PasswordStore {
|
|||
let decryptedData = try PasswordStore.shared.pgp.decryptData(encryptedData, passphrase: passphrase)
|
||||
let plainText = String(data: decryptedData, encoding: .utf8) ?? ""
|
||||
let escapedPath = passwordEntity.path!.stringByAddingPercentEncodingForRFC3986() ?? ""
|
||||
password = Password(name: passwordEntity.name!, url: URL(string: escapedPath), plainText: plainText)
|
||||
return password
|
||||
return Password(name: passwordEntity.name!, url: URL(string: escapedPath), plainText: plainText)
|
||||
}
|
||||
|
||||
func encrypt(password: Password) throws -> Data {
|
||||
guard let publicKey = pgp.getKeysOf(.public).first else {
|
||||
throw AppError.PGPPublicKeyNotExistError
|
||||
}
|
||||
let plainData = password.getPlainData()
|
||||
let pgp = PasswordStore.shared.pgp
|
||||
let encryptedData = try pgp.encryptData(plainData, usingPublicKey: pgp.getKeysOf(.public)[0], armored: Defaults[.encryptInArmored])
|
||||
let encryptedData = try pgp.encryptData(plainData, usingPublicKey: publicKey, armored: Defaults[.encryptInArmored])
|
||||
return encryptedData
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,9 +62,11 @@ class LabelTableViewCell: UITableViewCell {
|
|||
case "url":
|
||||
type = .URL
|
||||
contentLabel.text = content
|
||||
contentLabel.font = UIFont.systemFont(ofSize: contentLabel.font.pointSize)
|
||||
default:
|
||||
type = .other
|
||||
contentLabel.text = content
|
||||
contentLabel.font = UIFont.systemFont(ofSize: contentLabel.font.pointSize)
|
||||
}
|
||||
updateButtons()
|
||||
}
|
||||
|
|
@ -75,21 +77,6 @@ class LabelTableViewCell: UITableViewCell {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
}
|
||||
|
||||
override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
if buttons != nil {
|
||||
self.accessoryView = buttons
|
||||
}
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
}
|
||||
|
||||
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
|
||||
switch type {
|
||||
|
|
@ -208,5 +195,6 @@ class LabelTableViewCell: UITableViewCell {
|
|||
passwordDisplayButton = nil
|
||||
buttons = nil
|
||||
}
|
||||
self.accessoryView = buttons
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue