Add support for posts with more than four attachments

This commit is contained in:
Shadowfacts 2019-07-27 22:45:11 -04:00
parent c29ebbb6a0
commit 509e013380
Signed by untrusted user: shadowfacts
GPG Key ID: 94A5AB95422746E5
5 changed files with 71 additions and 34 deletions

View File

@ -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

View File

@ -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 gifData: Data? var index: Int!
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)
} }
} }

View File

@ -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)
@ -231,6 +258,12 @@ class AttachmentsContainerView: UIView {
blurView.alpha = 1 blurView.alpha = 1
} }
} }
@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)
}
} }

View File

@ -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)
} }
} }

View File

@ -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)
} }
} }