diff --git a/Remote Text.xcodeproj/project.pbxproj b/Remote Text.xcodeproj/project.pbxproj index 11da112..5ef6c12 100644 --- a/Remote Text.xcodeproj/project.pbxproj +++ b/Remote Text.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 22A1A13D29E0D3DA00D26FCC /* SFSafeSymbols in Frameworks */ = {isa = PBXBuildFile; productRef = 22A1A13C29E0D3DA00D26FCC /* SFSafeSymbols */; }; 22A1A13F29E0D71000D26FCC /* CreateFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22A1A13E29E0D71000D26FCC /* CreateFileView.swift */; }; 22A1A14129E0D72200D26FCC /* FileDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22A1A14029E0D72200D26FCC /* FileDetailView.swift */; }; + 22CCE7FA2B6303A900988701 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 22CCE7F92B6303A900988701 /* Settings.bundle */; }; 22FD4B8C29F3B1F000C64BC1 /* HighlightedTextEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 22FD4B8B29F3B1F000C64BC1 /* HighlightedTextEditor */; }; 22FD4B8F29F3B40000C64BC1 /* CodeEditor in Frameworks */ = {isa = PBXBuildFile; productRef = 22FD4B8E29F3B40000C64BC1 /* CodeEditor */; }; 231BDB2B29DF6C980024D52C /* Remote_TextApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 231BDB2A29DF6C980024D52C /* Remote_TextApp.swift */; }; @@ -32,6 +33,7 @@ 2266D60029F510E800DC8128 /* PDFDocument+Transferable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PDFDocument+Transferable.swift"; sourceTree = ""; }; 22A1A13E29E0D71000D26FCC /* CreateFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateFileView.swift; sourceTree = ""; }; 22A1A14029E0D72200D26FCC /* FileDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDetailView.swift; sourceTree = ""; }; + 22CCE7F92B6303A900988701 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; }; 231BDB2729DF6C980024D52C /* Remote Text.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Remote Text.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 231BDB2A29DF6C980024D52C /* Remote_TextApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Remote_TextApp.swift; sourceTree = ""; }; 231BDB2E29DF6C980024D52C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -77,6 +79,7 @@ isa = PBXGroup; children = ( 231BDB2A29DF6C980024D52C /* Remote_TextApp.swift */, + 22CCE7F92B6303A900988701 /* Settings.bundle */, 231BDB2E29DF6C980024D52C /* ContentView.swift */, 231BDB3B29DF6E810024D52C /* FileModel.swift */, 2266D60029F510E800DC8128 /* PDFDocument+Transferable.swift */, @@ -171,6 +174,7 @@ buildActionMask = 2147483647; files = ( 231BDB3429DF6C990024D52C /* Preview Assets.xcassets in Resources */, + 22CCE7FA2B6303A900988701 /* Settings.bundle in Resources */, 231BDB3129DF6C990024D52C /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Remote Text/ContentView.swift b/Remote Text/ContentView.swift index dd0fda9..6b1e32d 100644 --- a/Remote Text/ContentView.swift +++ b/Remote Text/ContentView.swift @@ -9,6 +9,7 @@ import SwiftUI import SFSafeSymbols struct ContentView: View { + @AppStorage("api_url") var serverURL: String = "" @ObservedObject var model: FileModel @State var files: [FileSummary] = [] @@ -29,6 +30,26 @@ struct ContentView: View { } var body: some View { + if serverURL == "" { + VStack { + Spacer() + Text("Please go to Settings to set the root API URL:").font(.title).multilineTextAlignment(.center) + Button { + UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!) + } label: { + Text("Open Settings") + } + Spacer() + Text("It will probably be of the form:").font(.caption) + Text("http://blinky.wholphin-wyvern.ts.net:3030/api").monospaced() + Spacer() + }.padding() + } else { + normalUsage + } + } + + var normalUsage: some View { NavigationStack(path: $model.path) { FileListView(files: self.$files) .navigationDestination(for: Navigation.self) { nav in diff --git a/Remote Text/CreateFileView.swift b/Remote Text/CreateFileView.swift index dc32327..576a304 100644 --- a/Remote Text/CreateFileView.swift +++ b/Remote Text/CreateFileView.swift @@ -33,7 +33,7 @@ struct CreateFileView: View { Task { let newFile = await model.createFile(named: fileName, withContent: content) self.model.path.removeLast() - self.model.path.append(ContentView.Navigation.fileEditor(file: newFile)) + self.model.path.append(ContentView.Navigation.fileEditor(file: newFile.toFileSummary())) } } label: { Text("Create") @@ -53,7 +53,7 @@ struct CreateFileView: View { let newFile = await model.createFile(named: fileName, withContent: content) let hash = await model.getHistory(id: newFile.id).commits[0].hash self.model.path.removeLast() - self.model.path.append(ContentView.Navigation.fileEditor(file: newFile)) + self.model.path.append(ContentView.Navigation.fileEditor(file: newFile.toFileSummary())) self.model.path.append(ContentView.Navigation.previewFile(id: newFile.id, hash: hash, filename: newFile.name)) } diff --git a/Remote Text/FileDetailView.swift b/Remote Text/FileDetailView.swift index 1e2a54d..ee70469 100644 --- a/Remote Text/FileDetailView.swift +++ b/Remote Text/FileDetailView.swift @@ -33,7 +33,7 @@ struct FileDetailView: View { .onAppear { Task { let history = await model.getHistory(id: id) - self.hash = history.refs.first { $0.name == "main" }!.hash + self.hash = history.refs.first { $0.name == "main" || $0.name == "master" }!.hash let file = await model.getFile(id: id, atVersion: self.hash) self.fileName = file.name self.content = file.content diff --git a/Remote Text/FileModel.swift b/Remote Text/FileModel.swift index 9665e24..bc4e831 100644 --- a/Remote Text/FileModel.swift +++ b/Remote Text/FileModel.swift @@ -12,11 +12,12 @@ class FileModel: ObservableObject { static let shared = FileModel() + @AppStorage("api_url") var BASE_URL: String = "" + // @Published var path = NavigationPath() @Published var path: [ContentView.Navigation] = [] private func request(to endpoint: String, with data: Codable?) throws -> URLRequest { - let BASE_URL = "http://localhost:3030/api" guard let url = URL(string: "\(BASE_URL)/\(endpoint)") else { fatalError("Cannot construct URL for API call!") } @@ -57,7 +58,7 @@ class FileModel: ObservableObject { } @discardableResult - func createFile(named name: String, withContent content: String) async -> FileSummary { + func createFile(named name: String, withContent content: String) async -> CreateFileResult { let dataToEncode = FileNameAndOptionalContent(name: name, content: content) let urlRequest = try! request(to: "createFile", with: dataToEncode) let (data, response) = try! await URLSession.shared.data(for: urlRequest) @@ -78,7 +79,7 @@ class FileModel: ObservableObject { decoder.keyDecodingStrategy = .convertFromSnakeCase decoder.dateDecodingStrategy = .iso8601 - let file = try! decoder.decode(FileSummary.self, from: data) + let file = try! decoder.decode(CreateFileResult.self, from: data) return file } diff --git a/Remote Text/Info.plist b/Remote Text/Info.plist index d965101..5e54cdc 100644 --- a/Remote Text/Info.plist +++ b/Remote Text/Info.plist @@ -35,5 +35,10 @@ + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + diff --git a/Remote Text/Remote_TextApp.swift b/Remote Text/Remote_TextApp.swift index 4a3ab37..92aeae8 100644 --- a/Remote Text/Remote_TextApp.swift +++ b/Remote Text/Remote_TextApp.swift @@ -9,10 +9,14 @@ import SwiftUI @main struct Remote_TextApp: App { - - var body: some Scene { - WindowGroup { - ContentView(model: FileModel.shared) + + init() { +// UserDefaults.standard.register(defaults: <#T##[String : Any]#>) + } + + var body: some Scene { + WindowGroup { + ContentView(model: FileModel.shared) + } } - } } diff --git a/Remote Text/Settings.bundle/Root.plist b/Remote Text/Settings.bundle/Root.plist new file mode 100644 index 0000000..5067f66 --- /dev/null +++ b/Remote Text/Settings.bundle/Root.plist @@ -0,0 +1,27 @@ + + + + + StringsTable + Root + PreferenceSpecifiers + + + Type + PSTextFieldSpecifier + Title + API URL + Key + api_url + IsSecure + + KeyboardType + URL + AutocapitalizationType + None + AutocorrectionType + No + + + + diff --git a/Remote Text/Settings.bundle/en.lproj/Root.strings b/Remote Text/Settings.bundle/en.lproj/Root.strings new file mode 100644 index 0000000..8cd87b9 Binary files /dev/null and b/Remote Text/Settings.bundle/en.lproj/Root.strings differ diff --git a/Remote Text/Structs.swift b/Remote Text/Structs.swift index 0bf6f59..d57e613 100644 --- a/Remote Text/Structs.swift +++ b/Remote Text/Structs.swift @@ -20,6 +20,22 @@ struct FileSummary: Identifiable, Codable, Hashable { let createdTime: Date } +struct CreateFileResult: Identifiable, Codable, Hashable { + let name: String + let id: UUID + let hash: String + let createdTime: Date + + func toFileSummary() -> FileSummary { + .init( + name: name, + id: id, + editedTime: createdTime, + createdTime: createdTime + ) + } +} + struct GitCommit: Codable { let hash: String let parent: String?