Allow text file editing

This commit is contained in:
Christoph Hagen 2025-01-14 20:18:26 +01:00
parent 4131b483e6
commit c1a3d22002
5 changed files with 60 additions and 14 deletions

View File

@ -17,7 +17,6 @@ import SFSafeSymbols
- Posts: Generate separate pages for posts to link to
- Settings: Introduce `Authors` (`name`, `image`, `description`)
- Page: Property `author`
- Text file editing
- Blocks: Convert more commands to blocks
- Graphs, Map, GPX for hikes

View File

@ -98,6 +98,10 @@ final class FileResource: Item, LocalizedItem {
content.storage.fileContent(for: id) ?? ""
}
func save(textContent: String) -> Bool {
content.storage.save(fileContent: textContent, for: id)
}
func dataContent() -> Foundation.Data? {
content.storage.fileData(for: id)
}

View File

@ -71,12 +71,15 @@ struct SecurityBookmark {
return write(data, to: relativePath)
}
func write(_ string: String,
/**
Write text to a file at the relative path.
*/
func write(_ content: String,
to relativePath: String,
createParentFolder: Bool = true,
ifFileExists overwrite: OverwriteBehaviour = .writeIfChanged) -> Bool {
guard let data = string.data(using: .utf8) else {
delegate?.securityBookmark(error: "Failed to encode string to write to \(relativePath)")
guard let data = content.data(using: .utf8) else {
delegate?.securityBookmark(error: "Failed to encode content to write to \(relativePath)")
return false
}
return write(data, to: relativePath, createParentFolder: createParentFolder, ifFileExists: overwrite)

View File

@ -360,6 +360,12 @@ final class Storage: ObservableObject {
return contentScope.readData(at: path)
}
func save(fileContent: String, for fileId: String) -> Bool {
guard let contentScope else { return false }
let path = filePath(file: fileId)
return contentScope.write(fileContent, to: path)
}
// MARK: Settings
func loadSettings() -> Settings.Data? {

View File

@ -8,31 +8,65 @@ struct TextFileContentView: View {
@State
private var fileContent: String = ""
@State
private var loadedFile: String?
var body: some View {
if fileContent != "" {
TextEditor(text: $fileContent)
.font(.body.monospaced())
.textEditorStyle(.plain)
//.background(.clear)
} else {
VStack {
VStack {
if fileContent != "" {
HStack {
Button("Reload", action: reload)
Button("Save", action: save)
Spacer()
}
TextEditor(text: $fileContent)
.font(.body.monospaced())
.textEditorStyle(.plain)
.foregroundStyle(.primary)
} else {
Image(systemSymbol: .docText)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 150)
Text("No preview available")
Text("No preview available or empty file")
.font(.title)
}
.foregroundStyle(.secondary)
.onAppear(perform: loadFileContent)
}
.foregroundStyle(.secondary)
.onAppear(perform: loadFileContent)
.onDisappear(perform: save)
}
private func loadFileContent() {
guard fileContent == "" else {
return
}
reload()
}
private func reload() {
fileContent = file.textContent()
loadedFile = file.id
print("Loaded content of file \(file.id)")
}
private func save() {
guard let loadedFile else {
print("[ERROR] Text File View: No file loaded to save")
return
}
guard loadedFile == file.id else {
print("[ERROR] Text File View: Not saving since file changed")
return
}
guard fileContent != "" else {
print("Text File View: Not saving empty file \(file.id)")
return
}
guard file.save(textContent: fileContent) else {
print("[ERROR] Text File View: Failed to save file \(file.id)")
return
}
print("Text File View: Saved file \(file.id)")
}
}