fix: snap to replied-to UX lag issue
This commit is contained in:
parent
add3d7d32c
commit
d61a9b315f
|
@ -860,20 +860,45 @@ extension ComposeViewController {
|
|||
|
||||
let repliedToCellFrame = viewModel.repliedToCellFrame.value
|
||||
guard repliedToCellFrame != .zero else { return }
|
||||
let throttle = viewModel.repliedToCellFrame.value.height - scrollView.adjustedContentInset.top
|
||||
// print("\(throttle) - \(scrollView.contentOffset.y)")
|
||||
|
||||
// try to find some patterns:
|
||||
// print("""
|
||||
// repliedToCellFrame: \(viewModel.repliedToCellFrame.value.height)
|
||||
// scrollView.contentOffset.y: \(scrollView.contentOffset.y)
|
||||
// scrollView.contentSize.height: \(scrollView.contentSize.height)
|
||||
// scrollView.frame: \(scrollView.frame)
|
||||
// scrollView.adjustedContentInset.top: \(scrollView.adjustedContentInset.top)
|
||||
// scrollView.adjustedContentInset.bottom: \(scrollView.adjustedContentInset.bottom)
|
||||
// """)
|
||||
|
||||
switch viewModel.collectionViewState.value {
|
||||
case .fold:
|
||||
if scrollView.contentOffset.y < throttle {
|
||||
os_log("%{public}s[%{public}ld], %{public}s: fold", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
guard velocity.y < 0 else { return }
|
||||
let offsetY = scrollView.contentOffset.y + scrollView.adjustedContentInset.top
|
||||
if offsetY < -44 {
|
||||
tableView.contentInset.top = 0
|
||||
targetContentOffset.pointee = CGPoint(x: 0, y: -scrollView.adjustedContentInset.top)
|
||||
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 {
|
||||
os_log("%{public}s[%{public}ld], %{public}s: expand", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
guard velocity.y > 0 else { return }
|
||||
// check if top across
|
||||
let topOffset = (scrollView.contentOffset.y + scrollView.adjustedContentInset.top) - repliedToCellFrame.height
|
||||
|
||||
// check if bottom bounce
|
||||
let bottomOffsetY = scrollView.contentOffset.y + (scrollView.frame.height - scrollView.adjustedContentInset.bottom)
|
||||
let bottomOffset = bottomOffsetY - scrollView.contentSize.height
|
||||
|
||||
if topOffset > 44 {
|
||||
// do not interrupt user scrolling
|
||||
viewModel.collectionViewState.value = .fold
|
||||
} else if bottomOffset > 44 {
|
||||
tableView.contentInset.top = -repliedToCellFrame.height
|
||||
targetContentOffset.pointee = CGPoint(x: 0, y: -repliedToCellFrame.height)
|
||||
viewModel.collectionViewState.value = .fold
|
||||
os_log("%{public}s[%{public}ld], %{public}s: expand", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -910,7 +935,8 @@ extension ComposeViewController: UICollectionViewDelegate {
|
|||
extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
|
||||
|
||||
func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
|
||||
return traitCollection.userInterfaceIdiom == .pad ? .formSheet : .automatic
|
||||
return .fullScreen
|
||||
//return traitCollection.userInterfaceIdiom == .pad ? .formSheet : .automatic
|
||||
}
|
||||
|
||||
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
|
||||
|
|
|
@ -253,6 +253,8 @@ extension ComposeViewModel: UITableViewDataSource {
|
|||
cell.statusContentWarningEditorView.alpha = 0
|
||||
UIView.animate(withDuration: 0.33, delay: 0, options: [.curveEaseOut]) {
|
||||
cell.statusContentWarningEditorView.alpha = 1
|
||||
tableView.beginUpdates()
|
||||
tableView.endUpdates()
|
||||
} completion: { _ in
|
||||
// do nothing
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ final class ComposeViewModel: NSObject {
|
|||
let selectedStatusVisibility: CurrentValueSubject<ComposeToolbarView.VisibilitySelectionType, Never>
|
||||
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 traitCollectionDidChangePublisher = CurrentValueSubject<Void, Never>(Void()) // use CurrentValueSubject to make initial event emit
|
||||
let repliedToCellFrame = CurrentValueSubject<CGRect, Never>(.zero)
|
||||
let autoCompleteRetryLayoutTimes = CurrentValueSubject<Int, Never>(0)
|
||||
let autoCompleteInfo = CurrentValueSubject<ComposeViewController.AutoCompleteInfo?, Never>(nil)
|
||||
|
|
|
@ -57,29 +57,43 @@ extension StatusContentWarningEditorView {
|
|||
containerBackgroundView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 1024),
|
||||
containerBackgroundView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
||||
])
|
||||
|
||||
iconImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(iconImageView)
|
||||
|
||||
let containerStackView = UIStackView()
|
||||
containerStackView.axis = .horizontal
|
||||
containerStackView.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(containerStackView)
|
||||
NSLayoutConstraint.activate([
|
||||
iconImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||
iconImageView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
|
||||
iconImageView.widthAnchor.constraint(equalToConstant: StatusView.avatarImageSize.width).priority(.defaultHigh), // center alignment to avatar
|
||||
])
|
||||
iconImageView.setContentHuggingPriority(.required - 2, for: .horizontal)
|
||||
|
||||
textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(textView)
|
||||
NSLayoutConstraint.activate([
|
||||
textView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||
textView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor, constant: 6).priority(.required - 1),
|
||||
textView.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: StatusView.avatarToLabelSpacing - 4), // align to name label. minus magic 4pt to remove addition inset
|
||||
textView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
|
||||
bottomAnchor.constraint(greaterThanOrEqualTo: textView.bottomAnchor, constant: 6).priority(.required - 1),
|
||||
//textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 44).priority(.defaultHigh),
|
||||
containerStackView.topAnchor.constraint(equalTo: topAnchor, constant: 6),
|
||||
containerStackView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
|
||||
containerStackView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
|
||||
bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 6),
|
||||
])
|
||||
|
||||
textView.setContentHuggingPriority(.required - 1, for: .vertical)
|
||||
textView.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
containerStackView.addArrangedSubview(iconImageView)
|
||||
iconImageView.setContentHuggingPriority(.required - 1, for: .horizontal)
|
||||
containerStackView.addArrangedSubview(textView)
|
||||
|
||||
// iconImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
// addSubview(iconImageView)
|
||||
// NSLayoutConstraint.activate([
|
||||
// iconImageView.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
|
||||
// iconImageView.widthAnchor.constraint(equalToConstant: StatusView.avatarImageSize.width).priority(.defaultHigh), // center alignment to avatar
|
||||
// ])
|
||||
// iconImageView.setContentHuggingPriority(.required - 2, for: .horizontal)
|
||||
//
|
||||
// textView.translatesAutoresizingMaskIntoConstraints = false
|
||||
// addSubview(textView)
|
||||
// NSLayoutConstraint.activate([
|
||||
// textView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||
// textView.topAnchor.constraint(equalTo: topAnchor, constant: 6),
|
||||
// textView.leadingAnchor.constraint(equalTo: iconImageView.trailingAnchor, constant: StatusView.avatarToLabelSpacing - 4), // align to name label. minus magic 4pt to remove addition inset
|
||||
// textView.trailingAnchor.constraint(equalTo: layoutMarginsGuide.trailingAnchor),
|
||||
// bottomAnchor.constraint(equalTo: textView.bottomAnchor, constant: 6),
|
||||
// textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 44).priority(.defaultHigh),
|
||||
// ])
|
||||
//
|
||||
// textView.setContentHuggingPriority(.required - 1, for: .vertical)
|
||||
// textView.setContentCompressionResistancePriority(.required - 1, for: .vertical)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue