Add support for posts with more than four attachments
This commit is contained in:
parent
c29ebbb6a0
commit
509e013380
|
@ -12,7 +12,8 @@ extension UIViewController: UIViewControllerTransitioningDelegate {
|
||||||
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
if presented is LargeImageViewController {
|
if presented is LargeImageViewController {
|
||||||
return LargeImageExpandAnimationController()
|
return LargeImageExpandAnimationController()
|
||||||
} else if presented is GalleryViewController {
|
} else if let presented = presented as? GalleryViewController,
|
||||||
|
presented.sourcesInfo[presented.startIndex] != nil {
|
||||||
return GalleryExpandAnimationController()
|
return GalleryExpandAnimationController()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -21,7 +22,8 @@ extension UIViewController: UIViewControllerTransitioningDelegate {
|
||||||
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
|
||||||
if let dismissed = dismissed as? LargeImageViewController {
|
if let dismissed = dismissed as? LargeImageViewController {
|
||||||
return LargeImageShrinkAnimationController(interactionController: dismissed.dismissInteractionController)
|
return LargeImageShrinkAnimationController(interactionController: dismissed.dismissInteractionController)
|
||||||
} else if let dismissed = dismissed as? GalleryViewController {
|
} else if let dismissed = dismissed as? GalleryViewController,
|
||||||
|
dismissed.sourcesInfo[dismissed.currentIndex] != nil {
|
||||||
return GalleryShrinkAnimationController(interactionController: dismissed.dismissInteractionController)
|
return GalleryShrinkAnimationController(interactionController: dismissed.dismissInteractionController)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Pachyderm
|
||||||
import Gifu
|
import Gifu
|
||||||
|
|
||||||
protocol AttachmentViewDelegate {
|
protocol AttachmentViewDelegate {
|
||||||
func showLargeAttachment(for attachmentView: AttachmentView)
|
func showAttachmentsGallery(startingAt index: Int)
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentView: UIImageView, GIFAnimatable {
|
class AttachmentView: UIImageView, GIFAnimatable {
|
||||||
|
@ -19,15 +19,18 @@ class AttachmentView: UIImageView, GIFAnimatable {
|
||||||
var delegate: AttachmentViewDelegate?
|
var delegate: AttachmentViewDelegate?
|
||||||
|
|
||||||
var attachment: Attachment!
|
var attachment: Attachment!
|
||||||
|
var index: Int!
|
||||||
|
|
||||||
var gifData: Data?
|
var gifData: Data?
|
||||||
|
|
||||||
public lazy var animator: Animator? = Animator(withDelegate: self)
|
public lazy var animator: Animator? = Animator(withDelegate: self)
|
||||||
|
|
||||||
init(attachment: Attachment) {
|
init(attachment: Attachment, index: Int) {
|
||||||
super.init(image: nil)
|
super.init(image: nil)
|
||||||
commonInit()
|
commonInit()
|
||||||
|
|
||||||
self.attachment = attachment
|
self.attachment = attachment
|
||||||
|
self.index = index
|
||||||
loadImage()
|
loadImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +65,8 @@ class AttachmentView: UIImageView, GIFAnimatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func imagePressed() {
|
@objc func imagePressed() {
|
||||||
delegate?.showLargeAttachment(for: self)
|
// delegate?.showLargeAttachment(for: self)
|
||||||
|
delegate?.showAttachmentsGallery(startingAt: index)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class AttachmentsContainerView: UIView {
|
||||||
var delegate: AttachmentViewDelegate?
|
var delegate: AttachmentViewDelegate?
|
||||||
|
|
||||||
var statusID: String!
|
var statusID: String!
|
||||||
|
var attachments: [Attachment]!
|
||||||
|
|
||||||
let attachmentViews: NSHashTable<AttachmentView> = .weakObjects()
|
let attachmentViews: NSHashTable<AttachmentView> = .weakObjects()
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ class AttachmentsContainerView: UIView {
|
||||||
|
|
||||||
func updateUI(status: Status) {
|
func updateUI(status: Status) {
|
||||||
self.statusID = status.id
|
self.statusID = status.id
|
||||||
let attachments = status.attachments.filter { $0.kind == .image }
|
attachments = status.attachments.filter { $0.kind == .image }
|
||||||
|
|
||||||
attachmentViews.removeAllObjects()
|
attachmentViews.removeAllObjects()
|
||||||
subviews.forEach { $0.removeFromSuperview() }
|
subviews.forEach { $0.removeFromSuperview() }
|
||||||
|
@ -57,24 +58,24 @@ class AttachmentsContainerView: UIView {
|
||||||
|
|
||||||
switch attachments.count {
|
switch attachments.count {
|
||||||
case 1:
|
case 1:
|
||||||
fillView(createAttachmentView(attachments[0]))
|
fillView(createAttachmentView(index: 0))
|
||||||
case 2:
|
case 2:
|
||||||
let left = createAttachmentView(attachments[0])
|
let left = createAttachmentView(index: 0)
|
||||||
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
||||||
left,
|
left,
|
||||||
createAttachmentView(attachments[1])
|
createAttachmentView(index: 1)
|
||||||
]))
|
]))
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
left.halfWidth()
|
left.halfWidth()
|
||||||
])
|
])
|
||||||
case 3:
|
case 3:
|
||||||
let left = createAttachmentView(attachments[0])
|
let left = createAttachmentView(index: 0)
|
||||||
let topRight = createAttachmentView(attachments[1])
|
let topRight = createAttachmentView(index: 1)
|
||||||
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
||||||
left,
|
left,
|
||||||
createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
||||||
topRight,
|
topRight,
|
||||||
createAttachmentView(attachments[2])
|
createAttachmentView(index: 2)
|
||||||
])
|
])
|
||||||
]))
|
]))
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
@ -82,17 +83,17 @@ class AttachmentsContainerView: UIView {
|
||||||
topRight.halfHeight(),
|
topRight.halfHeight(),
|
||||||
])
|
])
|
||||||
case 4:
|
case 4:
|
||||||
let topLeft = createAttachmentView(attachments[0])
|
let topLeft = createAttachmentView(index: 0)
|
||||||
let left = createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
let left = createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
||||||
topLeft,
|
topLeft,
|
||||||
createAttachmentView(attachments[2])
|
createAttachmentView(index: 2)
|
||||||
])
|
])
|
||||||
let topRight = createAttachmentView(attachments[1])
|
let topRight = createAttachmentView(index: 1)
|
||||||
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
||||||
left,
|
left,
|
||||||
createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
||||||
topRight,
|
topRight,
|
||||||
createAttachmentView(attachments[3])
|
createAttachmentView(index: 3)
|
||||||
])
|
])
|
||||||
]))
|
]))
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
|
@ -100,8 +101,41 @@ class AttachmentsContainerView: UIView {
|
||||||
topLeft.halfHeight(),
|
topLeft.halfHeight(),
|
||||||
topRight.halfHeight(),
|
topRight.halfHeight(),
|
||||||
])
|
])
|
||||||
default:
|
default: // more than 4
|
||||||
fatalError("Too many attachments")
|
let moreView = UIView()
|
||||||
|
moreView.backgroundColor = .secondarySystemBackground
|
||||||
|
moreView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
moreView.isUserInteractionEnabled = true
|
||||||
|
moreView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(moreViewTapped)))
|
||||||
|
let moreLabel = UILabel()
|
||||||
|
moreLabel.text = "\(attachments.count - 3) more..."
|
||||||
|
moreLabel.textColor = .secondaryLabel
|
||||||
|
moreLabel.textAlignment = .center
|
||||||
|
moreLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
moreView.addSubview(moreLabel)
|
||||||
|
|
||||||
|
let topLeft = createAttachmentView(index: 0)
|
||||||
|
let left = createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
||||||
|
topLeft,
|
||||||
|
createAttachmentView(index: 2)
|
||||||
|
])
|
||||||
|
let topRight = createAttachmentView(index: 1)
|
||||||
|
fillView(createAttachmentsStack(axis: .horizontal, arrangedSubviews: [
|
||||||
|
left,
|
||||||
|
createAttachmentsStack(axis: .vertical, arrangedSubviews: [
|
||||||
|
topRight,
|
||||||
|
moreView
|
||||||
|
])
|
||||||
|
]))
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
left.halfWidth(),
|
||||||
|
topLeft.halfHeight(),
|
||||||
|
topRight.halfHeight(),
|
||||||
|
moreView.leadingAnchor.constraint(equalTo: moreLabel.leadingAnchor),
|
||||||
|
moreLabel.trailingAnchor.constraint(equalTo: moreView.trailingAnchor),
|
||||||
|
moreView.topAnchor.constraint(equalTo: moreLabel.topAnchor),
|
||||||
|
moreLabel.bottomAnchor.constraint(equalTo: moreView.bottomAnchor),
|
||||||
|
])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.isHidden = true
|
self.isHidden = true
|
||||||
|
@ -114,8 +148,8 @@ class AttachmentsContainerView: UIView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createAttachmentView(_ attachment: Attachment) -> AttachmentView {
|
private func createAttachmentView(index: Int) -> AttachmentView {
|
||||||
let attachmentView = AttachmentView(attachment: attachment)
|
let attachmentView = AttachmentView(attachment: attachments[index], index: index)
|
||||||
attachmentView.delegate = delegate
|
attachmentView.delegate = delegate
|
||||||
attachmentView.translatesAutoresizingMaskIntoConstraints = false
|
attachmentView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
attachmentViews.add(attachmentView)
|
attachmentViews.add(attachmentView)
|
||||||
|
@ -133,17 +167,12 @@ class AttachmentsContainerView: UIView {
|
||||||
private func createBlurView() {
|
private func createBlurView() {
|
||||||
let blur = UIBlurEffect(style: .dark)
|
let blur = UIBlurEffect(style: .dark)
|
||||||
let blurView = UIVisualEffectView(effect: blur)
|
let blurView = UIVisualEffectView(effect: blur)
|
||||||
// let blurView = UIVisualEffectView(frame: bounds)
|
|
||||||
blurView.effect = blur
|
blurView.effect = blur
|
||||||
blurView.translatesAutoresizingMaskIntoConstraints = false
|
blurView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
fillView(blurView)
|
fillView(blurView)
|
||||||
// addSubview(blurView)
|
|
||||||
let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blur, style: .label))
|
let vibrancyView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: blur, style: .label))
|
||||||
// let vibrancyView = UIVisualEffectView(frame: blurView.bounds)
|
|
||||||
// vibrancyView.effect = UIVibrancyEffect(blurEffect: blur, style: .label)
|
|
||||||
vibrancyView.translatesAutoresizingMaskIntoConstraints = false
|
vibrancyView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
fillView(vibrancyView, in: blurView.contentView)
|
fillView(vibrancyView, in: blurView.contentView)
|
||||||
// addSubview(vibrancyView)
|
|
||||||
blurView.contentView.addSubview(vibrancyView)
|
blurView.contentView.addSubview(vibrancyView)
|
||||||
|
|
||||||
let image = UIImage(systemName: "eye")!
|
let image = UIImage(systemName: "eye")!
|
||||||
|
@ -179,8 +208,6 @@ class AttachmentsContainerView: UIView {
|
||||||
hideButton.alpha = 0
|
hideButton.alpha = 0
|
||||||
hideButton.layer.cornerRadius = 2
|
hideButton.layer.cornerRadius = 2
|
||||||
hideButton.layer.masksToBounds = true
|
hideButton.layer.masksToBounds = true
|
||||||
// hideButton.backgroundColor = tintColor
|
|
||||||
// hideButton.tintColor =
|
|
||||||
hideButton.setImage(UIImage(systemName: "eye.slash.fill"), for: .normal)
|
hideButton.setImage(UIImage(systemName: "eye.slash.fill"), for: .normal)
|
||||||
hideButton.addTarget(self, action: #selector(hideButtonTapped), for: .touchUpInside)
|
hideButton.addTarget(self, action: #selector(hideButtonTapped), for: .touchUpInside)
|
||||||
|
|
||||||
|
@ -232,6 +259,12 @@ class AttachmentsContainerView: UIView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc func moreViewTapped() {
|
||||||
|
guard attachments.count > 4 else { return }
|
||||||
|
// the more view shows up in place of the fourth attachemtn view, show tapping it should start at the fourth attachment
|
||||||
|
delegate?.showAttachmentsGallery(startingAt: 3)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate extension UIView {
|
fileprivate extension UIView {
|
||||||
|
|
|
@ -192,11 +192,10 @@ class ConversationMainStatusTableViewCell: UITableViewCell, PreferencesAdaptive
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ConversationMainStatusTableViewCell: AttachmentViewDelegate {
|
extension ConversationMainStatusTableViewCell: AttachmentViewDelegate {
|
||||||
func showLargeAttachment(for attachmentView: AttachmentView) {
|
func showAttachmentsGallery(startingAt index: Int) {
|
||||||
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||||
let startIndex = status.attachments.firstIndex { $0.id == attachmentView.attachment.id } ?? 0
|
|
||||||
let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:))
|
let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:))
|
||||||
delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: startIndex)
|
delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -304,11 +304,10 @@ extension StatusTableViewCell: TableViewSwipeActionProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension StatusTableViewCell: AttachmentViewDelegate {
|
extension StatusTableViewCell: AttachmentViewDelegate {
|
||||||
func showLargeAttachment(for attachmentView: AttachmentView) {
|
func showAttachmentsGallery(startingAt index: Int) {
|
||||||
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
guard let status = MastodonCache.status(for: statusID) else { fatalError("Missing cached status \(statusID!)") }
|
||||||
let startIndex = status.attachments.firstIndex { $0.id == attachmentView.attachment.id } ?? 0
|
|
||||||
let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:))
|
let sourceViews = status.attachments.map(attachmentsView.getAttachmentView(for:))
|
||||||
delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: startIndex)
|
delegate?.showGallery(attachments: status.attachments, sourceViews: sourceViews, startIndex: index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue