Merge branch 'release/0.2.3'
2
.gitignore
vendored
|
|
@ -62,7 +62,7 @@ Carthage/Build
|
|||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
|
||||
|
||||
fastlane
|
||||
fastlane/README.md
|
||||
fastlane/report.xml
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots
|
||||
|
|
|
|||
9
.travis.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
language: objective-c
|
||||
osx_image: xcode8.3
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
before_install:
|
||||
- echo -e "machine github.com\n login $GITHUB_ACCESS_TOKEN" >> ~/.netrc
|
||||
script:
|
||||
- ./fastlane/travis.sh
|
||||
2
Cartfile
|
|
@ -1,6 +1,6 @@
|
|||
github "SVProgressHUD/SVProgressHUD"
|
||||
github "radex/SwiftyUserDefaults"
|
||||
github "libgit2/objective-git" "master"
|
||||
github "libgit2/objective-git"
|
||||
github "zahlz/SwiftPasscodeLock" "master"
|
||||
github "bitserf/FavIcon"
|
||||
github "kishikawakatsumi/KeychainAccess" "master"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
[](https://github.com/mssun/pass-ios/releases)
|
||||

|
||||
[](https://gitter.im/passforios/passforios)
|
||||
[](https://travis-ci.org/mssun/passforios)
|
||||
|
||||
Pass is an iOS client compatible with [ZX2C4's Pass command line
|
||||
application](http://www.passwordstore.org/). It is a password manager using
|
||||
|
|
|
|||
4
fastlane/Appfile
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
app_identifier ENV["APP_IDENTIFIER"]
|
||||
apple_id ENV["APPLE_ID"]
|
||||
team_id ENV["TEAM_ID"]
|
||||
itc_team_id ENV["ITC_TEAM_ID"]
|
||||
101
fastlane/Fastfile
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# Customise this file, documentation can be found here:
|
||||
# https://github.com/fastlane/fastlane/tree/master/fastlane/docs
|
||||
# All available actions: https://docs.fastlane.tools/actions
|
||||
# can also be listed using the `fastlane actions` command
|
||||
|
||||
# Change the syntax highlighting to Ruby
|
||||
# All lines starting with a # are ignored when running `fastlane`
|
||||
|
||||
# If you want to automatically update fastlane if a new version is available:
|
||||
# update_fastlane
|
||||
|
||||
# This is the minimum version number required.
|
||||
# Update this, if you use features of a newer version
|
||||
fastlane_version "2.17.0"
|
||||
|
||||
default_platform :ios
|
||||
|
||||
platform :ios do
|
||||
before_all do
|
||||
cocoapods
|
||||
carthage(platform: "iOS")
|
||||
end
|
||||
|
||||
desc "Travis"
|
||||
lane :travis do
|
||||
test
|
||||
beta
|
||||
end
|
||||
|
||||
desc "Runs all the tests"
|
||||
lane :test do
|
||||
scan(
|
||||
scheme: "pass",
|
||||
device: "iPhone 7"
|
||||
)
|
||||
end
|
||||
|
||||
desc "Submit a new Beta Build to Apple TestFlight"
|
||||
desc "This will also make sure the profile is up to date"
|
||||
lane :beta do
|
||||
create_keychain(
|
||||
name: ENV["MATCH_KEYCHAIN_NAME"],
|
||||
password: ENV["MATCH_KEYCHAIN_PASSWORD"],
|
||||
default_keychain: true,
|
||||
unlock: true,
|
||||
timeout: 3600,
|
||||
add_to_search_list: true
|
||||
)
|
||||
match(
|
||||
type: "appstore",
|
||||
keychain_name: ENV["MATCH_KEYCHAIN_NAME"],
|
||||
keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"],
|
||||
readonly: true
|
||||
)
|
||||
# ensure_git_status_clean
|
||||
increment_build_number(
|
||||
build_number: latest_testflight_build_number + 1,
|
||||
xcodeproj: "pass.xcodeproj"
|
||||
)
|
||||
# commit_version_bump(xcodeproj: "pass.xcodeproj")
|
||||
# push_to_git_remote
|
||||
gym(scheme: "pass")
|
||||
pilot(skip_waiting_for_build_processing: true)
|
||||
mailgun(
|
||||
postmaster: ENV["MY_POSTMASTER"],
|
||||
apikey: ENV["MY_API_KEY"],
|
||||
to: ENV["DESTINATION_EMAIL"],
|
||||
from: ENV["EMAIL_FROM_NAME"],
|
||||
reply_to: ENV["EMAIL_REPLY_TO"],
|
||||
subject: "A new build of Pass for iOS has been uploaded",
|
||||
success: true,
|
||||
app_link: "https://github.com/mssun/passforios",
|
||||
ci_build_link: "https://travis-ci.org/mssun/passforios",
|
||||
message: "A new build has been uploaded by Travis CI.",
|
||||
)
|
||||
end
|
||||
|
||||
desc "Deploy a new version to the App Store"
|
||||
lane :release do
|
||||
# match(type: "appstore")
|
||||
# snapshot
|
||||
gym(scheme: "pass") # Build your app - more options available
|
||||
deliver(force: true)
|
||||
# frameit
|
||||
end
|
||||
|
||||
# You can define as many lanes as you want
|
||||
|
||||
after_all do |lane|
|
||||
end
|
||||
|
||||
error do |lane, exception|
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md
|
||||
# All available actions: https://docs.fastlane.tools/actions
|
||||
|
||||
# fastlane reports which actions are used
|
||||
# No personal data is recorded. Learn more at https://github.com/fastlane/enhancer
|
||||
9
fastlane/Matchfile
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
git_url "https://github.com/mssun/certificates-passforios.git"
|
||||
|
||||
type "development" # The default type, can be: appstore, adhoc, enterprise or development
|
||||
|
||||
# app_identifier ["tools.fastlane.app", "tools.fastlane.app2"]
|
||||
# username "user@fastlane.tools" # Your Apple Developer Portal username
|
||||
|
||||
# For all available options run `fastlane match --help`
|
||||
# Remove the # in the beginning of the line to enable the other options
|
||||
9
fastlane/travis.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/bin/sh
|
||||
|
||||
gem update fastlane
|
||||
if [ "$TRAVIS_PULL_REQUEST" == "true" ]; then
|
||||
fastlane test;
|
||||
else
|
||||
fastlane travis;
|
||||
fi
|
||||
exit $?
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */; };
|
||||
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */; };
|
||||
DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; };
|
||||
DC13B1511E8640810097803F /* passTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC13B1501E8640810097803F /* passTests.swift */; };
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; };
|
||||
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; };
|
||||
DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */; };
|
||||
|
|
@ -52,10 +53,10 @@
|
|||
DCC277D21E30D6EA00402246 /* pass.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DCC408C81E30BA1300F29B0E /* pass.xcdatamodeld */; };
|
||||
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */; };
|
||||
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 */; };
|
||||
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */; };
|
||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */; };
|
||||
DCE6C2671E71261C003038C6 /* PasswordWithFolderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */; };
|
||||
DCE6C2681E71261C003038C6 /* PasswordWithFolderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */; };
|
||||
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */; };
|
||||
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */; };
|
||||
DCFB779E1E4F40C7008DE471 /* FillPasswordTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */; };
|
||||
|
|
@ -67,6 +68,16 @@
|
|||
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
DC13B1531E8640810097803F /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = DC917BCB1E2E8231000FDF54 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = DC917BD21E2E8231000FDF54;
|
||||
remoteInfo = pass;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
274CCFCF32444A2FF46BE7F4 /* Pods-pass.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pass.debug.xcconfig"; path = "Pods/Target Support Files/Pods-pass/Pods-pass.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
A262A58C1E68749C006B0890 /* Base32.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Base32.framework; path = Carthage/Build/iOS/Base32.framework; sourceTree = "<group>"; };
|
||||
|
|
@ -87,6 +98,9 @@
|
|||
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextViewTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TextViewTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DC1208571E35EBE60042942E /* ObjectiveGit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectiveGit.framework; path = Carthage/Build/iOS/ObjectiveGit.framework; sourceTree = "<group>"; };
|
||||
DC13B14E1E8640810097803F /* passTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = passTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DC13B1501E8640810097803F /* passTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = passTests.swift; sourceTree = "<group>"; };
|
||||
DC13B1521E8640810097803F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsTableViewController.swift; sourceTree = "<group>"; };
|
||||
DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PasscodeLock.framework; path = Carthage/Build/iOS/PasscodeLock.framework; sourceTree = "<group>"; };
|
||||
DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockRepository.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -118,10 +132,10 @@
|
|||
DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordStore.swift; sourceTree = "<group>"; };
|
||||
DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordWithFolderTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordWithFolderTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleTextFieldTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TitleTextFieldTableViewCell.xib; sourceTree = "<group>"; };
|
||||
DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FillPasswordTableViewCell.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -134,6 +148,13 @@
|
|||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
DC13B14B1E8640810097803F /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DC917BD01E2E8231000FDF54 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -162,6 +183,15 @@
|
|||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC13B14F1E8640810097803F /* passTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DC13B1501E8640810097803F /* passTests.swift */,
|
||||
DC13B1521E8640810097803F /* Info.plist */,
|
||||
);
|
||||
path = passTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DC19400C1E4B39400077E0A3 /* Controllers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -177,12 +207,14 @@
|
|||
DCA049991E335CC800522E8F /* GitServerSettingTableViewController.swift */,
|
||||
DC037CA51E4B883900609409 /* OpenSourceComponentsTableViewController.swift */,
|
||||
DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */,
|
||||
DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */,
|
||||
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */,
|
||||
DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */,
|
||||
DCA0499B1E3362F400522E8F /* PGPKeySettingTableViewController.swift */,
|
||||
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
|
||||
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
|
||||
DC8963BF1E38EEB900828B09 /* SSHKeySettingTableViewController.swift */,
|
||||
DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */,
|
||||
);
|
||||
path = Controllers;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -229,8 +261,6 @@
|
|||
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */,
|
||||
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */,
|
||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
||||
DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */,
|
||||
DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -239,6 +269,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DC917BD51E2E8231000FDF54 /* pass */,
|
||||
DC13B14F1E8640810097803F /* passTests */,
|
||||
DC917BD41E2E8231000FDF54 /* Products */,
|
||||
DC917BED1E2F38C4000FDF54 /* Frameworks */,
|
||||
A51B01737D08DB47BB58F85A /* Pods */,
|
||||
|
|
@ -249,6 +280,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DC917BD31E2E8231000FDF54 /* pass.app */,
|
||||
DC13B14E1E8640810097803F /* passTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -289,6 +321,24 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
DC13B14D1E8640810097803F /* passTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DC13B1571E8640810097803F /* Build configuration list for PBXNativeTarget "passTests" */;
|
||||
buildPhases = (
|
||||
DC13B14A1E8640810097803F /* Sources */,
|
||||
DC13B14B1E8640810097803F /* Frameworks */,
|
||||
DC13B14C1E8640810097803F /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
DC13B1541E8640810097803F /* PBXTargetDependency */,
|
||||
);
|
||||
name = passTests;
|
||||
productName = passTests;
|
||||
productReference = DC13B14E1E8640810097803F /* passTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
DC917BD21E2E8231000FDF54 /* pass */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = DC917BE51E2E8231000FDF54 /* Build configuration list for PBXNativeTarget "pass" */;
|
||||
|
|
@ -316,14 +366,20 @@
|
|||
DC917BCB1E2E8231000FDF54 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0820;
|
||||
LastSwiftUpdateCheck = 0830;
|
||||
LastUpgradeCheck = 0820;
|
||||
ORGANIZATIONNAME = "Bob Sun";
|
||||
TargetAttributes = {
|
||||
DC13B14D1E8640810097803F = {
|
||||
CreatedOnToolsVersion = 8.3;
|
||||
DevelopmentTeam = 4WDM8E95VU;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = DC917BD21E2E8231000FDF54;
|
||||
};
|
||||
DC917BD21E2E8231000FDF54 = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
DevelopmentTeam = 4WDM8E95VU;
|
||||
ProvisioningStyle = Automatic;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -341,11 +397,19 @@
|
|||
projectRoot = "";
|
||||
targets = (
|
||||
DC917BD21E2E8231000FDF54 /* pass */,
|
||||
DC13B14D1E8640810097803F /* passTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
DC13B14C1E8640810097803F /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DC917BD11E2E8231000FDF54 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -357,7 +421,6 @@
|
|||
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */,
|
||||
DC917BDC1E2E8231000FDF54 /* Main.storyboard in Resources */,
|
||||
A2802BFA1E70813A00879216 /* SliderTableViewCell.xib in Resources */,
|
||||
DCE6C2681E71261C003038C6 /* PasswordWithFolderTableViewCell.xib in Resources */,
|
||||
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */,
|
||||
DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */,
|
||||
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */,
|
||||
|
|
@ -437,12 +500,21 @@
|
|||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
DC13B14A1E8640810097803F /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DC13B1511E8640810097803F /* passTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
DC917BCF1E2E8231000FDF54 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */,
|
||||
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */,
|
||||
DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */,
|
||||
DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */,
|
||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
||||
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */,
|
||||
|
|
@ -452,7 +524,6 @@
|
|||
DC5F385B1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift in Sources */,
|
||||
A27424D91E7C35960093F436 /* NotificationNames.swift in Sources */,
|
||||
DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */,
|
||||
DCE6C2671E71261C003038C6 /* PasswordWithFolderTableViewCell.swift in Sources */,
|
||||
DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */,
|
||||
DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */,
|
||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */,
|
||||
|
|
@ -469,6 +540,7 @@
|
|||
DC037CB21E4CAB1700609409 /* AboutRepositoryTableViewController.swift in Sources */,
|
||||
DC037CB01E4CA51F00609409 /* GeneralSettingsTableViewController.swift in Sources */,
|
||||
DC037CB81E4DD1A500609409 /* AddPasswordTableViewController.swift in Sources */,
|
||||
DCC441521E8F6C06008A90C4 /* RawPasswordViewController.swift in Sources */,
|
||||
DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */,
|
||||
DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */,
|
||||
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */,
|
||||
|
|
@ -484,6 +556,14 @@
|
|||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
DC13B1541E8640810097803F /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = DC917BD21E2E8231000FDF54 /* pass */;
|
||||
targetProxy = DC13B1531E8640810097803F /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
DC917BDA1E2E8231000FDF54 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
|
|
@ -504,6 +584,38 @@
|
|||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
DC13B1551E8640810097803F /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
INFOPLIST_FILE = passTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
DC13B1561E8640810097803F /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
INFOPLIST_FILE = passTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
DC917BE31E2E8231000FDF54 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
|
|
@ -601,7 +713,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 24;
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEFINES_MODULE = NO;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
@ -620,6 +732,8 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "893c10b3-79b1-46f7-914a-e625bf10d665";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match Development me.mssun.passforios";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -632,8 +746,8 @@
|
|||
baseConfigurationReference = AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CURRENT_PROJECT_VERSION = 24;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
CURRENT_PROJECT_VERSION = 2;
|
||||
DEFINES_MODULE = NO;
|
||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
|
|
@ -652,6 +766,8 @@
|
|||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "aefeea85-1194-4db2-9ce4-fb9995e2fdff";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.mssun.passforios";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -662,6 +778,15 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
DC13B1571E8640810097803F /* Build configuration list for PBXNativeTarget "passTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
DC13B1551E8640810097803F /* Debug */,
|
||||
DC13B1561E8640810097803F /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
DC917BCE1E2E8231000FDF54 /* Build configuration list for PBXProject "pass" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
|
|||
108
pass.xcodeproj/xcshareddata/xcschemes/pass.xcscheme
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0820"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DC917BD21E2E8231000FDF54"
|
||||
BuildableName = "pass.app"
|
||||
BlueprintName = "pass"
|
||||
ReferencedContainer = "container:pass.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DC13B14D1E8640810097803F"
|
||||
BuildableName = "passTests.xctest"
|
||||
BlueprintName = "passTests"
|
||||
ReferencedContainer = "container:pass.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DC917BD21E2E8231000FDF54"
|
||||
BuildableName = "pass.app"
|
||||
BlueprintName = "pass"
|
||||
ReferencedContainer = "container:pass.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DC917BD21E2E8231000FDF54"
|
||||
BuildableName = "pass.app"
|
||||
BlueprintName = "pass"
|
||||
ReferencedContainer = "container:pass.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<EnvironmentVariables>
|
||||
<EnvironmentVariable
|
||||
key = "OS_ACTIVITY_MODE"
|
||||
value = "disable"
|
||||
isEnabled = "YES">
|
||||
</EnvironmentVariable>
|
||||
</EnvironmentVariables>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "DC917BD21E2E8231000FDF54"
|
||||
BuildableName = "pass.app"
|
||||
BlueprintName = "pass"
|
||||
ReferencedContainer = "container:pass.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
22
pass/Assets.xcassets/Camera.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Screenshot-50.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Screenshot-100.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
pass/Assets.xcassets/Camera.imageset/Screenshot-100.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
pass/Assets.xcassets/Camera.imageset/Screenshot-50.png
vendored
Normal file
|
After Width: | Height: | Size: 841 B |
22
pass/Assets.xcassets/Copy.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Copy-50.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Copy-100.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
pass/Assets.xcassets/Copy.imageset/Copy-100.png
vendored
Normal file
|
After Width: | Height: | Size: 853 B |
BIN
pass/Assets.xcassets/Copy.imageset/Copy-50.png
vendored
Normal file
|
After Width: | Height: | Size: 420 B |
22
pass/Assets.xcassets/HorizontalSettings.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Horizontal Settings Mixer-50.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Horizontal Settings Mixer-75.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-50.png
vendored
Normal file
|
After Width: | Height: | Size: 444 B |
BIN
pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-75.png
vendored
Normal file
|
After Width: | Height: | Size: 946 B |
12
pass/Assets.xcassets/Invisible.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "not-visible-interface-symbol-of-an-eye-with-a-slash-on-it.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
22
pass/Assets.xcassets/Refresh.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Refresh-64.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "Refresh-75.png",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
pass/Assets.xcassets/Refresh.imageset/Refresh-64.png
vendored
Normal file
|
After Width: | Height: | Size: 939 B |
BIN
pass/Assets.xcassets/Refresh.imageset/Refresh-75.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
12
pass/Assets.xcassets/Visible.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "eye-visible-outlined-interface-symbol.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
BIN
pass/Assets.xcassets/Visible.imageset/eye-visible-outlined-interface-symbol.pdf
vendored
Normal file
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" 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="12106.1" systemVersion="16F43c" 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>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<tableViewSection headerTitle="PASSCODE" id="Cx7-e4-wCO">
|
||||
<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"/>
|
||||
|
|
@ -167,8 +167,8 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="381" height="43.666666666666664"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Passcode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RaZ-6t-0CU">
|
||||
<rect key="frame" x="15" y="11.999999999999998" width="74.333333333333329" height="20.333333333333332"/>
|
||||
<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="15" y="11.999999999999998" width="115" height="20.333333333333332"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
|
|
@ -288,7 +288,7 @@
|
|||
<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="OfB-1N-1Am" id="fh0-au-C6q">
|
||||
<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.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="101" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="00/00/0000" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hj4-EP-LFW">
|
||||
|
|
@ -340,10 +340,10 @@
|
|||
<tableViewSection headerTitle="Git Repository URL" id="pbe-W6-w4V">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="gitRepositoryURLTabelViewCell" rowHeight="52" id="FRr-pf-aPO">
|
||||
<rect key="frame" x="0.0" y="55" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="55.5" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="FRr-pf-aPO" id="60A-PS-qGe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Git Repository URL" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="EVT-VU-sCi">
|
||||
|
|
@ -366,10 +366,10 @@
|
|||
<tableViewSection headerTitle="Username" id="fRu-A2-SCk">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="usernameTableVIewCell" rowHeight="52" id="tnj-5U-kMB">
|
||||
<rect key="frame" x="0.0" y="163" width="414" height="52"/>
|
||||
<rect key="frame" x="0.0" y="163.5" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tnj-5U-kMB" id="f0c-pI-MSJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Username" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="TMg-Gk-7nG">
|
||||
|
|
@ -392,10 +392,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" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="271.5" 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="43"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
|
||||
<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">
|
||||
|
|
@ -423,10 +423,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" width="414" height="44"/>
|
||||
<rect key="frame" x="0.0" y="315.5" 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="43"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="367" height="44"/>
|
||||
<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">
|
||||
|
|
@ -477,10 +477,11 @@
|
|||
<connections>
|
||||
<outlet property="authPasswordCell" destination="KrP-nb-haa" id="zjH-sg-dfJ"/>
|
||||
<outlet property="authSSHKeyCell" destination="Qmt-bo-CuJ" id="11L-Tt-MgM"/>
|
||||
<outlet property="gitRepositoryURLTextField" destination="EVT-VU-sCi" id="2EH-Uq-tbU"/>
|
||||
<outlet property="gitURLTextField" destination="EVT-VU-sCi" id="XdU-3l-Nsv"/>
|
||||
<outlet property="usernameTextField" destination="TMg-Gk-7nG" id="htL-4C-WJF"/>
|
||||
<segue destination="7K9-cE-9qq" kind="unwind" identifier="saveGitServerSettingSegue" unwindAction="saveGitServerSettingWithSegue:" id="5UN-sC-xCA"/>
|
||||
<segue destination="hqC-Ic-NMi" kind="show" identifier="showSSHKeySettingSegue" id="AP7-FV-2Ow"/>
|
||||
<segue destination="hqC-Ic-NMi" kind="show" identifier="setGitSSHKeyByURLSegue" id="AP7-FV-2Ow"/>
|
||||
<segue destination="WgM-cY-mig" kind="show" identifier="setGitSSHKeyByArmorSegue" id="HLm-0q-hUg"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="7c1-c7-Qyp" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
|
|
@ -503,7 +504,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="52"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<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">
|
||||
|
|
@ -533,7 +534,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="52"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="51.5"/>
|
||||
<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">
|
||||
|
|
@ -626,7 +627,7 @@
|
|||
<scene sceneID="9wY-d0-fB1">
|
||||
<objects>
|
||||
<tableViewController id="tW4-E9-CGv" customClass="PasswordDetailTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" allowsSelection="NO" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="hfi-6O-04U">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="hfi-6O-04U">
|
||||
<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"/>
|
||||
|
|
@ -638,6 +639,7 @@
|
|||
</tableView>
|
||||
<connections>
|
||||
<segue destination="eui-w4-P7T" kind="show" identifier="editPasswordSegue" id="Ydg-pZ-oNS"/>
|
||||
<segue destination="kNf-lG-BeC" kind="presentation" identifier="showRawPasswordSegue" modalTransitionStyle="flipHorizontal" id="qpR-3X-eyt"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="9sC-44-OKL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
|
|
@ -736,6 +738,50 @@
|
|||
</objects>
|
||||
<point key="canvasLocation" x="6084" y="601"/>
|
||||
</scene>
|
||||
<!--Raw Password View Controller-->
|
||||
<scene sceneID="Oqg-Vh-EYD">
|
||||
<objects>
|
||||
<viewController id="mlB-OK-hLo" customClass="RawPasswordViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="XeK-cv-AXf"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="7JD-uM-IyS"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="5YZ-6i-LST">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3dt-Ph-4As">
|
||||
<rect key="frame" x="20" y="4" width="374" height="732"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
|
||||
<fontDescription key="fontDescription" name="Courier" family="Courier" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="3dt-Ph-4As" secondAttribute="trailing" id="2IV-7r-9eG"/>
|
||||
<constraint firstItem="7JD-uM-IyS" firstAttribute="top" secondItem="3dt-Ph-4As" secondAttribute="bottom" id="3yp-aL-exH"/>
|
||||
<constraint firstItem="3dt-Ph-4As" firstAttribute="top" secondItem="XeK-cv-AXf" secondAttribute="bottom" constant="-60" id="R2h-nh-8eZ"/>
|
||||
<constraint firstAttribute="leadingMargin" secondItem="3dt-Ph-4As" secondAttribute="leading" id="jgf-j1-lNa"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="c13-zM-tLf">
|
||||
<barButtonItem key="leftBarButtonItem" title="Back" id="9yM-Mg-Cg8">
|
||||
<connections>
|
||||
<segue destination="pNY-ul-yzB" kind="unwind" unwindAction="backWithSegue:" id="SzI-Au-9rJ"/>
|
||||
</connections>
|
||||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<outlet property="rawPasswordTextView" destination="3dt-Ph-4As" id="SVL-F8-5yD"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="zgb-Ji-ZBp" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="pNY-ul-yzB" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="7721.739130434783" y="-24.456521739130437"/>
|
||||
</scene>
|
||||
<!--About Repository Table View Controller-->
|
||||
<scene sceneID="u1v-BP-jaG">
|
||||
<objects>
|
||||
|
|
@ -791,7 +837,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="Jy1-4S-Lvf" id="tJE-ww-okf">
|
||||
<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.5"/>
|
||||
<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">
|
||||
|
|
@ -821,7 +867,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="MA5-lE-8dT" id="pTv-Wj-psC">
|
||||
<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.5"/>
|
||||
<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">
|
||||
|
|
@ -847,36 +893,6 @@
|
|||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="passphrase" rowHeight="52" id="yER-vT-YTO">
|
||||
<rect key="frame" x="0.0" y="139" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="yER-vT-YTO" id="Mip-zw-xLu">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Passphrase" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Rnj-2x-ksO">
|
||||
<rect key="frame" x="15" y="8" width="391" height="15"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="Passphrase" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="4oZ-lc-EFS">
|
||||
<rect key="frame" x="15" y="23" width="391" height="21"/>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="URL" secureTextEntry="YES"/>
|
||||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Rnj-2x-ksO" firstAttribute="leading" secondItem="Mip-zw-xLu" secondAttribute="leadingMargin" constant="7" id="B0m-eX-UKn"/>
|
||||
<constraint firstItem="4oZ-lc-EFS" firstAttribute="top" secondItem="Rnj-2x-ksO" secondAttribute="bottom" id="V7l-fu-KnP"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Rnj-2x-ksO" secondAttribute="trailing" id="nEm-LM-Uwg"/>
|
||||
<constraint firstAttribute="topMargin" secondItem="Rnj-2x-ksO" secondAttribute="top" id="nPH-l3-bRA"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="4oZ-lc-EFS" secondAttribute="trailing" id="uIe-w7-hcX"/>
|
||||
<constraint firstItem="4oZ-lc-EFS" firstAttribute="leading" secondItem="Rnj-2x-ksO" secondAttribute="leading" id="vEc-EI-F0z"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
|
|
@ -886,14 +902,13 @@
|
|||
</connections>
|
||||
</tableView>
|
||||
<connections>
|
||||
<outlet property="passphraseTextField" destination="4oZ-lc-EFS" id="dtf-H3-gBh"/>
|
||||
<outlet property="privateKeyURLTextField" destination="4iJ-oB-R1f" id="scx-lz-dUW"/>
|
||||
<outlet property="publicKeyURLTextField" destination="Q1j-Z4-Ae8" id="nfA-W3-kJ2"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="eY3-aM-BJB" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="5132" y="2893"/>
|
||||
<point key="canvasLocation" x="7433" y="2204"/>
|
||||
</scene>
|
||||
<!--General Settings Table View Controller-->
|
||||
<scene sceneID="fho-xr-1Ah">
|
||||
|
|
@ -1135,7 +1150,7 @@
|
|||
<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="170"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="169.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" delaysContentTouches="NO" canCancelContentTouches="NO" bouncesZoom="NO" editable="NO" usesAttributedText="YES" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xzQ-5d-kdL">
|
||||
|
|
@ -1193,7 +1208,7 @@
|
|||
<rect key="frame" x="0.0" y="261" 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="160"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyB-oI-1fS">
|
||||
|
|
@ -1249,7 +1264,7 @@ pfZ36xQbOAQYKKf6ZTT5R/Y=
|
|||
<rect key="frame" x="0.0" y="477" 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="160"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="159.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lrQ-Ln-ZOv">
|
||||
|
|
@ -1326,7 +1341,7 @@ pfZ36xQbOAQYKKf6ZTT5R/Y=
|
|||
<placeholder placeholderIdentifier="IBFirstResponder" id="2Wn-7D-LLj" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="Ul9-vk-jhw" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6039.130434782609" y="4307.608695652174"/>
|
||||
<point key="canvasLocation" x="7094" y="4030"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="m18-ch-m92">
|
||||
|
|
@ -1346,6 +1361,218 @@ pfZ36xQbOAQYKKf6ZTT5R/Y=
|
|||
</objects>
|
||||
<point key="canvasLocation" x="5131.884057971015" y="4307.608695652174"/>
|
||||
</scene>
|
||||
<!--Navigation Controller-->
|
||||
<scene sceneID="Ps2-MC-JQX">
|
||||
<objects>
|
||||
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="kNf-lG-BeC" sceneMemberID="viewController">
|
||||
<toolbarItems/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="Dx6-8j-IzX">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<nil name="viewControllers"/>
|
||||
<connections>
|
||||
<segue destination="mlB-OK-hLo" kind="relationship" relationship="rootViewController" id="wp3-xi-lwY"/>
|
||||
</connections>
|
||||
</navigationController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ycf-Zv-ej8" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6720" y="-24"/>
|
||||
</scene>
|
||||
<!--GitSSH Key Armor Setting Table View Controller-->
|
||||
<scene sceneID="zWR-BT-dXv">
|
||||
<objects>
|
||||
<tableViewController id="WgM-cY-mig" customClass="GitSSHKeyArmorSettingTableViewController" 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="18" sectionFooterHeight="18" id="e2Q-qC-LUk">
|
||||
<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"/>
|
||||
<sections>
|
||||
<tableViewSection id="HgL-ju-8xi">
|
||||
<cells>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="pgpKeyURLTableViewCell" rowHeight="170" id="EMz-nP-2Om">
|
||||
<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.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" delaysContentTouches="NO" canCancelContentTouches="NO" bouncesZoom="NO" editable="NO" usesAttributedText="YES" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vkU-ka-wAm">
|
||||
<rect key="frame" x="15" y="22" width="391" height="146.66666666666666"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<attributedString key="attributedText">
|
||||
<fragment>
|
||||
<string key="content">ASCII-armored key format similar to uuencoded documents rather than binary format.
|
||||
|
||||
</string>
|
||||
<attributes>
|
||||
<color key="NSColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<font key="NSFont" size="14" name=".AppleSystemUIFont"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
<fragment>
|
||||
<string key="content"> $ cat ~/.ssh/id_rsa.pub
|
||||
$ cat ~/.ssh/id_rsa</string>
|
||||
<attributes>
|
||||
<color key="NSColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<font key="NSFont" size="13" name="Menlo-Regular"/>
|
||||
<paragraphStyle key="NSParagraphStyle" alignment="left" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
|
||||
</attributes>
|
||||
</fragment>
|
||||
</attributedString>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
|
||||
</textView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="ASCII-Armor Keys" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HIF-Zn-aBt">
|
||||
<rect key="frame" x="15" y="8" width="391" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="Sh8-Aj-s7i"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="HIF-Zn-aBt" firstAttribute="leading" secondItem="XW5-mL-PRC" secondAttribute="leadingMargin" constant="7" id="2fZ-Tu-6jx"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="vkU-ka-wAm" secondAttribute="trailing" id="I1w-xW-439"/>
|
||||
<constraint firstItem="vkU-ka-wAm" firstAttribute="top" secondItem="HIF-Zn-aBt" secondAttribute="bottom" constant="-7" id="QEU-iz-4AS"/>
|
||||
<constraint firstItem="vkU-ka-wAm" firstAttribute="leading" secondItem="XW5-mL-PRC" secondAttribute="leadingMargin" constant="7" id="UEQ-vW-A0q"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="HIF-Zn-aBt" secondAttribute="trailing" id="h7g-Ft-YVp"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="vkU-ka-wAm" secondAttribute="bottom" constant="-7" id="lHv-ws-fct"/>
|
||||
<constraint firstAttribute="topMargin" secondItem="HIF-Zn-aBt" secondAttribute="top" id="uqY-0s-I2H"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<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="261" 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"/>
|
||||
<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"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<string key="text">-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFiiqFoBCACzvPOW+J1RlQOI9oB7Iwuk92rzpkKGC8tiwo4otHMc3rxmzYlG
|
||||
gEdHmSi6Ix0+hYZ2vSWJamPQl9WUiYSBQmkVwoqiwXNWcqRePOylcqsj58owIxZt
|
||||
23nXUIG78t+5BatoWyl9/qXsMUMSink7RAlOnjCyvoSJw9yzUVeWn723rvAr7ypV
|
||||
yqjce4gOGIfGT8PpGXThDQjvg4gM+wxUD3+oNhW50Qb+crMsefxwEoGXbCA4+6ZO
|
||||
nJGy2MhRr4FkXwNAAcvTvTmYXQfH8Q8xCtgl4PyxQA4OAeoEfxl5FOuOGIbNKgMs
|
||||
133n2oue5dy3YERN2t9/Di8Iov4Bsc+nj6+vABEBAAG0E1Bhc3MgZm9yIGlPUyAo
|
||||
RGVtbymJATcEEwEKACEFAliiqFoCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AA
|
||||
CgkQl/oT92AAdt0TqAgAlTsGLTe9+qY9pfyBVpDk+z1SC9kaOYsvoj7hSWVOXxwP
|
||||
yn4jxjHUr1C9fyaZqP9K4yIdl9jsGBkpaR6lhnUm9x5RO5gEAAAaLhx3ZgE7/XQg
|
||||
y7WHibxsnLaTEMVnNh8BJzQveYSqO8frBkQofj0K9LNiqWHhcllKKNkVHqyeMRII
|
||||
KYPOXvDnsnKqywapu5VyyErMnPqq6h7i3Z7+xDfVk8iUew9i0LR/QEmJO7iTH98C
|
||||
DczQo+4VnflBIHiNcMaXQqC2Li5rS+O3a9hq5V/gJwBtIx1iXvDaRATH4aUANxTZ
|
||||
POHVLwxBuTwilhnEaAPGkGu+oG1XF+RWOyrGYluWc7kBDQRYoqhaAQgAoh9B+sY1
|
||||
jZZgnqP11a9wkjom2DcBJLreYNzgBFYhUcmxtq+ZWyorPFzMJpbIjzMGRiGWFIus
|
||||
DE5D5LZdAvkINWKsbVN6Y3OI6Tj+/O45SuJ7EusG8Z1bwmjJqHy/Y//Fk0rF6ZFs
|
||||
g0+p12Xzr5k8sMKUU4I5T4DNrsS+mwnOPItC7NGawkArPD7Mew0ma+Luv7b3g0gA
|
||||
DuofvxKiN0jq6W9QPUNRY4BKm+Y03CdZNXyMDs/NTguDdfarawTIAIlJOSg5rV7S
|
||||
74v73dtZkB5LySX1rBomRb5zkCg6/Ygap4RO1aO9gbXyPmc2lUQSBAJCS9d8h0qD
|
||||
sNGembqhGDwHpQARAQABiQEfBBgBCgAJBQJYoqhaAhsMAAoJEJf6E/dgAHbdKl4H
|
||||
/A/Q+hOh40M2B6Sh/Rsus+k1VL51+UXVJRyiNiqvofamufF5ULfeq3Pt5HfqpCsF
|
||||
/A7iRP0MuanKcZbLDjDv6wWDuRvW9Kwn5qjbb6iBPh+wfyReqNMWGksJTyap0SNR
|
||||
+Mn+sjbxGkUPjzVdRdqtw64R3DLW6SpMNIUVC6paazCViEtHsSauWwP/0+DRA/6j
|
||||
xBHSAr0UaLsRTHleOSWV6ABrh9skJRWLBcOoi5pxotBs/3BmjqERQf9bwmmyxj2K
|
||||
cE60Muv6qY4/KCQqPKhyFjJwXhS/e7BwxHEt1SbUb1aC4lH5UrbW9KYLu5lHJRdY
|
||||
pfZ36xQbOAQYKKf6ZTT5R/Y=
|
||||
=2pJ8
|
||||
-----END PGP PUBLIC KEY BLOCK-----</string>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="Y9t-DD-6uH" secondAttribute="bottom" id="EAK-Wn-RP8"/>
|
||||
<constraint firstItem="Y9t-DD-6uH" firstAttribute="top" secondItem="pet-if-EHU" secondAttribute="topMargin" id="LW7-SZ-CP3"/>
|
||||
<constraint firstItem="Y9t-DD-6uH" firstAttribute="leading" secondItem="pet-if-EHU" secondAttribute="leadingMargin" constant="7" id="bw3-EI-8oh"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Y9t-DD-6uH" secondAttribute="trailing" id="fCY-XN-Wtz"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
<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="477" 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"/>
|
||||
<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"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<string key="text">-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQENBFiiqFoBCACzvPOW+J1RlQOI9oB7Iwuk92rzpkKGC8tiwo4otHMc3rxmzYlG
|
||||
gEdHmSi6Ix0+hYZ2vSWJamPQl9WUiYSBQmkVwoqiwXNWcqRePOylcqsj58owIxZt
|
||||
23nXUIG78t+5BatoWyl9/qXsMUMSink7RAlOnjCyvoSJw9yzUVeWn723rvAr7ypV
|
||||
yqjce4gOGIfGT8PpGXThDQjvg4gM+wxUD3+oNhW50Qb+crMsefxwEoGXbCA4+6ZO
|
||||
nJGy2MhRr4FkXwNAAcvTvTmYXQfH8Q8xCtgl4PyxQA4OAeoEfxl5FOuOGIbNKgMs
|
||||
133n2oue5dy3YERN2t9/Di8Iov4Bsc+nj6+vABEBAAG0E1Bhc3MgZm9yIGlPUyAo
|
||||
RGVtbymJATcEEwEKACEFAliiqFoCGwMFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AA
|
||||
CgkQl/oT92AAdt0TqAgAlTsGLTe9+qY9pfyBVpDk+z1SC9kaOYsvoj7hSWVOXxwP
|
||||
yn4jxjHUr1C9fyaZqP9K4yIdl9jsGBkpaR6lhnUm9x5RO5gEAAAaLhx3ZgE7/XQg
|
||||
y7WHibxsnLaTEMVnNh8BJzQveYSqO8frBkQofj0K9LNiqWHhcllKKNkVHqyeMRII
|
||||
KYPOXvDnsnKqywapu5VyyErMnPqq6h7i3Z7+xDfVk8iUew9i0LR/QEmJO7iTH98C
|
||||
DczQo+4VnflBIHiNcMaXQqC2Li5rS+O3a9hq5V/gJwBtIx1iXvDaRATH4aUANxTZ
|
||||
POHVLwxBuTwilhnEaAPGkGu+oG1XF+RWOyrGYluWc7kBDQRYoqhaAQgAoh9B+sY1
|
||||
jZZgnqP11a9wkjom2DcBJLreYNzgBFYhUcmxtq+ZWyorPFzMJpbIjzMGRiGWFIus
|
||||
DE5D5LZdAvkINWKsbVN6Y3OI6Tj+/O45SuJ7EusG8Z1bwmjJqHy/Y//Fk0rF6ZFs
|
||||
g0+p12Xzr5k8sMKUU4I5T4DNrsS+mwnOPItC7NGawkArPD7Mew0ma+Luv7b3g0gA
|
||||
DuofvxKiN0jq6W9QPUNRY4BKm+Y03CdZNXyMDs/NTguDdfarawTIAIlJOSg5rV7S
|
||||
74v73dtZkB5LySX1rBomRb5zkCg6/Ygap4RO1aO9gbXyPmc2lUQSBAJCS9d8h0qD
|
||||
sNGembqhGDwHpQARAQABiQEfBBgBCgAJBQJYoqhaAhsMAAoJEJf6E/dgAHbdKl4H
|
||||
/A/Q+hOh40M2B6Sh/Rsus+k1VL51+UXVJRyiNiqvofamufF5ULfeq3Pt5HfqpCsF
|
||||
/A7iRP0MuanKcZbLDjDv6wWDuRvW9Kwn5qjbb6iBPh+wfyReqNMWGksJTyap0SNR
|
||||
+Mn+sjbxGkUPjzVdRdqtw64R3DLW6SpMNIUVC6paazCViEtHsSauWwP/0+DRA/6j
|
||||
xBHSAr0UaLsRTHleOSWV6ABrh9skJRWLBcOoi5pxotBs/3BmjqERQf9bwmmyxj2K
|
||||
cE60Muv6qY4/KCQqPKhyFjJwXhS/e7BwxHEt1SbUb1aC4lH5UrbW9KYLu5lHJRdY
|
||||
pfZ36xQbOAQYKKf6ZTT5R/Y=
|
||||
=2pJ8
|
||||
-----END PGP PUBLIC KEY BLOCK-----</string>
|
||||
<color key="textColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="8.5"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="23o-MP-wQY" secondAttribute="bottom" id="45J-dA-N4r"/>
|
||||
<constraint firstItem="23o-MP-wQY" firstAttribute="top" secondItem="TQD-GC-YOY" secondAttribute="topMargin" id="Tth-YH-Ni9"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="23o-MP-wQY" secondAttribute="trailing" id="lqq-rV-fZK"/>
|
||||
<constraint firstItem="23o-MP-wQY" firstAttribute="leading" secondItem="TQD-GC-YOY" secondAttribute="leadingMargin" constant="7" id="oYc-y1-XS9"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</cells>
|
||||
</tableViewSection>
|
||||
</sections>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="WgM-cY-mig" id="7bV-Gr-WNu"/>
|
||||
<outlet property="delegate" destination="WgM-cY-mig" id="lsz-m8-HZb"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
<connections>
|
||||
<outlet property="armorPrivateKeyTextView" destination="23o-MP-wQY" id="ybK-Ba-vJt"/>
|
||||
<outlet property="armorPublicKeyTextView" destination="Y9t-DD-6uH" id="307-xN-QZ9"/>
|
||||
</connections>
|
||||
</tableViewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="qJO-AN-K9p" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="6870" y="3117"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="Lock" width="25" height="25"/>
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class AboutRepositoryTableViewController: BasicStaticTableViewController {
|
|||
[[.style: CellDataStyle.value1, .accessoryType: type, .title: "Passwords", .detailText: numberOfPasswordsString],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Size", .detailText: sizeOfRepositoryString],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Local Commits", .detailText: String(self?.passwordStore.numberOfLocalCommits() ?? 0)],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Last Synced", .detailText: Utils.getLastUpdatedTimeString()],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Last Synced", .detailText: Utils.getLastSyncedTimeString()],
|
||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Commits", .detailText: numberOfCommitsString],
|
||||
[.title: "Commit Logs", .action: "segue", .link: "showCommitLogsSegue"],
|
||||
],
|
||||
|
|
|
|||
|
|
@ -22,14 +22,15 @@ class EditPasswordTableViewController: PasswordEditorTableViewController {
|
|||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if identifier == "saveEditPasswordSegue" {
|
||||
let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! ContentTableViewCell
|
||||
if nameCell.getContent() != password?.name {
|
||||
let alertTitle = "Cannot Save Edit"
|
||||
let alertMessage = "Editing name is not supported."
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self) {
|
||||
nameCell.setContent(content: self.password!.name)
|
||||
if let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? ContentTableViewCell {
|
||||
if nameCell.getContent() != password?.name {
|
||||
let alertTitle = "Cannot Save Edit"
|
||||
let alertMessage = "Editing name is not supported."
|
||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self) {
|
||||
nameCell.setContent(content: self.password!.name)
|
||||
}
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
//
|
||||
// GitSSHKeyArmorSettingTableViewController.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 2/4/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftyUserDefaults
|
||||
|
||||
class GitSSHKeyArmorSettingTableViewController: UITableViewController {
|
||||
@IBOutlet weak var armorPublicKeyTextView: UITextView!
|
||||
@IBOutlet weak var armorPrivateKeyTextView: UITextView!
|
||||
var gitSSHPrivateKeyPassphrase: String?
|
||||
let passwordStore = PasswordStore.shared
|
||||
var doneBarButtonItem: UIBarButtonItem?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
armorPublicKeyTextView.text = Defaults[.gitSSHPublicKeyArmor]
|
||||
armorPrivateKeyTextView.text = Defaults[.gitSSHPrivateKeyArmor]
|
||||
gitSSHPrivateKeyPassphrase = passwordStore.gitSSHPrivateKeyPassphrase
|
||||
|
||||
doneBarButtonItem = UIBarButtonItem(title: "Done",
|
||||
style: UIBarButtonItemStyle.done,
|
||||
target: self,
|
||||
action: #selector(doneButtonTapped(_:)))
|
||||
navigationItem.rightBarButtonItem = doneBarButtonItem
|
||||
navigationItem.title = "SSH Key"
|
||||
}
|
||||
|
||||
private func createSavePassphraseAlert() -> UIAlertController {
|
||||
let savePassphraseAlert = UIAlertController(title: "Passphrase", message: "Do you want to save the passphrase for later sync?", preferredStyle: UIAlertControllerStyle.alert)
|
||||
savePassphraseAlert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default) { _ in
|
||||
Defaults[.isRememberPassphraseOn] = false
|
||||
Defaults[.gitSSHKeySource] = "armor"
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
})
|
||||
savePassphraseAlert.addAction(UIAlertAction(title: "Save", style: UIAlertActionStyle.destructive) {_ in
|
||||
Defaults[.isRememberPassphraseOn] = true
|
||||
self.passwordStore.gitSSHPrivateKeyPassphrase = self.gitSSHPrivateKeyPassphrase
|
||||
Defaults[.gitSSHKeySource] = "armor"
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
})
|
||||
return savePassphraseAlert
|
||||
}
|
||||
|
||||
func doneButtonTapped(_ sender: Any) {
|
||||
Defaults[.gitSSHPublicKeyArmor] = armorPublicKeyTextView.text
|
||||
Defaults[.gitSSHPrivateKeyArmor] = armorPrivateKeyTextView.text
|
||||
do {
|
||||
try passwordStore.initGitSSHKey(with: armorPublicKeyTextView.text, .public)
|
||||
try passwordStore.initGitSSHKey(with: armorPrivateKeyTextView.text, .secret)
|
||||
} catch {
|
||||
Utils.alert(title: "Cannot Save", message: "Cannot Save SSH Key", controller: self, completion: nil)
|
||||
}
|
||||
let alert = UIAlertController(title: "Passphrase", message: "Please fill in the passphrase of your SSH secret key.", preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||
self.gitSSHPrivateKeyPassphrase = alert.textFields?.first?.text
|
||||
let savePassphraseAlert = self.createSavePassphraseAlert()
|
||||
self.present(savePassphraseAlert, animated: true, completion: nil)
|
||||
}))
|
||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = self.gitSSHPrivateKeyPassphrase
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -8,17 +8,18 @@
|
|||
|
||||
import UIKit
|
||||
import SwiftyUserDefaults
|
||||
import SVProgressHUD
|
||||
|
||||
class GitServerSettingTableViewController: UITableViewController {
|
||||
|
||||
@IBOutlet weak var gitRepositoryURLTextField: UITextField!
|
||||
@IBOutlet weak var gitURLTextField: UITextField!
|
||||
@IBOutlet weak var usernameTextField: UITextField!
|
||||
@IBOutlet weak var authSSHKeyCell: UITableViewCell!
|
||||
@IBOutlet weak var authPasswordCell: UITableViewCell!
|
||||
let passwordStore = PasswordStore.shared
|
||||
var password: String?
|
||||
|
||||
var authenticationMethod = Defaults[.gitRepositoryAuthenticationMethod]
|
||||
var authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||
|
||||
private func checkAuthenticationMethod(method: String) {
|
||||
let passwordCheckView = authPasswordCell.viewWithTag(1001)!
|
||||
|
|
@ -38,17 +39,17 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
}
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
if let url = Defaults[.gitRepositoryURL] {
|
||||
gitRepositoryURLTextField.text = url.absoluteString
|
||||
if let url = Defaults[.gitURL] {
|
||||
gitURLTextField.text = url.absoluteString
|
||||
}
|
||||
usernameTextField.text = Defaults[.gitRepositoryUsername]
|
||||
password = passwordStore.gitRepositoryPassword
|
||||
authenticationMethod = Defaults[.gitRepositoryAuthenticationMethod]
|
||||
usernameTextField.text = Defaults[.gitUsername]
|
||||
password = passwordStore.gitPassword
|
||||
authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||
|
||||
// Grey out ssh option if ssh_key and ssh_key.pub are not present
|
||||
let sshLabel = authSSHKeyCell.subviews[0].subviews[0] as! UILabel
|
||||
|
||||
sshLabel.isEnabled = sshKeyExists()
|
||||
sshLabel.isEnabled = gitSSHKeyExists()
|
||||
|
||||
if authenticationMethod == nil || !sshLabel.isEnabled {
|
||||
authenticationMethod = "Password"
|
||||
|
|
@ -61,7 +62,7 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
if cell == authSSHKeyCell {
|
||||
performSegue(withIdentifier: "showSSHKeySettingSegue", sender: self)
|
||||
showSSHKeyActionSheet()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
|
||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if identifier == "saveGitServerSettingSegue" {
|
||||
guard let _ = URL(string: gitRepositoryURLTextField.text!) else {
|
||||
guard let _ = URL(string: gitURLTextField.text!) else {
|
||||
Utils.alert(title: "Cannot Save", message: "Git Server is not set.", controller: self, completion: nil)
|
||||
return false
|
||||
}
|
||||
|
|
@ -89,18 +90,13 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
return true
|
||||
}
|
||||
|
||||
func sshKeyExists() -> Bool {
|
||||
return FileManager.default.fileExists(atPath: Globals.sshPublicKeyURL.path) &&
|
||||
FileManager.default.fileExists(atPath: Globals.sshPrivateKeyURL.path)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let cell = tableView.cellForRow(at: indexPath)
|
||||
if cell == authPasswordCell {
|
||||
authenticationMethod = "Password"
|
||||
} else if cell == authSSHKeyCell {
|
||||
|
||||
if !sshKeyExists() {
|
||||
if !gitSSHKeyExists() {
|
||||
Utils.alert(title: "Cannot Select SSH Key", message: "Please setup SSH key first.", controller: self, completion: nil)
|
||||
authenticationMethod = "Password"
|
||||
} else {
|
||||
|
|
@ -131,4 +127,74 @@ class GitServerSettingTableViewController: UITableViewController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func gitSSHKeyExists() -> Bool {
|
||||
return FileManager.default.fileExists(atPath: Globals.gitSSHPublicKeyPath) &&
|
||||
FileManager.default.fileExists(atPath: Globals.gitSSHPrivateKeyPath)
|
||||
}
|
||||
|
||||
func showSSHKeyActionSheet() {
|
||||
let optionMenu = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||
var urlActionTitle = "Download from URL"
|
||||
var armorActionTitle = "ASCII-Armor Encrypted Key"
|
||||
var fileActionTitle = "Use Uploaded Keys"
|
||||
|
||||
if Defaults[.gitSSHKeySource] == "url" {
|
||||
urlActionTitle = "✓ \(urlActionTitle)"
|
||||
} else if Defaults[.gitSSHKeySource] == "armor" {
|
||||
armorActionTitle = "✓ \(armorActionTitle)"
|
||||
} else if Defaults[.gitSSHKeySource] == "file" {
|
||||
fileActionTitle = "✓ \(fileActionTitle)"
|
||||
}
|
||||
let urlAction = UIAlertAction(title: urlActionTitle, style: .default) { _ in
|
||||
self.performSegue(withIdentifier: "setGitSSHKeyByURLSegue", sender: self)
|
||||
}
|
||||
let armorAction = UIAlertAction(title: armorActionTitle, style: .default) { _ in
|
||||
self.performSegue(withIdentifier: "setGitSSHKeyByArmorSegue", sender: self)
|
||||
}
|
||||
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
|
||||
optionMenu.addAction(urlAction)
|
||||
optionMenu.addAction(armorAction)
|
||||
|
||||
if (gitSSHKeyExists()) {
|
||||
let fileAction = UIAlertAction(title: fileActionTitle, style: .default) { _ in
|
||||
let alert = UIAlertController(
|
||||
title: "SSH Key Passphrase",
|
||||
message: "Please fill in the passphrase for your Git Repository SSH key.",
|
||||
preferredStyle: UIAlertControllerStyle.alert
|
||||
)
|
||||
|
||||
alert.addAction(
|
||||
UIAlertAction(
|
||||
title: "OK",
|
||||
style: UIAlertActionStyle.default,
|
||||
handler: {_ in
|
||||
self.passwordStore.gitSSHPrivateKeyPassphrase = alert.textFields!.first!.text!
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
alert.addTextField(
|
||||
configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = self.passwordStore.gitSSHPrivateKeyPassphrase
|
||||
textField.isSecureTextEntry = true
|
||||
}
|
||||
)
|
||||
}
|
||||
Defaults[.gitSSHKeySource] = "file"
|
||||
optionMenu.addAction(fileAction)
|
||||
}
|
||||
|
||||
if Defaults[.gitSSHKeySource] != nil {
|
||||
let deleteAction = UIAlertAction(title: "Remove Git SSH Keys", style: .destructive) { _ in
|
||||
Utils.removeGitSSHKeys()
|
||||
Defaults[.gitSSHKeySource] = nil
|
||||
}
|
||||
optionMenu.addAction(deleteAction)
|
||||
}
|
||||
optionMenu.addAction(cancelAction)
|
||||
optionMenu.popoverPresentationController?.sourceView = authSSHKeyCell
|
||||
optionMenu.popoverPresentationController?.sourceRect = authSSHKeyCell.bounds
|
||||
self.present(optionMenu, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
content = ""
|
||||
}
|
||||
|
||||
init(title: String) {
|
||||
self.title = title
|
||||
self.content = ""
|
||||
}
|
||||
|
||||
init(title: String, content: String) {
|
||||
self.title = title
|
||||
self.content = content
|
||||
|
|
@ -46,24 +51,39 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
|
||||
private struct TableSection {
|
||||
var title: String
|
||||
var type: PasswordDetailTableViewControllerSectionType
|
||||
var header: String?
|
||||
var item: Array<TableCell>
|
||||
init(type: PasswordDetailTableViewControllerSectionType) {
|
||||
self.type = type
|
||||
header = nil
|
||||
item = [TableCell]()
|
||||
}
|
||||
|
||||
init(type: PasswordDetailTableViewControllerSectionType, header: String) {
|
||||
self.init(type: type)
|
||||
self.header = header
|
||||
}
|
||||
}
|
||||
|
||||
private var tableData = Array<TableSection>()
|
||||
|
||||
private enum PasswordDetailTableViewControllerSectionType {
|
||||
case name, main, addition, misc
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.register(UINib(nibName: "LabelTableViewCell", bundle: nil), forCellReuseIdentifier: "labelCell")
|
||||
tableView.register(UINib(nibName: "PasswordDetailTitleTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordDetailTitleTableViewCell")
|
||||
|
||||
passwordCategoryText = passwordEntity!.getCategoryText()
|
||||
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PasswordDetailTableViewController.tapMenu(recognizer:)))
|
||||
tapGesture.cancelsTouchesInView = false
|
||||
tableView.addGestureRecognizer(tapGesture)
|
||||
tapGesture.delegate = self
|
||||
|
||||
tableView.contentInset = UIEdgeInsetsMake(-36, 0, 0, 0);
|
||||
tableView.contentInset = UIEdgeInsetsMake(-36, 0, 44, 0);
|
||||
tableView.rowHeight = UITableViewAutomaticDimension
|
||||
tableView.estimatedRowHeight = 52
|
||||
|
||||
|
|
@ -224,23 +244,31 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
|
||||
private func setTableData() {
|
||||
self.tableData = Array<TableSection>()
|
||||
tableData.append(TableSection(title: "", item: []))
|
||||
tableData[0].item.append(TableCell())
|
||||
var tableDataIndex = 1
|
||||
self.tableData.append(TableSection(title: "", item: []))
|
||||
|
||||
// name section
|
||||
var section = TableSection(type: .name)
|
||||
section.item.append(TableCell())
|
||||
tableData.append(section)
|
||||
|
||||
// main section
|
||||
section = TableSection(type: .main)
|
||||
let password = self.password!
|
||||
if let username = password.getUsername() {
|
||||
self.tableData[tableDataIndex].item.append(TableCell(title: "username", content: username))
|
||||
section.item.append(TableCell(title: "username", content: username))
|
||||
}
|
||||
self.tableData[tableDataIndex].item.append(TableCell(title: "password", content: password.password))
|
||||
section.item.append(TableCell(title: "password", content: password.password))
|
||||
tableData.append(section)
|
||||
|
||||
|
||||
// addition section
|
||||
|
||||
// show one time password
|
||||
if password.otpType != .none {
|
||||
if let (title, otp) = self.password?.getOtpStrings() {
|
||||
self.tableData.append(TableSection(title: "One time password", item: []))
|
||||
tableDataIndex += 1
|
||||
oneTimePasswordIndexPath = IndexPath(row: 0, section: tableDataIndex)
|
||||
self.tableData[tableDataIndex].item.append(TableCell(title: title, content: otp))
|
||||
section = TableSection(type: .addition, header: "One Time Password")
|
||||
section.item.append(TableCell(title: title, content: otp))
|
||||
tableData.append(section)
|
||||
oneTimePasswordIndexPath = IndexPath(row: 0, section: tableData.count - 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,12 +280,18 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
(!Password.otpKeywords.contains($0) || !Defaults[.isHideOTPOn]) }
|
||||
|
||||
if filteredAdditionKeys.count > 0 {
|
||||
self.tableData.append(TableSection(title: "additions", item: []))
|
||||
tableDataIndex += 1
|
||||
section = TableSection(type: .addition, header: "additions")
|
||||
for additionKey in filteredAdditionKeys {
|
||||
self.tableData[tableDataIndex].item.append(TableCell(title: additionKey, content: password.additions[additionKey]!))
|
||||
section.item.append(TableCell(title: additionKey, content: password.additions[additionKey]!))
|
||||
}
|
||||
tableData.append(section)
|
||||
}
|
||||
|
||||
// misc section
|
||||
section = TableSection(type: .misc)
|
||||
section.item.append(TableCell(title: "Show Raw"))
|
||||
tableData.append(section)
|
||||
|
||||
}
|
||||
|
||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
|
|
@ -267,6 +301,12 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
editController.password = password
|
||||
}
|
||||
}
|
||||
} else if segue.identifier == "showRawPasswordSegue" {
|
||||
if let controller = segue.destination as? UINavigationController {
|
||||
if let controller = controller.viewControllers.first as? RawPasswordViewController {
|
||||
controller.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -328,6 +368,16 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
||||
if touch.view!.isKind(of: UIButton.classForCoder()) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@IBAction func back(segue:UIStoryboardSegue) {
|
||||
}
|
||||
|
||||
func getNextHOTP() {
|
||||
guard password != nil, passwordEntity != nil, password?.otpType == .hotp else {
|
||||
DispatchQueue.main.async {
|
||||
|
|
@ -380,8 +430,9 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let sectionIndex = indexPath.section
|
||||
let rowIndex = indexPath.row
|
||||
|
||||
if sectionIndex == 0 && rowIndex == 0 {
|
||||
let tableDataItem = tableData[sectionIndex].item[rowIndex]
|
||||
switch(tableData[sectionIndex].type) {
|
||||
case .name:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordDetailTitleTableViewCell", for: indexPath) as! PasswordDetailTitleTableViewCell
|
||||
cell.passwordImageImageView.image = passwordImage ?? #imageLiteral(resourceName: "PasswordImagePlaceHolder")
|
||||
var passwordName = passwordEntity!.name!
|
||||
|
|
@ -390,22 +441,29 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
cell.nameLabel.text = passwordName
|
||||
cell.categoryLabel.text = passwordCategoryText
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
} else {
|
||||
case .main, .addition:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell", for: indexPath) as! LabelTableViewCell
|
||||
let titleData = tableData[sectionIndex].item[rowIndex].title
|
||||
let contentData = tableData[sectionIndex].item[rowIndex].content
|
||||
let titleData = tableDataItem.title
|
||||
let contentData = tableDataItem.content
|
||||
cell.delegatePasswordTableView = self
|
||||
cell.isPasswordCell = (titleData.lowercased() == "password" ? true : false)
|
||||
cell.isURLCell = (titleData.lowercased() == "url" ? true : false)
|
||||
cell.isHOTPCell = (titleData == "HMAC-based" ? true : false)
|
||||
cell.cellData = LabelTableViewCellData(title: titleData, content: contentData)
|
||||
cell.selectionStyle = .none
|
||||
return cell
|
||||
case .misc:
|
||||
let cell = UITableViewCell()
|
||||
cell.textLabel?.text = tableDataItem.title
|
||||
cell.selectionStyle = .default
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
return tableData[section].title
|
||||
return tableData[section].header
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
|
||||
|
|
@ -430,10 +488,26 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
|||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
|
||||
return action == #selector(UIResponderStandardEditActions.copy(_:))
|
||||
let section = tableData[indexPath.section]
|
||||
switch(section.type) {
|
||||
case .main, .addition:
|
||||
return action == #selector(UIResponderStandardEditActions.copy(_:))
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let section = tableData[indexPath.section]
|
||||
if section.type == .misc {
|
||||
if section.item[indexPath.row].title == "Show Raw" {
|
||||
performSegue(withIdentifier: "showRawPasswordSegue", sender: self)
|
||||
}
|
||||
}
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftyUserDefaults
|
||||
|
||||
enum PasswordEditorCellType {
|
||||
case textFieldCell, textViewCell, fillPasswordCell, passwordLengthCell, deletePasswordCell
|
||||
}
|
||||
|
|
@ -54,11 +56,6 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
tableView.estimatedRowHeight = 48
|
||||
self.tableView.sectionFooterHeight = UITableViewAutomaticDimension;
|
||||
self.tableView.estimatedSectionFooterHeight = 0;
|
||||
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableTapped))
|
||||
tapGesture.delegate = self
|
||||
tapGesture.cancelsTouchesInView = false
|
||||
tableView.addGestureRecognizer(tapGesture)
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
|
|
@ -76,7 +73,12 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
return fillPasswordCell!
|
||||
case .passwordLengthCell:
|
||||
passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell
|
||||
passwordLengthCell?.reset(title: "Length", minimumValue: Globals.passwordMinimumLength, maximumValue: Globals.passwordMaximumLength, defaultValue: Globals.passwordDefaultLength)
|
||||
let lengthSetting = Globals.passwordDefaultLength[Defaults[.passwordGeneratorFlavor]] ??
|
||||
Globals.passwordDefaultLength["Random"]
|
||||
passwordLengthCell?.reset(title: "Length",
|
||||
minimumValue: lengthSetting?.min ?? 0,
|
||||
maximumValue: lengthSetting?.max ?? 0,
|
||||
defaultValue: lengthSetting?.def ?? 0)
|
||||
passwordLengthCell?.delegate = self
|
||||
return passwordLengthCell!
|
||||
case .deletePasswordCell:
|
||||
|
|
@ -148,7 +150,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
hidePasswordSettings = false
|
||||
tableView.reloadSections([passwordSection], with: .fade)
|
||||
}
|
||||
let length = passwordLengthCell?.roundedValue ?? Globals.passwordDefaultLength
|
||||
let length = passwordLengthCell?.roundedValue ?? 0
|
||||
let plainPassword = Utils.generatePassword(length: length)
|
||||
Utils.copyToPasteboard(textToCopy: plainPassword)
|
||||
|
||||
|
|
@ -159,35 +161,8 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
|||
fillPasswordCell?.setContent(content: plainPassword)
|
||||
}
|
||||
|
||||
func tableTapped(recognizer: UITapGestureRecognizer) {
|
||||
if recognizer.state == UIGestureRecognizerState.ended {
|
||||
let tapLocation = recognizer.location(in: self.tableView)
|
||||
let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation)
|
||||
|
||||
// do nothing, if delete is tapped (a temporary solution)
|
||||
if tapIndexPath != nil, deletePasswordCell != nil,
|
||||
tableView.cellForRow(at: tapIndexPath!) == deletePasswordCell {
|
||||
return
|
||||
}
|
||||
|
||||
// hide password settings (e.g., the length slider)
|
||||
if tapIndexPath?.section != passwordSection, hidePasswordSettings == false {
|
||||
hidePasswordSettings = true
|
||||
tableView.reloadSections([passwordSection], with: .fade)
|
||||
// select the row at tapIndexPath manually
|
||||
if tapIndexPath != nil {
|
||||
self.tableView(self.tableView, didSelectRowAt: tapIndexPath!)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
if gestureRecognizer is UITapGestureRecognizer {
|
||||
// so that the tap gesture could be passed by
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
func showHidePasswordSettings() {
|
||||
hidePasswordSettings = !hidePasswordSettings
|
||||
tableView.reloadSections([passwordSection], with: .fade)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(parent: parent)
|
||||
} else {
|
||||
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
||||
|
||||
}
|
||||
passwordsTableEntries = passwordEntities.map {
|
||||
PasswordsTableEntry(title: $0.name!, isDir: $0.isDir, passwordEntity: $0)
|
||||
|
|
@ -109,8 +108,8 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
SVProgressHUD.showProgress(progress, status: "Encrypting")
|
||||
}
|
||||
})
|
||||
|
||||
DispatchQueue.main.async {
|
||||
// will trigger reloadTableView() by a notification
|
||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
}
|
||||
|
|
@ -144,8 +143,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
}
|
||||
DispatchQueue.main.async {
|
||||
self.reloadTableView(parent: nil)
|
||||
Defaults[.lastUpdatedTime] = Date()
|
||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
||||
Defaults[.gitPasswordAttempts] = 0
|
||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
}
|
||||
|
|
@ -174,9 +172,9 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
reloadTableView(parent: nil)
|
||||
|
||||
// reset the data table if some password (maybe another one) has been updated
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadTableView as (Void) -> Void), name: .passwordStoreUpdated, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(actOnReloadTableViewRelatedNotification), name: .passwordStoreUpdated, object: nil)
|
||||
// reset the data table if the disaply settings have been changed
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadTableView as (Void) -> Void), name: .passwordDisplaySettingChanged, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(actOnReloadTableViewRelatedNotification), name: .passwordDisplaySettingChanged, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(actOnSearchNotification), name: .passwordSearch, object: nil)
|
||||
}
|
||||
|
||||
|
|
@ -221,20 +219,23 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
} else {
|
||||
cell.textLabel?.text = "\(entry.title)"
|
||||
cell.accessoryType = .disclosureIndicator
|
||||
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||
cell.detailTextLabel?.text = "\(entry.passwordEntity?.children?.count ?? 0)"
|
||||
}
|
||||
return cell
|
||||
} else {
|
||||
let passwordWithFolderCell = tableView.dequeueReusableCell(withIdentifier: "passwordWithFolderTableViewCell", for: indexPath) as! PasswordWithFolderTableViewCell
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordTableViewCell", for: indexPath)
|
||||
let entry = getPasswordEntry(by: indexPath)
|
||||
if entry.passwordEntity!.synced {
|
||||
passwordWithFolderCell.passwordLabel?.text = entry.title
|
||||
cell.textLabel?.text = entry.title
|
||||
} else {
|
||||
passwordWithFolderCell.passwordLabel?.text = "↻ \(entry.title)"
|
||||
cell.textLabel?.text = "↻ \(entry.title)"
|
||||
}
|
||||
passwordWithFolderCell.folderLabel.text = entry.passwordEntity?.getCategoryText()
|
||||
passwordWithFolderCell.addGestureRecognizer(longPressGestureRecognizer)
|
||||
return passwordWithFolderCell
|
||||
cell.accessoryType = .none
|
||||
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
|
||||
cell.detailTextLabel?.text = entry.passwordEntity?.getCategoryText()
|
||||
cell.addGestureRecognizer(longPressGestureRecognizer)
|
||||
return cell
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -429,7 +430,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
self.tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
||||
|
||||
// set the sync control title
|
||||
let atribbutedTitle = "Last Synced: \(Utils.getLastUpdatedTimeString())"
|
||||
let atribbutedTitle = "Last Synced: \(Utils.getLastSyncedTimeString())"
|
||||
syncControl.attributedTitle = NSAttributedString(string: atribbutedTitle)
|
||||
}
|
||||
|
||||
|
|
@ -438,9 +439,12 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
|||
reloadTableView(data: passwordsTableEntries, anim: anim)
|
||||
}
|
||||
|
||||
func reloadTableView() {
|
||||
func actOnReloadTableViewRelatedNotification() {
|
||||
initPasswordsTableEntries(parent: nil)
|
||||
reloadTableView(data: passwordsTableEntries)
|
||||
DispatchQueue.main.async { [weak weakSelf = self] in
|
||||
guard let strongSelf = weakSelf else { return }
|
||||
strongSelf.reloadTableView(data: strongSelf.passwordsTableEntries)
|
||||
}
|
||||
}
|
||||
|
||||
func handleRefresh(_ syncControl: UIRefreshControl) {
|
||||
|
|
|
|||
21
pass/Controllers/RawPasswordViewController.swift
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// RawPasswordViewController.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 31/3/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class RawPasswordViewController: UIViewController {
|
||||
|
||||
@IBOutlet weak var rawPasswordTextView: UITextView!
|
||||
var password: Password?
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
navigationItem.title = "Raw"
|
||||
rawPasswordTextView.text = password?.plainText
|
||||
}
|
||||
}
|
||||
|
|
@ -12,15 +12,14 @@ import SVProgressHUD
|
|||
|
||||
class SSHKeySettingTableViewController: UITableViewController {
|
||||
|
||||
@IBOutlet weak var passphraseTextField: UITextField!
|
||||
@IBOutlet weak var privateKeyURLTextField: UITextField!
|
||||
@IBOutlet weak var publicKeyURLTextField: UITextField!
|
||||
let passwordStore = PasswordStore.shared
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
passphraseTextField.text = Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? ""
|
||||
privateKeyURLTextField.text = Defaults[.gitRepositorySSHPrivateKeyURL]?.absoluteString
|
||||
publicKeyURLTextField.text = Defaults[.gitRepositorySSHPublicKeyURL]?.absoluteString
|
||||
privateKeyURLTextField.text = Defaults[.gitSSHPrivateKeyURL]?.absoluteString
|
||||
publicKeyURLTextField.text = Defaults[.gitSSHPublicKeyURL]?.absoluteString
|
||||
var doneBarButtonItem: UIBarButtonItem?
|
||||
|
||||
doneBarButtonItem = UIBarButtonItem(title: "Done",
|
||||
|
|
@ -41,18 +40,42 @@ class SSHKeySettingTableViewController: UITableViewController {
|
|||
return
|
||||
}
|
||||
|
||||
Defaults[.gitRepositorySSHPublicKeyURL] = publicKeyURL
|
||||
Defaults[.gitRepositorySSHPrivateKeyURL] = privateKeyURL
|
||||
Utils.addPasswordToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: passphraseTextField.text!)
|
||||
Defaults[.gitSSHPublicKeyURL] = publicKeyURL
|
||||
Defaults[.gitSSHPrivateKeyURL] = privateKeyURL
|
||||
|
||||
do {
|
||||
try Data(contentsOf: publicKeyURL).write(to: Globals.sshPublicKeyURL, options: .atomic)
|
||||
try Data(contentsOf: privateKeyURL).write(to: Globals.sshPrivateKeyURL, options: .atomic)
|
||||
try Data(contentsOf: publicKeyURL).write(to: URL(fileURLWithPath: Globals.gitSSHPublicKeyPath), options: .atomic)
|
||||
try Data(contentsOf: privateKeyURL).write(to: URL(fileURLWithPath: Globals.gitSSHPrivateKeyPath), options: .atomic)
|
||||
} catch {
|
||||
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
|
||||
}
|
||||
|
||||
navigationController!.popViewController(animated: true)
|
||||
Defaults[.gitSSHKeySource] = "url"
|
||||
let alert = UIAlertController(
|
||||
title: "PGP Passphrase",
|
||||
message: "Please fill in the passphrase for your Git Repository SSH key.",
|
||||
preferredStyle: UIAlertControllerStyle.alert
|
||||
)
|
||||
|
||||
alert.addAction(
|
||||
UIAlertAction(
|
||||
title: "OK",
|
||||
style: UIAlertActionStyle.default,
|
||||
handler: {_ in
|
||||
Utils.addPasswordToKeychain(
|
||||
name: "gitSSHPrivateKeyPassphrase",
|
||||
password: alert.textFields!.first!.text!
|
||||
)
|
||||
self.navigationController!.popViewController(animated: true)
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
alert.addTextField(
|
||||
configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = self.passwordStore.gitSSHPrivateKeyPassphrase
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
self.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,16 +95,16 @@ class SettingsTableViewController: UITableViewController {
|
|||
|
||||
@IBAction func saveGitServerSetting(segue: UIStoryboardSegue) {
|
||||
if let controller = segue.source as? GitServerSettingTableViewController {
|
||||
let gitRepostiroyURL = controller.gitRepositoryURLTextField.text!
|
||||
let gitRepostiroyURL = controller.gitURLTextField.text!
|
||||
let username = controller.usernameTextField.text!
|
||||
let password = controller.password
|
||||
let auth = controller.authenticationMethod
|
||||
|
||||
if Defaults[.gitRepositoryURL] == nil ||
|
||||
Defaults[.gitRepositoryURL]!.absoluteString != gitRepostiroyURL ||
|
||||
auth != Defaults[.gitRepositoryAuthenticationMethod] ||
|
||||
username != Defaults[.gitRepositoryUsername] ||
|
||||
password != self.passwordStore.gitRepositoryPassword ||
|
||||
if Defaults[.gitURL] == nil ||
|
||||
Defaults[.gitURL]!.absoluteString != gitRepostiroyURL ||
|
||||
auth != Defaults[.gitAuthenticationMethod] ||
|
||||
username != Defaults[.gitUsername] ||
|
||||
password != self.passwordStore.gitPassword ||
|
||||
self.passwordStore.repositoryExisted() == false {
|
||||
|
||||
SVProgressHUD.setDefaultMaskType(.black)
|
||||
|
|
@ -117,9 +117,9 @@ class SettingsTableViewController: UITableViewController {
|
|||
gitCredential = GitCredential(
|
||||
credential: GitCredential.Credential.ssh(
|
||||
userName: username,
|
||||
password: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? "",
|
||||
publicKeyFile: Globals.sshPublicKeyURL,
|
||||
privateKeyFile: Globals.sshPrivateKeyURL,
|
||||
password: Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") ?? "",
|
||||
publicKeyFile: Globals.gitSSHPublicKeyURL,
|
||||
privateKeyFile: Globals.gitSSHPrivateKeyURL,
|
||||
passwordNotSetCallback: self.requestSshKeyPassword
|
||||
)
|
||||
)
|
||||
|
|
@ -140,12 +140,11 @@ class SettingsTableViewController: UITableViewController {
|
|||
}
|
||||
})
|
||||
DispatchQueue.main.async {
|
||||
Defaults[.lastUpdatedTime] = Date()
|
||||
Defaults[.gitRepositoryURL] = URL(string: gitRepostiroyURL)
|
||||
Defaults[.gitRepositoryUsername] = username
|
||||
Defaults[.gitRepositoryAuthenticationMethod] = auth
|
||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitRepositoryURL]?.host
|
||||
Defaults[.gitURL] = URL(string: gitRepostiroyURL)
|
||||
Defaults[.gitUsername] = username
|
||||
Defaults[.gitAuthenticationMethod] = auth
|
||||
Defaults[.gitPasswordAttempts] = 0
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitURL]?.host
|
||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||
SVProgressHUD.dismiss(withDelay: 1)
|
||||
}
|
||||
|
|
@ -163,7 +162,7 @@ class SettingsTableViewController: UITableViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(SettingsTableViewController.actOnPasswordStoreErasedNotification), name: .passwordStoreErased, object: nil)
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitRepositoryURL]?.host
|
||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitURL]?.host
|
||||
touchIDTableViewCell.accessoryView = touchIDSwitch
|
||||
setPGPKeyTableViewCellDetailText()
|
||||
setPasswordRepositoryTableViewCellDetailText()
|
||||
|
|
@ -190,10 +189,10 @@ class SettingsTableViewController: UITableViewController {
|
|||
}
|
||||
|
||||
private func setPasswordRepositoryTableViewCellDetailText() {
|
||||
if Defaults[.gitRepositoryURL] == nil {
|
||||
if Defaults[.gitURL] == nil {
|
||||
passwordRepositoryTableViewCell.detailTextLabel?.text = "Not Set"
|
||||
} else {
|
||||
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitRepositoryURL]!.host
|
||||
passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitURL]!.host
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,7 +218,7 @@ class SettingsTableViewController: UITableViewController {
|
|||
}))
|
||||
|
||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = self.passwordStore.gitRepositoryPassword
|
||||
textField.text = self.passwordStore.gitPassword
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -17,14 +17,19 @@ extension DefaultsKeys {
|
|||
static let pgpPublicKeyArmor = DefaultsKey<String?>("pgpPublicKeyArmor")
|
||||
static let pgpPrivateKeyArmor = DefaultsKey<String?>("pgpPrivateKeyArmor")
|
||||
|
||||
static let gitRepositoryURL = DefaultsKey<URL?>("gitRepositoryURL")
|
||||
static let gitRepositoryAuthenticationMethod = DefaultsKey<String?>("gitRepositoryAuthenticationMethod")
|
||||
static let gitRepositoryUsername = DefaultsKey<String?>("gitRepositoryUsername")
|
||||
static let gitRepositoryPasswordAttempts = DefaultsKey<Int>("gitRepositoryPasswordAttempts")
|
||||
static let gitRepositorySSHPublicKeyURL = DefaultsKey<URL?>("gitRepositorySSHPublicKeyURL")
|
||||
static let gitRepositorySSHPrivateKeyURL = DefaultsKey<URL?>("gitRepositorySSHPrivateKeyURL")
|
||||
static let gitURL = DefaultsKey<URL?>("gitURL")
|
||||
static let gitAuthenticationMethod = DefaultsKey<String?>("gitAuthenticationMethod")
|
||||
static let gitUsername = DefaultsKey<String?>("gitUsername")
|
||||
static let gitPasswordAttempts = DefaultsKey<Int>("gitPasswordAttempts")
|
||||
static let gitSSHPublicKeyURL = DefaultsKey<URL?>("gitSSHPublicKeyURL")
|
||||
static let gitSSHPrivateKeyURL = DefaultsKey<URL?>("gitSSHPrivateKeyURL")
|
||||
static let gitSSHKeySource = DefaultsKey<String?>("gitSSHKeySource")
|
||||
|
||||
static let gitSSHPublicKeyArmor = DefaultsKey<String?>("gitSSHPublicKeyArmor")
|
||||
static let gitSSHPrivateKeyArmor = DefaultsKey<String?>("gitSSHPrivateKeyArmor")
|
||||
|
||||
static let lastUpdatedTime = DefaultsKey<Date?>("lasteUpdatedTime")
|
||||
|
||||
static let lastSyncedTime = DefaultsKey<Date?>("lastSyncedTime")
|
||||
|
||||
static let isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")
|
||||
static let passcodeKey = DefaultsKey<String?>("passcodeKey")
|
||||
|
|
|
|||
|
|
@ -15,22 +15,25 @@ class Globals {
|
|||
static let pgpPublicKeyPath = "\(documentPath)/gpg_key.pub"
|
||||
static let pgpPrivateKeyPath = "\(documentPath)/gpg_key"
|
||||
|
||||
static let sshPublicKeyURL = URL(fileURLWithPath: "\(documentPath)/ssh_key.pub")
|
||||
static let sshPrivateKeyURL = URL(fileURLWithPath: "\(documentPath)/ssh_key")
|
||||
static let gitSSHPublicKeyPath = "\(documentPath)/ssh_key.pub"
|
||||
static let gitSSHPrivateKeyPath = "\(documentPath)/ssh_key"
|
||||
static let gitSSHPublicKeyURL = URL(fileURLWithPath: gitSSHPublicKeyPath)
|
||||
static let gitSSHPrivateKeyURL = URL(fileURLWithPath: gitSSHPrivateKeyPath)
|
||||
|
||||
static let repositoryPath = "\(libraryPath)/password-store"
|
||||
static var passcodeConfiguration = PasscodeLockConfiguration()
|
||||
|
||||
static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0)
|
||||
static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0)
|
||||
|
||||
static let passwordMinimumLength = 6
|
||||
static let passwordMaximumLength = 24
|
||||
static let passwordDefaultLength = 16
|
||||
static let passwordDefaultLength = ["Random": (min: 6, max: 24, def: 16),
|
||||
"Apple": (min: 15, max: 15, def: 15)]
|
||||
|
||||
static let passwordDots = "••••••••••••"
|
||||
static let passwordFonts = "Menlo"
|
||||
|
||||
// UI related
|
||||
static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0)
|
||||
static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0)
|
||||
static let tableCellButtonSize = CGFloat(20.0)
|
||||
|
||||
private init() { }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,15 +27,14 @@ class Utils {
|
|||
removeFileIfExists(atPath: url.path)
|
||||
}
|
||||
|
||||
static func getLastUpdatedTimeString() -> String {
|
||||
var lastUpdatedTimeString = ""
|
||||
if let lastUpdatedTime = Defaults[.lastUpdatedTime] {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .short
|
||||
lastUpdatedTimeString = formatter.string(from: lastUpdatedTime)
|
||||
static func getLastSyncedTimeString() -> String {
|
||||
guard let lastSyncedTime = Defaults[.lastSyncedTime] else {
|
||||
return "Oops! Sync again?"
|
||||
}
|
||||
return lastUpdatedTimeString
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .short
|
||||
return formatter.string(from: lastSyncedTime)
|
||||
}
|
||||
|
||||
static func generatePassword(length: Int) -> String{
|
||||
|
|
@ -84,6 +83,16 @@ class Utils {
|
|||
Utils.removeKeychain(name: ".pgpKeyPassphrase")
|
||||
}
|
||||
|
||||
static func removeGitSSHKeys() {
|
||||
removeFileIfExists(atPath: Globals.gitSSHPublicKeyPath)
|
||||
removeFileIfExists(atPath: Globals.gitSSHPrivateKeyPath)
|
||||
Defaults.remove(.gitSSHPublicKeyArmor)
|
||||
Defaults.remove(.gitSSHPrivateKeyArmor)
|
||||
Defaults.remove(.gitSSHPublicKeyURL)
|
||||
Defaults.remove(.gitSSHPrivateKeyURL)
|
||||
Utils.removeKeychain(name: ".gitSSHPrivateKeyPassphrase")
|
||||
}
|
||||
|
||||
static func getPasswordFromKeychain(name: String) -> String? {
|
||||
let keychain = Keychain(service: "me.mssun.passforios")
|
||||
do {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.2.2</string>
|
||||
<string>0.2.3</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ class Password {
|
|||
var additions = [String: String]()
|
||||
var additionKeys = [String]()
|
||||
var changed = false
|
||||
var plainText = ""
|
||||
|
||||
private var plainText = ""
|
||||
private var firstLineIsOTPField = false
|
||||
private var otpToken: Token?
|
||||
|
||||
|
|
@ -99,14 +99,17 @@ class Password {
|
|||
// return a key-value pair from the line
|
||||
// key might be nil, if there is no ":" in the line
|
||||
static private func getKeyValuePair(from line: String) -> (key: String?, value: String) {
|
||||
let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: true).map(String.init)
|
||||
var key : String?
|
||||
let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false).map{String($0).trimmingCharacters(in: .whitespaces)}
|
||||
var key : String? = nil
|
||||
var value = ""
|
||||
if items.count == 1 {
|
||||
value = items[0]
|
||||
} else if items.count == 2 {
|
||||
key = items[0]
|
||||
value = items[1].trimmingCharacters(in: .whitespaces)
|
||||
if items.count == 1 || (items[0].isEmpty && items[1].isEmpty) {
|
||||
// no ":" found, or empty on both sides of ":" (e.g., " : ")
|
||||
value = line
|
||||
} else {
|
||||
if !items[0].isEmpty {
|
||||
key = items[0]
|
||||
}
|
||||
value = items[1]
|
||||
}
|
||||
return (key, value)
|
||||
}
|
||||
|
|
@ -178,6 +181,8 @@ class Password {
|
|||
|
||||
*/
|
||||
private func updateOtpToken() {
|
||||
self.otpToken = nil
|
||||
|
||||
// get otpauth, if we are able to generate a token, return
|
||||
if var otpauthString = getAdditionValue(withKey: "otpauth") {
|
||||
if !otpauthString.hasPrefix("otpauth:") {
|
||||
|
|
|
|||
|
|
@ -27,9 +27,9 @@ struct GitCredential {
|
|||
var credential: GTCredential? = nil
|
||||
switch self.credential {
|
||||
case let .http(userName, password):
|
||||
print(Defaults[.gitRepositoryPasswordAttempts])
|
||||
print(Defaults[.gitPasswordAttempts])
|
||||
var newPassword: String = password
|
||||
if Defaults[.gitRepositoryPasswordAttempts] != 0 {
|
||||
if Defaults[.gitPasswordAttempts] != 0 {
|
||||
let sem = DispatchSemaphore(value: 0)
|
||||
DispatchQueue.main.async {
|
||||
SVProgressHUD.dismiss()
|
||||
|
|
@ -40,15 +40,15 @@ struct GitCredential {
|
|||
let alert = UIAlertController(title: "Password", message: "Please fill in the password of your Git account.", preferredStyle: UIAlertControllerStyle.alert)
|
||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||
newPassword = alert.textFields!.first!.text!
|
||||
PasswordStore.shared.gitRepositoryPassword = newPassword
|
||||
PasswordStore.shared.gitPassword = newPassword
|
||||
sem.signal()
|
||||
}))
|
||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
|
||||
Defaults[.gitRepositoryPasswordAttempts] = -1
|
||||
Defaults[.gitPasswordAttempts] = -1
|
||||
sem.signal()
|
||||
})
|
||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||
textField.text = PasswordStore.shared.gitRepositoryPassword
|
||||
textField.text = PasswordStore.shared.gitPassword
|
||||
textField.isSecureTextEntry = true
|
||||
})
|
||||
topController.present(alert, animated: true, completion: nil)
|
||||
|
|
@ -56,12 +56,12 @@ struct GitCredential {
|
|||
}
|
||||
let _ = sem.wait(timeout: DispatchTime.distantFuture)
|
||||
}
|
||||
if Defaults[.gitRepositoryPasswordAttempts] == -1 {
|
||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
||||
if Defaults[.gitPasswordAttempts] == -1 {
|
||||
Defaults[.gitPasswordAttempts] = 0
|
||||
return nil
|
||||
}
|
||||
Defaults[.gitRepositoryPasswordAttempts] += 1
|
||||
PasswordStore.shared.gitRepositoryPassword = newPassword
|
||||
Defaults[.gitPasswordAttempts] += 1
|
||||
PasswordStore.shared.gitPassword = newPassword
|
||||
credential = try? GTCredential(userName: userName, password: newPassword)
|
||||
case let .ssh(userName, password, publicKeyFile, privateKeyFile, passwordNotSetCallback):
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ struct GitCredential {
|
|||
}
|
||||
|
||||
// Save password for the future
|
||||
Utils.addPasswordToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: newPassword!)
|
||||
Utils.addPasswordToKeychain(name: "gitSSHPrivateKeyPassphrase", password: newPassword!)
|
||||
|
||||
// nil is expected in case of empty password
|
||||
if newPassword == "" {
|
||||
|
|
@ -112,7 +112,7 @@ class PasswordStore {
|
|||
|
||||
var gitSignatureForNow: GTSignature {
|
||||
get {
|
||||
return GTSignature(name: Defaults[.gitRepositoryUsername]!, email: Defaults[.gitRepositoryUsername]!+"@passforios", time: Date())!
|
||||
return GTSignature(name: Defaults[.gitUsername]!, email: Defaults[.gitUsername]!+"@passforios", time: Date())!
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,12 +126,21 @@ class PasswordStore {
|
|||
return Utils.getPasswordFromKeychain(name: "pgpKeyPassphrase")
|
||||
}
|
||||
}
|
||||
var gitRepositoryPassword: String? {
|
||||
var gitPassword: String? {
|
||||
set {
|
||||
Utils.addPasswordToKeychain(name: "gitRepositoryPassword", password: newValue)
|
||||
Utils.addPasswordToKeychain(name: "gitPassword", password: newValue)
|
||||
}
|
||||
get {
|
||||
return Utils.getPasswordFromKeychain(name: "gitRepositoryPassword")
|
||||
return Utils.getPasswordFromKeychain(name: "gitPassword")
|
||||
}
|
||||
}
|
||||
|
||||
var gitSSHPrivateKeyPassphrase: String? {
|
||||
set {
|
||||
Utils.addPasswordToKeychain(name: "gitSSHPrivateKeyPassphrase", password: newValue)
|
||||
}
|
||||
get {
|
||||
return Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,22 +173,41 @@ class PasswordStore {
|
|||
print(error)
|
||||
}
|
||||
initPGPKeys()
|
||||
if Defaults[.gitRepositoryAuthenticationMethod] == "Password" {
|
||||
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitRepositoryUsername]!, password: Utils.getPasswordFromKeychain(name: "gitRepositoryPassword") ?? ""))
|
||||
} else if Defaults[.gitRepositoryAuthenticationMethod] == "SSH Key"{
|
||||
initGitCredential()
|
||||
}
|
||||
|
||||
enum SSHKeyType {
|
||||
case `public`, secret
|
||||
}
|
||||
|
||||
public func initGitCredential() {
|
||||
if Defaults[.gitAuthenticationMethod] == "Password" {
|
||||
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitUsername]!, password: Utils.getPasswordFromKeychain(name: "gitPassword") ?? ""))
|
||||
} else if Defaults[.gitAuthenticationMethod] == "SSH Key"{
|
||||
gitCredential = GitCredential(
|
||||
credential: GitCredential.Credential.ssh(
|
||||
userName: Defaults[.gitRepositoryUsername]!,
|
||||
password: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? "",
|
||||
publicKeyFile: Globals.sshPublicKeyURL,
|
||||
privateKeyFile: Globals.sshPrivateKeyURL,
|
||||
userName: Defaults[.gitUsername]!,
|
||||
password: gitSSHPrivateKeyPassphrase ?? "",
|
||||
publicKeyFile: Globals.gitSSHPublicKeyURL,
|
||||
privateKeyFile: Globals.gitSSHPrivateKeyURL,
|
||||
passwordNotSetCallback: nil
|
||||
)
|
||||
)
|
||||
} else {
|
||||
gitCredential = nil
|
||||
}
|
||||
}
|
||||
|
||||
public func initGitSSHKey(with armorKey: String, _ keyType: SSHKeyType) throws {
|
||||
var keyPath = ""
|
||||
switch keyType {
|
||||
case .public:
|
||||
keyPath = Globals.gitSSHPublicKeyPath
|
||||
case .secret:
|
||||
keyPath = Globals.gitSSHPrivateKeyPath
|
||||
}
|
||||
|
||||
try armorKey.write(toFile: keyPath, atomically: true, encoding: .ascii)
|
||||
}
|
||||
|
||||
public func initPGPKeys() {
|
||||
|
|
@ -302,9 +330,11 @@ class PasswordStore {
|
|||
}
|
||||
storeRepository = try GTRepository(url: storeURL)
|
||||
gitCredential = credential
|
||||
self.updatePasswordEntityCoreData()
|
||||
|
||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||
Defaults[.lastSyncedTime] = Date()
|
||||
DispatchQueue.main.async {
|
||||
self.updatePasswordEntityCoreData()
|
||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func pullRepository(transferProgressBlock: @escaping (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
|
||||
|
|
@ -317,9 +347,12 @@ class PasswordStore {
|
|||
]
|
||||
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
||||
self.setAllSynced()
|
||||
self.updatePasswordEntityCoreData()
|
||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||
Defaults[.lastSyncedTime] = Date()
|
||||
DispatchQueue.main.async {
|
||||
self.setAllSynced()
|
||||
self.updatePasswordEntityCoreData()
|
||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private func updatePasswordEntityCoreData() {
|
||||
|
|
@ -649,8 +682,8 @@ class PasswordStore {
|
|||
|
||||
Utils.removeFileIfExists(atPath: Globals.pgpPublicKeyPath)
|
||||
Utils.removeFileIfExists(atPath: Globals.pgpPrivateKeyPath)
|
||||
Utils.removeFileIfExists(at: Globals.sshPrivateKeyURL)
|
||||
Utils.removeFileIfExists(at: Globals.sshPublicKeyURL)
|
||||
Utils.removeFileIfExists(atPath: Globals.gitSSHPublicKeyPath)
|
||||
Utils.removeFileIfExists(atPath: Globals.gitSSHPrivateKeyPath)
|
||||
|
||||
Utils.removeAllKeychain()
|
||||
|
||||
|
|
@ -678,6 +711,8 @@ class PasswordStore {
|
|||
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
||||
self.setAllSynced()
|
||||
self.updatePasswordEntityCoreData()
|
||||
Defaults[.lastSyncedTime] = nil
|
||||
|
||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||
NotificationCenter.default.post(name: .passwordStoreChangeDiscarded, object: nil)
|
||||
return localCommits.count
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import UIKit
|
|||
|
||||
protocol FillPasswordTableViewCellDelegate {
|
||||
func generateAndCopyPassword()
|
||||
func showHidePasswordSettings()
|
||||
}
|
||||
|
||||
class FillPasswordTableViewCell: ContentTableViewCell {
|
||||
|
|
@ -17,10 +18,17 @@ class FillPasswordTableViewCell: ContentTableViewCell {
|
|||
@IBOutlet weak var contentTextField: UITextField!
|
||||
var delegate: FillPasswordTableViewCellDelegate?
|
||||
|
||||
@IBOutlet weak var settingButton: UIButton!
|
||||
@IBOutlet weak var generateButton: UIButton!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
contentTextField.font = UIFont(name: Globals.passwordFonts, size: (contentTextField.font?.pointSize)!)
|
||||
|
||||
// Force aspect ratio of button images
|
||||
settingButton.imageView?.contentMode = .scaleAspectFit
|
||||
generateButton.imageView?.contentMode = .scaleAspectFit
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
|
|
@ -33,6 +41,10 @@ class FillPasswordTableViewCell: ContentTableViewCell {
|
|||
self.delegate?.generateAndCopyPassword()
|
||||
}
|
||||
|
||||
@IBAction func showHidePasswordSettings() {
|
||||
self.delegate?.showHidePasswordSettings()
|
||||
}
|
||||
|
||||
// re-color
|
||||
@IBAction func textFieldDidChange(_ sender: UITextField) {
|
||||
contentTextField.attributedText = Utils.attributedPassword(plainPassword: sender.text ?? "")
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -16,13 +16,13 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="89"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="89.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="password" textAlignment="natural" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="k0U-2N-YaX">
|
||||
<rect key="frame" x="15" y="8" width="220" height="74"/>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" horizontalHuggingPriority="249" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="password" textAlignment="natural" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="k0U-2N-YaX" userLabel="Password">
|
||||
<rect key="frame" x="16" y="8" width="231" height="74"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="qVX-ui-dIn"/>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="9gX-VT-F9P"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
|
|
@ -31,31 +31,52 @@
|
|||
<action selector="textFieldDidChange:" destination="KGk-i7-Jjw" eventType="editingChanged" id="U0t-2B-JxY"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" reversesTitleShadowWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hTh-ek-Xam">
|
||||
<rect key="frame" x="243" y="-0.5" width="64" height="89.5"/>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SZJ-aY-45Y" userLabel="Setting">
|
||||
<rect key="frame" x="275" y="8" width="30" height="73.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="64" id="X1A-kc-qJy"/>
|
||||
<constraint firstAttribute="width" constant="30" id="D9D-FC-ANz"/>
|
||||
</constraints>
|
||||
<state key="normal" title="Generate"/>
|
||||
<inset key="contentEdgeInsets" minX="5" minY="10" maxX="5" maxY="10"/>
|
||||
<state key="normal" image="HorizontalSettings"/>
|
||||
<connections>
|
||||
<action selector="showHidePasswordSettings" destination="KGk-i7-Jjw" eventType="touchUpInside" id="3I8-S0-qlo"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleAspectFit" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hTh-ek-Xam" userLabel="Generate">
|
||||
<rect key="frame" x="245" y="8" width="30" height="73.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="l0l-7B-Tws"/>
|
||||
</constraints>
|
||||
<inset key="contentEdgeInsets" minX="5" minY="10" maxX="5" maxY="10"/>
|
||||
<state key="normal" image="Refresh"/>
|
||||
<connections>
|
||||
<action selector="generatePassword:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="M61-hs-PCP"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="k0U-2N-YaX" secondAttribute="trailing" constant="77" id="3S1-gj-XVP" userLabel="trailingMargin = Content Text Field.trailing + 71"/>
|
||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="centerY" secondItem="k0U-2N-YaX" secondAttribute="centerY" id="Fls-do-khd"/>
|
||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="height" secondItem="H2p-sc-9uM" secondAttribute="height" id="Gok-dX-tQ5"/>
|
||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="leading" secondItem="k0U-2N-YaX" secondAttribute="trailing" constant="8" id="hsy-gb-ero" userLabel="Generate.leading = Content Text Field.trailing"/>
|
||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="jKd-Xa-tr5"/>
|
||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="lAm-D6-pir"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="k0U-2N-YaX" secondAttribute="bottom" constant="-1" id="pLC-H7-JTU" userLabel="bottomMargin = Content Text Field.bottom"/>
|
||||
<constraint firstItem="SZJ-aY-45Y" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="5XP-xZ-YWY"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="SZJ-aY-45Y" secondAttribute="trailing" constant="7" id="5bp-bm-9vv"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="SZJ-aY-45Y" secondAttribute="bottom" id="CMF-1f-MdG"/>
|
||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="OjQ-mD-CWV"/>
|
||||
<constraint firstItem="SZJ-aY-45Y" firstAttribute="leading" secondItem="hTh-ek-Xam" secondAttribute="trailing" id="UlR-NB-9So"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="hTh-ek-Xam" secondAttribute="bottom" id="bvu-Q0-QAG"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="k0U-2N-YaX" secondAttribute="trailing" constant="65" id="fz0-HW-sCe"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="k0U-2N-YaX" secondAttribute="bottom" id="lRv-MC-Cru"/>
|
||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="sUk-sk-JLT"/>
|
||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="8" id="zGn-an-SlK"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="contentTextField" destination="k0U-2N-YaX" id="kQO-tR-Epp"/>
|
||||
<outlet property="generateButton" destination="hTh-ek-Xam" id="MUa-qs-uw4"/>
|
||||
<outlet property="settingButton" destination="SZJ-aY-45Y" id="G4T-04-NBD"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="34" y="77"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="HorizontalSettings" width="25" height="25"/>
|
||||
<image name="Refresh" width="32" height="32"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ class LabelTableViewCell: UITableViewCell {
|
|||
|
||||
weak var delegatePasswordTableView : PasswordDetailTableViewController?
|
||||
|
||||
var passwordDisplayButton: UIButton?
|
||||
var buttons: UIView?
|
||||
|
||||
var cellData: LabelTableViewCellData? {
|
||||
didSet {
|
||||
titleLabel.text = cellData?.title ?? ""
|
||||
|
|
@ -43,9 +46,11 @@ class LabelTableViewCell: UITableViewCell {
|
|||
} else {
|
||||
contentLabel.text = Globals.passwordDots
|
||||
}
|
||||
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
|
||||
} else {
|
||||
contentLabel.text = cellData?.content
|
||||
}
|
||||
updateButtons()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -58,6 +63,13 @@ class LabelTableViewCell: UITableViewCell {
|
|||
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)
|
||||
|
|
@ -99,13 +111,26 @@ class LabelTableViewCell: UITableViewCell {
|
|||
contentLabel.text = ""
|
||||
}
|
||||
isReveal = true
|
||||
passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Invisible"), for: .normal)
|
||||
}
|
||||
|
||||
func concealPassword(_ sender: Any?) {
|
||||
contentLabel.text = Globals.passwordDots
|
||||
isReveal = false
|
||||
passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Visible"), for: .normal)
|
||||
}
|
||||
|
||||
func reversePasswordDisplay(_ sender: Any?) {
|
||||
if isReveal {
|
||||
// conceal
|
||||
concealPassword(sender)
|
||||
} else {
|
||||
// reveal
|
||||
revealPassword(sender)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func openLink(_ sender: Any?) {
|
||||
// if isURLCell, passwordTableView should not be nil
|
||||
delegatePasswordTableView!.openLink()
|
||||
|
|
@ -115,4 +140,50 @@ class LabelTableViewCell: UITableViewCell {
|
|||
// if isHOTPCell, passwordTableView should not be nil
|
||||
delegatePasswordTableView!.getNextHOTP()
|
||||
}
|
||||
|
||||
func updateButtons() {
|
||||
passwordDisplayButton = nil
|
||||
buttons = nil
|
||||
|
||||
// total width and height of a button
|
||||
let height = min(self.bounds.height, 36.0)
|
||||
let width = max(height * 0.8, Globals.tableCellButtonSize)
|
||||
|
||||
// margins (between button boundary and icon)
|
||||
let marginY = max((height - Globals.tableCellButtonSize) / 2, 0.0)
|
||||
let marginX = max((width - Globals.tableCellButtonSize) / 2, 0.0)
|
||||
|
||||
if isPasswordCell {
|
||||
// password button
|
||||
passwordDisplayButton = UIButton(type: .system)
|
||||
passwordDisplayButton!.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal)
|
||||
passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit
|
||||
passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
|
||||
passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside)
|
||||
buttons = passwordDisplayButton
|
||||
} else if isHOTPCell {
|
||||
// hotp button
|
||||
let nextButton = UIButton(type: .system)
|
||||
nextButton.frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
nextButton.setImage(#imageLiteral(resourceName: "Refresh"), for: .normal)
|
||||
nextButton.imageView?.contentMode = .scaleAspectFit
|
||||
nextButton.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
|
||||
nextButton.addTarget(self, action: #selector(getNextHOTP), for: UIControlEvents.touchUpInside)
|
||||
|
||||
// password button
|
||||
passwordDisplayButton = UIButton(type: .system)
|
||||
passwordDisplayButton!.frame = CGRect(x: width, y: 0, width: width, height: height)
|
||||
|
||||
passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal)
|
||||
passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit
|
||||
passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX)
|
||||
passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside)
|
||||
|
||||
buttons = UIView()
|
||||
buttons!.frame = CGRect(x: 0, y: 0, width: width * 2, height: height)
|
||||
buttons!.addSubview(nextButton)
|
||||
buttons!.addSubview(passwordDisplayButton!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -16,17 +16,20 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="333" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="333" height="51"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="333" height="51.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yyr-cF-QN0">
|
||||
<rect key="frame" x="15" y="26" width="310" height="17.5"/>
|
||||
<rect key="frame" x="16" y="22.5" width="309" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="pgw-DF-LQa"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Dqz-7n-uEZ">
|
||||
<rect key="frame" x="15" y="8" width="310" height="15"/>
|
||||
<rect key="frame" x="16" y="8" width="309" height="11.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<color key="textColor" red="0.0" green="0.47843137254901957" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
|
@ -34,7 +37,7 @@
|
|||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="Dqz-7n-uEZ" secondAttribute="trailing" id="228-VM-Z8Y"/>
|
||||
<constraint firstItem="Dqz-7n-uEZ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="CVm-uc-iVo"/>
|
||||
<constraint firstItem="Dqz-7n-uEZ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="8" id="CVm-uc-iVo"/>
|
||||
<constraint firstAttribute="topMargin" secondItem="Dqz-7n-uEZ" secondAttribute="top" id="N4y-iT-CiY"/>
|
||||
<constraint firstItem="yyr-cF-QN0" firstAttribute="leading" secondItem="Dqz-7n-uEZ" secondAttribute="leading" id="TpW-bu-QIx"/>
|
||||
<constraint firstItem="yyr-cF-QN0" firstAttribute="width" secondItem="Dqz-7n-uEZ" secondAttribute="width" id="ZXa-fK-0Bg"/>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="84"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="83"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="83.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" placeholderIntrinsicWidth="52" placeholderIntrinsicHeight="52" translatesAutoresizingMaskIntoConstraints="NO" id="gKV-Cd-wIk">
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
//
|
||||
// PasswordTableViewCell.swift
|
||||
// pass
|
||||
//
|
||||
// Created by Mingshen Sun on 8/3/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class PasswordWithFolderTableViewCell: UITableViewCell {
|
||||
|
||||
@IBOutlet weak var passwordLabel: UILabel!
|
||||
@IBOutlet weak var folderLabel: UILabel!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
// Initialization code
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16E183b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="passwordWithFolderTableViewCell" rowHeight="43" id="KGk-i7-Jjw" customClass="PasswordWithFolderTableViewCell" customModule="pass" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="42.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Password Entry" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="y5A-3S-tcq">
|
||||
<rect key="frame" x="15" y="8" width="297" height="26.5"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Family > Parents" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GEv-Cf-Cnx">
|
||||
<rect key="frame" x="8" y="12.5" width="297" height="18"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||
<color key="textColor" red="0.5568627451" green="0.5568627451" blue="0.57647058819999997" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="y5A-3S-tcq" firstAttribute="centerY" secondItem="GEv-Cf-Cnx" secondAttribute="centerY" id="Ev0-0v-v1c"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="GEv-Cf-Cnx" secondAttribute="trailing" constant="7" id="Hyk-Q8-5uU"/>
|
||||
<constraint firstItem="y5A-3S-tcq" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="VDn-B1-Tyg"/>
|
||||
<constraint firstItem="y5A-3S-tcq" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="e9F-C0-yGP"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="y5A-3S-tcq" secondAttribute="bottom" id="f52-hU-sEC"/>
|
||||
<constraint firstAttribute="leadingMargin" secondItem="GEv-Cf-Cnx" secondAttribute="leading" id="rjm-bp-jT3"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="y5A-3S-tcq" secondAttribute="trailing" id="vsW-4d-EEl"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="folderLabel" destination="GEv-Cf-Cnx" id="HHd-LU-wYW"/>
|
||||
<outlet property="passwordLabel" destination="y5A-3S-tcq" id="1OK-Io-6mP"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="34" y="53.5"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
@ -58,6 +58,13 @@ class SliderTableViewCell: ContentTableViewCell {
|
|||
slider.maximumValue = Float(maximumValue)
|
||||
slider.value = Float(defaultValue)
|
||||
valueLabel.text = String(defaultValue)
|
||||
|
||||
// "not editable"
|
||||
if minimumValue == maximumValue {
|
||||
titleLabel.textColor = UIColor.gray
|
||||
valueLabel.textColor = UIColor.gray
|
||||
slider.isUserInteractionEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="MwT-Jl-hhE">
|
||||
<rect key="frame" x="60.5" y="22" width="205.5" height="31"/>
|
||||
<rect key="frame" x="61.5" y="22" width="204.5" height="31"/>
|
||||
<connections>
|
||||
<action selector="handleSliderValueChange:" destination="KGk-i7-Jjw" eventType="valueChanged" id="WwM-ZE-yIB"/>
|
||||
</connections>
|
||||
|
|
@ -34,8 +34,8 @@
|
|||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t7T-HC-hUd" userLabel="Title">
|
||||
<rect key="frame" x="15" y="8" width="30" height="57.5"/>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t7T-HC-hUd" userLabel="Title">
|
||||
<rect key="frame" x="16" y="8" width="30" height="57.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="8Tz-Qo-Mkg"/>
|
||||
</constraints>
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="MwT-Jl-hhE" firstAttribute="leading" secondItem="t7T-HC-hUd" secondAttribute="trailing" constant="17" id="Cc9-kV-nZf"/>
|
||||
<constraint firstItem="t7T-HC-hUd" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="Kje-Zj-RaX"/>
|
||||
<constraint firstItem="t7T-HC-hUd" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="8" id="Kje-Zj-RaX"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="GJP-Fj-VZt" secondAttribute="trailing" constant="7" id="LjD-JH-dRT"/>
|
||||
<constraint firstItem="MwT-Jl-hhE" firstAttribute="centerY" secondItem="t7T-HC-hUd" secondAttribute="centerY" id="MHN-Vl-1le"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="GJP-Fj-VZt" secondAttribute="bottom" id="NmC-sS-9Yt"/>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -16,11 +16,11 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="55"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="55.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
|
||||
<rect key="frame" x="15" y="8" width="297" height="39.5"/>
|
||||
<rect key="frame" x="16" y="8" width="296" height="39.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="R1z-fU-Xr2"/>
|
||||
</constraints>
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
</textField>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="3h4-9E-oDJ"/>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="8" id="3h4-9E-oDJ"/>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="FH4-4T-aaK"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="8Ky-UZ-sLu" secondAttribute="trailing" id="Nii-Cg-gC1"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" id="h72-l3-Sb3"/>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16E189a" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xHX-Sh-1pR">
|
||||
<rect key="frame" x="15" y="15" width="297" height="186.5"/>
|
||||
<rect key="frame" x="12" y="16" width="300" height="184.5"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="120" id="Tvq-j8-Nvh"/>
|
||||
|
|
@ -31,9 +31,9 @@
|
|||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="xHX-Sh-1pR" secondAttribute="trailing" id="LWS-JW-9dS"/>
|
||||
<constraint firstItem="xHX-Sh-1pR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="SRq-7t-Gyr"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="xHX-Sh-1pR" secondAttribute="bottom" constant="7" id="UPQ-jk-QJR"/>
|
||||
<constraint firstItem="xHX-Sh-1pR" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="7" id="gwb-2C-4wp"/>
|
||||
<constraint firstItem="xHX-Sh-1pR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="4" id="SRq-7t-Gyr"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="xHX-Sh-1pR" secondAttribute="bottom" constant="8" id="UPQ-jk-QJR"/>
|
||||
<constraint firstItem="xHX-Sh-1pR" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="8" id="gwb-2C-4wp"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12106.1" systemVersion="16F43c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12074.1"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
|
|
@ -16,17 +16,20 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="55"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="55.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HPC-rQ-39b">
|
||||
<rect key="frame" x="15" y="8" width="297" height="15"/>
|
||||
<rect key="frame" x="16" y="8" width="296" height="15"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
|
||||
<rect key="frame" x="15" y="26" width="297" height="21"/>
|
||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="123" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
|
||||
<rect key="frame" x="16" y="26" width="296" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="21" id="dHY-dw-mFe"/>
|
||||
</constraints>
|
||||
<nil key="textColor"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" returnKeyType="next"/>
|
||||
|
|
@ -36,17 +39,17 @@
|
|||
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" id="11n-KG-zy6"/>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="trailing" secondItem="HPC-rQ-39b" secondAttribute="trailing" id="42z-vE-AsJ"/>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="leading" secondItem="HPC-rQ-39b" secondAttribute="leading" id="8F6-w6-BDY"/>
|
||||
<constraint firstItem="HPC-rQ-39b" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="8" id="8ps-9g-9zG"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="HPC-rQ-39b" secondAttribute="trailing" id="Ayv-Bg-JxT"/>
|
||||
<constraint firstItem="HPC-rQ-39b" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="JN2-lI-0ZY"/>
|
||||
<constraint firstItem="8Ky-UZ-sLu" firstAttribute="top" secondItem="HPC-rQ-39b" secondAttribute="bottom" constant="3" id="Pqs-gm-93j"/>
|
||||
<constraint firstItem="HPC-rQ-39b" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="vfA-M9-FEp"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<connections>
|
||||
<outlet property="contentTextField" destination="8Ky-UZ-sLu" id="unz-5T-fuK"/>
|
||||
<outlet property="titleLabel" destination="HPC-rQ-39b" id="VoV-gT-5lh"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="34" y="60"/>
|
||||
<point key="canvasLocation" x="0.0" y="61"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
</document>
|
||||
|
|
|
|||
22
passTests/Info.plist
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2</string>
|
||||
</dict>
|
||||
</plist>
|
||||
35
passTests/passTests.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// passTests.swift
|
||||
// passTests
|
||||
//
|
||||
// Created by Mingshen Sun on 24/3/2017.
|
||||
// Copyright © 2017 Bob Sun. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
|
||||
class passTests: XCTestCase {
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testExample() {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
}
|
||||
|
||||
func testPerformanceExample() {
|
||||
// This is an example of a performance test case.
|
||||
self.measure {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||