Skip to content

Commit

Permalink
Set root API URL in the Settings app; other fixes
Browse files Browse the repository at this point in the history
This allows me to publish the app to the App Store and let others point
it to their locally-hosted instances of the server. Note that storing
the settings in the Settings app means they are stored in UserDefaults,
which is why I use `@AppStorage` to access them.

Other changes include:
- Providing a button to jump to settings when the root API URL is unset
- update the API to expect a CreateFileResult upon creating new files,
  instead of the FileSummary that it used to return. I also provided a
  convenience function to convert CreateFileResult to FileSummary
- Support branches named 'master' as well as 'main'
- Allow insecure (i.e., HTTP) connections, trusting that users will only
  use them over a VPN
  • Loading branch information
Samasaur1 committed Jan 26, 2024
1 parent c014014 commit 9b9a09b
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 11 deletions.
4 changes: 4 additions & 0 deletions Remote Text.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */; };
Expand All @@ -32,6 +33,7 @@
2266D60029F510E800DC8128 /* PDFDocument+Transferable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PDFDocument+Transferable.swift"; sourceTree = "<group>"; };
22A1A13E29E0D71000D26FCC /* CreateFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateFileView.swift; sourceTree = "<group>"; };
22A1A14029E0D72200D26FCC /* FileDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDetailView.swift; sourceTree = "<group>"; };
22CCE7F92B6303A900988701 /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
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 = "<group>"; };
231BDB2E29DF6C980024D52C /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -77,6 +79,7 @@
isa = PBXGroup;
children = (
231BDB2A29DF6C980024D52C /* Remote_TextApp.swift */,
22CCE7F92B6303A900988701 /* Settings.bundle */,
231BDB2E29DF6C980024D52C /* ContentView.swift */,
231BDB3B29DF6E810024D52C /* FileModel.swift */,
2266D60029F510E800DC8128 /* PDFDocument+Transferable.swift */,
Expand Down Expand Up @@ -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;
Expand Down
21 changes: 21 additions & 0 deletions Remote Text/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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] = []
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Remote Text/CreateFileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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))
}
Expand Down
2 changes: 1 addition & 1 deletion Remote Text/FileDetailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions Remote Text/FileModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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!")
}
Expand Down Expand Up @@ -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)
Expand All @@ -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
}
Expand Down
5 changes: 5 additions & 0 deletions Remote Text/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,10 @@
</dict>
</dict>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>
14 changes: 9 additions & 5 deletions Remote Text/Remote_TextApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
}
27 changes: 27 additions & 0 deletions Remote Text/Settings.bundle/Root.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>StringsTable</key>
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>API URL</string>
<key>Key</key>
<string>api_url</string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>URL</string>
<key>AutocapitalizationType</key>
<string>None</string>
<key>AutocorrectionType</key>
<string>No</string>
</dict>
</array>
</dict>
</plist>
Binary file added Remote Text/Settings.bundle/en.lproj/Root.strings
Binary file not shown.
16 changes: 16 additions & 0 deletions Remote Text/Structs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down

0 comments on commit 9b9a09b

Please sign in to comment.