Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-3406, GH-3427 update libs #3426

Merged
merged 3 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Multisig.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7506,7 +7506,7 @@
repositoryURL = "https://github.com/KeystoneHQ/ur-registry-ios";
requirement = {
kind = exactVersion;
version = 1.0.0;
version = 1.1.0;
};
};
0A259AB3287D83F9006770E7 /* XCRemoteSwiftPackageReference "resolution-swift" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,8 @@
"repositoryURL": "https://github.com/KeystoneHQ/ur-registry-ios",
"state": {
"branch": null,
"revision": "10511be95146e8dfa2063e3ea21cceb9e6536fa1",
"version": "1.0.0"
"revision": "cafed3d8d3f73417c148d4a0b00046a45ef1ed30",
"version": "1.1.0"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CreateExportPasswordViewController: UIViewController {
var prompt: String = ""
var placeholder: String = ""
var plainTextPassword: String?
var passwordMeterEnabled: Bool = false
var completion: (String) -> Void = { _ in }
var validateValue: (String) -> Error? = { _ in nil }

Expand All @@ -22,7 +23,8 @@ class CreateExportPasswordViewController: UIViewController {
@IBOutlet weak var continueButton: UIButton!
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var buttonBottomConstraint: NSLayoutConstraint!

@IBOutlet weak var passwordMeter: UIProgressView!

private var debounceTimer: Timer!
private let debounceDuration: TimeInterval = 0.250
private var isValid: Bool = false
Expand Down Expand Up @@ -50,6 +52,8 @@ class CreateExportPasswordViewController: UIViewController {
descriptionLabel.setStyle(.body)

continueButton.setText("Continue", .filled)

passwordMeter.isHidden = !passwordMeterEnabled

validateText()

Expand Down Expand Up @@ -107,15 +111,39 @@ class CreateExportPasswordViewController: UIViewController {
}
}

private func validateText() {
func passwordScore(_ text: String) -> Double {
// We define score P as:
// P[ L >= 8 ] = 8 * L * (1 + 0.1 * N + 0.1 * S + 0.1 * C)
// P[ L < 8 ] = 8 * L
// where L = length of the password text string
// N = 1 if password contains numbers, 0 otherwise
// S = 1 if password contains symbols, 0 otherwise
// C = 1 if password contains capital letters, 0 otherwise
// Maximum P value equals 100, i.e.:
// P = min(P, 100)
let L = Double(text.count)
let N = text.rangeOfCharacter(from: .decimalDigits) == nil ? 0 : 1.0
let S = text.rangeOfCharacter(from: .symbols) == nil ? 0 : 1.0
let C = text.rangeOfCharacter(from: .capitalizedLetters) == nil ? 0 : 1.0
let P = min(100, (L < 8) ? (8 * L) : (8 * L * (1 + 0.1 * N + 0.1 * S + 0.1 * C)) )
return P
}

fileprivate func resetText() {
isValid = false
continueButton.isEnabled = false
textField.setError(nil)
passwordMeter.progress = 0
}

private func validateText() {
resetText()
guard let text = textField.textField.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!text.isEmpty else {
self.plainTextPassword = nil
return
}
passwordMeter.progress = Float(passwordScore(text) / 100)
if let error = validateValue(text) {
textField.setError(error)
return
Expand All @@ -135,6 +163,11 @@ extension CreateExportPasswordViewController: UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
keyboardBehavior.activeTextField = textField
}

func textFieldShouldClear(_ textField: UITextField) -> Bool {
self.resetText()
return true
}

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
debounceTimer?.invalidate()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<outlet property="buttonBottomConstraint" destination="BLR-Ri-2c1" id="4Mc-DW-AHm"/>
<outlet property="continueButton" destination="gXy-yX-Ihv" id="syz-ft-J4k"/>
<outlet property="descriptionLabel" destination="qCR-Ls-3Sv" id="jfH-3z-Fne"/>
<outlet property="passwordMeter" destination="gcV-dU-WLK" id="r9h-fI-pzf"/>
<outlet property="scrollView" destination="HvJ-08-RJo" id="Tzi-uc-zzt"/>
<outlet property="textField" destination="YAC-g2-UKn" id="96R-Fu-Bt2"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
Expand All @@ -32,10 +33,10 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="814"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="1Gx-rA-E0l">
<rect key="frame" x="16" y="16" width="382" height="105"/>
<rect key="frame" x="16" y="16" width="382" height="117"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="LsW-zt-ujG">
<rect key="frame" x="0.0" y="0.0" width="382" height="105"/>
<rect key="frame" x="0.0" y="0.0" width="382" height="117"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Choose a password for protecting the exported data." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qCR-Ls-3Sv">
<rect key="frame" x="0.0" y="0.0" width="382" height="41"/>
Expand All @@ -50,6 +51,9 @@
<constraint firstAttribute="height" constant="56" placeholder="YES" id="OVz-U6-IPi"/>
</constraints>
</view>
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="gcV-dU-WLK">
<rect key="frame" x="0.0" y="113" width="382" height="4"/>
</progressView>
</subviews>
<constraints>
<constraint firstItem="YAC-g2-UKn" firstAttribute="width" secondItem="LsW-zt-ujG" secondAttribute="width" id="Zri-CE-aSn"/>
Expand Down
14 changes: 11 additions & 3 deletions Multisig/Features/Data Export/ExportDataFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ExportDataFlow: UIFlow {
vc.steps = [
.header,
.step(number: "1", title: "Create a file password", description: "Enter a strong password for locking the export file."),
.step(number: "2", title: "Export the data", description: "Data includes the owner keys, safes and address book in an encrypted file format."),
.step(number: "2", title: "Export the data", description: "Data includes private keys, safes and address book in an encrypted file format."),
.step(number: "3", title: "Save the data file", description: "Store the export file in Files on your device or a secure location of your choice."),
.finalStep(title: "Export of data completed!")
]
Expand All @@ -43,8 +43,16 @@ class ExportDataFlow: UIFlow {
func createPassword() {
let vc = CreateExportPasswordViewController(nibName: nil, bundle: nil)
vc.title = "Create password"
vc.prompt = "Choose a password for protecting the exported data."
vc.prompt = "Your password protects the data, including private keys.\n• At least 8 characters long.\n• Use numbers, symbols, and capital letters.\n• Use a password manager like 1Password or iCloud Keychain."
vc.placeholder = "Enter password"
vc.passwordMeterEnabled = true
vc.validateValue = { [unowned vc] value in
let score = vc.passwordScore(value)
if score < 64 {
return "Password must be at least 8 characters long."
}
return nil
}
vc.completion = { [unowned self] plainTextPassword in
repeatPassword(plainTextPassword)
}
Expand Down Expand Up @@ -81,7 +89,7 @@ class ExportDataFlow: UIFlow {
if let url = tempFileURL {
let vc = SuccessViewController(
titleText: "Export completed",
bodyText: "Exported data is encrypted and includes owner keys, list of safes and address book",
bodyText: "Exported data is encrypted and includes private keys, list of safes and address book.\n\nSave it to Files - On My iPhone.",
primaryAction: "Save",
secondaryAction: "Done"
)
Expand Down
2 changes: 1 addition & 1 deletion Multisig/Features/Data Export/ImportDataFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ImportDataFlow: UIFlow {
.step(number: "2", title: "Enter file password",
description: "Enter the password to access the data from the file"),
.step(number: "3", title: "Import the data",
description: "The imported data includes owner keys, safes and address book. Duplicates will be skipped."),
description: "The imported data includes private keys, safes and address book. Duplicates will be skipped."),
.finalStep(title: "Import of data completed!")
]

Expand Down
Loading