Fix id of Items, saving
This commit is contained in:
@ -78,6 +78,10 @@ struct AddFileView: View {
|
||||
}
|
||||
|
||||
private func importSelectedFiles() {
|
||||
guard !filesToAdd.isEmpty else {
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
for file in filesToAdd {
|
||||
guard file.isSelected else {
|
||||
print("Skipping unselected file \(file.uniqueId)")
|
||||
|
@ -41,7 +41,7 @@ struct FileContentView: View {
|
||||
.foregroundStyle(.secondary)
|
||||
case .text, .code:
|
||||
TextFileContentView(file: file)
|
||||
.id(file.id + file.modifiedDate.description)
|
||||
.id(file.identifier + file.modifiedDate.description)
|
||||
case .video:
|
||||
VStack {
|
||||
if let image = file.imageToDisplay {
|
||||
|
@ -72,11 +72,12 @@ struct FileDetailView: View {
|
||||
}
|
||||
|
||||
IdPropertyView(
|
||||
id: $file.id,
|
||||
id: $file.identifier,
|
||||
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) })
|
||||
.id(file.id)
|
||||
|
||||
switch language {
|
||||
case .english:
|
||||
@ -154,7 +155,7 @@ struct FileDetailView: View {
|
||||
}
|
||||
|
||||
private func showFileInFinder() {
|
||||
content.storage.openFinderWindow(withSelectedFile: file.id)
|
||||
content.storage.openFinderWindow(withSelectedFile: file.identifier)
|
||||
}
|
||||
|
||||
private func markFileAsChanged() {
|
||||
@ -169,11 +170,11 @@ struct FileDetailView: View {
|
||||
|
||||
private func replaceFile() {
|
||||
guard let url = openFilePanel() else {
|
||||
print("File '\(file.id)': No file selected as replacement")
|
||||
print("File '\(file.identifier)': No file selected as replacement")
|
||||
return
|
||||
}
|
||||
guard content.storage.importExternalFile(at: url, fileId: file.id) else {
|
||||
print("File '\(file.id)': Failed to replace file")
|
||||
guard content.storage.importExternalFile(at: url, fileId: file.identifier) else {
|
||||
print("File '\(file.identifier)': Failed to replace file")
|
||||
return
|
||||
}
|
||||
|
||||
@ -197,7 +198,7 @@ struct FileDetailView: View {
|
||||
|
||||
let response = panel.runModal()
|
||||
guard response == .OK else {
|
||||
print("File '\(file.id)': Failed to select file to replace")
|
||||
print("File '\(file.identifier)': Failed to select file to replace")
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -209,8 +210,8 @@ struct FileDetailView: View {
|
||||
return
|
||||
}
|
||||
|
||||
guard content.storage.removeFileContent(file: file.id) else {
|
||||
print("File '\(file.id)': Failed to delete file to make it external")
|
||||
guard content.storage.removeFileContent(file: file.identifier) else {
|
||||
print("File '\(file.identifier)': Failed to delete file to make it external")
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
@ -220,8 +221,8 @@ struct FileDetailView: View {
|
||||
}
|
||||
|
||||
private func deleteFile() {
|
||||
guard content.storage.delete(file: file.id) else {
|
||||
print("File '\(file.id)': Failed to delete file in content folder")
|
||||
guard content.storage.delete(file: file.identifier) else {
|
||||
print("File '\(file.identifier)': Failed to delete file in content folder")
|
||||
return
|
||||
}
|
||||
content.remove(file)
|
||||
|
@ -32,7 +32,7 @@ struct FileListView: View {
|
||||
guard !searchString.isEmpty else {
|
||||
return filesBySelectedType
|
||||
}
|
||||
return filesBySelectedType.filter { $0.id.contains(searchString) }
|
||||
return filesBySelectedType.filter { $0.identifier.contains(searchString) }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@ -55,10 +55,10 @@ struct FileListView: View {
|
||||
LazyVStack(spacing: 0) {
|
||||
ForEach(filteredFiles) { file in
|
||||
SelectableListItem(selected: selectedFile == file) {
|
||||
Text(file.id)
|
||||
Text(file.identifier)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.id(file.id)
|
||||
.id(file.identifier)
|
||||
.onTapGesture {
|
||||
selectedFile = file
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ final class FileToAdd: ObservableObject {
|
||||
}
|
||||
|
||||
var idAlreadyExists: Bool {
|
||||
content.files.contains { $0.id == uniqueId }
|
||||
content.files.contains { $0.identifier == uniqueId }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ struct MultiFileSelectionView: View {
|
||||
guard !searchString.isEmpty else {
|
||||
return filesBySelectedType
|
||||
}
|
||||
return filesBySelectedType.filter { $0.id.contains(searchString) }
|
||||
return filesBySelectedType.filter { $0.identifier.contains(searchString) }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@ -59,7 +59,7 @@ struct MultiFileSelectionView: View {
|
||||
.foregroundStyle(.red)
|
||||
.contentShape(Rectangle())
|
||||
.onTapGesture { deselect(file: file) }
|
||||
Text(file.id)
|
||||
Text(file.identifier)
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ struct MultiFileSelectionView: View {
|
||||
Image(systemSymbol: .plusCircleFill)
|
||||
.foregroundStyle(.green)
|
||||
}
|
||||
Text(file.id)
|
||||
Text(file.identifier)
|
||||
Spacer()
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
|
@ -49,9 +49,9 @@ struct TextFileContentView: View {
|
||||
|
||||
private func reload() {
|
||||
fileContent = file.textContent()
|
||||
loadedFile = file.id
|
||||
loadedFile = file.identifier
|
||||
loadedFileDate = file.modifiedDate
|
||||
print("Loaded content of file \(file.id)")
|
||||
print("Loaded content of file \(file.identifier)")
|
||||
}
|
||||
|
||||
private func save() {
|
||||
@ -59,25 +59,25 @@ struct TextFileContentView: View {
|
||||
print("[ERROR] Text File View: No file loaded to save")
|
||||
return
|
||||
}
|
||||
guard loadedFile == file.id else {
|
||||
guard loadedFile == file.identifier else {
|
||||
print("[ERROR] Text File View: Not saving since file changed")
|
||||
reload()
|
||||
return
|
||||
}
|
||||
guard loadedFileDate == file.modifiedDate else {
|
||||
print("Text File View: Not saving changed file \(file.id)")
|
||||
print("Text File View: Not saving changed file \(file.identifier)")
|
||||
reload()
|
||||
return
|
||||
}
|
||||
guard fileContent != "" else {
|
||||
print("Text File View: Not saving empty file \(file.id)")
|
||||
print("Text File View: Not saving empty file \(file.identifier)")
|
||||
return
|
||||
}
|
||||
guard file.save(textContent: fileContent) else {
|
||||
print("[ERROR] Text File View: Failed to save file \(file.id)")
|
||||
print("[ERROR] Text File View: Failed to save file \(file.identifier)")
|
||||
return
|
||||
}
|
||||
loadedFileDate = file.modifiedDate
|
||||
print("Text File View: Saved file \(file.id)")
|
||||
print("Text File View: Saved file \(file.identifier)")
|
||||
}
|
||||
}
|
||||
|
@ -72,11 +72,11 @@ struct GenerationContentView: View {
|
||||
GenerationStringIssuesView(
|
||||
text: "required files",
|
||||
statusWhenNonEmpty: .nominal,
|
||||
items: content.results.requiredFiles) { $0.id }
|
||||
items: content.results.requiredFiles) { $0.identifier }
|
||||
GenerationStringIssuesView(
|
||||
text: "external files",
|
||||
statusWhenNonEmpty: .nominal,
|
||||
items: content.results.externalFiles) { $0.id }
|
||||
items: content.results.externalFiles) { $0.identifier }
|
||||
GenerationIssuesView(
|
||||
text: "empty pages",
|
||||
statusWhenNonEmpty: .warning,
|
||||
@ -96,14 +96,14 @@ struct GenerationContentView: View {
|
||||
statusWhenNonEmpty: .warning,
|
||||
items: draftPages,
|
||||
buttonText: "Show",
|
||||
itemText: { $0.id },
|
||||
itemText: { $0.identifier },
|
||||
action: { show($0) })
|
||||
GenerationIssuesActionView(
|
||||
title: "draft posts",
|
||||
statusWhenNonEmpty: .warning,
|
||||
items: draftPosts,
|
||||
buttonText: "Show",
|
||||
itemText: { $0.id },
|
||||
itemText: { $0.identifier },
|
||||
action: { show($0) })
|
||||
GenerationIssuesView(
|
||||
text: "additional output files",
|
||||
@ -117,10 +117,10 @@ struct GenerationContentView: View {
|
||||
}
|
||||
GenerationStringIssuesView(
|
||||
text: "inaccessible files",
|
||||
items: content.results.inaccessibleFiles) { $0.id }
|
||||
items: content.results.inaccessibleFiles) { $0.identifier }
|
||||
GenerationStringIssuesView(
|
||||
text: "unparsable files",
|
||||
items: content.results.unparsableFiles) { $0.id }
|
||||
items: content.results.unparsableFiles) { $0.identifier }
|
||||
GenerationStringIssuesView(
|
||||
text: "unsaved output files",
|
||||
items: content.results.unsavedOutputFiles)
|
||||
|
@ -24,7 +24,7 @@ struct FilePropertyView: View {
|
||||
var body: some View {
|
||||
GenericPropertyView(title: title, footer: footer) {
|
||||
HStack {
|
||||
Text(selectedFile?.id ?? "No file selected")
|
||||
Text(selectedFile?.identifier ?? "No file selected")
|
||||
Spacer()
|
||||
Button("Select") {
|
||||
showFileSelectionSheet = true
|
||||
|
@ -36,7 +36,7 @@ struct OptionalImagePropertyView: View {
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text(selectedImage?.id ?? "No file selected")
|
||||
Text(selectedImage?.identifier ?? "No file selected")
|
||||
Spacer()
|
||||
Button("Select") {
|
||||
showSelectionSheet = true
|
||||
|
@ -15,7 +15,7 @@ struct PagePropertyView: View {
|
||||
var body: some View {
|
||||
GenericPropertyView(title: title, footer: footer) {
|
||||
HStack {
|
||||
Text(selectedPage?.id ?? "No page selected")
|
||||
Text(selectedPage?.identifier ?? "No page selected")
|
||||
Spacer()
|
||||
Button("Select") {
|
||||
showPageSelectionSheet = true
|
||||
|
@ -16,7 +16,7 @@ struct TagDisplayView: View {
|
||||
|
||||
var body: some View {
|
||||
FlowHStack {
|
||||
ForEach(tags, id: \.id) { tag in
|
||||
ForEach(tags, id: \.identifier) { tag in
|
||||
TagView(text: tag.localized(in: language).name)
|
||||
.foregroundStyle(.white)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ struct TagPickerView: View {
|
||||
Text("Select a tag to link to")
|
||||
List(content.tags, selection: $newSelection) { tag in
|
||||
let loc = tag.localized(in: language)
|
||||
Text("\(loc.title) (\(tag.id))")
|
||||
Text("\(loc.title) (\(tag.identifier))")
|
||||
.tag(tag)
|
||||
}
|
||||
.frame(minHeight: 300)
|
||||
|
@ -15,7 +15,7 @@ struct TagPropertyView: View {
|
||||
var body: some View {
|
||||
GenericPropertyView(title: title, footer: footer) {
|
||||
HStack {
|
||||
Text(selectedTag?.id ?? "No tag selected")
|
||||
Text(selectedTag?.identifier ?? "No tag selected")
|
||||
Spacer()
|
||||
Button("Select") {
|
||||
showTagSelectionSheet = true
|
||||
|
@ -20,7 +20,7 @@ final class InsertableFileButton: ObservableObject {
|
||||
"""
|
||||
icon: \(label.icon.rawValue)
|
||||
text: \(label.value)
|
||||
file: \(file.id)
|
||||
file: \(file.identifier)
|
||||
"""
|
||||
guard let downloadedFileName else {
|
||||
return result
|
||||
@ -86,7 +86,7 @@ struct InsertableButtons: View, InsertableCommandView {
|
||||
var id: String {
|
||||
switch self {
|
||||
case .file(let file):
|
||||
return "file-\(file.file?.id ?? "none")"
|
||||
return "file-\(file.file?.identifier ?? "none")"
|
||||
case .url(let url):
|
||||
return "url-\(url.url)"
|
||||
case .event(let event):
|
||||
@ -161,7 +161,7 @@ private struct FileButtonView: View {
|
||||
var body: some View {
|
||||
HStack {
|
||||
LabelEditingView(label: $content.label)
|
||||
Button("\(content.file?.id ?? "Select file")", action: { showFileSelectionSheet = true })
|
||||
Button("\(content.file?.identifier ?? "Select file")", action: { showFileSelectionSheet = true })
|
||||
OptionalTextField("", text: $content.downloadedFileName, prompt: "Downloaded file name")
|
||||
.textFieldStyle(.roundedBorder)
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ struct InsertableGallery: View, InsertableCommandView {
|
||||
}
|
||||
return (
|
||||
["```\(GalleryBlock.blockId)"] +
|
||||
images.map { $0.id } +
|
||||
images.map { $0.identifier } +
|
||||
["```"]
|
||||
).joined(separator: "\n")
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ struct InsertableImage: View, InsertableCommandView {
|
||||
return nil
|
||||
}
|
||||
guard let caption else {
|
||||
return ")"
|
||||
return ")"
|
||||
}
|
||||
return ";\(caption))"
|
||||
return ";\(caption))"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,11 +45,11 @@ struct InsertableLink: View, InsertableCommandView {
|
||||
case .post, .tagOverview:
|
||||
return nil
|
||||
case .page:
|
||||
return selectedPage?.id
|
||||
return selectedPage?.identifier
|
||||
case .tag:
|
||||
return selectedTag?.id
|
||||
return selectedTag?.identifier
|
||||
case .file:
|
||||
return selectedFile?.id
|
||||
return selectedFile?.identifier
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,8 +40,8 @@ struct InsertableRoute: View, InsertableCommandView {
|
||||
return nil
|
||||
}
|
||||
var result = ["```route"]
|
||||
result.append("\(RouteBlock.Key.image.rawValue): \(selectedImage.id)")
|
||||
result.append("\(RouteBlock.Key.file.rawValue): \(dataFile.id)")
|
||||
result.append("\(RouteBlock.Key.image.rawValue): \(selectedImage.identifier)")
|
||||
result.append("\(RouteBlock.Key.file.rawValue): \(dataFile.identifier)")
|
||||
if components != Set(RouteStatisticType.allCases) {
|
||||
let list = components
|
||||
.map { $0.rawValue }
|
||||
|
@ -50,16 +50,16 @@ struct InsertableVideo: View, InsertableCommandView {
|
||||
var lines: [String] = []
|
||||
lines.append("```video")
|
||||
if let posterImage {
|
||||
lines.append("\(VideoBlock.Key.poster): \(posterImage.id)")
|
||||
lines.append("\(VideoBlock.Key.poster): \(posterImage.identifier)")
|
||||
}
|
||||
if let videoH265 {
|
||||
lines.append("\(VideoBlock.Key.h265): \(videoH265.id)")
|
||||
lines.append("\(VideoBlock.Key.h265): \(videoH265.identifier)")
|
||||
}
|
||||
if let videoH264 {
|
||||
lines.append("\(VideoBlock.Key.h264): \(videoH264.id)")
|
||||
lines.append("\(VideoBlock.Key.h264): \(videoH264.identifier)")
|
||||
}
|
||||
if let videoWebm {
|
||||
lines.append("\(VideoBlock.Key.webm): \(videoWebm.id)")
|
||||
lines.append("\(VideoBlock.Key.webm): \(videoWebm.identifier)")
|
||||
}
|
||||
if controls { lines.append(VideoBlock.Key.controls.rawValue) }
|
||||
if autoplay { lines.append(VideoBlock.Key.autoplay.rawValue) }
|
||||
|
@ -35,7 +35,7 @@ struct PageContentResultsView: View {
|
||||
TextWithSymbol(
|
||||
symbol: $0.type.category.symbol,
|
||||
color: .blue,
|
||||
text: $0.id)
|
||||
text: $0.identifier)
|
||||
}
|
||||
+ results.missingFiles.keys.map {
|
||||
TextWithSymbol(
|
||||
|
@ -32,7 +32,7 @@ struct PageContentView: View {
|
||||
if page.isExternalUrl {
|
||||
VStack {
|
||||
PageTitleView(page: page.localized(in: language))
|
||||
.id(page.id + language.rawValue)
|
||||
.id(page.identifier + language.rawValue)
|
||||
Spacer()
|
||||
Text("No content available for external page")
|
||||
.font(.title)
|
||||
@ -42,10 +42,10 @@ struct PageContentView: View {
|
||||
} else {
|
||||
VStack(alignment: .leading) {
|
||||
PageTitleView(page: page.localized(in: language))
|
||||
.id(page.id + language.rawValue)
|
||||
.id(page.identifier + language.rawValue)
|
||||
TagDisplayView(tags: $page.tags)
|
||||
LocalizedPageContentView(page: page, language: language)
|
||||
.id(page.id + language.rawValue)
|
||||
.id(page.identifier + language.rawValue)
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ struct PageDetailView: View {
|
||||
title: "Page",
|
||||
text: "A page contains longer content")
|
||||
IdPropertyView(
|
||||
id: $page.id,
|
||||
id: $page.identifier,
|
||||
footer: "The page id is used to link to it internally.",
|
||||
validation: page.isValid,
|
||||
update: { page.update(id: $0) })
|
||||
@ -75,7 +75,7 @@ struct PageDetailView: View {
|
||||
isExternalPage: page.isExternalUrl,
|
||||
page: page.localized(in: language),
|
||||
transferImage: transferImage)
|
||||
.id(page.id + language.rawValue)
|
||||
.id(page.identifier + language.rawValue)
|
||||
ColoredButton(delete: deletePage)
|
||||
}
|
||||
.padding()
|
||||
@ -83,8 +83,8 @@ struct PageDetailView: View {
|
||||
}
|
||||
|
||||
private func deletePage() {
|
||||
guard content.storage.delete(page: page.id) else {
|
||||
print("Page '\(page.id)': Failed to delete file in content folder")
|
||||
guard content.storage.delete(page: page.identifier) else {
|
||||
print("Page '\(page.identifier)': Failed to delete file in content folder")
|
||||
return
|
||||
}
|
||||
content.remove(page)
|
||||
|
@ -27,7 +27,7 @@ struct PagePickerView: View {
|
||||
Text("Select a page to link to")
|
||||
List(content.pages, selection: $newSelection) { page in
|
||||
let loc = page.localized(in: language)
|
||||
Text("\(loc.title) (\(page.id))")
|
||||
Text("\(loc.title) (\(page.identifier))")
|
||||
.tag(page)
|
||||
}
|
||||
.frame(minHeight: 300)
|
||||
|
@ -43,7 +43,7 @@ struct PostDetailView: View {
|
||||
}
|
||||
|
||||
IdPropertyView(
|
||||
id: $post.id,
|
||||
id: $post.identifier,
|
||||
footer: "The id is used to link to post and store them",
|
||||
validation: post.isValid,
|
||||
update: { post.update(id: $0) })
|
||||
@ -99,8 +99,8 @@ struct PostDetailView: View {
|
||||
}
|
||||
|
||||
private func deletePost() {
|
||||
guard content.storage.delete(post: post.id) else {
|
||||
print("Post '\(post.id)': Failed to delete file in content folder")
|
||||
guard content.storage.delete(post: post.identifier) else {
|
||||
print("Post '\(post.identifier)': Failed to delete file in content folder")
|
||||
return
|
||||
}
|
||||
content.remove(post)
|
||||
|
@ -18,7 +18,7 @@ struct PostImageView: View {
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 100)
|
||||
Text(image.id)
|
||||
Text(image.identifier)
|
||||
.font(.title)
|
||||
Text("Failed to load image")
|
||||
.font(.body)
|
||||
@ -32,7 +32,7 @@ struct PostImageView: View {
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 100)
|
||||
Text(image.id)
|
||||
Text(image.identifier)
|
||||
.font(.title)
|
||||
Button("Generate preview") {
|
||||
generateVideoPreview(image)
|
||||
@ -48,7 +48,7 @@ struct PostImageView: View {
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(height: 100)
|
||||
Text(image.id)
|
||||
Text(image.identifier)
|
||||
.font(.title)
|
||||
Text("Invalid media type")
|
||||
.font(.body)
|
||||
|
@ -10,7 +10,7 @@ private struct PostListItem: View {
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
LocalizedPostListItem(id: post.id, post: post.localized(in: language))
|
||||
LocalizedPostListItem(id: post.identifier, post: post.localized(in: language))
|
||||
if post.isDraft {
|
||||
TextIndicator(text: "Draft", background: .yellow)
|
||||
} else {
|
||||
|
@ -32,7 +32,7 @@ struct TagDetailView: View {
|
||||
footer: "Indicate if the tag should appear in the tag list of posts and pages. If the tag is not visible, then it can still be used as a filter.")
|
||||
|
||||
IdPropertyView(
|
||||
id: $tag.id,
|
||||
id: $tag.identifier,
|
||||
title: "Tag id",
|
||||
footer: "The unique id of the tag for references",
|
||||
validation: tag.isValid) {
|
||||
@ -42,7 +42,7 @@ struct TagDetailView: View {
|
||||
LocalizedTagDetailView(
|
||||
tag: tag.localized(in: language),
|
||||
transferImage: transferImage)
|
||||
.id(tag.id + language.rawValue)
|
||||
.id(tag.identifier + language.rawValue)
|
||||
ColoredButton(delete: deleteTag)
|
||||
}
|
||||
.padding()
|
||||
@ -50,8 +50,8 @@ struct TagDetailView: View {
|
||||
}
|
||||
|
||||
private func deleteTag() {
|
||||
guard content.storage.delete(tag: tag.id) else {
|
||||
print("Tag '\(tag.id)': Failed to delete file in content folder")
|
||||
guard content.storage.delete(tag: tag.identifier) else {
|
||||
print("Tag '\(tag.identifier)': Failed to delete file in content folder")
|
||||
return
|
||||
}
|
||||
content.remove(tag)
|
||||
|
Reference in New Issue
Block a user