From ce524c140f7e3a7f8a492b86c9ecf2386cbfd4cf Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Wed, 4 Dec 2019 16:54:46 +1100 Subject: [PATCH] Start implementing settings screen redesign --- Signal.xcodeproj/project.pbxproj | 4 + .../src/Loki/Redesign/Components/Button.swift | 11 +- .../Loki/Redesign/Style Guide/Colors.swift | 1 + .../Loki/Redesign/Style Guide/Values.swift | 3 +- .../Redesign/View Controllers/HomeVC.swift | 6 +- .../View Controllers/JoinPublicChatVC.swift | 3 + .../View Controllers/NewPrivateChatVC.swift | 3 + .../View Controllers/SettingsVC.swift | 176 ++++++++++++++++++ .../translations/en.lproj/Localizable.strings | 6 + 9 files changed, 203 insertions(+), 10 deletions(-) create mode 100644 Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 583d52bb7..fd0fae770 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -597,6 +597,7 @@ B8CCF63723961D6D0091D419 /* NewPrivateChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */; }; B8CCF639239721E20091D419 /* TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF638239721E20091D419 /* TabBar.swift */; }; B8CCF63F23975CFB0091D419 /* JoinPublicChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */; }; + B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF6422397711F0091D419 /* SettingsVC.swift */; }; B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; B9EB5ABD1884C002007CBB57 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9EB5ABC1884C002007CBB57 /* MessageUI.framework */; }; BFF3FB9730634F37D25903F4 /* Pods_Signal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D17BB5C25D615AB49813100C /* Pods_Signal.framework */; }; @@ -1422,6 +1423,7 @@ B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPrivateChatVC.swift; sourceTree = ""; }; B8CCF638239721E20091D419 /* TabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = ""; }; B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinPublicChatVC.swift; sourceTree = ""; }; + B8CCF6422397711F0091D419 /* SettingsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVC.swift; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; B90418E5183E9DD40038554A /* DateUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DateUtil.m; sourceTree = ""; }; B97940251832BD2400BD66CB /* UIUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIUtil.h; sourceTree = ""; }; @@ -2804,6 +2806,7 @@ B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */, B8CCF63E23975CFB0091D419 /* JoinPublicChatVC.swift */, B893063E2383961A005EAA8E /* ScanQRCodeWrapperVC.swift */, + B8CCF6422397711F0091D419 /* SettingsVC.swift */, ); path = "View Controllers"; sourceTree = ""; @@ -3971,6 +3974,7 @@ 340FC8B1204DAC8D007AEB0F /* BlockListViewController.m in Sources */, 45B5360E206DD8BB00D61655 /* UIResponder+OWS.swift in Sources */, 4CFE6B6C21F92BA700006701 /* LegacyNotificationsAdaptee.swift in Sources */, + B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */, 3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */, 45F659821E1BE77000444429 /* NonCallKitCallUIAdaptee.swift in Sources */, 4C5250D221E7BD7D00CE3D95 /* PhoneNumberValidator.swift in Sources */, diff --git a/Signal/src/Loki/Redesign/Components/Button.swift b/Signal/src/Loki/Redesign/Components/Button.swift index dee36c80b..3d2040e1f 100644 --- a/Signal/src/Loki/Redesign/Components/Button.swift +++ b/Signal/src/Loki/Redesign/Components/Button.swift @@ -3,7 +3,7 @@ final class Button : UIButton { private let style: Style enum Style { - case unimportant, prominent + case unimportant, regular, prominent } init(style: Style) { @@ -24,23 +24,22 @@ final class Button : UIButton { let fillColor: UIColor switch style { case .unimportant: fillColor = Colors.unimportantButtonBackground + case .regular: fillColor = UIColor.clear case .prominent: fillColor = UIColor.clear } let borderColor: UIColor switch style { case .unimportant: borderColor = Colors.unimportantButtonBackground + case .regular: borderColor = Colors.text case .prominent: borderColor = Colors.accent } let textColor: UIColor switch style { case .unimportant: textColor = Colors.text + case .regular: textColor = Colors.text case .prominent: textColor = Colors.accent } - let height: CGFloat - switch style { - case .unimportant: height = Values.mediumButtonHeight - case .prominent: height = Values.largeButtonHeight - } + let height = Values.buttonHeight set(.height, to: height) layer.cornerRadius = height / 2 backgroundColor = fillColor diff --git a/Signal/src/Loki/Redesign/Style Guide/Colors.swift b/Signal/src/Loki/Redesign/Style Guide/Colors.swift index 92e7df0c0..06d6ad79b 100644 --- a/Signal/src/Loki/Redesign/Style Guide/Colors.swift +++ b/Signal/src/Loki/Redesign/Style Guide/Colors.swift @@ -14,6 +14,7 @@ final class Colors : NSObject { @objc static let accent = UIColor(hex: 0x00F782) @objc static let text = UIColor(hex: 0xFFFFFF) + @objc static let destructive = UIColor(hex: 0xFF453A) @objc static let unimportant = UIColor(hex: 0xD8D8D8) @objc static let border = UIColor(hex: 0x979797) @objc static let conversationCellBackground = UIColor(hex: 0x1B1B1B) diff --git a/Signal/src/Loki/Redesign/Style Guide/Values.swift b/Signal/src/Loki/Redesign/Style Guide/Values.swift index fa060f23a..058e4af90 100644 --- a/Signal/src/Loki/Redesign/Style Guide/Values.swift +++ b/Signal/src/Loki/Redesign/Style Guide/Values.swift @@ -15,8 +15,7 @@ final class Values : NSObject { @objc static let massiveFontSize = CGFloat(50) // MARK: - Element Sizes - @objc static let mediumButtonHeight = CGFloat(34) - @objc static let largeButtonHeight = CGFloat(45) + @objc static let buttonHeight = CGFloat(34) @objc static let accentLineThickness = CGFloat(4) @objc static let verySmallProfilePictureSize = CGFloat(26) @objc static let smallProfilePictureSize = CGFloat(35) diff --git a/Signal/src/Loki/Redesign/View Controllers/HomeVC.swift b/Signal/src/Loki/Redesign/View Controllers/HomeVC.swift index 3223f30e5..0d1dadd7a 100644 --- a/Signal/src/Loki/Redesign/View Controllers/HomeVC.swift +++ b/Signal/src/Loki/Redesign/View Controllers/HomeVC.swift @@ -19,7 +19,7 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat private let editingDatabaseConnection = OWSPrimaryStorage.shared().newDatabaseConnection() // MARK: Settings - public override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } // MARK: Components private lazy var searchBar = SearchBar() @@ -284,6 +284,7 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat guard let self = self else { return } self.present(alert, animated: true, completion: nil) } + delete.backgroundColor = Colors.destructive if let publicChat = publicChat { return publicChat.isDeletable ? [ delete ] : [] } else { @@ -292,7 +293,8 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat } @objc private func openSettings() { - let navigationController = AppSettingsViewController.inModalNavigationController() + let settingsVC = SettingsVC() + let navigationController = OWSNavigationController(rootViewController: settingsVC) present(navigationController, animated: true, completion: nil) } diff --git a/Signal/src/Loki/Redesign/View Controllers/JoinPublicChatVC.swift b/Signal/src/Loki/Redesign/View Controllers/JoinPublicChatVC.swift index fd8e7091a..85a975bbf 100644 --- a/Signal/src/Loki/Redesign/View Controllers/JoinPublicChatVC.swift +++ b/Signal/src/Loki/Redesign/View Controllers/JoinPublicChatVC.swift @@ -5,6 +5,9 @@ final class JoinPublicChatVC : UIViewController, UIPageViewControllerDataSource, private var isJoining = false private var targetVCIndex: Int? + // MARK: Settings + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } + // MARK: Components private lazy var tabBar: TabBar = { let tabs = [ diff --git a/Signal/src/Loki/Redesign/View Controllers/NewPrivateChatVC.swift b/Signal/src/Loki/Redesign/View Controllers/NewPrivateChatVC.swift index 0ffd22357..3f17149ff 100644 --- a/Signal/src/Loki/Redesign/View Controllers/NewPrivateChatVC.swift +++ b/Signal/src/Loki/Redesign/View Controllers/NewPrivateChatVC.swift @@ -4,6 +4,9 @@ final class NewPrivateChatVC : UIViewController, UIPageViewControllerDataSource, private var pages: [UIViewController] = [] private var targetVCIndex: Int? + // MARK: Settings + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } + // MARK: Components private lazy var tabBar: TabBar = { let tabs = [ diff --git a/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift b/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift new file mode 100644 index 000000000..92a855c8f --- /dev/null +++ b/Signal/src/Loki/Redesign/View Controllers/SettingsVC.swift @@ -0,0 +1,176 @@ + +final class SettingsVC : UIViewController { + + private lazy var settings: [Setting] = { + return [ + Setting(title: NSLocalizedString("Privacy", comment: ""), color: Colors.text) { [weak self] in self?.showPrivacySettings() }, + Setting(title: NSLocalizedString("Notifications", comment: ""), color: Colors.text) { [weak self] in self?.showNotificationSettings() }, + Setting(title: NSLocalizedString("Linked Devices", comment: ""), color: Colors.text) { [weak self] in self?.showLinkedDevices() }, + Setting(title: NSLocalizedString("Show Seed", comment: ""), color: Colors.text) { [weak self] in self?.showSeed() }, + Setting(title: NSLocalizedString("Clear All Data", comment: ""), color: Colors.destructive) { [weak self] in self?.clearAllData() } + ] + }() + + private lazy var userHexEncodedPublicKey: String = { + let userDefaults = UserDefaults.standard + if let masterHexEncodedPublicKey = userDefaults.string(forKey: "masterDeviceHexEncodedPublicKey") { + return masterHexEncodedPublicKey + } else { + return OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey + } + }() + + // MARK: Settings + override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent } + + // MARK: Components + private lazy var copyButton: Button = { + let result = Button(style: .prominent) + result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal) + result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside) + return result + }() + + // MARK: Types + private struct Setting { + let title: String + let color: UIColor + let onTap: () -> Void + } + + // MARK: Lifecycle + override func viewDidLoad() { + // Set gradient background + view.backgroundColor = .clear + let gradient = Gradients.defaultLokiBackground + view.setGradient(gradient) + // Set navigation bar background color + let navigationBar = navigationController!.navigationBar + navigationBar.setBackgroundImage(UIImage(), for: UIBarMetrics.default) + navigationBar.shadowImage = UIImage() + navigationBar.isTranslucent = false + navigationBar.barTintColor = Colors.navigationBarBackground + // Set up navigation bar buttons + let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close)) + closeButton.tintColor = Colors.text + navigationItem.leftBarButtonItem = closeButton + let qrCodeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "QRCodeFilled"), style: .plain, target: self, action: #selector(showQRCode)) + qrCodeButton.tintColor = Colors.text + navigationItem.rightBarButtonItem = qrCodeButton + // Customize title + let titleLabel = UILabel() + titleLabel.text = NSLocalizedString("Settings", comment: "") + titleLabel.textColor = Colors.text + titleLabel.font = UIFont.boldSystemFont(ofSize: Values.veryLargeFontSize) + navigationItem.titleView = titleLabel + // Set up profile picture view + let profilePictureView = ProfilePictureView() + profilePictureView.hexEncodedPublicKey = userHexEncodedPublicKey + let profilePictureSize = Values.largeProfilePictureSize + profilePictureView.size = profilePictureSize + profilePictureView.set(.width, to: profilePictureSize) + profilePictureView.set(.height, to: profilePictureSize) + profilePictureView.update() + // Set up display name label + let displayNameLabel = UILabel() + displayNameLabel.textColor = Colors.text + displayNameLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + displayNameLabel.text = OWSProfileManager.shared().profileName(forRecipientId: userHexEncodedPublicKey) + displayNameLabel.lineBreakMode = .byTruncatingTail + // Set up header view + let headerStackView = UIStackView(arrangedSubviews: [ profilePictureView, displayNameLabel ]) + headerStackView.axis = .vertical + headerStackView.spacing = Values.smallSpacing + headerStackView.alignment = .center + // Set up separator + let separator = Separator(title: NSLocalizedString("Your Public Key", comment: "")) + // Set up public key label + let publicKeyLabel = UILabel() + publicKeyLabel.textColor = Colors.text + publicKeyLabel.font = Fonts.spaceMono(ofSize: Values.largeFontSize) + publicKeyLabel.numberOfLines = 0 + publicKeyLabel.textAlignment = .center + publicKeyLabel.lineBreakMode = .byCharWrapping + publicKeyLabel.text = userHexEncodedPublicKey + // Set up share button + let shareButton = Button(style: .regular) + shareButton.setTitle(NSLocalizedString("Share", comment: ""), for: UIControl.State.normal) + shareButton.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside) + // Set up button container + let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ]) + buttonContainer.axis = .horizontal + buttonContainer.spacing = Values.mediumSpacing + buttonContainer.distribution = .fillEqually + // Set up settings stack view + let settingViews: [UIButton] = settings.map { setting in + let button = UIButton() + button.setTitle(setting.title, for: UIControl.State.normal) + button.setTitleColor(setting.color, for: UIControl.State.normal) + button.titleLabel!.textAlignment = .center + button.set(.height, to: 75) + return button + } + let settingsStackView = UIStackView(arrangedSubviews: settingViews) + settingsStackView.axis = .vertical + settingsStackView.alignment = .fill + // Set up stack view + let stackView = UIStackView(arrangedSubviews: [ headerStackView, separator, publicKeyLabel, buttonContainer, settingsStackView, UIView.vStretchingSpacer() ]) + stackView.axis = .vertical + stackView.spacing = Values.largeSpacing + stackView.alignment = .fill + stackView.layoutMargins = UIEdgeInsets(top: Values.mediumSpacing, left: Values.largeSpacing, bottom: Values.mediumSpacing, right: Values.largeSpacing) + stackView.isLayoutMarginsRelativeArrangement = true + view.addSubview(stackView) + stackView.pin(to: view) + } + + @objc private func enableCopyButton() { + copyButton.isUserInteractionEnabled = true + UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: { + self.copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal) + }, completion: nil) + } + + // MARK: Interaction + @objc private func close() { + dismiss(animated: true, completion: nil) + } + + @objc private func showQRCode() { + // TODO: Implement + } + + @objc private func copyPublicKey() { + UIPasteboard.general.string = userHexEncodedPublicKey + copyButton.isUserInteractionEnabled = false + UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: { + self.copyButton.setTitle(NSLocalizedString("Copied", comment: ""), for: UIControl.State.normal) + }, completion: nil) + Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false) + } + + @objc private func sharePublicKey() { + let shareVC = UIActivityViewController(activityItems: [ userHexEncodedPublicKey ], applicationActivities: nil) + navigationController!.present(shareVC, animated: true, completion: nil) + } + + private func showPrivacySettings() { + + } + + private func showNotificationSettings() { + + } + + private func showLinkedDevices() { + + } + + private func showSeed() { + + } + + private func clearAllData() { + + } +} diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 1968a580b..8d33ec3ad 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2699,3 +2699,9 @@ "Invalid URL" = "Invalid URL"; "Please check the URL you entered and try again" = "Please check the URL you entered and try again"; "Couldn't Join" = "Couldn't Join"; +"Settings" = "Settings"; +"Privacy" = "Privacy"; +"Notifications" = "Notifications"; +"Linked Devices" = "Linked Devices"; +"Show Seed" = "Show Seed"; +"Clear All Data" = "Clear All Data";