Add more file properties, organize storage, add video block
This commit is contained in:
@ -98,7 +98,9 @@ struct AddFileView: View {
|
||||
content: content,
|
||||
id: file.uniqueId,
|
||||
isExternallyStored: file.url == nil,
|
||||
en: "", de: "")
|
||||
english: "",
|
||||
german: "")
|
||||
|
||||
content.add(resource)
|
||||
selectedFile = resource
|
||||
}
|
||||
|
@ -1,10 +1,42 @@
|
||||
import SwiftUI
|
||||
import SFSafeSymbols
|
||||
|
||||
private extension Button {
|
||||
|
||||
init(_ symbol: SFSymbol, action: @escaping @MainActor () -> Void) where Label == Image {
|
||||
self.init(action: action, label: { Image(systemSymbol: symbol) })
|
||||
}
|
||||
}
|
||||
|
||||
private struct ButtonIcon: View {
|
||||
|
||||
let symbol: SFSymbol
|
||||
|
||||
let action: @MainActor () -> Void
|
||||
|
||||
init(_ symbol: SFSymbol, action: @escaping @MainActor () -> Void) {
|
||||
self.symbol = symbol
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button(action: action) {
|
||||
Image(systemSymbol: symbol)
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FileDetailView: View {
|
||||
|
||||
@EnvironmentObject
|
||||
private var content: Content
|
||||
|
||||
@Environment(\.language)
|
||||
private var language
|
||||
|
||||
@ObservedObject
|
||||
var file: FileResource
|
||||
|
||||
@ -15,58 +47,97 @@ struct FileDetailView: View {
|
||||
private var selectedFile: FileResource?
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
DetailTitle(
|
||||
title: "File",
|
||||
text: "A file that can be used in a post or page")
|
||||
|
||||
ScrollView {
|
||||
VStack(alignment: .leading) {
|
||||
Button("Show in Finder", action: showFileInFinder)
|
||||
Button("Mark as changed", action: markFileAsChanged)
|
||||
Button("Delete resource", action: deleteFile)
|
||||
if file.isExternallyStored {
|
||||
Button("Import file", action: replaceFile)
|
||||
} else {
|
||||
Button("Replace file", action: replaceFile)
|
||||
Button("Make external", action: convertToExternal)
|
||||
}
|
||||
}
|
||||
DetailTitle(
|
||||
title: "File",
|
||||
text: "A file that can be used in a post or page")
|
||||
|
||||
IdPropertyView(
|
||||
id: $file.id,
|
||||
title: "Name",
|
||||
footer: "The unique name of the file, which is also used to reference it in posts and pages.",
|
||||
validation: file.isValid,
|
||||
update: { file.update(id: $0) })
|
||||
|
||||
StringPropertyView(
|
||||
title: "German Description",
|
||||
text: $file.german,
|
||||
footer: "The description for the file in German. Descriptions are used for images and to explain the content of a file.")
|
||||
|
||||
StringPropertyView(
|
||||
title: "English Description",
|
||||
text: $file.english,
|
||||
footer: "The description for the file in English. Descriptions are used for images and to explain the content of a file.")
|
||||
|
||||
if let imageDimensions = file.imageDimensions {
|
||||
GenericPropertyView(title: "Image dimensions") {
|
||||
Text("\(Int(imageDimensions.width)) x \(Int(imageDimensions.height)) (\(file.aspectRatio))")
|
||||
GenericPropertyView(title: "Actions") {
|
||||
HStack(spacing: 10) {
|
||||
ButtonIcon(.folder, action: showFileInFinder)
|
||||
ButtonIcon(.arrowClockwise, action: markFileAsChanged)
|
||||
if file.isExternallyStored {
|
||||
ButtonIcon(.squareAndArrowDown, action: replaceFile)
|
||||
} else {
|
||||
ButtonIcon(.arrowLeftArrowRight, action: replaceFile)
|
||||
ButtonIcon(.squareDashed, action: convertToExternal)
|
||||
}
|
||||
ButtonIcon(.trash, action: deleteFile)
|
||||
.foregroundStyle(.red)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.foregroundStyle(.blue)
|
||||
}
|
||||
#warning("Add button to show image versions")
|
||||
}
|
||||
if let fileSize = file.fileSize {
|
||||
GenericPropertyView(title: "File size") {
|
||||
Text(formatBytes(fileSize))
|
||||
|
||||
IdPropertyView(
|
||||
id: $file.id,
|
||||
title: "Name",
|
||||
footer: "The unique name of the file, which is also used to reference it in posts and pages.",
|
||||
validation: file.isValid,
|
||||
update: { file.update(id: $0) })
|
||||
|
||||
switch language {
|
||||
case .english:
|
||||
StringPropertyView(
|
||||
title: "Description",
|
||||
text: $file.english,
|
||||
footer: "The description for the file. Descriptions are used for images and to explain the content of a file.")
|
||||
case .german:
|
||||
StringPropertyView(
|
||||
title: "Description",
|
||||
text: $file.german,
|
||||
footer: "The description for the file. Descriptions are used for images and to explain the content of a file.")
|
||||
}
|
||||
}
|
||||
Spacer()
|
||||
}.padding()
|
||||
.onAppear {
|
||||
if file.fileSize == nil {
|
||||
file.determineFileSize()
|
||||
|
||||
OptionalStringPropertyView(
|
||||
title: "Version",
|
||||
text: $file.version,
|
||||
footer: "The version of this file.")
|
||||
|
||||
OptionalStringPropertyView(
|
||||
title: "Source URL",
|
||||
text: $file.sourceUrl,
|
||||
footer: "The url where this file can be downloaded from.")
|
||||
|
||||
OptionalStringPropertyView(
|
||||
title: "Custom output path",
|
||||
text: $file.customOutputPath,
|
||||
footer: "A custom path where the file is stored in the output folder")
|
||||
|
||||
if let imageDimensions = file.imageDimensions {
|
||||
GenericPropertyView(title: "Image dimensions") {
|
||||
Text("\(Int(imageDimensions.width)) x \(Int(imageDimensions.height)) (\(file.aspectRatio))")
|
||||
}
|
||||
}
|
||||
if let fileSize = file.fileSize {
|
||||
GenericPropertyView(title: "File size") {
|
||||
Text(formatBytes(fileSize))
|
||||
}
|
||||
}
|
||||
GenericPropertyView(title: "Added") {
|
||||
Text(file.addedDate.formatted())
|
||||
}
|
||||
|
||||
GenericPropertyView(title: "Modified") {
|
||||
Text(file.modifiedDate.formatted())
|
||||
}
|
||||
|
||||
if !file.generatedImageVersions.isEmpty {
|
||||
GenericPropertyView(title: "Image versions") {
|
||||
VStack(alignment: .leading) {
|
||||
ForEach(file.generatedImageVersions.sorted(), id: \.self) { version in
|
||||
Text(version)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.padding()
|
||||
}.onAppear {
|
||||
if file.fileSize == nil {
|
||||
file.determineFileSize()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func formatBytes(_ bytes: Int) -> String {
|
||||
@ -133,7 +204,7 @@ struct FileDetailView: View {
|
||||
return
|
||||
}
|
||||
|
||||
guard content.storage.delete(file: file.id) else {
|
||||
guard content.storage.removeFileContent(file: file.id) else {
|
||||
print("File '\(file.id)': Failed to delete file to make it external")
|
||||
return
|
||||
}
|
||||
|
@ -184,8 +184,8 @@ struct PageIssueView: View {
|
||||
content: content,
|
||||
id: fileId,
|
||||
isExternallyStored: true,
|
||||
en: "",
|
||||
de: "")
|
||||
english: "",
|
||||
german: "")
|
||||
content.add(file)
|
||||
|
||||
retryPageCheck()
|
||||
|
Reference in New Issue
Block a user