aboutsummaryrefslogtreecommitdiff
path: root/Hotline/macOS/AccountManagerView.swift
diff options
context:
space:
mode:
Diffstat (limited to 'Hotline/macOS/AccountManagerView.swift')
-rw-r--r--Hotline/macOS/AccountManagerView.swift117
1 files changed, 62 insertions, 55 deletions
diff --git a/Hotline/macOS/AccountManagerView.swift b/Hotline/macOS/AccountManagerView.swift
index 57682cc..84ae6dc 100644
--- a/Hotline/macOS/AccountManagerView.swift
+++ b/Hotline/macOS/AccountManagerView.swift
@@ -2,20 +2,20 @@ import SwiftUI
struct AccountManagerView: View {
@Environment(Hotline.self) private var model: Hotline
-
+
@State private var accounts: [HotlineAccount] = []
@State private var selection: HotlineAccount?
@State private var loading: Bool = true
-
+
@State private var pendingName: String = ""
@State private var pendingLogin: String = ""
@State private var pendingPassword: String = ""
@State private var pendingAccess = HotlineUserAccessOptions.defaultAccess
-
+
@State private var toDelete: HotlineAccount?
-
+
let placeholderPassword = "xxxxxxxxxxxxxxxxxx"
-
+
var body: some View {
HStack(spacing: 0) {
ZStack {
@@ -26,8 +26,7 @@ struct AccountManagerView: View {
}
if selection != nil {
accountDetails
- }
- else {
+ } else {
ZStack(alignment: .center) {
Text("No Account Selected")
.font(.title)
@@ -50,8 +49,9 @@ struct AccountManagerView: View {
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button {
- let newAccount = HotlineAccount("unnamed", "unnamed", HotlineUserAccessOptions.defaultAccess)
-
+ let newAccount = HotlineAccount(
+ "unnamed", "unnamed", HotlineUserAccessOptions.defaultAccess)
+
pendingPassword = HotlineAccount.randomPassword()
accounts.append(newAccount)
selection = newAccount
@@ -61,7 +61,7 @@ struct AccountManagerView: View {
.help("Create a new account")
.disabled(model.access?.contains(.canCreateUsers) != true)
}
-
+
ToolbarItem(placement: .destructiveAction) {
Button {
toDelete = selection
@@ -73,7 +73,7 @@ struct AccountManagerView: View {
}
}
}
-
+
var accountDetails: some View {
VStack(alignment: .center, spacing: 0) {
ScrollView(.vertical) {
@@ -92,7 +92,7 @@ struct AccountManagerView: View {
}
.textFieldStyle(.roundedBorder)
.controlSize(.large)
-
+
Section("File System Maintenance") {
Toggle("Can Download Files", isOn: $pendingAccess.bind(.canDownloadFiles))
.disabled(model.access?.contains(.canDownloadFiles) == false)
@@ -127,7 +127,7 @@ struct AccountManagerView: View {
Toggle("Can Make Aliases", isOn: $pendingAccess.bind(.canMakeAliases))
.disabled(model.access?.contains(.canMakeAliases) == false)
}
-
+
Section("User Maintenance") {
Toggle("Can Create Accounts", isOn: $pendingAccess.bind(.canCreateUsers))
.disabled(model.access?.contains(.canCreateUsers) == false)
@@ -139,20 +139,20 @@ struct AccountManagerView: View {
.disabled(model.access?.contains(.canModifyUsers) == false)
Toggle("Can Get User Info", isOn: $pendingAccess.bind(.canGetClientInfo))
.disabled(model.access?.contains(.canGetClientInfo) == false)
-
+
Toggle("Can Disconnect Users", isOn: $pendingAccess.bind(.canDisconnectUsers))
.disabled(model.access?.contains(.canDisconnectUsers) == false)
Toggle("Cannot be Disconnected", isOn: $pendingAccess.bind(.cantBeDisconnected))
.disabled(model.access?.contains(.cantBeDisconnected) == false)
}
-
+
Section("Messaging") {
Toggle("Can Send Messages", isOn: $pendingAccess.bind(.canSendMessages))
.disabled(model.access?.contains(.canSendMessages) == false)
Toggle("Can Broadcast", isOn: $pendingAccess.bind(.canBroadcast))
.disabled(model.access?.contains(.canBroadcast) == false)
}
-
+
Section("News") {
Toggle("Can Read Articles", isOn: $pendingAccess.bind(.canReadMessageBoard))
.disabled(model.access?.contains(.canReadMessageBoard) == false)
@@ -169,7 +169,7 @@ struct AccountManagerView: View {
Toggle("Can Delete News Bundles", isOn: $pendingAccess.bind(.canDeleteNewsFolders))
.disabled(model.access?.contains(.canDeleteNewsFolders) == false)
}
-
+
Section("Chat") {
Toggle("Can Initiate Private Chat", isOn: $pendingAccess.bind(.canCreateChat))
.disabled(model.access?.contains(.canCreateChat) == false)
@@ -178,7 +178,7 @@ struct AccountManagerView: View {
Toggle("Can Send Chat", isOn: $pendingAccess.bind(.canSendChat))
.disabled(model.access?.contains(.canSendChat) == false)
}
-
+
Section("Miscellaneous") {
Toggle("Can Use Any Name", isOn: $pendingAccess.bind(.canUseAnyName))
.disabled(model.access?.contains(.canUseAnyName) == false)
@@ -193,7 +193,7 @@ struct AccountManagerView: View {
pendingName = selection.name
pendingLogin = selection.login
pendingAccess = selection.access
-
+
if selection.persisted {
if selection.password == nil {
pendingPassword = ""
@@ -203,12 +203,12 @@ struct AccountManagerView: View {
}
}
}
- .onAppear() {
+ .onAppear {
if let selection {
pendingName = selection.name
pendingLogin = selection.login
pendingAccess = selection.access
-
+
if selection.persisted {
if selection.password == nil {
pendingPassword = ""
@@ -216,22 +216,22 @@ struct AccountManagerView: View {
pendingPassword = placeholderPassword
}
} else {
- pendingPassword = HotlineAccount.randomPassword()
+ pendingPassword = HotlineAccount.randomPassword()
}
}
}
}
.frame(maxWidth: .infinity)
-
+
Divider()
-
- HStack() {
+
+ HStack {
Button("Revert") {
if let selection {
pendingAccess = selection.access
pendingName = selection.name
pendingLogin = selection.login
-
+
if selection.password != nil {
pendingPassword = selection.password!
}
@@ -240,46 +240,52 @@ struct AccountManagerView: View {
.controlSize(.large)
.frame(minWidth: 75)
.disabled(!self.isSaveable())
-// .padding()
-
+ // .padding()
+
Spacer()
-
- Button("Save"){
+
+ Button("Save") {
guard let selection else {
return
}
-
+
// Update existing account
if selection.persisted == true {
if pendingPassword == placeholderPassword {
Task { @MainActor in
- model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: nil, access: pendingAccess.rawValue)
+ model.client.sendSetUser(
+ name: pendingName, login: pendingLogin, newLogin: nil, password: nil,
+ access: pendingAccess.rawValue)
}
} else {
Task { @MainActor in
- model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: pendingPassword, access: pendingAccess.rawValue)
+ model.client.sendSetUser(
+ name: pendingName, login: pendingLogin, newLogin: nil, password: pendingPassword,
+ access: pendingAccess.rawValue)
}
}
} else {
// Create new existing account
Task { @MainActor in
- model.client.sendCreateUser(name: pendingName, login: pendingLogin, password: pendingPassword, access: pendingAccess.rawValue)
+ model.client.sendCreateUser(
+ name: pendingName, login: pendingLogin, password: pendingPassword,
+ access: pendingAccess.rawValue)
}
self.selection?.password = pendingPassword
pendingPassword = placeholderPassword
}
-
+
var account = HotlineAccount(pendingName, pendingLogin, pendingAccess)
account.persisted = true
account.password = placeholderPassword
-
+
accounts = accounts.filter { $0.persisted == true && $0.login != selection.login }
-
+
// Add new account to list
accounts.append(account)
-
+
// Re-sort accounts
accounts.sort { $0.login < $1.login }
self.selection = account
@@ -291,9 +297,9 @@ struct AccountManagerView: View {
}
.padding()
}
-
+
}
-
+
var accountList: some View {
List(accounts, id: \.self, selection: $selection) { account in
HStack(spacing: 5) {
@@ -304,8 +310,7 @@ struct AccountManagerView: View {
// .padding(.leading, 4)
Text(account.login)
.foregroundStyle(Color.hotlineRed)
- }
- else if account.access.rawValue == 0 {
+ } else if account.access.rawValue == 0 {
Image("User")
.frame(width: 16, height: 16)
// .padding(.leading, 4)
@@ -333,65 +338,67 @@ struct AccountManagerView: View {
.frame(width: 250)
.sheet(item: $toDelete) { item in
Form {
- HStack{
+ HStack {
Image(systemName: "exclamationmark.triangle")
.font(.system(size: 30))
Text("Delete account \"\(item.name)\" and all associated files?")
.lineSpacing(4)
}
}
- .frame(minWidth: 300, idealWidth: 450, maxWidth: .infinity, minHeight: 100, idealHeight: 100, maxHeight: .infinity)
+ .frame(
+ minWidth: 300, idealWidth: 450, maxWidth: .infinity, minHeight: 100, idealHeight: 100,
+ maxHeight: .infinity
+ )
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
toDelete = nil
}
}
-
+
ToolbarItem(placement: .primaryAction) {
Button("Delete") {
guard let userToDelete = toDelete else {
return
}
-
+
self.toDelete = nil
self.selection = nil
-
+
if userToDelete.persisted {
Task { @MainActor in
model.client.sendDeleteUser(login: userToDelete.login)
}
}
-
+
accounts = accounts.filter { $0.login != userToDelete.login }
-
+
}
}
}
}
}
-
-
+
private func isSaveable() -> Bool {
guard let selection else {
return false
}
-
+
// Disable save if login field is cleared
if pendingLogin == "" {
return false
}
-
+
// If the account initial has a password and it was updated
if selection.password != nil && pendingPassword != placeholderPassword {
return true
}
-
+
// If the account initial has no password, but was updated to have one
if selection.password == nil && pendingPassword != "" {
return true
}
-
+
// If the access bits or user name have been changed
return pendingAccess.rawValue != selection.access.rawValue || selection.name != pendingName
}