Unified detail views, model

This commit is contained in:
Christoph Hagen
2024-12-16 09:54:21 +01:00
parent 1e67a99866
commit 31d1ecb8bd
57 changed files with 853 additions and 954 deletions

View File

@ -5,44 +5,29 @@ struct FileDetailView: View {
@ObservedObject
var file: FileResource
@State
private var newId: String
init(file: FileResource) {
self.file = file
self.newId = file.id
}
private let allowedCharactersInPostId = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-.")).inverted
private var idExists: Bool {
file.content.files.contains { $0.id == newId }
}
private var containsInvalidCharacters: Bool {
newId.rangeOfCharacter(from: allowedCharactersInPostId) != nil
}
var body: some View {
VStack(alignment: .leading) {
Text("File Name")
.font(.headline)
HStack {
TextField("", text: $newId)
.textFieldStyle(.roundedBorder)
Button(action: setNewId) {
Text("Update")
}
.disabled(newId.isEmpty || containsInvalidCharacters || idExists)
}
Text("German Description")
.font(.headline)
TextField("", text: $file.german)
.textFieldStyle(.roundedBorder)
Text("English Description")
.font(.headline)
TextField("", text: $file.english)
.textFieldStyle(.roundedBorder)
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 file.type.isImage {
Text("Image size")
.font(.headline)
@ -53,12 +38,6 @@ struct FileDetailView: View {
Spacer()
}.padding()
}
private func setNewId() {
if !file.update(id: newId) {
newId = file.id
}
}
}
extension FileDetailView: MainContentView {

View File

@ -1,6 +1,6 @@
import SwiftUI
private enum FileFilterType: String, Hashable, CaseIterable, Identifiable {
enum FileFilterType: String, Hashable, CaseIterable, Identifiable {
case images
case text
case videos
@ -38,11 +38,19 @@ struct FileListView: View {
var selectedFile: FileResource?
@State
private var selectedFileType: FileFilterType = .images
private var selectedFileType: FileFilterType
@State
private var searchString = ""
let allowedType: FileFilterType?
init(selectedFile: Binding<FileResource?>, allowedType: FileFilterType? = nil) {
self._selectedFile = selectedFile
self.allowedType = allowedType
self.selectedFileType = allowedType ?? .images
}
var filesBySelectedType: [FileResource] {
content.files.filter { selectedFileType.matches($0.type) }
}
@ -63,6 +71,7 @@ struct FileListView: View {
}
.pickerStyle(.segmented)
.padding(.trailing, 7)
.disabled(allowedType != nil)
TextField("", text: $searchString, prompt: Text("Search"))
.textFieldStyle(.roundedBorder)
.padding(.horizontal, 8)

View File

@ -2,15 +2,18 @@ import SwiftUI
struct FileSelectionView: View {
@Binding
private var selectedFile: FileResource?
@Environment(\.dismiss)
private var dismiss
init(selectedFile: Binding<FileResource?>) {
@Binding
private var selectedFile: FileResource?
let allowedType: FileFilterType?
init(selectedFile: Binding<FileResource?>, allowedType: FileFilterType? = nil) {
self._selectedFile = selectedFile
self.newSelection = selectedFile.wrappedValue
self.allowedType = allowedType
}
@State
@ -18,7 +21,7 @@ struct FileSelectionView: View {
var body: some View {
VStack {
FileListView(selectedFile: $newSelection)
FileListView(selectedFile: $newSelection, allowedType: allowedType)
.frame(minHeight: 500, idealHeight: 600)
HStack {
Button("Cancel") {