feat: make reply to foldable in compose scene

This commit is contained in:
CMK 2021-04-15 12:10:43 +08:00
parent 83904126dd
commit ccb74b08f7
5 changed files with 70 additions and 1 deletions

View File

@ -34,6 +34,7 @@ extension ComposeStatusSection {
dependency: NeedsDependency,
managedObjectContext: NSManagedObjectContext,
composeKind: ComposeKind,
repliedToCellFrameSubscriber: CurrentValueSubject<CGRect, Never>,
customEmojiPickerInputViewModel: CustomEmojiPickerInputViewModel,
textEditorViewTextAttributesDelegate: TextEditorViewTextAttributesDelegate,
composeStatusAttachmentTableViewCellDelegate: ComposeStatusAttachmentCollectionViewCellDelegate,
@ -70,6 +71,8 @@ extension ComposeStatusSection {
cell.statusView.activeTextLabel.configure(content: status.content)
// set date
cell.statusView.dateLabel.text = status.createdAt.shortTimeAgoSinceNow
cell.framePublisher.assign(to: \.value, on: repliedToCellFrameSubscriber).store(in: &cell.disposeBag)
}
return cell
case .input(let replyToStatusObjectID, let attribute):

View File

@ -14,6 +14,8 @@ final class ComposeRepliedToStatusContentCollectionViewCell: UICollectionViewCel
let statusView = StatusView()
let framePublisher = PassthroughSubject<CGRect, Never>()
override func prepareForReuse() {
super.prepareForReuse()
@ -32,6 +34,11 @@ final class ComposeRepliedToStatusContentCollectionViewCell: UICollectionViewCel
_init()
}
override func layoutSubviews() {
super.layoutSubviews()
framePublisher.send(bounds)
}
}
extension ComposeRepliedToStatusContentCollectionViewCell {

View File

@ -31,7 +31,7 @@ final class ComposeViewController: UIViewController, NeedsDependency {
button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.normal.color.withAlphaComponent(0.5)), for: .highlighted)
button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.disabled.color), for: .disabled)
button.setTitleColor(.white, for: .normal)
button.contentEdgeInsets = UIEdgeInsets(top: 5.5, left: 16, bottom: 5.5, right: 16) // set 28pt height
button.contentEdgeInsets = UIEdgeInsets(top: 6, left: 16, bottom: 5, right: 16) // set 28pt height
button.adjustsImageWhenHighlighted = false
return button
}()
@ -50,6 +50,7 @@ final class ComposeViewController: UIViewController, NeedsDependency {
collectionView.register(ComposeStatusPollOptionAppendEntryCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusPollOptionAppendEntryCollectionViewCell.self))
collectionView.register(ComposeStatusPollExpiresOptionCollectionViewCell.self, forCellWithReuseIdentifier: String(describing: ComposeStatusPollExpiresOptionCollectionViewCell.self))
collectionView.backgroundColor = Asset.Scene.Compose.background.color
collectionView.alwaysBounceVertical = true
return collectionView
}()
@ -331,6 +332,24 @@ extension ComposeViewController {
}
})
.store(in: &disposeBag)
// setup snap behavior
Publishers.CombineLatest(
viewModel.repliedToCellFrame.removeDuplicates().eraseToAnyPublisher(),
viewModel.collectionViewState.eraseToAnyPublisher()
)
.receive(on: DispatchQueue.main)
.sink { [weak self] repliedToCellFrame, collectionViewState in
guard let self = self else { return }
guard repliedToCellFrame != .zero else { return }
switch collectionViewState {
case .fold:
self.collectionView.contentInset.top = -repliedToCellFrame.height
case .expand:
self.collectionView.contentInset.top = 0
}
}
.store(in: &disposeBag)
}
override func viewWillAppear(_ animated: Bool) {
@ -754,6 +773,32 @@ extension ComposeViewController: ComposeToolbarViewDelegate {
}
// MARK: - UIScrollViewDelegate
extension ComposeViewController {
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
guard scrollView === collectionView else { return }
let repliedToCellFrame = viewModel.repliedToCellFrame.value
guard repliedToCellFrame != .zero else { return }
let throttle = viewModel.repliedToCellFrame.value.height - scrollView.adjustedContentInset.top
// print("\(throttle) - \(scrollView.contentOffset.y)")
switch viewModel.collectionViewState.value {
case .fold:
if scrollView.contentOffset.y < throttle {
viewModel.collectionViewState.value = .expand
}
os_log("%{public}s[%{public}ld], %{public}s: fold", ((#file as NSString).lastPathComponent), #line, #function)
case .expand:
if scrollView.contentOffset.y > -44 {
viewModel.collectionViewState.value = .fold
os_log("%{public}s[%{public}ld], %{public}s: expand", ((#file as NSString).lastPathComponent), #line, #function)
}
}
}
}
// MARK: - UITableViewDelegate
extension ComposeViewController: UICollectionViewDelegate {
@ -791,6 +836,10 @@ extension ComposeViewController: UICollectionViewDelegate {
// MARK: - UIAdaptivePresentationControllerDelegate
extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
return .fullScreen
}
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
return viewModel.shouldDismiss.value
}

View File

@ -27,6 +27,7 @@ extension ComposeViewModel {
dependency: dependency,
managedObjectContext: context.managedObjectContext,
composeKind: composeKind,
repliedToCellFrameSubscriber: repliedToCellFrame,
customEmojiPickerInputViewModel: customEmojiPickerInputViewModel,
textEditorViewTextAttributesDelegate: textEditorViewTextAttributesDelegate,
composeStatusAttachmentTableViewCellDelegate: composeStatusAttachmentTableViewCellDelegate,

View File

@ -30,6 +30,7 @@ final class ComposeViewModel {
let activeAuthentication: CurrentValueSubject<MastodonAuthentication?, Never>
let activeAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
let traitCollectionDidChangePublisher = CurrentValueSubject<Void, Never>(Void()) // use CurrentValueSubject to make intial event emit
let repliedToCellFrame = CurrentValueSubject<CGRect, Never>(.zero)
// output
var diffableDataSource: UICollectionViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
@ -56,6 +57,7 @@ final class ComposeViewModel {
let isMediaToolbarButtonEnabled = CurrentValueSubject<Bool, Never>(true)
let isPollToolbarButtonEnabled = CurrentValueSubject<Bool, Never>(true)
let characterCount = CurrentValueSubject<Int, Never>(0)
let collectionViewState = CurrentValueSubject<CollectionViewState, Never>(.fold)
// for hashtag: #<hashag>' '
// for mention: @<mention>' '
@ -377,6 +379,13 @@ final class ComposeViewModel {
}
extension ComposeViewModel {
enum CollectionViewState {
case fold // snap to input
case expand // snap to reply
}
}
extension ComposeViewModel {
func createNewPollOptionIfPossible() {
guard pollOptionAttributes.value.count < 4 else { return }