aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Cleberg <hello@cleberg.net>2024-01-14 11:09:32 -0600
committerChristian Cleberg <hello@cleberg.net>2024-01-14 11:09:32 -0600
commitb5a5dc8963dbd73d30c188eb9f3018add76a2c06 (patch)
tree3b73910d6bb0f151b3fde6a6a50c044e6d28d657
parent9e2c7e09543cf5288303e59125e897f8731b8a1a (diff)
downloadlibre-edit-b5a5dc8963dbd73d30c188eb9f3018add76a2c06.tar.gz
libre-edit-b5a5dc8963dbd73d30c188eb9f3018add76a2c06.tar.bz2
libre-edit-b5a5dc8963dbd73d30c188eb9f3018add76a2c06.zip
feat: update app to use native file manager as the base
-rw-r--r--LibreEdit/ContentView.swift136
-rw-r--r--LibreEdit/LibreEditApp.swift4
2 files changed, 56 insertions, 84 deletions
diff --git a/LibreEdit/ContentView.swift b/LibreEdit/ContentView.swift
index 87def10..641a534 100644
--- a/LibreEdit/ContentView.swift
+++ b/LibreEdit/ContentView.swift
@@ -6,104 +6,81 @@
//
import SwiftUI
+import UniformTypeIdentifiers
-func getDatetime() -> String {
- let dateFormatter = DateFormatter()
- let enUSPosixLocale = Locale(identifier: "en_US_POSIX")
- dateFormatter.locale = enUSPosixLocale
- dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
- dateFormatter.calendar = Calendar(identifier: .gregorian)
+struct TextFile: FileDocument {
+ // tell the system we support only plain text
+ static var readableContentTypes = [UTType.plainText]
- let iso8601String = dateFormatter.string(from: Date())
+ // by default our document is empty
+ var text = ""
- return iso8601String
+ // a simple initializer that creates new, empty documents
+ init(initialText: String = "") {
+ text = initialText
+ }
+
+ // this initializer loads data that has been saved previously
+ init(configuration: ReadConfiguration) throws {
+ if let data = configuration.file.regularFileContents {
+ text = String(decoding: data, as: UTF8.self)
+ } else {
+ throw CocoaError(.fileReadCorruptFile)
+ }
+ }
+
+ // this will be called when the system wants to write our data to disk
+ func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
+ let data = Data(text.utf8)
+ return FileWrapper(regularFileWithContents: data)
+ }
}
-// Ensure that `Supports Document Browser` = YES in the `ios-edit.xcodeproj` file,
-// so that users can browse saved files in the Files app
-func getDocumentsDirectory() -> URL {
- let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
- let documentsDirectory = paths[0]
- return documentsDirectory
+func countWords(text: String) -> Int {
+ let words = text.split { $0 == " " || $0.isNewline }
+ return words.count
}
struct ContentView: View {
- enum FocusedField {
- case content
- }
-
- @State private var content = ""
- @State private var wordCount: Int = 0
+ @Binding var document: TextFile
@State private var showingPopover = false
- @FocusState private var focusedField: FocusedField?
-
+ @State private var wordCount: Int = 0
+
var body: some View {
- NavigationView {
- VStack(alignment: .leading) {
- Text("\(wordCount) words")
- .font(.headline)
- .foregroundColor(.secondary)
- .padding(.trailing)
- TextEditor(text: $content)
- .onChange(of: content) {
- let words = content.split { $0 == " " || $0.isNewline }
- self.wordCount = words.count
- }
- .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
- .focused($focusedField, equals: .content)
- }
+ Text("\(wordCount) words")
+ .foregroundColor(Color.white)
+ .font(.headline)
+ .padding(.trailing)
+ .frame(maxWidth: .infinity, maxHeight: 50)
+ .background(Color.gray.opacity(0.3))
+ .padding(.top, 20)
+ TextEditor(text: $document.text)
.onAppear {
- focusedField = .content
+ self.wordCount = countWords(text: document.text)
+ }
+ .onChange(of: document.text) {
+ self.wordCount = countWords(text: document.text)
}
- .padding()
- .navigationTitle("Libre Edit")
.toolbar {
- ToolbarItemGroup(placement: .primaryAction) {
- Button(action: {
- do {
- let data = Data(self.content.utf8)
- let url = URL.documentsDirectory.appending(path: (getDatetime() + ".txt"))
- try data.write(to: url, options: [.atomic, .completeFileProtection])
-
- // TODO: Alerts currently aren't working/aren't visible
- Text("File saved successfully!")
- .foregroundColor(.white)
- .bold()
- .font(.footnote)
- .frame(width: 140, height: 30)
- .background(Color.indigo.cornerRadius(7))
- print("Saved content to file: \(url)")
- } catch {
- // TODO: Alerts currently aren't working/aren't visible
- Text("Failed to save file.")
- .foregroundColor(.white)
- .bold()
- .font(.footnote)
- .frame(width: 140, height: 30)
- .background(Color.red.cornerRadius(7))
- print("Error saving content to file: \(error)")
- }
- }) {
- Text("Save")
- }
- // TODO: Confirm (possibly save) & then clear TextEditor
- Button(action: {
- print("TODO: This will create a new note.")
- }) {
- Text("New")
- }
- }
ToolbarItemGroup(placement: .secondaryAction) {
Button {
showingPopover = true
} label: {
- Text("App Info")
+ Text("More Info")
}.popover(isPresented: $showingPopover) {
VStack(alignment: .leading) {
- Text("App Info")
+ Text("More Info")
.font(.largeTitle)
Text("")
- Text("Libre Edit is a free and open source text editor for iOS built by [Christian Cleberg](https://cleberg.net).")
+ Text("Instructions")
+ .font(.title)
+ Text("")
+ Text("LibreEdit provides a direct interface with the Apple Files app on your iPhone. Simply navigate to your preferred directory, edit existing files, or create new files!")
+ Text("")
+ Text("Developer")
+ .font(.title)
+ Text("")
+ Text("LibreEdit is a free and open source text editor for iOS built by [Christian Cleberg](https://cleberg.net).")
Text("")
Text("Visit the [GitHub Repository](https://github.com/ccleberg/ios-edit) to view the source code.")
Text("")
@@ -114,10 +91,5 @@ struct ContentView: View {
}
}
}
- }
}
}
-
-#Preview {
- ContentView()
-}
diff --git a/LibreEdit/LibreEditApp.swift b/LibreEdit/LibreEditApp.swift
index 23a791f..b2c9736 100644
--- a/LibreEdit/LibreEditApp.swift
+++ b/LibreEdit/LibreEditApp.swift
@@ -10,8 +10,8 @@ import SwiftUI
@main
struct LibreEditApp: App {
var body: some Scene {
- WindowGroup {
- ContentView()
+ DocumentGroup(newDocument: TextFile()) { file in
+ ContentView(document: file.$document)
}
}
}