diff --git a/ntfy.xcodeproj/xcuserdata/pheckel.xcuserdatad/xcschemes/xcschememanagement.plist b/ntfy.xcodeproj/xcuserdata/pheckel.xcuserdatad/xcschemes/xcschememanagement.plist
index d407d7f..cffa0e4 100644
--- a/ntfy.xcodeproj/xcuserdata/pheckel.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/ntfy.xcodeproj/xcuserdata/pheckel.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -28,12 +28,12 @@
ntfy.xcscheme_^#shared#^_
orderHint
- 1
+ 0
ntfyNSE.xcscheme_^#shared#^_
orderHint
- 0
+ 1
diff --git a/ntfy/Views/SettingsView.swift b/ntfy/Views/SettingsView.swift
index f6393ed..e86abc4 100644
--- a/ntfy/Views/SettingsView.swift
+++ b/ntfy/Views/SettingsView.swift
@@ -7,34 +7,107 @@ struct SettingsView: View {
var body: some View {
NavigationView {
Form {
- /*Section(header: Text("General")) {
- NavigationLink(destination: UsersView()) {
- Text("Manage users")
- }
- }*/
+ Section(header: Text("General")) {
+ DefaultServerView()
+ }
Section(
header: Text("Users"),
footer: Text("To access read-protected topics, you may add or edit users here. All topics for a given server will use the same user.")
) {
- UsersView()
+ UserTableView()
}
Section(header: Text("About")) {
HStack {
Text("Version")
- .foregroundColor(.gray)
Spacer()
Text("ntfy \(Config.version) (\(Config.build))")
+ .foregroundColor(.gray)
+
}
}
}
.navigationTitle("Settings")
-
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
-struct UsersView: View {
+
+struct DefaultServerView: View {
+ @EnvironmentObject private var store: Store
+ @State private var showDialog = false
+ @State private var defaultBaseUrl = ""
+
+ var body: some View {
+ Button(action: {
+ showDialog = true
+ }) {
+ HStack {
+ Text("Default server")
+ .foregroundColor(.primary)
+ Spacer()
+ Text("ntfy.sh")
+ .foregroundColor(.gray)
+ }
+ .contentShape(Rectangle())
+ }
+ .sheet(isPresented: $showDialog) {
+ NavigationView {
+ Form {
+ Section(
+ footer: Text("When subscribing to new topics, this server will be used as a default. Note that if you pick your own ntfy server, you must configure upstream-base-url to receive instant push notifications.")
+ ) {
+ TextField(Config.appBaseUrl, text: $defaultBaseUrl)
+ .disableAutocapitalization()
+ .disableAutocorrection(true)
+ }
+ }
+ .navigationTitle("Default server")
+ .navigationBarTitleDisplayMode(.inline)
+ .toolbar {
+ ToolbarItem(placement: .navigationBarLeading) {
+
+ Button(action: cancelAction) {
+ Text("Cancel")
+ }
+ }
+
+ ToolbarItem(placement: .navigationBarTrailing) {
+ Button(action: saveAction) {
+ Text("Save")
+ }
+ .disabled(!isValid())
+ }
+ }
+ }
+ }
+ }
+
+ private func saveAction() {
+ resetAndHide()
+ }
+
+ private func cancelAction() {
+ resetAndHide()
+ }
+
+ private func isValid() -> Bool {
+ if !defaultBaseUrl.isEmpty && defaultBaseUrl.range(of: "^https?://.+", options: .regularExpression, range: nil, locale: nil) == nil {
+ return false
+ }
+ return true
+ }
+
+ private func resetAndHide() {
+ showDialog = false
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
+ // Hide first and then reset, otherwise we'll see the text fields change
+ defaultBaseUrl = ""
+ }
+ }
+}
+
+struct UserTableView: View {
@EnvironmentObject private var store: Store
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.baseUrl, ascending: true)]) var users: FetchedResults
@@ -49,22 +122,26 @@ struct UsersView: View {
let _ = selectedUser?.username // Workaround for FB7823148, see https://developer.apple.com/forums/thread/652080
List {
ForEach(users) { user in
- UserRowView(user: user)
- .onTapGesture {
- selectedUser = user
- baseUrl = user.baseUrl ?? "?"
- username = user.username ?? "?"
- showDialog = true
- }
+ Button(action: {
+ selectedUser = user
+ baseUrl = user.baseUrl ?? "?"
+ username = user.username ?? "?"
+ showDialog = true
+ }) {
+ UserRowView(user: user)
+ .foregroundColor(.primary)
+ }
}
- HStack {
- Image(systemName: "plus")
- Text("Add user")
+ Button(action: {
+ showDialog = true
+ }) {
+ HStack {
+ Image(systemName: "plus")
+ Text("Add user")
+ }
+ .foregroundColor(.primary)
}
.padding(.all, 4)
- .onTapGesture {
- showDialog = true
- }
}
.sheet(isPresented: $showDialog) {
NavigationView {
@@ -164,7 +241,7 @@ struct UsersView: View {
private func resetAndHide() {
showDialog = false
- DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
+ DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
// Hide first and then reset, otherwise we'll see the text fields change
selectedUser = nil
baseUrl = ""