Generate video thumbnails

This commit is contained in:
Christoph Hagen
2025-01-25 22:14:31 +01:00
parent 200fdc813d
commit 06b4c1ed76
10 changed files with 254 additions and 54 deletions

View File

@ -104,6 +104,7 @@ struct AddFileView: View {
content.add(resource)
selectedFile = resource
}
content.generateMissingVideoThumbnails()
dismiss()
}
}

View File

@ -26,7 +26,7 @@ struct FileContentView: View {
} else {
switch file.type.category {
case .image:
file.imageToDisplay
(file.imageToDisplay ?? Image(systemSymbol: .exclamationmarkTriangle))
.resizable()
.aspectRatio(contentMode: .fit)
case .model:
@ -44,14 +44,19 @@ struct FileContentView: View {
.id(file.id)
case .video:
VStack {
Image(systemSymbol: .film)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconSize)
Text("No preview available")
.font(.title)
}
.foregroundStyle(.secondary)
if let image = file.imageToDisplay {
image
.resizable()
.aspectRatio(contentMode: .fit)
} else {
Image(systemSymbol: .film)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: iconSize)
Button("Generate preview", action: generateVideoPreview)
.font(.body)
}
}.foregroundStyle(.secondary)
case .resource:
VStack {
Image(systemSymbol: .docQuestionmark)
@ -76,6 +81,10 @@ struct FileContentView: View {
}
}.padding()
}
private func generateVideoPreview() {
file.createVideoThumbnail()
}
}
extension FileContentView: MainContentView {

View File

@ -28,7 +28,7 @@ struct OptionalImagePropertyView: View {
}
if let image = selectedImage {
image.imageToDisplay
(image.imageToDisplay ?? Image(systemSymbol: .exclamationmarkTriangle))
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxHeight: 300)

View File

@ -42,6 +42,70 @@ private struct LinkedPageTagView: View {
}
}
private struct PostImageView: View {
@ObservedObject
var image: FileResource
var body: some View {
if let preview = image.imageToDisplay {
preview
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: 300, maxHeight: 200)
.cornerRadius(8)
} else if image.type.isImage {
VStack {
Image(systemSymbol: .exclamationmarkTriangle)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 100)
Text(image.id)
.font(.title)
Text("Failed to load image")
.font(.body)
}
.frame(width: 300, height: 200)
.background(Color.gray)
.cornerRadius(8)
} else if image.type.isVideo {
VStack {
Image(systemSymbol: .film)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 100)
Text(image.id)
.font(.title)
Button("Generate preview") {
generateVideoPreview(image)
}
.font(.body)
}
.frame(width: 300, height: 200)
.background(Color.gray)
.cornerRadius(8)
} else {
VStack {
Image(systemSymbol: .exclamationmarkTriangle)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 100)
Text(image.id)
.font(.title)
Text("Invalid media type")
.font(.body)
}
.frame(width: 300, height: 200)
.background(Color.gray)
.cornerRadius(8)
}
}
private func generateVideoPreview(_ image: FileResource) {
image.createVideoThumbnail()
}
}
struct LocalizedPostContentView: View {
@Environment(\.language)
@ -98,27 +162,7 @@ struct LocalizedPostContentView: View {
ScrollView(.horizontal) {
HStack(alignment: .center, spacing: 8) {
ForEach(post.images) { image in
if image.type.isImage {
image.imageToDisplay
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: 300, maxHeight: 200)
.cornerRadius(8)
} else {
VStack {
Image(systemSymbol: .film)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 100)
Text(image.id)
.font(.title)
}
//.foregroundStyle(.secondary)
.frame(width: 300, height: 200)
.background(Color.gray)
.cornerRadius(8)
}
PostImageView(image: image)
}
}
}