diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index 010df1024..97c43b93d 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1183,28 +1183,31 @@ extension ConversationVC: func openUrl(_ urlString: String) { guard let url: URL = URL(string: urlString) else { return } - // URLs can be unsafe, so always ask the user whether they want to open one - let actionSheet: UIAlertController = UIAlertController( - title: "urlOpen".localized(), - message: "urlOpenDescription" - .put(key: "url", value: url.absoluteString) - .localized(), - preferredStyle: .actionSheet + let modal: ConfirmationModal = ConfirmationModal( + targetView: self.view, + info: ConfirmationModal.Info( + title: "urlOpen".localized(), + body: .text( + "urlOpenDescription" + .put(key: "url", value: url.absoluteString) + .localized() + ), + confirmTitle: "open".localized(), + confirmStyle: .danger, + cancelTitle: "urlCopy".localized(), + cancelStyle: .alert_text, + onConfirm: { [weak self] _ in + UIApplication.shared.open(url, options: [:], completionHandler: nil) + self?.showInputAccessoryView() + }, + onCancel: { [weak self] _ in + UIPasteboard.general.string = url.absoluteString + self?.showInputAccessoryView() + } + ) ) - actionSheet.addAction(UIAlertAction(title: "open".localized(), style: .default) { [weak self] _ in - UIApplication.shared.open(url, options: [:], completionHandler: nil) - self?.showInputAccessoryView() - }) - actionSheet.addAction(UIAlertAction(title: "urlCopy".localized(), style: .default) { [weak self] _ in - UIPasteboard.general.string = url.absoluteString - self?.showInputAccessoryView() - }) - actionSheet.addAction(UIAlertAction(title: "cancel".localized(), style: .cancel) { [weak self] _ in - self?.showInputAccessoryView() - }) - Modal.setupForIPadIfNeeded(actionSheet, targetView: self.view) - self.present(actionSheet, animated: true) + self.present(modal, animated: true) } func handleReplyButtonTapped(for cellViewModel: MessageViewModel, using dependencies: Dependencies) { diff --git a/SessionUIKit/Components/ConfirmationModal.swift b/SessionUIKit/Components/ConfirmationModal.swift index 68376b433..82c7ad29d 100644 --- a/SessionUIKit/Components/ConfirmationModal.swift +++ b/SessionUIKit/Components/ConfirmationModal.swift @@ -47,6 +47,15 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { return result }() + private lazy var explanationLabelContainer: UIScrollView = { + let result: UIScrollView = UIScrollView() + result.isHidden = true + + return result + }() + + private lazy var explanationLabelContainerHeightConstraint = explanationLabelContainer.set(.height, to: 0) + private lazy var explanationLabel: UILabel = { let result: UILabel = UILabel() result.font = .systemFont(ofSize: Values.smallFontSize) @@ -54,7 +63,6 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { result.textAlignment = .center result.lineBreakMode = .byWordWrapping result.numberOfLines = 0 - result.isHidden = true return result }() @@ -107,7 +115,7 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { }() private lazy var contentStackView: UIStackView = { - let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabel, textFieldContainer, imageViewContainer ]) + let result = UIStackView(arrangedSubviews: [ titleLabel, explanationLabelContainer, textFieldContainer, imageViewContainer ]) result.axis = .vertical result.spacing = Values.smallSpacing result.isLayoutMarginsRelativeArrangement = true @@ -178,6 +186,10 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { contentView.addSubview(mainStackView) contentView.addSubview(closeButton) + explanationLabelContainer.addSubview(explanationLabel) + explanationLabel.pin(to: explanationLabelContainer) + explanationLabel.set(.width, to: .width, of: explanationLabelContainer) + textFieldContainer.addSubview(textField) textField.pin(to: textFieldContainer, withInset: 12) @@ -191,6 +203,14 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { closeButton.pin(.right, to: .right, of: contentView, withInset: -8) } + private func layoutExplanationLabel() { + let labelWidth = view.frame.width - 2 * Values.veryLargeSpacing + let maxLabelSize = CGSize(width: labelWidth, height: CGFloat.greatestFiniteMagnitude) + let expectedLabelSize = explanationLabel.sizeThatFits(maxLabelSize) + let lineHeight = explanationLabel.font.lineHeight + explanationLabelContainerHeightConstraint.constant = min(expectedLabelSize.height, lineHeight * 5) + } + // MARK: - Content public func updateContent(with info: Info) { @@ -221,16 +241,18 @@ public class ConfirmationModal: Modal, UITextFieldDelegate { case .text(let text): mainStackView.spacing = Values.smallSpacing explanationLabel.text = text - explanationLabel.isHidden = false + explanationLabelContainer.isHidden = false + self.layoutExplanationLabel() case .attributedText(let attributedText): mainStackView.spacing = Values.smallSpacing explanationLabel.attributedText = attributedText - explanationLabel.isHidden = false + explanationLabelContainer.isHidden = false + self.layoutExplanationLabel() case .input(let explanation, let placeholder, let value, let clearButton, let onTextChanged): explanationLabel.attributedText = explanation - explanationLabel.isHidden = (explanation == nil) + explanationLabelContainer.isHidden = (explanation == nil) textField.placeholder = placeholder textField.text = (value ?? "") textField.clearButtonMode = (clearButton ? .always : .never)