diff --git a/View Controllers/NewStatusViewController.swift b/View Controllers/NewStatusViewController.swift index 08240db..8fee7c2 100644 --- a/View Controllers/NewStatusViewController.swift +++ b/View Controllers/NewStatusViewController.swift @@ -174,6 +174,13 @@ private extension NewStatusViewController { stackView.arrangedSubviews.first { ($0 as? CompositionView)?.id == id }?.removeFromSuperview() } + + for compositionView in stackView.arrangedSubviews.compactMap({ $0 as? CompositionView }) { + compositionView.removeButton.isHidden = compositionViewModels.count == 1 + compositionView.inReplyToView.isHidden = compositionView === stackView.arrangedSubviews.first + && viewModel.inReplyToViewModel == nil + compositionView.hasReplyFollowingView.isHidden = compositionView === stackView.arrangedSubviews.last + } } func dismiss() { diff --git a/ViewModels/Sources/ViewModels/NewStatusViewModel.swift b/ViewModels/Sources/ViewModels/NewStatusViewModel.swift index 1a35fcf..af6b1b3 100644 --- a/ViewModels/Sources/ViewModels/NewStatusViewModel.swift +++ b/ViewModels/Sources/ViewModels/NewStatusViewModel.swift @@ -89,6 +89,10 @@ public extension NewStatusViewModel { eventsSubject.send(.presentCamera(viewModel)) } + func remove(viewModel: CompositionViewModel) { + compositionViewModels.removeAll { $0 === viewModel } + } + func insert(after: CompositionViewModel) { guard let index = compositionViewModels.firstIndex(where: { $0 === after }) else { return } diff --git a/Views/CompositionView.swift b/Views/CompositionView.swift index f211e55..5b17f15 100644 --- a/Views/CompositionView.swift +++ b/Views/CompositionView.swift @@ -10,6 +10,9 @@ final class CompositionView: UIView { let spoilerTextField = UITextField() let textView = UITextView() let textViewPlaceholder = UILabel() + let removeButton = UIButton(type: .close) + let inReplyToView = UIView() + let hasReplyFollowingView = UIView() let attachmentsView = AttachmentsView() let attachmentUploadView: AttachmentUploadView let markAttachmentsSensitiveView: MarkAttachmentsSensitiveView @@ -57,6 +60,7 @@ private extension CompositionView { avatarImageView.translatesAutoresizingMaskIntoConstraints = false avatarImageView.layer.cornerRadius = .avatarDimension / 2 avatarImageView.clipsToBounds = true + avatarImageView.setContentHuggingPriority(.required, for: .horizontal) let stackView = UIStackView() let inputAccessoryView = CompositionInputAccessoryView(viewModel: viewModel, parentViewModel: parentViewModel) @@ -100,8 +104,34 @@ private extension CompositionView { textViewPlaceholder.text = NSLocalizedString("compose.prompt", comment: "") stackView.addArrangedSubview(attachmentsView) + attachmentsView.isHidden = true stackView.addArrangedSubview(attachmentUploadView) + attachmentUploadView.isHidden = true stackView.addArrangedSubview(markAttachmentsSensitiveView) + markAttachmentsSensitiveView.isHidden = true + + addSubview(removeButton) + removeButton.translatesAutoresizingMaskIntoConstraints = false + removeButton.showsMenuAsPrimaryAction = true + removeButton.menu = UIMenu( + children: [ + UIAction( + title: NSLocalizedString("remove", comment: ""), + image: UIImage(systemName: "trash"), + attributes: .destructive) { [weak self] _ in + guard let self = self else { return } + + self.parentViewModel.remove(viewModel: self.viewModel) + }]) + removeButton.setContentHuggingPriority(.required, for: .horizontal) + removeButton.setContentCompressionResistancePriority(.required, for: .horizontal) + + for view in [inReplyToView, hasReplyFollowingView] { + addSubview(view) + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .opaqueSeparator + view.widthAnchor.constraint(equalToConstant: .hairline).isActive = true + } textView.text = viewModel.text spoilerTextField.text = viewModel.contentWarning @@ -151,19 +181,21 @@ private extension CompositionView { avatarImageView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor), stackView.leadingAnchor.constraint(equalTo: avatarImageView.trailingAnchor, constant: .defaultSpacing), stackView.topAnchor.constraint(greaterThanOrEqualTo: guide.topAnchor), - stackView.trailingAnchor.constraint(equalTo: guide.trailingAnchor), stackView.bottomAnchor.constraint(lessThanOrEqualTo: guide.bottomAnchor), textViewPlaceholder.leadingAnchor.constraint(equalTo: textView.leadingAnchor), textViewPlaceholder.topAnchor.constraint(equalTo: textView.topAnchor), - textViewPlaceholder.trailingAnchor.constraint(equalTo: textView.trailingAnchor) + textViewPlaceholder.trailingAnchor.constraint(equalTo: textView.trailingAnchor), + removeButton.leadingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: .defaultSpacing), + removeButton.topAnchor.constraint(equalTo: guide.topAnchor), + removeButton.trailingAnchor.constraint(equalTo: guide.trailingAnchor), + inReplyToView.centerXAnchor.constraint(equalTo: avatarImageView.centerXAnchor), + inReplyToView.topAnchor.constraint(equalTo: topAnchor), + inReplyToView.bottomAnchor.constraint(equalTo: avatarImageView.topAnchor), + hasReplyFollowingView.centerXAnchor.constraint(equalTo: avatarImageView.centerXAnchor), + hasReplyFollowingView.topAnchor.constraint(equalTo: avatarImageView.bottomAnchor), + hasReplyFollowingView.bottomAnchor.constraint(equalTo: bottomAnchor) ] - if UIDevice.current.userInterfaceIdiom == .pad { - for constraint in constraints { - constraint.priority = .justBelowMax - } - } - NSLayoutConstraint.activate(constraints) } }