Merge branch 'release/0.2.3'
2
.gitignore
vendored
|
|
@ -62,7 +62,7 @@ Carthage/Build
|
||||||
# For more information about the recommended setup visit:
|
# For more information about the recommended setup visit:
|
||||||
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
|
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
|
||||||
|
|
||||||
fastlane
|
fastlane/README.md
|
||||||
fastlane/report.xml
|
fastlane/report.xml
|
||||||
fastlane/Preview.html
|
fastlane/Preview.html
|
||||||
fastlane/screenshots
|
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 "SVProgressHUD/SVProgressHUD"
|
||||||
github "radex/SwiftyUserDefaults"
|
github "radex/SwiftyUserDefaults"
|
||||||
github "libgit2/objective-git" "master"
|
github "libgit2/objective-git"
|
||||||
github "zahlz/SwiftPasscodeLock" "master"
|
github "zahlz/SwiftPasscodeLock" "master"
|
||||||
github "bitserf/FavIcon"
|
github "bitserf/FavIcon"
|
||||||
github "kishikawakatsumi/KeychainAccess" "master"
|
github "kishikawakatsumi/KeychainAccess" "master"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
[](https://github.com/mssun/pass-ios/releases)
|
[](https://github.com/mssun/pass-ios/releases)
|
||||||

|

|
||||||
[](https://gitter.im/passforios/passforios)
|
[](https://gitter.im/passforios/passforios)
|
||||||
|
[](https://travis-ci.org/mssun/passforios)
|
||||||
|
|
||||||
Pass is an iOS client compatible with [ZX2C4's Pass command line
|
Pass is an iOS client compatible with [ZX2C4's Pass command line
|
||||||
application](http://www.passwordstore.org/). It is a password manager using
|
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 */; };
|
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */; };
|
||||||
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */; };
|
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */; };
|
||||||
DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; };
|
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 */; };
|
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; };
|
||||||
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; };
|
DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; };
|
||||||
DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */; };
|
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 */; };
|
DCC277D21E30D6EA00402246 /* pass.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DCC408C81E30BA1300F29B0E /* pass.xcdatamodeld */; };
|
||||||
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */; };
|
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */; };
|
||||||
DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */; };
|
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 */; };
|
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */; };
|
||||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */; };
|
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 */; };
|
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */; };
|
||||||
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */; };
|
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */; };
|
||||||
DCFB779E1E4F40C7008DE471 /* FillPasswordTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */; };
|
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 */; };
|
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* 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 */
|
/* 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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FillPasswordTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -134,6 +148,13 @@
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
DC13B14B1E8640810097803F /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
DC917BD01E2E8231000FDF54 /* Frameworks */ = {
|
DC917BD01E2E8231000FDF54 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -162,6 +183,15 @@
|
||||||
name = Pods;
|
name = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DC13B14F1E8640810097803F /* passTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DC13B1501E8640810097803F /* passTests.swift */,
|
||||||
|
DC13B1521E8640810097803F /* Info.plist */,
|
||||||
|
);
|
||||||
|
path = passTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DC19400C1E4B39400077E0A3 /* Controllers */ = {
|
DC19400C1E4B39400077E0A3 /* Controllers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -177,12 +207,14 @@
|
||||||
DCA049991E335CC800522E8F /* GitServerSettingTableViewController.swift */,
|
DCA049991E335CC800522E8F /* GitServerSettingTableViewController.swift */,
|
||||||
DC037CA51E4B883900609409 /* OpenSourceComponentsTableViewController.swift */,
|
DC037CA51E4B883900609409 /* OpenSourceComponentsTableViewController.swift */,
|
||||||
DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */,
|
DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */,
|
||||||
|
DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */,
|
||||||
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */,
|
DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */,
|
||||||
DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */,
|
DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */,
|
||||||
DCA0499B1E3362F400522E8F /* PGPKeySettingTableViewController.swift */,
|
DCA0499B1E3362F400522E8F /* PGPKeySettingTableViewController.swift */,
|
||||||
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
|
DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */,
|
||||||
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
|
DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */,
|
||||||
DC8963BF1E38EEB900828B09 /* SSHKeySettingTableViewController.swift */,
|
DC8963BF1E38EEB900828B09 /* SSHKeySettingTableViewController.swift */,
|
||||||
|
DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */,
|
||||||
);
|
);
|
||||||
path = Controllers;
|
path = Controllers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -229,8 +261,6 @@
|
||||||
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */,
|
DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */,
|
||||||
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */,
|
DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */,
|
||||||
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */,
|
||||||
DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */,
|
|
||||||
DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */,
|
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -239,6 +269,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DC917BD51E2E8231000FDF54 /* pass */,
|
DC917BD51E2E8231000FDF54 /* pass */,
|
||||||
|
DC13B14F1E8640810097803F /* passTests */,
|
||||||
DC917BD41E2E8231000FDF54 /* Products */,
|
DC917BD41E2E8231000FDF54 /* Products */,
|
||||||
DC917BED1E2F38C4000FDF54 /* Frameworks */,
|
DC917BED1E2F38C4000FDF54 /* Frameworks */,
|
||||||
A51B01737D08DB47BB58F85A /* Pods */,
|
A51B01737D08DB47BB58F85A /* Pods */,
|
||||||
|
|
@ -249,6 +280,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DC917BD31E2E8231000FDF54 /* pass.app */,
|
DC917BD31E2E8231000FDF54 /* pass.app */,
|
||||||
|
DC13B14E1E8640810097803F /* passTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -289,6 +321,24 @@
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget 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 */ = {
|
DC917BD21E2E8231000FDF54 /* pass */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = DC917BE51E2E8231000FDF54 /* Build configuration list for PBXNativeTarget "pass" */;
|
buildConfigurationList = DC917BE51E2E8231000FDF54 /* Build configuration list for PBXNativeTarget "pass" */;
|
||||||
|
|
@ -316,14 +366,20 @@
|
||||||
DC917BCB1E2E8231000FDF54 /* Project object */ = {
|
DC917BCB1E2E8231000FDF54 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0820;
|
LastSwiftUpdateCheck = 0830;
|
||||||
LastUpgradeCheck = 0820;
|
LastUpgradeCheck = 0820;
|
||||||
ORGANIZATIONNAME = "Bob Sun";
|
ORGANIZATIONNAME = "Bob Sun";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
DC13B14D1E8640810097803F = {
|
||||||
|
CreatedOnToolsVersion = 8.3;
|
||||||
|
DevelopmentTeam = 4WDM8E95VU;
|
||||||
|
ProvisioningStyle = Automatic;
|
||||||
|
TestTargetID = DC917BD21E2E8231000FDF54;
|
||||||
|
};
|
||||||
DC917BD21E2E8231000FDF54 = {
|
DC917BD21E2E8231000FDF54 = {
|
||||||
CreatedOnToolsVersion = 8.2.1;
|
CreatedOnToolsVersion = 8.2.1;
|
||||||
DevelopmentTeam = 4WDM8E95VU;
|
DevelopmentTeam = 4WDM8E95VU;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Manual;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -341,11 +397,19 @@
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
DC917BD21E2E8231000FDF54 /* pass */,
|
DC917BD21E2E8231000FDF54 /* pass */,
|
||||||
|
DC13B14D1E8640810097803F /* passTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
DC13B14C1E8640810097803F /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
DC917BD11E2E8231000FDF54 /* Resources */ = {
|
DC917BD11E2E8231000FDF54 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
|
|
@ -357,7 +421,6 @@
|
||||||
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */,
|
DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */,
|
||||||
DC917BDC1E2E8231000FDF54 /* Main.storyboard in Resources */,
|
DC917BDC1E2E8231000FDF54 /* Main.storyboard in Resources */,
|
||||||
A2802BFA1E70813A00879216 /* SliderTableViewCell.xib in Resources */,
|
A2802BFA1E70813A00879216 /* SliderTableViewCell.xib in Resources */,
|
||||||
DCE6C2681E71261C003038C6 /* PasswordWithFolderTableViewCell.xib in Resources */,
|
|
||||||
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */,
|
DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */,
|
||||||
DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */,
|
DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */,
|
||||||
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */,
|
DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */,
|
||||||
|
|
@ -437,12 +500,21 @@
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
DC13B14A1E8640810097803F /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
DC13B1511E8640810097803F /* passTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
DC917BCF1E2E8231000FDF54 /* Sources */ = {
|
DC917BCF1E2E8231000FDF54 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */,
|
DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */,
|
||||||
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */,
|
DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */,
|
||||||
|
DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */,
|
||||||
DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */,
|
DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */,
|
||||||
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */,
|
||||||
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */,
|
DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */,
|
||||||
|
|
@ -452,7 +524,6 @@
|
||||||
DC5F385B1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift in Sources */,
|
DC5F385B1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift in Sources */,
|
||||||
A27424D91E7C35960093F436 /* NotificationNames.swift in Sources */,
|
A27424D91E7C35960093F436 /* NotificationNames.swift in Sources */,
|
||||||
DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */,
|
DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */,
|
||||||
DCE6C2671E71261C003038C6 /* PasswordWithFolderTableViewCell.swift in Sources */,
|
|
||||||
DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */,
|
DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */,
|
||||||
DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */,
|
DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */,
|
||||||
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */,
|
DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */,
|
||||||
|
|
@ -469,6 +540,7 @@
|
||||||
DC037CB21E4CAB1700609409 /* AboutRepositoryTableViewController.swift in Sources */,
|
DC037CB21E4CAB1700609409 /* AboutRepositoryTableViewController.swift in Sources */,
|
||||||
DC037CB01E4CA51F00609409 /* GeneralSettingsTableViewController.swift in Sources */,
|
DC037CB01E4CA51F00609409 /* GeneralSettingsTableViewController.swift in Sources */,
|
||||||
DC037CB81E4DD1A500609409 /* AddPasswordTableViewController.swift in Sources */,
|
DC037CB81E4DD1A500609409 /* AddPasswordTableViewController.swift in Sources */,
|
||||||
|
DCC441521E8F6C06008A90C4 /* RawPasswordViewController.swift in Sources */,
|
||||||
DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */,
|
DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */,
|
||||||
DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */,
|
DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */,
|
||||||
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */,
|
DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */,
|
||||||
|
|
@ -484,6 +556,14 @@
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
DC13B1541E8640810097803F /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = DC917BD21E2E8231000FDF54 /* pass */;
|
||||||
|
targetProxy = DC13B1531E8640810097803F /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
DC917BDA1E2E8231000FDF54 /* Main.storyboard */ = {
|
DC917BDA1E2E8231000FDF54 /* Main.storyboard */ = {
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
|
|
@ -504,6 +584,38 @@
|
||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration 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 */ = {
|
DC917BE31E2E8231000FDF54 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
|
@ -601,7 +713,7 @@
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
CURRENT_PROJECT_VERSION = 24;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEFINES_MODULE = NO;
|
DEFINES_MODULE = NO;
|
||||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
|
@ -620,6 +732,8 @@
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
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_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 3.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
@ -632,8 +746,8 @@
|
||||||
baseConfigurationReference = AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */;
|
baseConfigurationReference = AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||||
CURRENT_PROJECT_VERSION = 24;
|
CURRENT_PROJECT_VERSION = 2;
|
||||||
DEFINES_MODULE = NO;
|
DEFINES_MODULE = NO;
|
||||||
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
DEVELOPMENT_TEAM = 4WDM8E95VU;
|
||||||
FRAMEWORK_SEARCH_PATHS = (
|
FRAMEWORK_SEARCH_PATHS = (
|
||||||
|
|
@ -652,6 +766,8 @@
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
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_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 3.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
|
@ -662,6 +778,15 @@
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList 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" */ = {
|
DC917BCE1E2E8231000FDF54 /* Build configuration list for PBXProject "pass" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
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"?>
|
<?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">
|
<device id="retina5_5" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -158,7 +158,7 @@
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
</tableViewSection>
|
</tableViewSection>
|
||||||
<tableViewSection headerTitle="PASSCODE" id="Cx7-e4-wCO">
|
<tableViewSection headerTitle="SECURITY" id="Cx7-e4-wCO">
|
||||||
<cells>
|
<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">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="passcodeTableViewCell" textLabel="RaZ-6t-0CU" detailTextLabel="HXb-ZX-HUv" style="IBUITableViewCellStyleValue1" id="6Y0-mj-qhA">
|
||||||
<rect key="frame" x="0.0" y="223" width="414" height="44"/>
|
<rect key="frame" x="0.0" y="223" width="414" height="44"/>
|
||||||
|
|
@ -167,8 +167,8 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="381" height="43.666666666666664"/>
|
<rect key="frame" x="0.0" y="0.0" width="381" height="43.666666666666664"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Passcode" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="RaZ-6t-0CU">
|
<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="74.333333333333329" height="20.333333333333332"/>
|
<rect key="frame" x="15" y="11.999999999999998" width="115" height="20.333333333333332"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
|
|
@ -288,7 +288,7 @@
|
||||||
<rect key="frame" x="0.0" y="28" width="414" height="44"/>
|
<rect key="frame" x="0.0" y="28" width="414" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="OfB-1N-1Am" id="fh0-au-C6q">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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">
|
<tableViewSection headerTitle="Git Repository URL" id="pbe-W6-w4V">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="gitRepositoryURLTabelViewCell" rowHeight="52" id="FRr-pf-aPO">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="FRr-pf-aPO" id="60A-PS-qGe">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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">
|
<tableViewSection headerTitle="Username" id="fRu-A2-SCk">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="usernameTableVIewCell" rowHeight="52" id="tnj-5U-kMB">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="tnj-5U-kMB" id="f0c-pI-MSJ">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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">
|
<tableViewSection headerTitle="Authentication Method" id="h0N-tI-shZ">
|
||||||
<cells>
|
<cells>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="2" indentationWidth="0.0" shouldIndentWhileEditing="NO" id="KrP-nb-haa">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KrP-nb-haa" id="1uB-oE-kfI">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<inset key="separatorInset" minX="62" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="blue" accessoryType="detailButton" hidesAccessoryWhenEditing="NO" indentationLevel="2" indentationWidth="0.0" shouldIndentWhileEditing="NO" id="Qmt-bo-CuJ">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Qmt-bo-CuJ" id="p3u-8b-h3U">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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>
|
<connections>
|
||||||
<outlet property="authPasswordCell" destination="KrP-nb-haa" id="zjH-sg-dfJ"/>
|
<outlet property="authPasswordCell" destination="KrP-nb-haa" id="zjH-sg-dfJ"/>
|
||||||
<outlet property="authSSHKeyCell" destination="Qmt-bo-CuJ" id="11L-Tt-MgM"/>
|
<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"/>
|
<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="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>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="7c1-c7-Qyp" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<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"/>
|
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="BYZ-9g-xZy" id="Zfn-rK-sN1">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<rect key="frame" x="0.0" y="87" width="414" height="52"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="vpk-J8-j7t" id="1td-qT-6ts">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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">
|
<scene sceneID="9wY-d0-fB1">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="tW4-E9-CGv" customClass="PasswordDetailTableViewController" customModule="pass" customModuleProvider="target" sceneMemberID="viewController">
|
<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"/>
|
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||||
|
|
@ -638,6 +639,7 @@
|
||||||
</tableView>
|
</tableView>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="eui-w4-P7T" kind="show" identifier="editPasswordSegue" id="Ydg-pZ-oNS"/>
|
<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>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="9sC-44-OKL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="9sC-44-OKL" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
|
@ -736,6 +738,50 @@
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="6084" y="601"/>
|
<point key="canvasLocation" x="6084" y="601"/>
|
||||||
</scene>
|
</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-->
|
<!--About Repository Table View Controller-->
|
||||||
<scene sceneID="u1v-BP-jaG">
|
<scene sceneID="u1v-BP-jaG">
|
||||||
<objects>
|
<objects>
|
||||||
|
|
@ -791,7 +837,7 @@
|
||||||
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
<rect key="frame" x="0.0" y="35" width="414" height="52"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Jy1-4S-Lvf" id="tJE-ww-okf">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<rect key="frame" x="0.0" y="87" width="414" height="52"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="MA5-lE-8dT" id="pTv-Wj-psC">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
</tableViewCell>
|
</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>
|
</cells>
|
||||||
</tableViewSection>
|
</tableViewSection>
|
||||||
</sections>
|
</sections>
|
||||||
|
|
@ -886,14 +902,13 @@
|
||||||
</connections>
|
</connections>
|
||||||
</tableView>
|
</tableView>
|
||||||
<connections>
|
<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="privateKeyURLTextField" destination="4iJ-oB-R1f" id="scx-lz-dUW"/>
|
||||||
<outlet property="publicKeyURLTextField" destination="Q1j-Z4-Ae8" id="nfA-W3-kJ2"/>
|
<outlet property="publicKeyURLTextField" destination="Q1j-Z4-Ae8" id="nfA-W3-kJ2"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="eY3-aM-BJB" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="eY3-aM-BJB" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="5132" y="2893"/>
|
<point key="canvasLocation" x="7433" y="2204"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--General Settings Table View Controller-->
|
<!--General Settings Table View Controller-->
|
||||||
<scene sceneID="fho-xr-1Ah">
|
<scene sceneID="fho-xr-1Ah">
|
||||||
|
|
@ -1135,7 +1150,7 @@
|
||||||
<rect key="frame" x="0.0" y="35" width="414" height="170"/>
|
<rect key="frame" x="0.0" y="35" width="414" height="170"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Pv0-ev-stj" id="ywz-II-W1g">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<rect key="frame" x="0.0" y="261" width="414" height="160"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Lom-iT-l16" id="eya-Tv-r0q">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oyB-oI-1fS">
|
<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"/>
|
<rect key="frame" x="0.0" y="477" width="414" height="160"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="J8U-ev-FRQ" id="eb0-vb-Fcc">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lrQ-Ln-ZOv">
|
<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"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="2Wn-7D-LLj" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
<exit id="Ul9-vk-jhw" userLabel="Exit" sceneMemberID="exit"/>
|
<exit id="Ul9-vk-jhw" userLabel="Exit" sceneMemberID="exit"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="6039.130434782609" y="4307.608695652174"/>
|
<point key="canvasLocation" x="7094" y="4030"/>
|
||||||
</scene>
|
</scene>
|
||||||
<!--Navigation Controller-->
|
<!--Navigation Controller-->
|
||||||
<scene sceneID="m18-ch-m92">
|
<scene sceneID="m18-ch-m92">
|
||||||
|
|
@ -1346,6 +1361,218 @@ pfZ36xQbOAQYKKf6ZTT5R/Y=
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="5131.884057971015" y="4307.608695652174"/>
|
<point key="canvasLocation" x="5131.884057971015" y="4307.608695652174"/>
|
||||||
</scene>
|
</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>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="Lock" width="25" height="25"/>
|
<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: "Passwords", .detailText: numberOfPasswordsString],
|
||||||
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Size", .detailText: sizeOfRepositoryString],
|
[.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: "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],
|
[.style: CellDataStyle.value1, .accessoryType: type, .title: "Commits", .detailText: numberOfCommitsString],
|
||||||
[.title: "Commit Logs", .action: "segue", .link: "showCommitLogsSegue"],
|
[.title: "Commit Logs", .action: "segue", .link: "showCommitLogsSegue"],
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,15 @@ class EditPasswordTableViewController: PasswordEditorTableViewController {
|
||||||
|
|
||||||
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
if identifier == "saveEditPasswordSegue" {
|
if identifier == "saveEditPasswordSegue" {
|
||||||
let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! ContentTableViewCell
|
if let nameCell = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as? ContentTableViewCell {
|
||||||
if nameCell.getContent() != password?.name {
|
if nameCell.getContent() != password?.name {
|
||||||
let alertTitle = "Cannot Save Edit"
|
let alertTitle = "Cannot Save Edit"
|
||||||
let alertMessage = "Editing name is not supported."
|
let alertMessage = "Editing name is not supported."
|
||||||
Utils.alert(title: alertTitle, message: alertMessage, controller: self) {
|
Utils.alert(title: alertTitle, message: alertMessage, controller: self) {
|
||||||
nameCell.setContent(content: self.password!.name)
|
nameCell.setContent(content: self.password!.name)
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
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 UIKit
|
||||||
import SwiftyUserDefaults
|
import SwiftyUserDefaults
|
||||||
|
import SVProgressHUD
|
||||||
|
|
||||||
class GitServerSettingTableViewController: UITableViewController {
|
class GitServerSettingTableViewController: UITableViewController {
|
||||||
|
|
||||||
@IBOutlet weak var gitRepositoryURLTextField: UITextField!
|
@IBOutlet weak var gitURLTextField: UITextField!
|
||||||
@IBOutlet weak var usernameTextField: UITextField!
|
@IBOutlet weak var usernameTextField: UITextField!
|
||||||
@IBOutlet weak var authSSHKeyCell: UITableViewCell!
|
@IBOutlet weak var authSSHKeyCell: UITableViewCell!
|
||||||
@IBOutlet weak var authPasswordCell: UITableViewCell!
|
@IBOutlet weak var authPasswordCell: UITableViewCell!
|
||||||
let passwordStore = PasswordStore.shared
|
let passwordStore = PasswordStore.shared
|
||||||
var password: String?
|
var password: String?
|
||||||
|
|
||||||
var authenticationMethod = Defaults[.gitRepositoryAuthenticationMethod]
|
var authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||||
|
|
||||||
private func checkAuthenticationMethod(method: String) {
|
private func checkAuthenticationMethod(method: String) {
|
||||||
let passwordCheckView = authPasswordCell.viewWithTag(1001)!
|
let passwordCheckView = authPasswordCell.viewWithTag(1001)!
|
||||||
|
|
@ -38,17 +39,17 @@ class GitServerSettingTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
if let url = Defaults[.gitRepositoryURL] {
|
if let url = Defaults[.gitURL] {
|
||||||
gitRepositoryURLTextField.text = url.absoluteString
|
gitURLTextField.text = url.absoluteString
|
||||||
}
|
}
|
||||||
usernameTextField.text = Defaults[.gitRepositoryUsername]
|
usernameTextField.text = Defaults[.gitUsername]
|
||||||
password = passwordStore.gitRepositoryPassword
|
password = passwordStore.gitPassword
|
||||||
authenticationMethod = Defaults[.gitRepositoryAuthenticationMethod]
|
authenticationMethod = Defaults[.gitAuthenticationMethod]
|
||||||
|
|
||||||
// Grey out ssh option if ssh_key and ssh_key.pub are not present
|
// Grey out ssh option if ssh_key and ssh_key.pub are not present
|
||||||
let sshLabel = authSSHKeyCell.subviews[0].subviews[0] as! UILabel
|
let sshLabel = authSSHKeyCell.subviews[0].subviews[0] as! UILabel
|
||||||
|
|
||||||
sshLabel.isEnabled = sshKeyExists()
|
sshLabel.isEnabled = gitSSHKeyExists()
|
||||||
|
|
||||||
if authenticationMethod == nil || !sshLabel.isEnabled {
|
if authenticationMethod == nil || !sshLabel.isEnabled {
|
||||||
authenticationMethod = "Password"
|
authenticationMethod = "Password"
|
||||||
|
|
@ -61,7 +62,7 @@ class GitServerSettingTableViewController: UITableViewController {
|
||||||
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
|
||||||
let cell = tableView.cellForRow(at: indexPath)
|
let cell = tableView.cellForRow(at: indexPath)
|
||||||
if cell == authSSHKeyCell {
|
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 {
|
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||||
if identifier == "saveGitServerSettingSegue" {
|
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)
|
Utils.alert(title: "Cannot Save", message: "Git Server is not set.", controller: self, completion: nil)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -89,18 +90,13 @@ class GitServerSettingTableViewController: UITableViewController {
|
||||||
return true
|
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) {
|
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
let cell = tableView.cellForRow(at: indexPath)
|
let cell = tableView.cellForRow(at: indexPath)
|
||||||
if cell == authPasswordCell {
|
if cell == authPasswordCell {
|
||||||
authenticationMethod = "Password"
|
authenticationMethod = "Password"
|
||||||
} else if cell == authSSHKeyCell {
|
} 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)
|
Utils.alert(title: "Cannot Select SSH Key", message: "Please setup SSH key first.", controller: self, completion: nil)
|
||||||
authenticationMethod = "Password"
|
authenticationMethod = "Password"
|
||||||
} else {
|
} 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 = ""
|
content = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init(title: String) {
|
||||||
|
self.title = title
|
||||||
|
self.content = ""
|
||||||
|
}
|
||||||
|
|
||||||
init(title: String, content: String) {
|
init(title: String, content: String) {
|
||||||
self.title = title
|
self.title = title
|
||||||
self.content = content
|
self.content = content
|
||||||
|
|
@ -46,24 +51,39 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct TableSection {
|
private struct TableSection {
|
||||||
var title: String
|
var type: PasswordDetailTableViewControllerSectionType
|
||||||
|
var header: String?
|
||||||
var item: Array<TableCell>
|
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 var tableData = Array<TableSection>()
|
||||||
|
|
||||||
|
private enum PasswordDetailTableViewControllerSectionType {
|
||||||
|
case name, main, addition, misc
|
||||||
|
}
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
tableView.register(UINib(nibName: "LabelTableViewCell", bundle: nil), forCellReuseIdentifier: "labelCell")
|
tableView.register(UINib(nibName: "LabelTableViewCell", bundle: nil), forCellReuseIdentifier: "labelCell")
|
||||||
tableView.register(UINib(nibName: "PasswordDetailTitleTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordDetailTitleTableViewCell")
|
tableView.register(UINib(nibName: "PasswordDetailTitleTableViewCell", bundle: nil), forCellReuseIdentifier: "passwordDetailTitleTableViewCell")
|
||||||
|
|
||||||
passwordCategoryText = passwordEntity!.getCategoryText()
|
passwordCategoryText = passwordEntity!.getCategoryText()
|
||||||
|
|
||||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PasswordDetailTableViewController.tapMenu(recognizer:)))
|
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(PasswordDetailTableViewController.tapMenu(recognizer:)))
|
||||||
|
tapGesture.cancelsTouchesInView = false
|
||||||
tableView.addGestureRecognizer(tapGesture)
|
tableView.addGestureRecognizer(tapGesture)
|
||||||
tapGesture.delegate = self
|
tapGesture.delegate = self
|
||||||
|
|
||||||
tableView.contentInset = UIEdgeInsetsMake(-36, 0, 0, 0);
|
tableView.contentInset = UIEdgeInsetsMake(-36, 0, 44, 0);
|
||||||
tableView.rowHeight = UITableViewAutomaticDimension
|
tableView.rowHeight = UITableViewAutomaticDimension
|
||||||
tableView.estimatedRowHeight = 52
|
tableView.estimatedRowHeight = 52
|
||||||
|
|
||||||
|
|
@ -224,23 +244,31 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
|
|
||||||
private func setTableData() {
|
private func setTableData() {
|
||||||
self.tableData = Array<TableSection>()
|
self.tableData = Array<TableSection>()
|
||||||
tableData.append(TableSection(title: "", item: []))
|
|
||||||
tableData[0].item.append(TableCell())
|
// name section
|
||||||
var tableDataIndex = 1
|
var section = TableSection(type: .name)
|
||||||
self.tableData.append(TableSection(title: "", item: []))
|
section.item.append(TableCell())
|
||||||
|
tableData.append(section)
|
||||||
|
|
||||||
|
// main section
|
||||||
|
section = TableSection(type: .main)
|
||||||
let password = self.password!
|
let password = self.password!
|
||||||
if let username = password.getUsername() {
|
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
|
// show one time password
|
||||||
if password.otpType != .none {
|
if password.otpType != .none {
|
||||||
if let (title, otp) = self.password?.getOtpStrings() {
|
if let (title, otp) = self.password?.getOtpStrings() {
|
||||||
self.tableData.append(TableSection(title: "One time password", item: []))
|
section = TableSection(type: .addition, header: "One Time Password")
|
||||||
tableDataIndex += 1
|
section.item.append(TableCell(title: title, content: otp))
|
||||||
oneTimePasswordIndexPath = IndexPath(row: 0, section: tableDataIndex)
|
tableData.append(section)
|
||||||
self.tableData[tableDataIndex].item.append(TableCell(title: title, content: otp))
|
oneTimePasswordIndexPath = IndexPath(row: 0, section: tableData.count - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -252,12 +280,18 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
(!Password.otpKeywords.contains($0) || !Defaults[.isHideOTPOn]) }
|
(!Password.otpKeywords.contains($0) || !Defaults[.isHideOTPOn]) }
|
||||||
|
|
||||||
if filteredAdditionKeys.count > 0 {
|
if filteredAdditionKeys.count > 0 {
|
||||||
self.tableData.append(TableSection(title: "additions", item: []))
|
section = TableSection(type: .addition, header: "additions")
|
||||||
tableDataIndex += 1
|
|
||||||
for additionKey in filteredAdditionKeys {
|
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?) {
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||||
|
|
@ -267,6 +301,12 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
editController.password = password
|
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() {
|
func getNextHOTP() {
|
||||||
guard password != nil, passwordEntity != nil, password?.otpType == .hotp else {
|
guard password != nil, passwordEntity != nil, password?.otpType == .hotp else {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
@ -380,8 +430,9 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
let sectionIndex = indexPath.section
|
let sectionIndex = indexPath.section
|
||||||
let rowIndex = indexPath.row
|
let rowIndex = indexPath.row
|
||||||
|
let tableDataItem = tableData[sectionIndex].item[rowIndex]
|
||||||
if sectionIndex == 0 && rowIndex == 0 {
|
switch(tableData[sectionIndex].type) {
|
||||||
|
case .name:
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordDetailTitleTableViewCell", for: indexPath) as! PasswordDetailTitleTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordDetailTitleTableViewCell", for: indexPath) as! PasswordDetailTitleTableViewCell
|
||||||
cell.passwordImageImageView.image = passwordImage ?? #imageLiteral(resourceName: "PasswordImagePlaceHolder")
|
cell.passwordImageImageView.image = passwordImage ?? #imageLiteral(resourceName: "PasswordImagePlaceHolder")
|
||||||
var passwordName = passwordEntity!.name!
|
var passwordName = passwordEntity!.name!
|
||||||
|
|
@ -390,22 +441,29 @@ class PasswordDetailTableViewController: UITableViewController, UIGestureRecogni
|
||||||
}
|
}
|
||||||
cell.nameLabel.text = passwordName
|
cell.nameLabel.text = passwordName
|
||||||
cell.categoryLabel.text = passwordCategoryText
|
cell.categoryLabel.text = passwordCategoryText
|
||||||
|
cell.selectionStyle = .none
|
||||||
return cell
|
return cell
|
||||||
} else {
|
case .main, .addition:
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell", for: indexPath) as! LabelTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "labelCell", for: indexPath) as! LabelTableViewCell
|
||||||
let titleData = tableData[sectionIndex].item[rowIndex].title
|
let titleData = tableDataItem.title
|
||||||
let contentData = tableData[sectionIndex].item[rowIndex].content
|
let contentData = tableDataItem.content
|
||||||
cell.delegatePasswordTableView = self
|
cell.delegatePasswordTableView = self
|
||||||
cell.isPasswordCell = (titleData.lowercased() == "password" ? true : false)
|
cell.isPasswordCell = (titleData.lowercased() == "password" ? true : false)
|
||||||
cell.isURLCell = (titleData.lowercased() == "url" ? true : false)
|
cell.isURLCell = (titleData.lowercased() == "url" ? true : false)
|
||||||
cell.isHOTPCell = (titleData == "HMAC-based" ? true : false)
|
cell.isHOTPCell = (titleData == "HMAC-based" ? true : false)
|
||||||
cell.cellData = LabelTableViewCellData(title: titleData, content: contentData)
|
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
|
return cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
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? {
|
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 {
|
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 {
|
override func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
|
||||||
return true
|
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 UIKit
|
||||||
|
import SwiftyUserDefaults
|
||||||
|
|
||||||
enum PasswordEditorCellType {
|
enum PasswordEditorCellType {
|
||||||
case textFieldCell, textViewCell, fillPasswordCell, passwordLengthCell, deletePasswordCell
|
case textFieldCell, textViewCell, fillPasswordCell, passwordLengthCell, deletePasswordCell
|
||||||
}
|
}
|
||||||
|
|
@ -54,11 +56,6 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
||||||
tableView.estimatedRowHeight = 48
|
tableView.estimatedRowHeight = 48
|
||||||
self.tableView.sectionFooterHeight = UITableViewAutomaticDimension;
|
self.tableView.sectionFooterHeight = UITableViewAutomaticDimension;
|
||||||
self.tableView.estimatedSectionFooterHeight = 0;
|
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 {
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
|
@ -76,7 +73,12 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
||||||
return fillPasswordCell!
|
return fillPasswordCell!
|
||||||
case .passwordLengthCell:
|
case .passwordLengthCell:
|
||||||
passwordLengthCell = tableView.dequeueReusableCell(withIdentifier: "passwordLengthCell", for: indexPath) as? SliderTableViewCell
|
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
|
passwordLengthCell?.delegate = self
|
||||||
return passwordLengthCell!
|
return passwordLengthCell!
|
||||||
case .deletePasswordCell:
|
case .deletePasswordCell:
|
||||||
|
|
@ -148,7 +150,7 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
||||||
hidePasswordSettings = false
|
hidePasswordSettings = false
|
||||||
tableView.reloadSections([passwordSection], with: .fade)
|
tableView.reloadSections([passwordSection], with: .fade)
|
||||||
}
|
}
|
||||||
let length = passwordLengthCell?.roundedValue ?? Globals.passwordDefaultLength
|
let length = passwordLengthCell?.roundedValue ?? 0
|
||||||
let plainPassword = Utils.generatePassword(length: length)
|
let plainPassword = Utils.generatePassword(length: length)
|
||||||
Utils.copyToPasteboard(textToCopy: plainPassword)
|
Utils.copyToPasteboard(textToCopy: plainPassword)
|
||||||
|
|
||||||
|
|
@ -159,35 +161,8 @@ class PasswordEditorTableViewController: UITableViewController, FillPasswordTabl
|
||||||
fillPasswordCell?.setContent(content: plainPassword)
|
fillPasswordCell?.setContent(content: plainPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tableTapped(recognizer: UITapGestureRecognizer) {
|
func showHidePasswordSettings() {
|
||||||
if recognizer.state == UIGestureRecognizerState.ended {
|
hidePasswordSettings = !hidePasswordSettings
|
||||||
let tapLocation = recognizer.location(in: self.tableView)
|
tableView.reloadSections([passwordSection], with: .fade)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,6 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(parent: parent)
|
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(parent: parent)
|
||||||
} else {
|
} else {
|
||||||
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
passwordEntities = self.passwordStore.fetchPasswordEntityCoreData(withDir: false)
|
||||||
|
|
||||||
}
|
}
|
||||||
passwordsTableEntries = passwordEntities.map {
|
passwordsTableEntries = passwordEntities.map {
|
||||||
PasswordsTableEntry(title: $0.name!, isDir: $0.isDir, passwordEntity: $0)
|
PasswordsTableEntry(title: $0.name!, isDir: $0.isDir, passwordEntity: $0)
|
||||||
|
|
@ -109,8 +108,8 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
SVProgressHUD.showProgress(progress, status: "Encrypting")
|
SVProgressHUD.showProgress(progress, status: "Encrypting")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
// will trigger reloadTableView() by a notification
|
||||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||||
SVProgressHUD.dismiss(withDelay: 1)
|
SVProgressHUD.dismiss(withDelay: 1)
|
||||||
}
|
}
|
||||||
|
|
@ -144,8 +143,7 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.reloadTableView(parent: nil)
|
self.reloadTableView(parent: nil)
|
||||||
Defaults[.lastUpdatedTime] = Date()
|
Defaults[.gitPasswordAttempts] = 0
|
||||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
|
||||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||||
SVProgressHUD.dismiss(withDelay: 1)
|
SVProgressHUD.dismiss(withDelay: 1)
|
||||||
}
|
}
|
||||||
|
|
@ -174,9 +172,9 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
reloadTableView(parent: nil)
|
reloadTableView(parent: nil)
|
||||||
|
|
||||||
// reset the data table if some password (maybe another one) has been updated
|
// 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
|
// 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)
|
NotificationCenter.default.addObserver(self, selector: #selector(actOnSearchNotification), name: .passwordSearch, object: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -221,20 +219,23 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
} else {
|
} else {
|
||||||
cell.textLabel?.text = "\(entry.title)"
|
cell.textLabel?.text = "\(entry.title)"
|
||||||
cell.accessoryType = .disclosureIndicator
|
cell.accessoryType = .disclosureIndicator
|
||||||
|
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .body)
|
||||||
cell.detailTextLabel?.text = "\(entry.passwordEntity?.children?.count ?? 0)"
|
cell.detailTextLabel?.text = "\(entry.passwordEntity?.children?.count ?? 0)"
|
||||||
}
|
}
|
||||||
return cell
|
return cell
|
||||||
} else {
|
} else {
|
||||||
let passwordWithFolderCell = tableView.dequeueReusableCell(withIdentifier: "passwordWithFolderTableViewCell", for: indexPath) as! PasswordWithFolderTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "passwordTableViewCell", for: indexPath)
|
||||||
let entry = getPasswordEntry(by: indexPath)
|
let entry = getPasswordEntry(by: indexPath)
|
||||||
if entry.passwordEntity!.synced {
|
if entry.passwordEntity!.synced {
|
||||||
passwordWithFolderCell.passwordLabel?.text = entry.title
|
cell.textLabel?.text = entry.title
|
||||||
} else {
|
} else {
|
||||||
passwordWithFolderCell.passwordLabel?.text = "↻ \(entry.title)"
|
cell.textLabel?.text = "↻ \(entry.title)"
|
||||||
}
|
}
|
||||||
passwordWithFolderCell.folderLabel.text = entry.passwordEntity?.getCategoryText()
|
cell.accessoryType = .none
|
||||||
passwordWithFolderCell.addGestureRecognizer(longPressGestureRecognizer)
|
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .footnote)
|
||||||
return passwordWithFolderCell
|
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")
|
self.tableView.layer.removeAnimation(forKey: "UITableViewReloadDataAnimationKey")
|
||||||
|
|
||||||
// set the sync control title
|
// set the sync control title
|
||||||
let atribbutedTitle = "Last Synced: \(Utils.getLastUpdatedTimeString())"
|
let atribbutedTitle = "Last Synced: \(Utils.getLastSyncedTimeString())"
|
||||||
syncControl.attributedTitle = NSAttributedString(string: atribbutedTitle)
|
syncControl.attributedTitle = NSAttributedString(string: atribbutedTitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -438,9 +439,12 @@ class PasswordsViewController: UIViewController, UITableViewDataSource, UITableV
|
||||||
reloadTableView(data: passwordsTableEntries, anim: anim)
|
reloadTableView(data: passwordsTableEntries, anim: anim)
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadTableView() {
|
func actOnReloadTableViewRelatedNotification() {
|
||||||
initPasswordsTableEntries(parent: nil)
|
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) {
|
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 {
|
class SSHKeySettingTableViewController: UITableViewController {
|
||||||
|
|
||||||
@IBOutlet weak var passphraseTextField: UITextField!
|
|
||||||
@IBOutlet weak var privateKeyURLTextField: UITextField!
|
@IBOutlet weak var privateKeyURLTextField: UITextField!
|
||||||
@IBOutlet weak var publicKeyURLTextField: UITextField!
|
@IBOutlet weak var publicKeyURLTextField: UITextField!
|
||||||
|
let passwordStore = PasswordStore.shared
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
passphraseTextField.text = Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? ""
|
privateKeyURLTextField.text = Defaults[.gitSSHPrivateKeyURL]?.absoluteString
|
||||||
privateKeyURLTextField.text = Defaults[.gitRepositorySSHPrivateKeyURL]?.absoluteString
|
publicKeyURLTextField.text = Defaults[.gitSSHPublicKeyURL]?.absoluteString
|
||||||
publicKeyURLTextField.text = Defaults[.gitRepositorySSHPublicKeyURL]?.absoluteString
|
|
||||||
var doneBarButtonItem: UIBarButtonItem?
|
var doneBarButtonItem: UIBarButtonItem?
|
||||||
|
|
||||||
doneBarButtonItem = UIBarButtonItem(title: "Done",
|
doneBarButtonItem = UIBarButtonItem(title: "Done",
|
||||||
|
|
@ -41,18 +40,42 @@ class SSHKeySettingTableViewController: UITableViewController {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Defaults[.gitRepositorySSHPublicKeyURL] = publicKeyURL
|
Defaults[.gitSSHPublicKeyURL] = publicKeyURL
|
||||||
Defaults[.gitRepositorySSHPrivateKeyURL] = privateKeyURL
|
Defaults[.gitSSHPrivateKeyURL] = privateKeyURL
|
||||||
Utils.addPasswordToKeychain(name: "gitRepositorySSHPrivateKeyPassphrase", password: passphraseTextField.text!)
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try Data(contentsOf: publicKeyURL).write(to: Globals.sshPublicKeyURL, options: .atomic)
|
try Data(contentsOf: publicKeyURL).write(to: URL(fileURLWithPath: Globals.gitSSHPublicKeyPath), options: .atomic)
|
||||||
try Data(contentsOf: privateKeyURL).write(to: Globals.sshPrivateKeyURL, options: .atomic)
|
try Data(contentsOf: privateKeyURL).write(to: URL(fileURLWithPath: Globals.gitSSHPrivateKeyPath), options: .atomic)
|
||||||
} catch {
|
} catch {
|
||||||
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
|
Utils.alert(title: "Error", message: error.localizedDescription, controller: self, completion: nil)
|
||||||
}
|
}
|
||||||
|
Defaults[.gitSSHKeySource] = "url"
|
||||||
navigationController!.popViewController(animated: true)
|
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) {
|
@IBAction func saveGitServerSetting(segue: UIStoryboardSegue) {
|
||||||
if let controller = segue.source as? GitServerSettingTableViewController {
|
if let controller = segue.source as? GitServerSettingTableViewController {
|
||||||
let gitRepostiroyURL = controller.gitRepositoryURLTextField.text!
|
let gitRepostiroyURL = controller.gitURLTextField.text!
|
||||||
let username = controller.usernameTextField.text!
|
let username = controller.usernameTextField.text!
|
||||||
let password = controller.password
|
let password = controller.password
|
||||||
let auth = controller.authenticationMethod
|
let auth = controller.authenticationMethod
|
||||||
|
|
||||||
if Defaults[.gitRepositoryURL] == nil ||
|
if Defaults[.gitURL] == nil ||
|
||||||
Defaults[.gitRepositoryURL]!.absoluteString != gitRepostiroyURL ||
|
Defaults[.gitURL]!.absoluteString != gitRepostiroyURL ||
|
||||||
auth != Defaults[.gitRepositoryAuthenticationMethod] ||
|
auth != Defaults[.gitAuthenticationMethod] ||
|
||||||
username != Defaults[.gitRepositoryUsername] ||
|
username != Defaults[.gitUsername] ||
|
||||||
password != self.passwordStore.gitRepositoryPassword ||
|
password != self.passwordStore.gitPassword ||
|
||||||
self.passwordStore.repositoryExisted() == false {
|
self.passwordStore.repositoryExisted() == false {
|
||||||
|
|
||||||
SVProgressHUD.setDefaultMaskType(.black)
|
SVProgressHUD.setDefaultMaskType(.black)
|
||||||
|
|
@ -117,9 +117,9 @@ class SettingsTableViewController: UITableViewController {
|
||||||
gitCredential = GitCredential(
|
gitCredential = GitCredential(
|
||||||
credential: GitCredential.Credential.ssh(
|
credential: GitCredential.Credential.ssh(
|
||||||
userName: username,
|
userName: username,
|
||||||
password: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? "",
|
password: Utils.getPasswordFromKeychain(name: "gitSSHPrivateKeyPassphrase") ?? "",
|
||||||
publicKeyFile: Globals.sshPublicKeyURL,
|
publicKeyFile: Globals.gitSSHPublicKeyURL,
|
||||||
privateKeyFile: Globals.sshPrivateKeyURL,
|
privateKeyFile: Globals.gitSSHPrivateKeyURL,
|
||||||
passwordNotSetCallback: self.requestSshKeyPassword
|
passwordNotSetCallback: self.requestSshKeyPassword
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -140,12 +140,11 @@ class SettingsTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
Defaults[.lastUpdatedTime] = Date()
|
Defaults[.gitURL] = URL(string: gitRepostiroyURL)
|
||||||
Defaults[.gitRepositoryURL] = URL(string: gitRepostiroyURL)
|
Defaults[.gitUsername] = username
|
||||||
Defaults[.gitRepositoryUsername] = username
|
Defaults[.gitAuthenticationMethod] = auth
|
||||||
Defaults[.gitRepositoryAuthenticationMethod] = auth
|
Defaults[.gitPasswordAttempts] = 0
|
||||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitURL]?.host
|
||||||
self.passwordRepositoryTableViewCell.detailTextLabel?.text = Defaults[.gitRepositoryURL]?.host
|
|
||||||
SVProgressHUD.showSuccess(withStatus: "Done")
|
SVProgressHUD.showSuccess(withStatus: "Done")
|
||||||
SVProgressHUD.dismiss(withDelay: 1)
|
SVProgressHUD.dismiss(withDelay: 1)
|
||||||
}
|
}
|
||||||
|
|
@ -163,7 +162,7 @@ class SettingsTableViewController: UITableViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(SettingsTableViewController.actOnPasswordStoreErasedNotification), name: .passwordStoreErased, object: nil)
|
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
|
touchIDTableViewCell.accessoryView = touchIDSwitch
|
||||||
setPGPKeyTableViewCellDetailText()
|
setPGPKeyTableViewCellDetailText()
|
||||||
setPasswordRepositoryTableViewCellDetailText()
|
setPasswordRepositoryTableViewCellDetailText()
|
||||||
|
|
@ -190,10 +189,10 @@ class SettingsTableViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setPasswordRepositoryTableViewCellDetailText() {
|
private func setPasswordRepositoryTableViewCellDetailText() {
|
||||||
if Defaults[.gitRepositoryURL] == nil {
|
if Defaults[.gitURL] == nil {
|
||||||
passwordRepositoryTableViewCell.detailTextLabel?.text = "Not Set"
|
passwordRepositoryTableViewCell.detailTextLabel?.text = "Not Set"
|
||||||
} else {
|
} 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
|
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||||
textField.text = self.passwordStore.gitRepositoryPassword
|
textField.text = self.passwordStore.gitPassword
|
||||||
textField.isSecureTextEntry = true
|
textField.isSecureTextEntry = true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,14 +17,19 @@ extension DefaultsKeys {
|
||||||
static let pgpPublicKeyArmor = DefaultsKey<String?>("pgpPublicKeyArmor")
|
static let pgpPublicKeyArmor = DefaultsKey<String?>("pgpPublicKeyArmor")
|
||||||
static let pgpPrivateKeyArmor = DefaultsKey<String?>("pgpPrivateKeyArmor")
|
static let pgpPrivateKeyArmor = DefaultsKey<String?>("pgpPrivateKeyArmor")
|
||||||
|
|
||||||
static let gitRepositoryURL = DefaultsKey<URL?>("gitRepositoryURL")
|
static let gitURL = DefaultsKey<URL?>("gitURL")
|
||||||
static let gitRepositoryAuthenticationMethod = DefaultsKey<String?>("gitRepositoryAuthenticationMethod")
|
static let gitAuthenticationMethod = DefaultsKey<String?>("gitAuthenticationMethod")
|
||||||
static let gitRepositoryUsername = DefaultsKey<String?>("gitRepositoryUsername")
|
static let gitUsername = DefaultsKey<String?>("gitUsername")
|
||||||
static let gitRepositoryPasswordAttempts = DefaultsKey<Int>("gitRepositoryPasswordAttempts")
|
static let gitPasswordAttempts = DefaultsKey<Int>("gitPasswordAttempts")
|
||||||
static let gitRepositorySSHPublicKeyURL = DefaultsKey<URL?>("gitRepositorySSHPublicKeyURL")
|
static let gitSSHPublicKeyURL = DefaultsKey<URL?>("gitSSHPublicKeyURL")
|
||||||
static let gitRepositorySSHPrivateKeyURL = DefaultsKey<URL?>("gitRepositorySSHPrivateKeyURL")
|
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 isTouchIDOn = DefaultsKey<Bool>("isTouchIDOn")
|
||||||
static let passcodeKey = DefaultsKey<String?>("passcodeKey")
|
static let passcodeKey = DefaultsKey<String?>("passcodeKey")
|
||||||
|
|
|
||||||
|
|
@ -15,22 +15,25 @@ class Globals {
|
||||||
static let pgpPublicKeyPath = "\(documentPath)/gpg_key.pub"
|
static let pgpPublicKeyPath = "\(documentPath)/gpg_key.pub"
|
||||||
static let pgpPrivateKeyPath = "\(documentPath)/gpg_key"
|
static let pgpPrivateKeyPath = "\(documentPath)/gpg_key"
|
||||||
|
|
||||||
static let sshPublicKeyURL = URL(fileURLWithPath: "\(documentPath)/ssh_key.pub")
|
static let gitSSHPublicKeyPath = "\(documentPath)/ssh_key.pub"
|
||||||
static let sshPrivateKeyURL = URL(fileURLWithPath: "\(documentPath)/ssh_key")
|
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 let repositoryPath = "\(libraryPath)/password-store"
|
||||||
static var passcodeConfiguration = PasscodeLockConfiguration()
|
static var passcodeConfiguration = PasscodeLockConfiguration()
|
||||||
|
|
||||||
static let red = UIColor(red:1.00, green:0.23, blue:0.19, alpha:1.0)
|
static let passwordDefaultLength = ["Random": (min: 6, max: 24, def: 16),
|
||||||
static let blue = UIColor(red:0.00, green:0.48, blue:1.00, alpha:1.0)
|
"Apple": (min: 15, max: 15, def: 15)]
|
||||||
|
|
||||||
static let passwordMinimumLength = 6
|
|
||||||
static let passwordMaximumLength = 24
|
|
||||||
static let passwordDefaultLength = 16
|
|
||||||
|
|
||||||
static let passwordDots = "••••••••••••"
|
static let passwordDots = "••••••••••••"
|
||||||
static let passwordFonts = "Menlo"
|
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() { }
|
private init() { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,14 @@ class Utils {
|
||||||
removeFileIfExists(atPath: url.path)
|
removeFileIfExists(atPath: url.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func getLastUpdatedTimeString() -> String {
|
static func getLastSyncedTimeString() -> String {
|
||||||
var lastUpdatedTimeString = ""
|
guard let lastSyncedTime = Defaults[.lastSyncedTime] else {
|
||||||
if let lastUpdatedTime = Defaults[.lastUpdatedTime] {
|
return "Oops! Sync again?"
|
||||||
let formatter = DateFormatter()
|
|
||||||
formatter.dateStyle = .medium
|
|
||||||
formatter.timeStyle = .short
|
|
||||||
lastUpdatedTimeString = formatter.string(from: lastUpdatedTime)
|
|
||||||
}
|
}
|
||||||
return lastUpdatedTimeString
|
let formatter = DateFormatter()
|
||||||
|
formatter.dateStyle = .medium
|
||||||
|
formatter.timeStyle = .short
|
||||||
|
return formatter.string(from: lastSyncedTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func generatePassword(length: Int) -> String{
|
static func generatePassword(length: Int) -> String{
|
||||||
|
|
@ -84,6 +83,16 @@ class Utils {
|
||||||
Utils.removeKeychain(name: ".pgpKeyPassphrase")
|
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? {
|
static func getPasswordFromKeychain(name: String) -> String? {
|
||||||
let keychain = Keychain(service: "me.mssun.passforios")
|
let keychain = Keychain(service: "me.mssun.passforios")
|
||||||
do {
|
do {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.2.2</string>
|
<string>0.2.3</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ class Password {
|
||||||
var additions = [String: String]()
|
var additions = [String: String]()
|
||||||
var additionKeys = [String]()
|
var additionKeys = [String]()
|
||||||
var changed = false
|
var changed = false
|
||||||
|
var plainText = ""
|
||||||
|
|
||||||
private var plainText = ""
|
|
||||||
private var firstLineIsOTPField = false
|
private var firstLineIsOTPField = false
|
||||||
private var otpToken: Token?
|
private var otpToken: Token?
|
||||||
|
|
||||||
|
|
@ -99,14 +99,17 @@ class Password {
|
||||||
// return a key-value pair from the line
|
// return a key-value pair from the line
|
||||||
// key might be nil, if there is no ":" in the line
|
// key might be nil, if there is no ":" in the line
|
||||||
static private func getKeyValuePair(from line: String) -> (key: String?, value: String) {
|
static private func getKeyValuePair(from line: String) -> (key: String?, value: String) {
|
||||||
let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: true).map(String.init)
|
let items = line.characters.split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false).map{String($0).trimmingCharacters(in: .whitespaces)}
|
||||||
var key : String?
|
var key : String? = nil
|
||||||
var value = ""
|
var value = ""
|
||||||
if items.count == 1 {
|
if items.count == 1 || (items[0].isEmpty && items[1].isEmpty) {
|
||||||
value = items[0]
|
// no ":" found, or empty on both sides of ":" (e.g., " : ")
|
||||||
} else if items.count == 2 {
|
value = line
|
||||||
key = items[0]
|
} else {
|
||||||
value = items[1].trimmingCharacters(in: .whitespaces)
|
if !items[0].isEmpty {
|
||||||
|
key = items[0]
|
||||||
|
}
|
||||||
|
value = items[1]
|
||||||
}
|
}
|
||||||
return (key, value)
|
return (key, value)
|
||||||
}
|
}
|
||||||
|
|
@ -178,6 +181,8 @@ class Password {
|
||||||
|
|
||||||
*/
|
*/
|
||||||
private func updateOtpToken() {
|
private func updateOtpToken() {
|
||||||
|
self.otpToken = nil
|
||||||
|
|
||||||
// get otpauth, if we are able to generate a token, return
|
// get otpauth, if we are able to generate a token, return
|
||||||
if var otpauthString = getAdditionValue(withKey: "otpauth") {
|
if var otpauthString = getAdditionValue(withKey: "otpauth") {
|
||||||
if !otpauthString.hasPrefix("otpauth:") {
|
if !otpauthString.hasPrefix("otpauth:") {
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ struct GitCredential {
|
||||||
var credential: GTCredential? = nil
|
var credential: GTCredential? = nil
|
||||||
switch self.credential {
|
switch self.credential {
|
||||||
case let .http(userName, password):
|
case let .http(userName, password):
|
||||||
print(Defaults[.gitRepositoryPasswordAttempts])
|
print(Defaults[.gitPasswordAttempts])
|
||||||
var newPassword: String = password
|
var newPassword: String = password
|
||||||
if Defaults[.gitRepositoryPasswordAttempts] != 0 {
|
if Defaults[.gitPasswordAttempts] != 0 {
|
||||||
let sem = DispatchSemaphore(value: 0)
|
let sem = DispatchSemaphore(value: 0)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
SVProgressHUD.dismiss()
|
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)
|
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
|
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: {_ in
|
||||||
newPassword = alert.textFields!.first!.text!
|
newPassword = alert.textFields!.first!.text!
|
||||||
PasswordStore.shared.gitRepositoryPassword = newPassword
|
PasswordStore.shared.gitPassword = newPassword
|
||||||
sem.signal()
|
sem.signal()
|
||||||
}))
|
}))
|
||||||
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
|
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { _ in
|
||||||
Defaults[.gitRepositoryPasswordAttempts] = -1
|
Defaults[.gitPasswordAttempts] = -1
|
||||||
sem.signal()
|
sem.signal()
|
||||||
})
|
})
|
||||||
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
alert.addTextField(configurationHandler: {(textField: UITextField!) in
|
||||||
textField.text = PasswordStore.shared.gitRepositoryPassword
|
textField.text = PasswordStore.shared.gitPassword
|
||||||
textField.isSecureTextEntry = true
|
textField.isSecureTextEntry = true
|
||||||
})
|
})
|
||||||
topController.present(alert, animated: true, completion: nil)
|
topController.present(alert, animated: true, completion: nil)
|
||||||
|
|
@ -56,12 +56,12 @@ struct GitCredential {
|
||||||
}
|
}
|
||||||
let _ = sem.wait(timeout: DispatchTime.distantFuture)
|
let _ = sem.wait(timeout: DispatchTime.distantFuture)
|
||||||
}
|
}
|
||||||
if Defaults[.gitRepositoryPasswordAttempts] == -1 {
|
if Defaults[.gitPasswordAttempts] == -1 {
|
||||||
Defaults[.gitRepositoryPasswordAttempts] = 0
|
Defaults[.gitPasswordAttempts] = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
Defaults[.gitRepositoryPasswordAttempts] += 1
|
Defaults[.gitPasswordAttempts] += 1
|
||||||
PasswordStore.shared.gitRepositoryPassword = newPassword
|
PasswordStore.shared.gitPassword = newPassword
|
||||||
credential = try? GTCredential(userName: userName, password: newPassword)
|
credential = try? GTCredential(userName: userName, password: newPassword)
|
||||||
case let .ssh(userName, password, publicKeyFile, privateKeyFile, passwordNotSetCallback):
|
case let .ssh(userName, password, publicKeyFile, privateKeyFile, passwordNotSetCallback):
|
||||||
|
|
||||||
|
|
@ -76,7 +76,7 @@ struct GitCredential {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save password for the future
|
// 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
|
// nil is expected in case of empty password
|
||||||
if newPassword == "" {
|
if newPassword == "" {
|
||||||
|
|
@ -112,7 +112,7 @@ class PasswordStore {
|
||||||
|
|
||||||
var gitSignatureForNow: GTSignature {
|
var gitSignatureForNow: GTSignature {
|
||||||
get {
|
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")
|
return Utils.getPasswordFromKeychain(name: "pgpKeyPassphrase")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var gitRepositoryPassword: String? {
|
var gitPassword: String? {
|
||||||
set {
|
set {
|
||||||
Utils.addPasswordToKeychain(name: "gitRepositoryPassword", password: newValue)
|
Utils.addPasswordToKeychain(name: "gitPassword", password: newValue)
|
||||||
}
|
}
|
||||||
get {
|
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)
|
print(error)
|
||||||
}
|
}
|
||||||
initPGPKeys()
|
initPGPKeys()
|
||||||
if Defaults[.gitRepositoryAuthenticationMethod] == "Password" {
|
initGitCredential()
|
||||||
gitCredential = GitCredential(credential: GitCredential.Credential.http(userName: Defaults[.gitRepositoryUsername]!, password: Utils.getPasswordFromKeychain(name: "gitRepositoryPassword") ?? ""))
|
}
|
||||||
} else if Defaults[.gitRepositoryAuthenticationMethod] == "SSH Key"{
|
|
||||||
|
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(
|
gitCredential = GitCredential(
|
||||||
credential: GitCredential.Credential.ssh(
|
credential: GitCredential.Credential.ssh(
|
||||||
userName: Defaults[.gitRepositoryUsername]!,
|
userName: Defaults[.gitUsername]!,
|
||||||
password: Utils.getPasswordFromKeychain(name: "gitRepositorySSHPrivateKeyPassphrase") ?? "",
|
password: gitSSHPrivateKeyPassphrase ?? "",
|
||||||
publicKeyFile: Globals.sshPublicKeyURL,
|
publicKeyFile: Globals.gitSSHPublicKeyURL,
|
||||||
privateKeyFile: Globals.sshPrivateKeyURL,
|
privateKeyFile: Globals.gitSSHPrivateKeyURL,
|
||||||
passwordNotSetCallback: nil
|
passwordNotSetCallback: nil
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
gitCredential = nil
|
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() {
|
public func initPGPKeys() {
|
||||||
|
|
@ -302,9 +330,11 @@ class PasswordStore {
|
||||||
}
|
}
|
||||||
storeRepository = try GTRepository(url: storeURL)
|
storeRepository = try GTRepository(url: storeURL)
|
||||||
gitCredential = credential
|
gitCredential = credential
|
||||||
self.updatePasswordEntityCoreData()
|
Defaults[.lastSyncedTime] = Date()
|
||||||
|
DispatchQueue.main.async {
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
self.updatePasswordEntityCoreData()
|
||||||
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pullRepository(transferProgressBlock: @escaping (UnsafePointer<git_transfer_progress>, UnsafeMutablePointer<ObjCBool>) -> Void) throws {
|
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!)
|
let remote = try GTRemote(name: "origin", in: storeRepository!)
|
||||||
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
try storeRepository?.pull((storeRepository?.currentBranch())!, from: remote, withOptions: options, progress: transferProgressBlock)
|
||||||
self.setAllSynced()
|
Defaults[.lastSyncedTime] = Date()
|
||||||
self.updatePasswordEntityCoreData()
|
DispatchQueue.main.async {
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
self.setAllSynced()
|
||||||
|
self.updatePasswordEntityCoreData()
|
||||||
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updatePasswordEntityCoreData() {
|
private func updatePasswordEntityCoreData() {
|
||||||
|
|
@ -649,8 +682,8 @@ class PasswordStore {
|
||||||
|
|
||||||
Utils.removeFileIfExists(atPath: Globals.pgpPublicKeyPath)
|
Utils.removeFileIfExists(atPath: Globals.pgpPublicKeyPath)
|
||||||
Utils.removeFileIfExists(atPath: Globals.pgpPrivateKeyPath)
|
Utils.removeFileIfExists(atPath: Globals.pgpPrivateKeyPath)
|
||||||
Utils.removeFileIfExists(at: Globals.sshPrivateKeyURL)
|
Utils.removeFileIfExists(atPath: Globals.gitSSHPublicKeyPath)
|
||||||
Utils.removeFileIfExists(at: Globals.sshPublicKeyURL)
|
Utils.removeFileIfExists(atPath: Globals.gitSSHPrivateKeyPath)
|
||||||
|
|
||||||
Utils.removeAllKeychain()
|
Utils.removeAllKeychain()
|
||||||
|
|
||||||
|
|
@ -678,6 +711,8 @@ class PasswordStore {
|
||||||
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
try self.storeRepository?.reset(to: newHead, resetType: GTRepositoryResetType.hard)
|
||||||
self.setAllSynced()
|
self.setAllSynced()
|
||||||
self.updatePasswordEntityCoreData()
|
self.updatePasswordEntityCoreData()
|
||||||
|
Defaults[.lastSyncedTime] = nil
|
||||||
|
|
||||||
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreUpdated, object: nil)
|
||||||
NotificationCenter.default.post(name: .passwordStoreChangeDiscarded, object: nil)
|
NotificationCenter.default.post(name: .passwordStoreChangeDiscarded, object: nil)
|
||||||
return localCommits.count
|
return localCommits.count
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import UIKit
|
||||||
|
|
||||||
protocol FillPasswordTableViewCellDelegate {
|
protocol FillPasswordTableViewCellDelegate {
|
||||||
func generateAndCopyPassword()
|
func generateAndCopyPassword()
|
||||||
|
func showHidePasswordSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
class FillPasswordTableViewCell: ContentTableViewCell {
|
class FillPasswordTableViewCell: ContentTableViewCell {
|
||||||
|
|
@ -17,10 +18,17 @@ class FillPasswordTableViewCell: ContentTableViewCell {
|
||||||
@IBOutlet weak var contentTextField: UITextField!
|
@IBOutlet weak var contentTextField: UITextField!
|
||||||
var delegate: FillPasswordTableViewCellDelegate?
|
var delegate: FillPasswordTableViewCellDelegate?
|
||||||
|
|
||||||
|
@IBOutlet weak var settingButton: UIButton!
|
||||||
|
@IBOutlet weak var generateButton: UIButton!
|
||||||
|
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
// Initialization code
|
// Initialization code
|
||||||
contentTextField.font = UIFont(name: Globals.passwordFonts, size: (contentTextField.font?.pointSize)!)
|
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) {
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
|
@ -33,6 +41,10 @@ class FillPasswordTableViewCell: ContentTableViewCell {
|
||||||
self.delegate?.generateAndCopyPassword()
|
self.delegate?.generateAndCopyPassword()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func showHidePasswordSettings() {
|
||||||
|
self.delegate?.showHidePasswordSettings()
|
||||||
|
}
|
||||||
|
|
||||||
// re-color
|
// re-color
|
||||||
@IBAction func textFieldDidChange(_ sender: UITextField) {
|
@IBAction func textFieldDidChange(_ sender: UITextField) {
|
||||||
contentTextField.attributedText = Utils.attributedPassword(plainPassword: sender.text ?? "")
|
contentTextField.attributedText = Utils.attributedPassword(plainPassword: sender.text ?? "")
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -16,13 +16,13 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<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">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="password" textAlignment="natural" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="k0U-2N-YaX">
|
<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="15" y="8" width="220" height="74"/>
|
<rect key="frame" x="16" y="8" width="231" height="74"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="qVX-ui-dIn"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="9gX-VT-F9P"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
|
|
@ -31,31 +31,52 @@
|
||||||
<action selector="textFieldDidChange:" destination="KGk-i7-Jjw" eventType="editingChanged" id="U0t-2B-JxY"/>
|
<action selector="textFieldDidChange:" destination="KGk-i7-Jjw" eventType="editingChanged" id="U0t-2B-JxY"/>
|
||||||
</connections>
|
</connections>
|
||||||
</textField>
|
</textField>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" reversesTitleShadowWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hTh-ek-Xam">
|
<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="243" y="-0.5" width="64" height="89.5"/>
|
<rect key="frame" x="275" y="8" width="30" height="73.5"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="64" id="X1A-kc-qJy"/>
|
<constraint firstAttribute="width" constant="30" id="D9D-FC-ANz"/>
|
||||||
</constraints>
|
</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>
|
<connections>
|
||||||
<action selector="generatePassword:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="M61-hs-PCP"/>
|
<action selector="generatePassword:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="M61-hs-PCP"/>
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<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="SZJ-aY-45Y" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="5XP-xZ-YWY"/>
|
||||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="centerY" secondItem="k0U-2N-YaX" secondAttribute="centerY" id="Fls-do-khd"/>
|
<constraint firstAttribute="trailingMargin" secondItem="SZJ-aY-45Y" secondAttribute="trailing" constant="7" id="5bp-bm-9vv"/>
|
||||||
<constraint firstItem="hTh-ek-Xam" firstAttribute="height" secondItem="H2p-sc-9uM" secondAttribute="height" id="Gok-dX-tQ5"/>
|
<constraint firstAttribute="bottomMargin" secondItem="SZJ-aY-45Y" secondAttribute="bottom" id="CMF-1f-MdG"/>
|
||||||
<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="hTh-ek-Xam" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="OjQ-mD-CWV"/>
|
||||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="jKd-Xa-tr5"/>
|
<constraint firstItem="SZJ-aY-45Y" firstAttribute="leading" secondItem="hTh-ek-Xam" secondAttribute="trailing" id="UlR-NB-9So"/>
|
||||||
<constraint firstItem="k0U-2N-YaX" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="7" id="lAm-D6-pir"/>
|
<constraint firstAttribute="bottomMargin" secondItem="hTh-ek-Xam" secondAttribute="bottom" id="bvu-Q0-QAG"/>
|
||||||
<constraint firstAttribute="bottomMargin" secondItem="k0U-2N-YaX" secondAttribute="bottom" constant="-1" id="pLC-H7-JTU" userLabel="bottomMargin = Content Text Field.bottom"/>
|
<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>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="contentTextField" destination="k0U-2N-YaX" id="kQO-tR-Epp"/>
|
<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>
|
</connections>
|
||||||
<point key="canvasLocation" x="34" y="77"/>
|
<point key="canvasLocation" x="34" y="77"/>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</objects>
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="HorizontalSettings" width="25" height="25"/>
|
||||||
|
<image name="Refresh" width="32" height="32"/>
|
||||||
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@ class LabelTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
weak var delegatePasswordTableView : PasswordDetailTableViewController?
|
weak var delegatePasswordTableView : PasswordDetailTableViewController?
|
||||||
|
|
||||||
|
var passwordDisplayButton: UIButton?
|
||||||
|
var buttons: UIView?
|
||||||
|
|
||||||
var cellData: LabelTableViewCellData? {
|
var cellData: LabelTableViewCellData? {
|
||||||
didSet {
|
didSet {
|
||||||
titleLabel.text = cellData?.title ?? ""
|
titleLabel.text = cellData?.title ?? ""
|
||||||
|
|
@ -43,9 +46,11 @@ class LabelTableViewCell: UITableViewCell {
|
||||||
} else {
|
} else {
|
||||||
contentLabel.text = Globals.passwordDots
|
contentLabel.text = Globals.passwordDots
|
||||||
}
|
}
|
||||||
|
contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize)
|
||||||
} else {
|
} else {
|
||||||
contentLabel.text = cellData?.content
|
contentLabel.text = cellData?.content
|
||||||
}
|
}
|
||||||
|
updateButtons()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,6 +63,13 @@ class LabelTableViewCell: UITableViewCell {
|
||||||
override func awakeFromNib() {
|
override func awakeFromNib() {
|
||||||
super.awakeFromNib()
|
super.awakeFromNib()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
if buttons != nil {
|
||||||
|
self.accessoryView = buttons
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
super.setSelected(selected, animated: animated)
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
@ -99,13 +111,26 @@ class LabelTableViewCell: UITableViewCell {
|
||||||
contentLabel.text = ""
|
contentLabel.text = ""
|
||||||
}
|
}
|
||||||
isReveal = true
|
isReveal = true
|
||||||
|
passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Invisible"), for: .normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
func concealPassword(_ sender: Any?) {
|
func concealPassword(_ sender: Any?) {
|
||||||
contentLabel.text = Globals.passwordDots
|
contentLabel.text = Globals.passwordDots
|
||||||
isReveal = false
|
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?) {
|
func openLink(_ sender: Any?) {
|
||||||
// if isURLCell, passwordTableView should not be nil
|
// if isURLCell, passwordTableView should not be nil
|
||||||
delegatePasswordTableView!.openLink()
|
delegatePasswordTableView!.openLink()
|
||||||
|
|
@ -115,4 +140,50 @@ class LabelTableViewCell: UITableViewCell {
|
||||||
// if isHOTPCell, passwordTableView should not be nil
|
// if isHOTPCell, passwordTableView should not be nil
|
||||||
delegatePasswordTableView!.getNextHOTP()
|
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"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -16,17 +16,20 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="333" height="52"/>
|
<rect key="frame" x="0.0" y="0.0" width="333" height="52"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<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">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</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">
|
<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"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||||
<color key="textColor" red="0.0" green="0.47843137254901957" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.47843137254901957" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
|
|
@ -34,7 +37,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="trailingMargin" secondItem="Dqz-7n-uEZ" secondAttribute="trailing" id="228-VM-Z8Y"/>
|
<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 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="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"/>
|
<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"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.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"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="84"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
<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">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalCompressionResistancePriority="250" verticalCompressionResistancePriority="250" placeholderIntrinsicWidth="52" placeholderIntrinsicHeight="52" translatesAutoresizingMaskIntoConstraints="NO" id="gKV-Cd-wIk">
|
<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.maximumValue = Float(maximumValue)
|
||||||
slider.value = Float(defaultValue)
|
slider.value = Float(defaultValue)
|
||||||
valueLabel.text = String(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"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.5" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="MwT-Jl-hhE">
|
<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>
|
<connections>
|
||||||
<action selector="handleSliderValueChange:" destination="KGk-i7-Jjw" eventType="valueChanged" id="WwM-ZE-yIB"/>
|
<action selector="handleSliderValueChange:" destination="KGk-i7-Jjw" eventType="valueChanged" id="WwM-ZE-yIB"/>
|
||||||
</connections>
|
</connections>
|
||||||
|
|
@ -34,8 +34,8 @@
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</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">
|
<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="15" y="8" width="30" height="57.5"/>
|
<rect key="frame" x="16" y="8" width="30" height="57.5"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="8Tz-Qo-Mkg"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="8Tz-Qo-Mkg"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
|
@ -46,7 +46,7 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="MwT-Jl-hhE" firstAttribute="leading" secondItem="t7T-HC-hUd" secondAttribute="trailing" constant="17" id="Cc9-kV-nZf"/>
|
<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 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 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"/>
|
<constraint firstAttribute="bottomMargin" secondItem="GJP-Fj-VZt" secondAttribute="bottom" id="NmC-sS-9Yt"/>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -16,11 +16,11 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<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">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
|
<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>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="R1z-fU-Xr2"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="38" id="R1z-fU-Xr2"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
</textField>
|
</textField>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<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 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="trailingMargin" secondItem="8Ky-UZ-sLu" secondAttribute="trailing" id="Nii-Cg-gC1"/>
|
||||||
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" id="h72-l3-Sb3"/>
|
<constraint firstAttribute="bottomMargin" secondItem="8Ky-UZ-sLu" secondAttribute="bottom" id="h72-l3-Sb3"/>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xHX-Sh-1pR">
|
<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"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="120" id="Tvq-j8-Nvh"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="120" id="Tvq-j8-Nvh"/>
|
||||||
|
|
@ -31,9 +31,9 @@
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="trailingMargin" secondItem="xHX-Sh-1pR" secondAttribute="trailing" id="LWS-JW-9dS"/>
|
<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 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="7" id="UPQ-jk-QJR"/>
|
<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="7" id="gwb-2C-4wp"/>
|
<constraint firstItem="xHX-Sh-1pR" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="8" id="gwb-2C-4wp"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<connections>
|
<connections>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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">
|
<device id="retina4_7" orientation="portrait">
|
||||||
<adaptation id="fullscreen"/>
|
<adaptation id="fullscreen"/>
|
||||||
</device>
|
</device>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<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="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
@ -16,17 +16,20 @@
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="56"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<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">
|
<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"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<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">
|
<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"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||||
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="textColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8Ky-UZ-sLu">
|
<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="15" y="26" width="297" height="21"/>
|
<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"/>
|
<nil key="textColor"/>
|
||||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||||
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" returnKeyType="next"/>
|
<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 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="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="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 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="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="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>
|
</constraints>
|
||||||
</tableViewCellContentView>
|
</tableViewCellContentView>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="contentTextField" destination="8Ky-UZ-sLu" id="unz-5T-fuK"/>
|
<outlet property="contentTextField" destination="8Ky-UZ-sLu" id="unz-5T-fuK"/>
|
||||||
<outlet property="titleLabel" destination="HPC-rQ-39b" id="VoV-gT-5lh"/>
|
<outlet property="titleLabel" destination="HPC-rQ-39b" id="VoV-gT-5lh"/>
|
||||||
</connections>
|
</connections>
|
||||||
<point key="canvasLocation" x="34" y="60"/>
|
<point key="canvasLocation" x="0.0" y="61"/>
|
||||||
</tableViewCell>
|
</tableViewCell>
|
||||||
</objects>
|
</objects>
|
||||||
</document>
|
</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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||