MediaPreview.swift 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import UIKit
  2. import SDWebImage
  3. import DcCore
  4. class MediaPreview: DraftPreview {
  5. var imageWidthConstraint: NSLayoutConstraint?
  6. weak var delegate: DraftPreviewDelegate?
  7. public lazy var contentImageView: SDAnimatedImageView = {
  8. let imageView = SDAnimatedImageView()
  9. imageView.translatesAutoresizingMaskIntoConstraints = false
  10. imageView.contentMode = .scaleAspectFit
  11. imageView.clipsToBounds = true
  12. imageView.layer.cornerRadius = 4
  13. imageView.isUserInteractionEnabled = true
  14. return imageView
  15. }()
  16. override func setupSubviews() {
  17. super.setupSubviews()
  18. mainContentView.addSubview(contentImageView)
  19. addConstraints([
  20. contentImageView.constraintAlignTopTo(mainContentView),
  21. contentImageView.constraintAlignLeadingTo(mainContentView, paddingLeading: 14),
  22. contentImageView.constraintAlignTrailingMaxTo(mainContentView, paddingTrailing: 14),
  23. contentImageView.constraintAlignBottomTo(mainContentView),
  24. contentImageView.constraintHeightTo(90)
  25. ])
  26. let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
  27. contentImageView.addGestureRecognizer(gestureRecognizer)
  28. }
  29. override func configure(draft: DraftModel) {
  30. if draft.isEditing {
  31. self.isHidden = true
  32. return
  33. }
  34. if draft.viewType == DC_MSG_GIF || draft.viewType == DC_MSG_IMAGE, let path = draft.attachment {
  35. contentImageView.sd_setImage(with: URL(fileURLWithPath: path, isDirectory: false), completed: { image, error, _, _ in
  36. if let error = error {
  37. logger.error("could not load draft image: \(error)")
  38. self.cancel()
  39. } else if let image = image {
  40. self.setAspectRatio(image: image)
  41. self.delegate?.onAttachmentAdded()
  42. self.accessibilityLabel =
  43. "\(String.localized("attachment")), \(draft.viewType == DC_MSG_GIF ? String.localized("gif") : String.localized("image"))"
  44. }
  45. })
  46. isHidden = false
  47. } else if draft.viewType == DC_MSG_VIDEO, let path = draft.attachment {
  48. if let image = ThumbnailCache.shared.restoreImage(key: path) {
  49. self.contentImageView.image = image
  50. self.setAspectRatio(image: image)
  51. self.delegate?.onAttachmentAdded()
  52. } else {
  53. DispatchQueue.global(qos: .userInteractive).async {
  54. let thumbnailImage = DcUtils.generateThumbnailFromVideo(url: URL(fileURLWithPath: path, isDirectory: false))
  55. if let thumbnailImage = thumbnailImage {
  56. DispatchQueue.main.async { [weak self] in
  57. guard let self = self else { return }
  58. self.contentImageView.image = thumbnailImage
  59. self.setAspectRatio(image: thumbnailImage)
  60. ThumbnailCache.shared.storeImage(image: thumbnailImage, key: path)
  61. self.delegate?.onAttachmentAdded()
  62. }
  63. }
  64. }
  65. }
  66. self.isHidden = false
  67. self.accessibilityLabel = "\(String.localized("attachment")), \(String.localized("video"))"
  68. } else {
  69. isHidden = true
  70. }
  71. }
  72. override public func cancel() {
  73. contentImageView.sd_cancelCurrentImageLoad()
  74. contentImageView.image = nil
  75. delegate?.onCancelAttachment()
  76. accessibilityLabel = nil
  77. }
  78. func setAspectRatio(image: UIImage) {
  79. let height = image.size.height
  80. let width = image.size.width
  81. imageWidthConstraint?.isActive = false
  82. imageWidthConstraint = contentImageView.widthAnchor.constraint(lessThanOrEqualTo: contentImageView.heightAnchor, multiplier: width / height)
  83. imageWidthConstraint?.isActive = true
  84. }
  85. @objc func imageTapped() {
  86. delegate?.onAttachmentTapped()
  87. }
  88. func reload(draft: DraftModel) {
  89. guard let attachment = draft.attachment else { return }
  90. let url = URL(fileURLWithPath: attachment, isDirectory: false)
  91. // there are editing options for DC_MSG_GIF, so that can be ignored
  92. if draft.viewType == DC_MSG_IMAGE {
  93. SDImageCache.shared.removeImage(forKey: url.absoluteString, withCompletion: { [weak self] in
  94. self?.configure(draft: draft)
  95. })
  96. } else if draft.viewType == DC_MSG_VIDEO {
  97. ThumbnailCache.shared.deleteImage(key: attachment)
  98. self.configure(draft: draft)
  99. }
  100. }
  101. }