Continue work on usermanagement

This commit is contained in:
Philipp Heckel 2022-06-04 21:42:54 -04:00
parent 5c39d6a17c
commit 64e9763604
3 changed files with 114 additions and 45 deletions

View file

@ -86,9 +86,9 @@ class Store: ObservableObject {
try? context.save() try? context.save()
} }
func save(userBaseUrl baseUrl: String, username: String, password: String) { func saveUser(baseUrl: String, username: String, password: String) {
do { do {
let user = User(context: context) let user = getUser(baseUrl: baseUrl) ?? User(context: context)
user.baseUrl = baseUrl user.baseUrl = baseUrl
user.username = username user.username = username
user.password = password user.password = password
@ -195,8 +195,8 @@ extension Store {
} }
// Users // Users
store.save(userBaseUrl: "https://ntfy.sh", username: "testuser", password: "testuser") store.saveUser(baseUrl: "https://ntfy.sh", username: "testuser", password: "testuser")
store.save(userBaseUrl: "https://ntfy.example.com", username: "phil", password: "phil12") store.saveUser(baseUrl: "https://ntfy.example.com", username: "phil", password: "phil12")
} }
return store return store
}() }()

View file

@ -3,37 +3,17 @@ import SwiftUI
struct SettingsView: View { struct SettingsView: View {
@EnvironmentObject private var store: Store @EnvironmentObject private var store: Store
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.baseUrl, ascending: true)]) var users: FetchedResults<User>
var body: some View { var body: some View {
NavigationView { NavigationView {
Form { Form {
/*Section(header: Text("General")) { /*Section(header: Text("General")) {
NavigationLink(destination: UsersView()) { NavigationLink(destination: UsersView()) {
Text("Manage users") Text("Manage users")
} }
}*/ }*/
Section( Section(header: Text("Users")) {
header: Text("Users") UsersView()
) {
List {
ForEach(users) { user in
HStack {
Image(systemName: "person.fill")
VStack(alignment: .leading, spacing: 0) {
Text(user.username ?? "?")
Text(user.baseUrl ?? "?")
.font(.subheadline)
.foregroundColor(.gray)
}
}
}
HStack {
Image(systemName: "plus")
Text("Add user")
}
}
} }
Section(header: Text("About")) { Section(header: Text("About")) {
HStack { HStack {
@ -41,39 +21,128 @@ struct SettingsView: View {
.foregroundColor(.gray) .foregroundColor(.gray)
Spacer() Spacer()
Text("ntfy 1.1") Text("ntfy 1.1")
} }
} }
} }
.navigationTitle("Settings") .navigationTitle("Settings")
} }
.navigationViewStyle(StackNavigationViewStyle()) .navigationViewStyle(StackNavigationViewStyle())
} }
} }
struct UsersView: View { struct UsersView: View {
@EnvironmentObject private var store: Store @EnvironmentObject private var store: Store
@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.baseUrl, ascending: true)]) var users: FetchedResults<User> @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.baseUrl, ascending: true)]) var users: FetchedResults<User>
@State private var selectedUser: User?
@State private var showDialog = false
@State private var baseUrl: String = ""
@State private var username: String = ""
@State private var password: String = ""
var body: some View { var body: some View {
let _ = selectedUser?.username // Workaround for FB7823148, see https://developer.apple.com/forums/thread/652080
List { List {
ForEach(users) { user in ForEach(users) { user in
Text(user.username ?? "") UserRowView(user: user)
.onTapGesture {
selectedUser = user
baseUrl = user.baseUrl ?? "?"
username = user.username ?? "?"
showDialog = true
}
}
HStack {
Image(systemName: "plus")
Text("Add user")
}
.onTapGesture {
showDialog = true
} }
} }
.listStyle(PlainListStyle()) .sheet(isPresented: $showDialog) {
.navigationTitle("Manage users") NavigationView {
.toolbar { Form {
ToolbarItem(placement: .navigationBarTrailing) { Section(footer:
Button { Text("You can add a user here. All topics for the given server will use this user.")
//self.showingAddDialog = true ) {
} label: { if selectedUser == nil {
Image(systemName: "plus") TextField("Service URL, e.g. https://ntfy.example.com", text: $baseUrl)
.disableAutocapitalization()
.disableAutocorrection(true)
}
TextField("Username", text: $username)
.disableAutocapitalization()
.disableAutocorrection(true)
TextField("Password", text: $password)
.disableAutocapitalization()
.disableAutocorrection(true)
}
}
.navigationTitle(selectedUser == nil ? "Add user" : "Edit user")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: cancelAction) {
Text("Cancel")
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button(action: saveAction) {
Text("Save")
}
.disabled(!isValid())
}
} }
} }
} }
} }
private func saveAction() {
store.saveUser(baseUrl: baseUrl, username: username, password: password)
resetAndHide()
}
private func cancelAction() {
resetAndHide()
}
private func isValid() -> Bool {
return true // FIXME: validate
}
private func resetAndHide() {
selectedUser = nil
baseUrl = ""
username = ""
password = ""
showDialog = false
}
}
struct UserRowView: View {
@ObservedObject var user: User
var body: some View {
HStack {
Image(systemName: "person.fill")
VStack(alignment: .leading, spacing: 0) {
VStack(alignment: .leading, spacing: 0) {
Text(user.username ?? "?")
Text(user.baseUrl ?? "?")
.font(.subheadline)
.foregroundColor(.gray)
}
}
Spacer()
Image(systemName: "chevron.forward")
.font(.system(size: 12.0))
.foregroundColor(.gray)
}
.padding(.all, 4)
}
} }
struct SettingsView_Previews: PreviewProvider { struct SettingsView_Previews: PreviewProvider {

View file

@ -127,7 +127,7 @@ struct SubscriptionAddView: View {
ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: topic, user: user) { (response, error) in ApiService.shared.checkAuth(baseUrl: selectedBaseUrl, topic: topic, user: user) { (response, error) in
if response?.success == true { if response?.success == true {
DispatchQueue.global(qos: .background).async { DispatchQueue.global(qos: .background).async {
store.save(userBaseUrl: selectedBaseUrl, username: username, password: password) store.saveUser(baseUrl: selectedBaseUrl, username: username, password: password)
subscriptionManager.subscribe(baseUrl: selectedBaseUrl, topic: sanitizedTopic) subscriptionManager.subscribe(baseUrl: selectedBaseUrl, topic: sanitizedTopic)
} }
isShowing = false isShowing = false