Tusker/Tusker/Screens/Attachment Gallery/StatusAttachmentsGalleryDat...

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.image {
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, 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 })
}
}