107 lines
4.2 KiB
Swift
107 lines
4.2 KiB
Swift
//
|
|
// StatusAttachmentsGalleryDataSource.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 3/17/24.
|
|
// Copyright © 2024 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import GalleryVC
|
|
import Pachyderm
|
|
import TuskerComponents
|
|
import AVFoundation
|
|
|
|
class StatusAttachmentsGalleryDataSource: GalleryDataSource {
|
|
let attachments: [Attachment]
|
|
let sourceViews: NSHashTable<AttachmentView>
|
|
|
|
init(attachments: [Attachment], sourceViews: NSHashTable<AttachmentView>) {
|
|
self.attachments = attachments
|
|
self.sourceViews = sourceViews
|
|
}
|
|
|
|
func galleryItemsCount() -> Int {
|
|
attachments.count
|
|
}
|
|
|
|
func galleryContentViewController(forItemAt index: Int) -> any GalleryContentViewController {
|
|
let attachment = attachments[index]
|
|
switch attachment.kind {
|
|
case .image:
|
|
if let view = attachmentView(for: attachment),
|
|
let image = view.attachmentImage {
|
|
return ImageGalleryContentViewController(
|
|
url: attachment.url,
|
|
caption: attachment.description,
|
|
originalData: view.originalData,
|
|
image: image,
|
|
// TODO: if automatically play gifs is off, this will start the source view playing too
|
|
gifController: view.gifController
|
|
)
|
|
} else {
|
|
return LoadingGalleryContentViewController {
|
|
let (data, image) = await ImageCache.attachments.get(attachment.url, loadOriginal: true)
|
|
if let image {
|
|
let gifController: GIFController? =
|
|
if attachment.url.pathExtension == "gif",
|
|
let data {
|
|
GIFController(gifData: data)
|
|
} else {
|
|
nil
|
|
}
|
|
return ImageGalleryContentViewController(
|
|
url: attachment.url,
|
|
caption: attachment.description,
|
|
originalData: data,
|
|
image: image,
|
|
gifController: gifController
|
|
)
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
case .gifv:
|
|
let controller: GifvController =
|
|
if Preferences.shared.automaticallyPlayGifs,
|
|
let view = attachmentView(for: attachment),
|
|
let controller = view.gifvView?.controller {
|
|
controller
|
|
} else {
|
|
GifvController(asset: AVAsset(url: attachment.url))
|
|
}
|
|
return GifvGalleryContentViewController(controller: controller, url: attachment.url, caption: attachment.description)
|
|
case .video:
|
|
return VideoGalleryContentViewController(url: attachment.url, caption: attachment.description)
|
|
case .audio:
|
|
// TODO: use separate content VC with audio visualization?
|
|
return VideoGalleryContentViewController(url: attachment.url, caption: attachment.description)
|
|
case .unknown:
|
|
return LoadingGalleryContentViewController {
|
|
do {
|
|
let (data, _) = try await URLSession.shared.data(from: attachment.url)
|
|
let url = FileManager.default.temporaryDirectory.appendingPathComponent(attachment.url.lastPathComponent)
|
|
try data.write(to: url)
|
|
return FallbackGalleryNavigationController(url: url)
|
|
} catch {
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func galleryContentTransitionSourceView(forItemAt index: Int) -> UIView? {
|
|
let attachment = attachments[index]
|
|
return attachmentView(for: attachment)
|
|
}
|
|
|
|
func galleryApplicationActivities(forItemAt index: Int) -> [UIActivity]? {
|
|
[SaveToPhotosActivity()]
|
|
}
|
|
|
|
private func attachmentView(for attachment: Attachment) -> AttachmentView? {
|
|
return sourceViews.allObjects.first(where: { $0.attachment?.id == attachment.id })
|
|
}
|
|
}
|