diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index fd0fae770..ee0bcd6a2 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2709,9 +2709,7 @@ B80C6B562384A56D00FDBC8B /* DeviceLinksVC.swift */, B80C6B582384C4E700FDBC8B /* DeviceNameModal.swift */, B80C6B5A2384C7F900FDBC8B /* DeviceNameModalDelegate.swift */, - B894D0742339EDCF00B4D94D /* NukeDataModal.swift */, B86BD08023399883000F5AE3 /* QRCodeModal.swift */, - B86BD08523399CEF000F5AE3 /* SeedModal.swift */, ); path = Settings; sourceTree = ""; @@ -2729,7 +2727,6 @@ isa = PBXGroup; children = ( B84664F4235022F30083A1CD /* MentionUtilities.swift */, - B86BD08323399ACF000F5AE3 /* Modal.swift */, ); path = Utilities; sourceTree = ""; @@ -2782,8 +2779,11 @@ children = ( B8B5BCEB2394D869003823C9 /* Button.swift */, B8BB82AA238F669C00BA5194 /* ConversationCell.swift */, + B86BD08323399ACF000F5AE3 /* Modal.swift */, + B894D0742339EDCF00B4D94D /* NukeDataModal.swift */, B8BB82AC238F734800BA5194 /* ProfilePictureView.swift */, B8BB82B02390C37000BA5194 /* SearchBar.swift */, + B86BD08523399CEF000F5AE3 /* SeedModal.swift */, B8BB82B82394911B00BA5194 /* Separator.swift */, B8CCF638239721E20091D419 /* TabBar.swift */, B8BB82B423947F2D00BA5194 /* TextField.swift */, diff --git a/Signal/src/Loki/Redesign/Components/Modal.swift b/Signal/src/Loki/Redesign/Components/Modal.swift new file mode 100644 index 000000000..366118eab --- /dev/null +++ b/Signal/src/Loki/Redesign/Components/Modal.swift @@ -0,0 +1,79 @@ + +@objc(LKModal) +internal class Modal : UIViewController { + private(set) var verticalCenteringConstraint: NSLayoutConstraint! + + // MARK: Settings + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } + + // MARK: Components + lazy var contentView: UIView = { + let result = UIView() + result.backgroundColor = Colors.modalBackground + result.layer.cornerRadius = Values.modalCornerRadius + result.layer.masksToBounds = false + result.layer.borderColor = Colors.modalBorder.cgColor + result.layer.borderWidth = Values.borderThickness + result.layer.shadowColor = UIColor.black.cgColor + result.layer.shadowRadius = 8 + result.layer.shadowOpacity = 0.64 + return result + }() + + lazy var cancelButton: UIButton = { + let result = UIButton() + result.set(.height, to: Values.mediumButtonHeight) + result.layer.cornerRadius = Values.modalButtonCornerRadius + result.backgroundColor = Colors.buttonBackground + result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize) + result.setTitleColor(Colors.text, for: UIControl.State.normal) + result.setTitle(NSLocalizedString("Cancel", comment: ""), for: UIControl.State.normal) + return result + }() + + // MARK: Lifecycle + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = UIColor(hex: 0x000000).withAlphaComponent(Values.modalBackgroundOpacity) + cancelButton.addTarget(self, action: #selector(cancel), for: UIControl.Event.touchUpInside) + setUpViewHierarchy() + } + + private func setUpViewHierarchy() { + view.addSubview(contentView) + contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Values.veryLargeSpacing).isActive = true + view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: Values.veryLargeSpacing).isActive = true + verticalCenteringConstraint = contentView.center(.vertical, in: view) + populateContentView() + } + + /// To be overridden by subclasses. + func populateContentView() { + preconditionFailure("populateContentView() is abstract and must be overridden.") + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + verticalCenteringConstraint.constant = contentView.height() / 2 + view.height() / 2 + view.layoutIfNeeded() + verticalCenteringConstraint.constant = 0 + UIView.animate(withDuration: 0.25) { + self.view.layoutIfNeeded() + } + } + + // MARK: Interaction + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + let touch = touches.first! + let location = touch.location(in: view) + if contentView.frame.contains(location) { + super.touchesBegan(touches, with: event) + } else { + cancel() + } + } + + @objc func cancel() { + dismiss(animated: true, completion: nil) + } +} diff --git a/Signal/src/Loki/Redesign/Components/NukeDataModal.swift b/Signal/src/Loki/Redesign/Components/NukeDataModal.swift new file mode 100644 index 000000000..9df32dbf6 --- /dev/null +++ b/Signal/src/Loki/Redesign/Components/NukeDataModal.swift @@ -0,0 +1,53 @@ + +@objc(LKNukeDataModal) +final class NukeDataModal : Modal { + + // MARK: Lifecycle + override func populateContentView() { + // Set up title label + let titleLabel = UILabel() + titleLabel.textColor = Colors.text + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) + titleLabel.text = NSLocalizedString("Clear All Data", comment: "") + titleLabel.numberOfLines = 0 + titleLabel.lineBreakMode = .byWordWrapping + titleLabel.textAlignment = .center + // Set up explanation label + let explanationLabel = UILabel() + explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity) + explanationLabel.font = .systemFont(ofSize: Values.smallFontSize) + explanationLabel.text = NSLocalizedString("This will delete your entire account, including all data, any messages currently linked to your public key, as well as your personal key pair.", comment: "") + explanationLabel.numberOfLines = 0 + explanationLabel.textAlignment = .center + explanationLabel.lineBreakMode = .byWordWrapping + // Set up nuke data button + let nukeDataButton = UIButton() + nukeDataButton.set(.height, to: Values.mediumButtonHeight) + nukeDataButton.layer.cornerRadius = Values.modalButtonCornerRadius + nukeDataButton.backgroundColor = Colors.destructive + nukeDataButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize) + nukeDataButton.setTitleColor(Colors.text, for: UIControl.State.normal) + nukeDataButton.setTitle(NSLocalizedString("Delete", comment: ""), for: UIControl.State.normal) + nukeDataButton.addTarget(self, action: #selector(nuke), for: UIControl.Event.touchUpInside) + // Set up button stack view + let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, nukeDataButton ]) + buttonStackView.axis = .horizontal + buttonStackView.spacing = Values.mediumSpacing + buttonStackView.distribution = .fillEqually + // Set up stack view + let stackView = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, buttonStackView ]) + stackView.axis = .vertical + stackView.spacing = Values.largeSpacing + contentView.addSubview(stackView) + stackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) + stackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) + contentView.pin(.trailing, to: .trailing, of: stackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.largeSpacing) + } + + // MARK: Interaction + @objc private func nuke() { + UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later + NotificationCenter.default.post(name: .dataNukeRequested, object: nil) + } +} diff --git a/Signal/src/Loki/Redesign/Components/SeedModal.swift b/Signal/src/Loki/Redesign/Components/SeedModal.swift new file mode 100644 index 000000000..9a6c5d9ea --- /dev/null +++ b/Signal/src/Loki/Redesign/Components/SeedModal.swift @@ -0,0 +1,71 @@ + +@objc(LKSeedModal) +final class SeedModal : Modal { + + private let mnemonic: String = { + let identityManager = OWSIdentityManager.shared() + let databaseConnection = identityManager.value(forKey: "dbConnection") as! YapDatabaseConnection + var hexEncodedSeed: String! = databaseConnection.object(forKey: "LKLokiSeed", inCollection: OWSPrimaryStorageIdentityKeyStoreCollection) as! String? + if hexEncodedSeed == nil { + hexEncodedSeed = identityManager.identityKeyPair()!.hexEncodedPrivateKey // Legacy account + } + return Mnemonic.encode(hexEncodedString: hexEncodedSeed) + }() + + // MARK: Lifecycle + override func populateContentView() { + // Set up title label + let titleLabel = UILabel() + titleLabel.textColor = Colors.text + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) + titleLabel.text = NSLocalizedString("Your Seed", comment: "") + titleLabel.numberOfLines = 0 + titleLabel.lineBreakMode = .byWordWrapping + titleLabel.textAlignment = .center + // Set up mnemonic label + let mnemonicLabel = UILabel() + mnemonicLabel.textColor = Colors.text + mnemonicLabel.font = .systemFont(ofSize: Values.smallFontSize) + mnemonicLabel.text = mnemonic + mnemonicLabel.numberOfLines = 0 + mnemonicLabel.lineBreakMode = .byWordWrapping + mnemonicLabel.textAlignment = .center + // Set up explanation label + let explanationLabel = UILabel() + explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity) + explanationLabel.font = .systemFont(ofSize: Values.smallFontSize) + explanationLabel.text = NSLocalizedString("This is your personal password. It can be used to restore your account or migrate your account to a new device.", comment: "") + explanationLabel.numberOfLines = 0 + explanationLabel.lineBreakMode = .byWordWrapping + explanationLabel.textAlignment = .center + // Set up copy button + let copyButton = UIButton() + copyButton.set(.height, to: Values.mediumButtonHeight) + copyButton.layer.cornerRadius = Values.modalButtonCornerRadius + copyButton.backgroundColor = Colors.buttonBackground + copyButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize) + copyButton.setTitleColor(Colors.text, for: UIControl.State.normal) + copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal) + copyButton.addTarget(self, action: #selector(copySeed), for: UIControl.Event.touchUpInside) + // Set up button stack view + let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, copyButton ]) + buttonStackView.axis = .horizontal + buttonStackView.spacing = Values.mediumSpacing + buttonStackView.distribution = .fillEqually + // Set up stack view + let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabel, explanationLabel, buttonStackView ]) + stackView.axis = .vertical + stackView.spacing = Values.largeSpacing + contentView.addSubview(stackView) + stackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) + stackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) + contentView.pin(.trailing, to: .trailing, of: stackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.largeSpacing) + } + + // MARK: Interaction + @objc private func copySeed() { + UIPasteboard.general.string = mnemonic + dismiss(animated: true, completion: nil) + } +} diff --git a/Signal/src/Loki/Redesign/Style Guide/Colors.swift b/Signal/src/Loki/Redesign/Style Guide/Colors.swift index 506df0a2e..e69ec92d6 100644 --- a/Signal/src/Loki/Redesign/Style Guide/Colors.swift +++ b/Signal/src/Loki/Redesign/Style Guide/Colors.swift @@ -25,6 +25,8 @@ final class Colors : NSObject { @objc static let newConversationButtonShadow = UIColor(hex: 0x077C44) @objc static let separator = UIColor(hex: 0x36383C) @objc static let unimportantButtonBackground = UIColor(hex: 0x323232) - @objc static let settingButtonBackground = UIColor(hex: 0x1B1B1B) + @objc static let buttonBackground = UIColor(hex: 0x1B1B1B) @objc static let settingButtonSelected = UIColor(hex: 0x0C0C0C) + @objc static let modalBackground = UIColor(hex: 0x101011) + @objc static let modalBorder = UIColor(hex: 0x212121) } diff --git a/Signal/src/Loki/Redesign/Style Guide/Values.swift b/Signal/src/Loki/Redesign/Style Guide/Values.swift index 409c1962f..f3a048f5d 100644 --- a/Signal/src/Loki/Redesign/Style Guide/Values.swift +++ b/Signal/src/Loki/Redesign/Style Guide/Values.swift @@ -6,6 +6,7 @@ final class Values : NSObject { @objc static let unimportantElementOpacity = CGFloat(0.6) @objc static let conversationCellTimestampOpacity = CGFloat(0.4) @objc static let textFieldBorderOpacity = CGFloat(0.4) + @objc static let modalBackgroundOpacity = CGFloat(0.75) // MARK: - Font Sizes @objc static let smallFontSize = CGFloat(13) @@ -32,6 +33,8 @@ final class Values : NSObject { @objc static var separatorThickness: CGFloat { return 1 / UIScreen.main.scale } @objc static let tabBarHeight = CGFloat(48) @objc static let settingsButtonHeight = CGFloat(75) + @objc static let modalCornerRadius = CGFloat(10) + @objc static let modalButtonCornerRadius = CGFloat(5) // MARK: - Distances @objc static let smallSpacing = CGFloat(8) diff --git a/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift b/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift index dbc0943dd..f6863084f 100644 --- a/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift +++ b/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift @@ -137,7 +137,7 @@ final class SettingsVC : UIViewController { UIGraphicsEndImageContext() return image! } - button.setBackgroundImage(getImage(withColor: Colors.settingButtonBackground), for: UIControl.State.normal) + button.setBackgroundImage(getImage(withColor: Colors.buttonBackground), for: UIControl.State.normal) button.setBackgroundImage(getImage(withColor: Colors.settingButtonSelected), for: UIControl.State.highlighted) button.addTarget(self, action: selector, for: UIControl.Event.touchUpInside) button.set(.height, to: Values.settingsButtonHeight) @@ -209,12 +209,14 @@ final class SettingsVC : UIViewController { @objc private func showSeed() { let seedModal = SeedModal() seedModal.modalPresentationStyle = .overFullScreen + seedModal.modalTransitionStyle = .crossDissolve present(seedModal, animated: true, completion: nil) } @objc private func clearAllData() { let nukeDataModal = NukeDataModal() nukeDataModal.modalPresentationStyle = .overFullScreen + nukeDataModal.modalTransitionStyle = .crossDissolve present(nukeDataModal, animated: true, completion: nil) } } diff --git a/Signal/src/Loki/Settings/DeviceLinkingModal.swift b/Signal/src/Loki/Settings/DeviceLinkingModal.swift index 7ce3674e4..f2d11f126 100644 --- a/Signal/src/Loki/Settings/DeviceLinkingModal.swift +++ b/Signal/src/Loki/Settings/DeviceLinkingModal.swift @@ -137,7 +137,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate { let hexEncodedPublicKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() mnemonicLabel.text = Mnemonic.hash(hexEncodedString: hexEncodedPublicKey) } - let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 + let buttonHeight = cancelButton.titleLabel!.font.pointSize * 48 / 17 authorizeButton.set(.height, to: buttonHeight) cancelButton.set(.height, to: buttonHeight) authorizeButton.isHidden = true diff --git a/Signal/src/Loki/Settings/DeviceNameModal.swift b/Signal/src/Loki/Settings/DeviceNameModal.swift index d3dcf32af..cd2d76fd4 100644 --- a/Signal/src/Loki/Settings/DeviceNameModal.swift +++ b/Signal/src/Loki/Settings/DeviceNameModal.swift @@ -47,7 +47,7 @@ final class DeviceNameModal : Modal { let buttonStackView = UIStackView(arrangedSubviews: [ okButton, cancelButton ]) buttonStackView.axis = .horizontal buttonStackView.distribution = .fillEqually - let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 + let buttonHeight = cancelButton.titleLabel!.font.pointSize * 48 / 17 okButton.set(.height, to: buttonHeight) cancelButton.set(.height, to: buttonHeight) // Stack view diff --git a/Signal/src/Loki/Settings/NukeDataModal.swift b/Signal/src/Loki/Settings/NukeDataModal.swift deleted file mode 100644 index 1b59f4e5b..000000000 --- a/Signal/src/Loki/Settings/NukeDataModal.swift +++ /dev/null @@ -1,54 +0,0 @@ - -@objc(LKNukeDataModal) -final class NukeDataModal : Modal { - - // MARK: Lifecycle - override func viewDidLoad() { - super.viewDidLoad() - Analytics.shared.track("Nuke Data Modal Shown") - } - - override func populateContentView() { - // Label - let titleLabel = UILabel() - titleLabel.textColor = Theme.primaryColor - titleLabel.font = UIFont.ows_dynamicTypeHeadlineClamped - titleLabel.text = NSLocalizedString("Clear All Data", comment: "") - titleLabel.numberOfLines = 0 - titleLabel.lineBreakMode = .byWordWrapping - titleLabel.textAlignment = .center - // Explanation label - let explanationLabel = UILabel() - explanationLabel.font = UIFont.ows_dynamicTypeCaption1Clamped - explanationLabel.text = NSLocalizedString("Are you sure you want to clear all your data? This will delete your entire account, including all conversations and your personal key pair.", comment: "") - explanationLabel.numberOfLines = 0 - explanationLabel.textAlignment = .center - explanationLabel.lineBreakMode = .byWordWrapping - explanationLabel.textColor = UIColor.ows_white - // Button stack view - let nukeButton = OWSFlatButton.button(title: NSLocalizedString("OK", comment: ""), font: .ows_dynamicTypeBodyClamped, titleColor: .white, backgroundColor: .clear, target: self, selector: #selector(nuke)) - nukeButton.setBackgroundColors(upColor: .clear, downColor: .clear) - let buttonStackView = UIStackView(arrangedSubviews: [ nukeButton, cancelButton ]) - buttonStackView.axis = .horizontal - buttonStackView.distribution = .fillEqually - let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 - nukeButton.set(.height, to: buttonHeight) - cancelButton.set(.height, to: buttonHeight) - // Stack view - let stackView = UIStackView(arrangedSubviews: [ UIView.spacer(withHeight: 2), titleLabel, explanationLabel, buttonStackView ]) - stackView.axis = .vertical - stackView.spacing = 16 - contentView.addSubview(stackView) - stackView.pin(.leading, to: .leading, of: contentView, withInset: 16) - stackView.pin(.top, to: .top, of: contentView, withInset: 16) - contentView.pin(.trailing, to: .trailing, of: stackView, withInset: 16) - contentView.pin(.bottom, to: .bottom, of: stackView, withInset: 16) - } - - // MARK: Interaction - @objc private func nuke() { - Analytics.shared.track("Data Nuked") - UserDefaults.removeAll() // Not done in the nuke data implementation as unlinking requires this to happen later - NotificationCenter.default.post(name: .dataNukeRequested, object: nil) - } -} diff --git a/Signal/src/Loki/Settings/QRCodeModal.swift b/Signal/src/Loki/Settings/QRCodeModal.swift index 653a96794..ba2c293d2 100644 --- a/Signal/src/Loki/Settings/QRCodeModal.swift +++ b/Signal/src/Loki/Settings/QRCodeModal.swift @@ -27,7 +27,7 @@ final class QRCodeModal : Modal { let qrCode = UIImage(ciImage: scaledQRCodeAsCIImage) imageView.image = qrCode // Cancel button - let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 + let buttonHeight = cancelButton.titleLabel!.font.pointSize * 48 / 17 cancelButton.set(.height, to: buttonHeight) // Stack view let stackView = UIStackView(arrangedSubviews: [ UIView.spacer(withHeight: 2), label, UIView.spacer(withHeight: 2), imageView, cancelButton ]) diff --git a/Signal/src/Loki/Settings/SeedModal.swift b/Signal/src/Loki/Settings/SeedModal.swift deleted file mode 100644 index 71d17b6f6..000000000 --- a/Signal/src/Loki/Settings/SeedModal.swift +++ /dev/null @@ -1,73 +0,0 @@ - -@objc(LKSeedModal) -final class SeedModal : Modal { - - private let mnemonic: String = { - let identityManager = OWSIdentityManager.shared() - let databaseConnection = identityManager.value(forKey: "dbConnection") as! YapDatabaseConnection - var hexEncodedSeed: String! = databaseConnection.object(forKey: "LKLokiSeed", inCollection: OWSPrimaryStorageIdentityKeyStoreCollection) as! String? - if hexEncodedSeed == nil { - hexEncodedSeed = identityManager.identityKeyPair()!.hexEncodedPrivateKey // Legacy account - } - return Mnemonic.encode(hexEncodedString: hexEncodedSeed) - }() - - // MARK: Lifecycle - override func viewDidLoad() { - super.viewDidLoad() - Analytics.shared.track("Seed Modal Shown") - } - - override func populateContentView() { - // Label - let titleLabel = UILabel() - titleLabel.textColor = Theme.primaryColor - titleLabel.font = UIFont.ows_dynamicTypeHeadlineClamped - titleLabel.text = NSLocalizedString("Your Seed", comment: "") - titleLabel.numberOfLines = 0 - titleLabel.lineBreakMode = .byWordWrapping - titleLabel.textAlignment = .center - // Subtitle label - let subtitleLabel = UILabel() - subtitleLabel.textColor = Theme.primaryColor - subtitleLabel.font = UIFont.ows_dynamicTypeCaption1Clamped - subtitleLabel.text = NSLocalizedString("This is your personal secret. It can be used to restore your account if you lose access, or to migrate your account to a new device.", comment: "") - subtitleLabel.numberOfLines = 0 - subtitleLabel.lineBreakMode = .byWordWrapping - subtitleLabel.textAlignment = .center - // Mnemonic label - let mnemonicLabel = UILabel() - let font = UIFont.ows_dynamicTypeCaption1Clamped - mnemonicLabel.font = UIFont(descriptor: font.fontDescriptor.withSymbolicTraits(.traitItalic)!, size: font.pointSize) - mnemonicLabel.text = mnemonic - mnemonicLabel.numberOfLines = 0 - mnemonicLabel.textAlignment = .center - mnemonicLabel.lineBreakMode = .byWordWrapping - mnemonicLabel.textColor = UIColor.ows_white - mnemonicLabel.alpha = 0.8 - // Button stack view - let copyButton = OWSFlatButton.button(title: NSLocalizedString("Copy", comment: ""), font: .ows_dynamicTypeBodyClamped, titleColor: .white, backgroundColor: .clear, target: self, selector: #selector(copySeed)) - copyButton.setBackgroundColors(upColor: .clear, downColor: .clear) - let buttonStackView = UIStackView(arrangedSubviews: [ copyButton, cancelButton ]) - buttonStackView.axis = .horizontal - buttonStackView.distribution = .fillEqually - let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 - copyButton.set(.height, to: buttonHeight) - cancelButton.set(.height, to: buttonHeight) - // Stack view - let stackView = UIStackView(arrangedSubviews: [ UIView.spacer(withHeight: 2), titleLabel, subtitleLabel, mnemonicLabel, buttonStackView ]) - stackView.axis = .vertical - stackView.spacing = 16 - contentView.addSubview(stackView) - stackView.pin(.leading, to: .leading, of: contentView, withInset: 16) - stackView.pin(.top, to: .top, of: contentView, withInset: 16) - contentView.pin(.trailing, to: .trailing, of: stackView, withInset: 16) - contentView.pin(.bottom, to: .bottom, of: stackView, withInset: 16) - } - - // MARK: Interaction - @objc private func copySeed() { - UIPasteboard.general.string = mnemonic - dismiss(animated: true, completion: nil) - } -} diff --git a/Signal/src/Loki/Utilities/Modal.swift b/Signal/src/Loki/Utilities/Modal.swift deleted file mode 100644 index 0af8499a8..000000000 --- a/Signal/src/Loki/Utilities/Modal.swift +++ /dev/null @@ -1,58 +0,0 @@ - -@objc(LKModal) -internal class Modal : UIViewController { - private(set) var verticalCenteringConstraint: NSLayoutConstraint! - - // MARK: Components - lazy var contentView: UIView = { - let result = UIView() - result.backgroundColor = .lokiDarkGray() - result.layer.cornerRadius = 4 - result.layer.masksToBounds = false - result.layer.shadowColor = UIColor.black.cgColor - result.layer.shadowRadius = 8 - result.layer.shadowOpacity = 0.64 - return result - }() - - lazy var cancelButton: OWSFlatButton = { - let result = OWSFlatButton.button(title: NSLocalizedString("Cancel", comment: ""), font: .ows_dynamicTypeBodyClamped, titleColor: .white, backgroundColor: .clear, target: self, selector: #selector(cancel)) - result.setBackgroundColors(upColor: .clear, downColor: .clear) - return result - }() - - // MARK: Lifecycle - override func viewDidLoad() { - super.viewDidLoad() - setUpViewHierarchy() - } - - private func setUpViewHierarchy() { - view.backgroundColor = .clear - view.addSubview(contentView) - contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 32).isActive = true - view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 32).isActive = true - verticalCenteringConstraint = contentView.center(.vertical, in: view) - populateContentView() - } - - /// To be overridden by subclasses. - func populateContentView() { - preconditionFailure("populateContentView() is abstract and must be overridden.") - } - - // MARK: Interaction - override func touchesBegan(_ touches: Set, with event: UIEvent?) { - let touch = touches.first! - let location = touch.location(in: view) - if contentView.frame.contains(location) { - super.touchesBegan(touches, with: event) - } else { - cancel() - } - } - - @objc func cancel() { - dismiss(animated: true, completion: nil) - } -} diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 8d33ec3ad..28a541159 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2705,3 +2705,6 @@ "Linked Devices" = "Linked Devices"; "Show Seed" = "Show Seed"; "Clear All Data" = "Clear All Data"; +"This will delete your entire account, including all data, any messages currently linked to your public key, as well as your personal key pair." = "This will delete your entire account, including all data, any messages currently linked to your public key, as well as your personal key pair."; +"Delete" = "Delete"; +"This is your personal password. It can be used to restore your account or migrate your account to a new device." = "This is your personal password. It can be used to restore your account or migrate your account to a new device.";