diff --git a/Session/Conversations/Views & Modals/BlockedModal.swift b/Session/Conversations/Views & Modals/BlockedModal.swift index c41e76632..ff95bdf24 100644 --- a/Session/Conversations/Views & Modals/BlockedModal.swift +++ b/Session/Conversations/Views & Modals/BlockedModal.swift @@ -22,7 +22,7 @@ final class BlockedModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = String(format: NSLocalizedString("modal_blocked_title", comment: ""), name) titleLabel.textAlignment = .center // Message @@ -50,15 +50,20 @@ final class BlockedModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/DownloadAttachmentModal.swift b/Session/Conversations/Views & Modals/DownloadAttachmentModal.swift index 1c8c88842..474ba422c 100644 --- a/Session/Conversations/Views & Modals/DownloadAttachmentModal.swift +++ b/Session/Conversations/Views & Modals/DownloadAttachmentModal.swift @@ -23,7 +23,7 @@ final class DownloadAttachmentModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = String(format: NSLocalizedString("modal_download_attachment_title", comment: ""), name) titleLabel.textAlignment = .center // Message @@ -41,7 +41,6 @@ final class DownloadAttachmentModal : Modal { let downloadButton = UIButton() downloadButton.set(.height, to: Values.mediumButtonHeight) downloadButton.layer.cornerRadius = Modal.buttonCornerRadius - downloadButton.backgroundColor = Colors.buttonBackground downloadButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize) downloadButton.setTitleColor(Colors.text, for: UIControl.State.normal) downloadButton.setTitle(NSLocalizedString("modal_download_button_title", comment: ""), for: UIControl.State.normal) @@ -51,15 +50,20 @@ final class DownloadAttachmentModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/JoinOpenGroupModal.swift b/Session/Conversations/Views & Modals/JoinOpenGroupModal.swift index 61ea8f12a..453c5cdec 100644 --- a/Session/Conversations/Views & Modals/JoinOpenGroupModal.swift +++ b/Session/Conversations/Views & Modals/JoinOpenGroupModal.swift @@ -22,7 +22,7 @@ final class JoinOpenGroupModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = "Join \(name)?" titleLabel.textAlignment = .center // Message @@ -50,15 +50,20 @@ final class JoinOpenGroupModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/LinkPreviewModal.swift b/Session/Conversations/Views & Modals/LinkPreviewModal.swift index b8bf44dd5..0c1f3b3e2 100644 --- a/Session/Conversations/Views & Modals/LinkPreviewModal.swift +++ b/Session/Conversations/Views & Modals/LinkPreviewModal.swift @@ -20,7 +20,7 @@ final class LinkPreviewModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = NSLocalizedString("modal_link_previews_title", comment: "") titleLabel.textAlignment = .center // Message @@ -46,15 +46,20 @@ final class LinkPreviewModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/PermissionMissingModal.swift b/Session/Conversations/Views & Modals/PermissionMissingModal.swift index 721089492..d8ce615ce 100644 --- a/Session/Conversations/Views & Modals/PermissionMissingModal.swift +++ b/Session/Conversations/Views & Modals/PermissionMissingModal.swift @@ -22,7 +22,7 @@ final class PermissionMissingModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = "Session" titleLabel.textAlignment = .center // Message @@ -50,15 +50,20 @@ final class PermissionMissingModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/SendSeedModal.swift b/Session/Conversations/Views & Modals/SendSeedModal.swift index 0e8ac6221..e7027a85e 100644 --- a/Session/Conversations/Views & Modals/SendSeedModal.swift +++ b/Session/Conversations/Views & Modals/SendSeedModal.swift @@ -5,7 +5,7 @@ final class SendSeedModal : Modal { private lazy var titleLabel: UILabel = { let result = UILabel() result.textColor = Colors.text - result.font = .boldSystemFont(ofSize: Values.largeFontSize) + result.font = .boldSystemFont(ofSize: Values.mediumFontSize) result.text = NSLocalizedString("modal_send_seed_title", comment: "") result.textAlignment = .center return result @@ -44,19 +44,27 @@ final class SendSeedModal : Modal { return result }() - private lazy var mainStackView: UIStackView = { - let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, buttonStackView ]) + private lazy var contentStackView: UIStackView = { + let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel ]) result.axis = .vertical result.spacing = Values.largeSpacing return result }() + private lazy var mainStackView: UIStackView = { + let result = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) + result.axis = .vertical + result.spacing = Values.largeSpacing - Values.smallFontSize / 2 + return result + }() + + // MARK: Lifecycle override func populateContentView() { contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: mainStackView.spacing) } // MARK: Interaction diff --git a/Session/Conversations/Views & Modals/URLModal.swift b/Session/Conversations/Views & Modals/URLModal.swift index 3280b01bc..8beb2db6a 100644 --- a/Session/Conversations/Views & Modals/URLModal.swift +++ b/Session/Conversations/Views & Modals/URLModal.swift @@ -20,7 +20,7 @@ final class URLModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = NSLocalizedString("modal_open_url_title", comment: "") titleLabel.textAlignment = .center // Message @@ -48,15 +48,20 @@ final class URLModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/DMs/NewDMVC.swift b/Session/DMs/NewDMVC.swift index 6b8fb1ef9..05ff3f049 100644 --- a/Session/DMs/NewDMVC.swift +++ b/Session/DMs/NewDMVC.swift @@ -177,6 +177,7 @@ private final class EnterPublicKeyVC : UIViewController { weak var NewDMVC: NewDMVC! private var isKeyboardShowing = false private var bottomConstraint: NSLayoutConstraint! + private let bottomMargin: CGFloat = UIDevice.current.isIPad ? Values.largeSpacing : 0 // MARK: Components private lazy var publicKeyTextView: TextView = { @@ -214,6 +215,10 @@ private final class EnterPublicKeyVC : UIViewController { result.axis = .horizontal result.spacing = UIDevice.current.isIPad ? Values.iPadButtonSpacing : Values.mediumSpacing result.distribution = .fillEqually + if (UIDevice.current.isIPad) { + result.layoutMargins = UIEdgeInsets(top: 0, left: Values.iPadButtonContainerMargin, bottom: 0, right: Values.iPadButtonContainerMargin) + result.isLayoutMarginsRelativeArrangement = true + } return result }() @@ -221,6 +226,8 @@ private final class EnterPublicKeyVC : UIViewController { override func viewDidLoad() { // Remove background color view.backgroundColor = .clear + // User session id container + let userPublicKeyContainer = UIView(wrapping: userPublicKeyLabel, withInsets: .zero, shouldAdaptForIPadWithWidth: Values.iPadUserSessionIdContainerWidth) // Explanation label let explanationLabel = UILabel() explanationLabel.textColor = Colors.text.withAlphaComponent(Values.mediumOpacity) @@ -240,9 +247,9 @@ private final class EnterPublicKeyVC : UIViewController { let nextButton = Button(style: .prominentOutline, size: .large) nextButton.setTitle(NSLocalizedString("next", comment: ""), for: UIControl.State.normal) nextButton.addTarget(self, action: #selector(startNewDMIfPossible), for: UIControl.Event.touchUpInside) - let nextButtonContainer = UIView(wrapping: nextButton, withInsets: UIEdgeInsets(top: 0, leading: 80, bottom: 0, trailing: 80), shouldAdaptForIPad: true) + let nextButtonContainer = UIView(wrapping: nextButton, withInsets: UIEdgeInsets(top: 0, leading: 80, bottom: 0, trailing: 80), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ publicKeyTextView, UIView.spacer(withHeight: Values.smallSpacing), explanationLabel, spacer1, separator, spacer2, userPublicKeyLabel, spacer3, buttonContainer, UIView.vStretchingSpacer(), nextButtonContainer ]) + let mainStackView = UIStackView(arrangedSubviews: [ publicKeyTextView, UIView.spacer(withHeight: Values.smallSpacing), explanationLabel, spacer1, separator, spacer2, userPublicKeyContainer, spacer3, buttonContainer, UIView.vStretchingSpacer(), nextButtonContainer ]) mainStackView.axis = .vertical mainStackView.alignment = .fill mainStackView.layoutMargins = UIEdgeInsets(top: Values.largeSpacing, left: Values.largeSpacing, bottom: Values.largeSpacing, right: Values.largeSpacing) @@ -251,7 +258,7 @@ private final class EnterPublicKeyVC : UIViewController { mainStackView.pin(.leading, to: .leading, of: view) mainStackView.pin(.top, to: .top, of: view) view.pin(.trailing, to: .trailing, of: mainStackView) - bottomConstraint = view.pin(.bottom, to: .bottom, of: mainStackView) + bottomConstraint = view.pin(.bottom, to: .bottom, of: mainStackView, withInset: bottomMargin) // Width constraint view.set(.width, to: UIScreen.main.bounds.width) // Dismiss keyboard on tap @@ -292,7 +299,7 @@ private final class EnterPublicKeyVC : UIViewController { guard !isKeyboardShowing else { return } isKeyboardShowing = true guard let newHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height else { return } - bottomConstraint.constant = newHeight + bottomConstraint.constant = newHeight + bottomMargin UIView.animate(withDuration: 0.25) { [ self.spacer1, self.separator, self.spacer2, self.userPublicKeyLabel, self.spacer3, self.buttonContainer ].forEach { $0.alpha = 0 @@ -305,7 +312,7 @@ private final class EnterPublicKeyVC : UIViewController { @objc private func handleKeyboardWillHideNotification(_ notification: Notification) { guard isKeyboardShowing else { return } isKeyboardShowing = false - bottomConstraint.constant = 0 + bottomConstraint.constant = bottomMargin UIView.animate(withDuration: 0.25) { [ self.spacer1, self.separator, self.spacer2, self.userPublicKeyLabel, self.spacer3, self.buttonContainer ].forEach { $0.alpha = 1 diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index e3daacaed..ae903cd8e 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -70,7 +70,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large) createNewPrivateChatButton.setTitle(NSLocalizedString("vc_home_empty_state_button_title", comment: ""), for: UIControl.State.normal) createNewPrivateChatButton.addTarget(self, action: #selector(createNewDM), for: UIControl.Event.touchUpInside) - createNewPrivateChatButton.set(.width, to: 196) + createNewPrivateChatButton.set(.width, to: Values.iPadButtonWidth) let result = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ]) result.axis = .vertical result.spacing = Values.mediumSpacing diff --git a/Session/Home/Message Requests/MessageRequestsViewController.swift b/Session/Home/Message Requests/MessageRequestsViewController.swift index 32e1fc46e..d7eeda35c 100644 --- a/Session/Home/Message Requests/MessageRequestsViewController.swift +++ b/Session/Home/Message Requests/MessageRequestsViewController.swift @@ -159,8 +159,7 @@ class MessageRequestsViewController: BaseVC, UITableViewDelegate, UITableViewDat equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -Values.largeSpacing ), - // Note: The '182' is to match the 'Next' button on the New DM page (which doesn't have a fixed width) - clearAllButton.widthAnchor.constraint(equalToConstant: 182), + clearAllButton.widthAnchor.constraint(equalToConstant: Values.iPadButtonWidth), clearAllButton.heightAnchor.constraint(equalToConstant: NewConversationButtonSet.collapsedButtonSize) ]) } diff --git a/Session/Onboarding/LinkDeviceVC.swift b/Session/Onboarding/LinkDeviceVC.swift index 621f5cf53..f8d1fb514 100644 --- a/Session/Onboarding/LinkDeviceVC.swift +++ b/Session/Onboarding/LinkDeviceVC.swift @@ -196,7 +196,7 @@ private final class RecoveryPhraseVC : UIViewController { continueButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize) continueButton.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside) // Continue button container - let continueButtonContainer = UIView(wrapping: continueButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPad: true) + let continueButtonContainer = UIView(wrapping: continueButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Top stack view let topStackView = UIStackView(arrangedSubviews: [ titleLabel, spacer1, explanationLabel, spacer2, mnemonicTextView ]) topStackView.axis = .vertical diff --git a/Session/Onboarding/PNModeVC.swift b/Session/Onboarding/PNModeVC.swift index 393041fc2..d8684976d 100644 --- a/Session/Onboarding/PNModeVC.swift +++ b/Session/Onboarding/PNModeVC.swift @@ -52,7 +52,7 @@ final class PNModeVC : BaseVC, OptionViewDelegate { registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize) registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside) // Set up register button container - let registerButtonContainer = UIView(wrapping: registerButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPad: true) + let registerButtonContainer = UIView(wrapping: registerButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Set up options stack view let optionsStackView = UIStackView(arrangedSubviews: optionViews) optionsStackView.axis = .vertical diff --git a/Session/Onboarding/RestoreVC.swift b/Session/Onboarding/RestoreVC.swift index e1dc36d36..35ed24610 100644 --- a/Session/Onboarding/RestoreVC.swift +++ b/Session/Onboarding/RestoreVC.swift @@ -71,7 +71,7 @@ final class RestoreVC : BaseVC { restoreButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize) restoreButton.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside) // Set up restore button container - let restoreButtonContainer = UIView(wrapping: restoreButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPad: true) + let restoreButtonContainer = UIView(wrapping: restoreButton, withInsets: UIEdgeInsets(top: 0, leading: Values.massiveSpacing, bottom: 0, trailing: Values.massiveSpacing), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Set up top stack view let topStackView = UIStackView(arrangedSubviews: [ titleLabel, spacer1, explanationLabel, spacer2, mnemonicTextView, spacer3, legalLabel ]) topStackView.axis = .vertical diff --git a/Session/Open Groups/JoinOpenGroupVC.swift b/Session/Open Groups/JoinOpenGroupVC.swift index 63504b4a9..86cbdbf24 100644 --- a/Session/Open Groups/JoinOpenGroupVC.swift +++ b/Session/Open Groups/JoinOpenGroupVC.swift @@ -168,6 +168,9 @@ final class JoinOpenGroupVC : BaseVC, UIPageViewControllerDataSource, UIPageView private final class EnterURLVC : UIViewController, UIGestureRecognizerDelegate, OpenGroupSuggestionGridDelegate { weak var joinOpenGroupVC: JoinOpenGroupVC! + private var isKeyboardShowing = false + private var bottomConstraint: NSLayoutConstraint! + private let bottomMargin: CGFloat = UIDevice.current.isIPad ? Values.largeSpacing : 0 // MARK: Components private lazy var urlTextView: TextView = { @@ -200,7 +203,7 @@ private final class EnterURLVC : UIViewController, UIGestureRecognizerDelegate, let nextButton = Button(style: .prominentOutline, size: .large) nextButton.setTitle(NSLocalizedString("next", comment: ""), for: UIControl.State.normal) nextButton.addTarget(self, action: #selector(joinOpenGroup), for: UIControl.Event.touchUpInside) - let nextButtonContainer = UIView(wrapping: nextButton, withInsets: UIEdgeInsets(top: 0, leading: 80, bottom: 0, trailing: 80), shouldAdaptForIPad: true) + let nextButtonContainer = UIView(wrapping: nextButton, withInsets: UIEdgeInsets(top: 0, leading: 80, bottom: 0, trailing: 80), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Stack view let stackView = UIStackView(arrangedSubviews: [ urlTextView, UIView.spacer(withHeight: Values.mediumSpacing), suggestionGridTitleLabel, UIView.spacer(withHeight: Values.mediumSpacing), suggestionGrid, UIView.vStretchingSpacer(), nextButtonContainer ]) @@ -209,13 +212,24 @@ private final class EnterURLVC : UIViewController, UIGestureRecognizerDelegate, stackView.layoutMargins = UIEdgeInsets(uniform: Values.largeSpacing) stackView.isLayoutMarginsRelativeArrangement = true view.addSubview(stackView) - stackView.pin(to: view) + stackView.pin(.leading, to: .leading, of: view) + stackView.pin(.top, to: .top, of: view) + view.pin(.trailing, to: .trailing, of: stackView) + bottomConstraint = view.pin(.bottom, to: .bottom, of: stackView, withInset: bottomMargin) // Constraints view.set(.width, to: UIScreen.main.bounds.width) // Dismiss keyboard on tap let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) tapGestureRecognizer.delegate = self view.addGestureRecognizer(tapGestureRecognizer) + // Listen to keyboard notifications + let notificationCenter = NotificationCenter.default + notificationCenter.addObserver(self, selector: #selector(handleKeyboardWillChangeFrameNotification(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil) + notificationCenter.addObserver(self, selector: #selector(handleKeyboardWillHideNotification(_:)), name: UIResponder.keyboardWillHideNotification, object: nil) + } + + deinit { + NotificationCenter.default.removeObserver(self) } // MARK: General @@ -241,6 +255,26 @@ private final class EnterURLVC : UIViewController, UIGestureRecognizerDelegate, let url = urlTextView.text?.trimmingCharacters(in: .whitespaces) ?? "" joinOpenGroupVC.joinOpenGroup(with: url) } + + // MARK: Updating + @objc private func handleKeyboardWillChangeFrameNotification(_ notification: Notification) { + guard !isKeyboardShowing else { return } + isKeyboardShowing = true + guard let newHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.size.height else { return } + bottomConstraint.constant = newHeight + bottomMargin + UIView.animate(withDuration: 0.25) { + self.view.layoutIfNeeded() + } + } + + @objc private func handleKeyboardWillHideNotification(_ notification: Notification) { + guard isKeyboardShowing else { return } + isKeyboardShowing = false + bottomConstraint.constant = bottomMargin + UIView.animate(withDuration: 0.25) { + self.view.layoutIfNeeded() + } + } } private final class ScanQRCodePlaceholderVC : UIViewController { diff --git a/Session/Path/PathVC.swift b/Session/Path/PathVC.swift index 7e08f6dd9..26e7f9392 100644 --- a/Session/Path/PathVC.swift +++ b/Session/Path/PathVC.swift @@ -67,7 +67,7 @@ final class PathVC : BaseVC { spinner.center(in: pathStackViewContainer) // Set up rebuild path button let inset: CGFloat = isIPhone5OrSmaller ? 64 : 80 - let learnMoreButtonContainer = UIView(wrapping: learnMoreButton, withInsets: UIEdgeInsets(top: 0, leading: inset, bottom: 0, trailing: inset), shouldAdaptForIPad: true) + let learnMoreButtonContainer = UIView(wrapping: learnMoreButton, withInsets: UIEdgeInsets(top: 0, leading: inset, bottom: 0, trailing: inset), shouldAdaptForIPadWithWidth: Values.iPadButtonWidth) // Set up spacers let topSpacer = UIView.vStretchingSpacer() let bottomSpacer = UIView.vStretchingSpacer() diff --git a/Session/Settings/NukeDataModal.swift b/Session/Settings/NukeDataModal.swift index 7c86d629c..1972095ba 100644 --- a/Session/Settings/NukeDataModal.swift +++ b/Session/Settings/NukeDataModal.swift @@ -92,20 +92,27 @@ final class NukeDataModal : Modal { return result }() - private lazy var mainStackView: UIStackView = { - let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, buttonStackViewContainer ]) + private lazy var contentStackView: UIStackView = { + let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel ]) result.axis = .vertical result.spacing = Values.largeSpacing return result }() + private lazy var mainStackView: UIStackView = { + let result = UIStackView(arrangedSubviews: [ contentStackView, buttonStackViewContainer ]) + result.axis = .vertical + result.spacing = Values.largeSpacing - Values.smallFontSize / 2 + return result + }() + // MARK: Lifecycle override func populateContentView() { contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: mainStackView.spacing) } // MARK: Interaction diff --git a/Session/Settings/SeedModal.swift b/Session/Settings/SeedModal.swift index 11528450b..46612e81b 100644 --- a/Session/Settings/SeedModal.swift +++ b/Session/Settings/SeedModal.swift @@ -59,15 +59,20 @@ final class SeedModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Set up stack view - let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let stackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) stackView.axis = .vertical - stackView.spacing = Values.largeSpacing + stackView.spacing = spacing 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) + contentView.pin(.bottom, to: .bottom, of: stackView, withInset: spacing) // Mark seed as viewed UserDefaults.standard[.hasViewedSeed] = true NotificationCenter.default.post(name: .seedViewed, object: nil) diff --git a/Session/Settings/SettingsVC.swift b/Session/Settings/SettingsVC.swift index 8f6d4d484..a4febb1f0 100644 --- a/Session/Settings/SettingsVC.swift +++ b/Session/Settings/SettingsVC.swift @@ -175,8 +175,14 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate { buttonContainer.axis = .horizontal buttonContainer.spacing = UIDevice.current.isIPad ? Values.iPadButtonSpacing : Values.mediumSpacing buttonContainer.distribution = .fillEqually + if (UIDevice.current.isIPad) { + buttonContainer.layoutMargins = UIEdgeInsets(top: 0, left: Values.iPadButtonContainerMargin, bottom: 0, right: Values.iPadButtonContainerMargin) + buttonContainer.isLayoutMarginsRelativeArrangement = true + } + // User session id container + let userPublicKeyContainer = UIView(wrapping: publicKeyLabel, withInsets: .zero, shouldAdaptForIPadWithWidth: Values.iPadUserSessionIdContainerWidth) // Top stack view - let topStackView = UIStackView(arrangedSubviews: [ headerStackView, separator, publicKeyLabel, buttonContainer ]) + let topStackView = UIStackView(arrangedSubviews: [ headerStackView, separator, userPublicKeyContainer, buttonContainer ]) topStackView.axis = .vertical topStackView.spacing = Values.largeSpacing topStackView.alignment = .fill diff --git a/Session/Settings/ShareLogsModal.swift b/Session/Settings/ShareLogsModal.swift index 0a93acff1..72c3ae22e 100644 --- a/Session/Settings/ShareLogsModal.swift +++ b/Session/Settings/ShareLogsModal.swift @@ -19,7 +19,7 @@ final class ShareLogsModal : Modal { // Title let titleLabel = UILabel() titleLabel.textColor = Colors.text - titleLabel.font = .boldSystemFont(ofSize: Values.largeFontSize) + titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize) titleLabel.text = NSLocalizedString("modal_share_logs_title", comment: "") titleLabel.textAlignment = .center // Message @@ -44,15 +44,20 @@ final class ShareLogsModal : Modal { buttonStackView.axis = .horizontal buttonStackView.spacing = Values.mediumSpacing buttonStackView.distribution = .fillEqually + // Content stack view + let contentStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel ]) + contentStackView.axis = .vertical + contentStackView.spacing = Values.largeSpacing // Main stack view - let mainStackView = UIStackView(arrangedSubviews: [ titleLabel, messageLabel, buttonStackView ]) + let spacing = Values.largeSpacing - Values.smallFontSize / 2 + let mainStackView = UIStackView(arrangedSubviews: [ contentStackView, buttonStackView ]) mainStackView.axis = .vertical - mainStackView.spacing = Values.largeSpacing + mainStackView.spacing = spacing contentView.addSubview(mainStackView) mainStackView.pin(.leading, to: .leading, of: contentView, withInset: Values.largeSpacing) mainStackView.pin(.top, to: .top, of: contentView, withInset: Values.largeSpacing) contentView.pin(.trailing, to: .trailing, of: mainStackView, withInset: Values.largeSpacing) - contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: Values.largeSpacing) + contentView.pin(.bottom, to: .bottom, of: mainStackView, withInset: spacing) } // MARK: Interaction diff --git a/Session/Sheets & Modals/Modal.swift b/Session/Sheets & Modals/Modal.swift index e2a3acb20..f77cb4bc1 100644 --- a/Session/Sheets & Modals/Modal.swift +++ b/Session/Sheets & Modals/Modal.swift @@ -53,7 +53,7 @@ class Modal: BaseVC, UIGestureRecognizerDelegate { private func setUpViewHierarchy() { view.addSubview(contentView) if UIDevice.current.isIPad { - contentView.set(.width, to: Values.iPadButtonWidth) + contentView.set(.width, to: Values.iPadModalWidth) contentView.center(in: view) } else { contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: Values.veryLargeSpacing).isActive = true diff --git a/Session/Utilities/UIView+Wrapping.swift b/Session/Utilities/UIView+Wrapping.swift index d7804d0a2..5bfc0553f 100644 --- a/Session/Utilities/UIView+Wrapping.swift +++ b/Session/Utilities/UIView+Wrapping.swift @@ -1,11 +1,11 @@ extension UIView { - convenience init(wrapping view: UIView, withInsets insets: UIEdgeInsets, shouldAdaptForIPad: Bool = false) { + convenience init(wrapping view: UIView, withInsets insets: UIEdgeInsets, shouldAdaptForIPadWithWidth width: CGFloat? = nil) { self.init() addSubview(view) - if UIDevice.current.isIPad && shouldAdaptForIPad { - view.set(.width, to: Values.iPadButtonWidth) + if UIDevice.current.isIPad, let width = width { + view.set(.width, to: width) view.center(in: self) } else { view.pin(.leading, to: .leading, of: self, withInset: insets.left) diff --git a/SessionUIKit/Style Guide/Values.swift b/SessionUIKit/Style Guide/Values.swift index 90dbdc8bc..3f86dd61c 100644 --- a/SessionUIKit/Style Guide/Values.swift +++ b/SessionUIKit/Style Guide/Values.swift @@ -44,6 +44,9 @@ public final class Values : NSObject { @objc public static let onboardingButtonBottomOffset = isIPhone5OrSmaller ? CGFloat(52) : CGFloat(72) // MARK: - iPad Sizes - @objc public static let iPadButtonWidth = UIScreen.main.bounds.width / 2 + @objc public static let iPadModalWidth = UIScreen.main.bounds.width / 2 + @objc public static let iPadButtonWidth = CGFloat(196) @objc public static let iPadButtonSpacing = CGFloat(32) + @objc public static let iPadUserSessionIdContainerWidth = iPadButtonWidth * 2 + iPadButtonSpacing + @objc public static let iPadButtonContainerMargin = (UIScreen.main.bounds.width - iPadButtonSpacing) / 2 - iPadButtonWidth - largeSpacing }