Impressia/Vernissage/Widgets/ImagesCarousel.swift

129 lines
4.6 KiB
Swift
Raw Normal View History

2023-01-03 14:09:22 +01:00
//
// https://mczachurski.dev
// Copyright © 2023 Marcin Czachurski and the repository contributors.
2023-03-28 10:35:38 +02:00
// Licensed under the Apache License 2.0.
2023-01-03 14:09:22 +01:00
//
2023-01-03 14:09:22 +01:00
import SwiftUI
2023-02-19 10:32:38 +01:00
import PixelfedKit
2023-04-07 14:20:12 +02:00
import ClientKit
2023-04-07 14:38:50 +02:00
import ServicesKit
2023-01-03 14:09:22 +01:00
struct ImagesCarousel: View {
@State public var attachments: [AttachmentModel]
2023-01-26 15:10:47 +01:00
@State private var imageHeight: Double
@State private var imageWidth: Double
@State private var selected: String
@State private var heightWasPrecalculated: Bool
@Binding public var selectedAttachment: AttachmentModel?
2023-01-08 15:43:55 +01:00
@Binding public var exifCamera: String?
@Binding public var exifExposure: String?
@Binding public var exifCreatedDate: String?
@Binding public var exifLens: String?
2023-03-08 17:43:05 +01:00
@Binding public var description: String?
init(attachments: [AttachmentModel],
selectedAttachment: Binding<AttachmentModel?>,
2023-01-26 15:10:47 +01:00
exifCamera: Binding<String?>,
exifExposure: Binding<String?>,
exifCreatedDate: Binding<String?>,
2023-03-08 17:43:05 +01:00
exifLens: Binding<String?>,
description: Binding<String?>
2023-01-26 15:10:47 +01:00
) {
_selectedAttachment = selectedAttachment
2023-01-26 15:10:47 +01:00
_exifCamera = exifCamera
_exifExposure = exifExposure
_exifCreatedDate = exifCreatedDate
_exifLens = exifLens
2023-03-08 17:43:05 +01:00
_description = description
2023-01-26 15:10:47 +01:00
self.attachments = attachments
self.selected = String.empty()
2023-01-27 15:46:09 +01:00
let highestImage = attachments.getHighestImage()
let imgHeight = Double((highestImage?.meta as? ImageMetadata)?.original?.height ?? 0)
let imgWidth = Double((highestImage?.meta as? ImageMetadata)?.original?.width ?? 0)
2023-01-26 20:35:24 +01:00
// Calculate size of frame (first from cache, then from metadata).
2023-01-28 21:09:31 +01:00
if let highestImage, let size = ImageSizeService.shared.get(for: highestImage.url) {
2023-01-26 20:35:24 +01:00
self.imageWidth = size.width
self.imageHeight = size.height
self.heightWasPrecalculated = true
2023-01-27 15:46:09 +01:00
} else if let highestImage, imgHeight > 0 && imgWidth > 0 {
2023-01-28 21:09:31 +01:00
let size = ImageSizeService.shared.calculate(for: highestImage.url, width: imgWidth, height: imgHeight)
2023-01-26 20:35:24 +01:00
self.imageWidth = size.width
self.imageHeight = size.height
2023-01-26 15:10:47 +01:00
self.heightWasPrecalculated = true
} else {
self.imageWidth = UIScreen.main.bounds.width
self.imageHeight = UIScreen.main.bounds.width * 0.75
self.heightWasPrecalculated = false
}
}
2023-01-03 14:09:22 +01:00
var body: some View {
2023-01-14 11:57:28 +01:00
TabView(selection: $selected) {
2023-01-08 14:50:37 +01:00
ForEach(attachments, id: \.id) { attachment in
2023-01-26 15:10:47 +01:00
ImageCarouselPicture(attachment: attachment) { (attachment, imageData) in
withAnimation {
self.recalculateImageHeight(attachment: attachment, imageData: imageData)
2023-01-26 15:10:47 +01:00
}
2023-01-26 15:10:47 +01:00
DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
attachment.set(data: imageData)
}
2023-01-03 14:09:22 +01:00
}
2023-01-26 15:10:47 +01:00
.tag(attachment.id)
2023-01-03 14:09:22 +01:00
}
}
2023-01-27 15:46:09 +01:00
.frame(height: self.imageHeight)
2023-01-03 14:09:22 +01:00
.tabViewStyle(PageTabViewStyle())
2023-01-14 11:57:28 +01:00
.onChange(of: selected, perform: { index in
2023-01-08 14:50:37 +01:00
if let attachment = attachments.first(where: { item in item.id == index }) {
self.selectedAttachment = attachment
2023-01-08 15:43:55 +01:00
self.exifCamera = attachment.exifCamera
self.exifExposure = attachment.exifExposure
self.exifCreatedDate = attachment.exifCreatedDate
self.exifLens = attachment.exifLens
2023-03-08 17:43:05 +01:00
self.description = attachment.description
2023-01-08 14:50:37 +01:00
}
})
2023-01-03 14:09:22 +01:00
.onAppear {
2023-01-14 11:57:28 +01:00
self.selected = self.attachments.first?.id ?? String.empty()
2023-01-03 14:09:22 +01:00
}
}
private func recalculateImageHeight(attachment: AttachmentModel, imageData: Data) {
2023-01-26 15:10:47 +01:00
guard heightWasPrecalculated == false else {
return
}
2023-01-03 14:09:22 +01:00
var imageHeight = 0.0
var imageWidth = 0.0
2023-01-03 14:09:22 +01:00
for item in attachments {
2023-01-10 20:38:02 +01:00
if let data = item.data, let image = UIImage(data: data) {
2023-01-03 14:09:22 +01:00
if image.size.height > imageHeight {
imageHeight = image.size.height
imageWidth = image.size.width
}
}
}
2023-01-26 15:10:47 +01:00
if let image = UIImage(data: imageData) {
if image.size.height > imageHeight {
imageHeight = image.size.height
imageWidth = image.size.width
}
}
2023-01-28 21:09:31 +01:00
let size = ImageSizeService.shared.calculate(for: attachment.url, width: imageWidth, height: imageHeight)
2023-01-26 20:35:24 +01:00
self.imageWidth = size.width
self.imageHeight = size.height
2023-01-03 14:09:22 +01:00
}
}