diff options
42 files changed, 300 insertions, 152 deletions
diff --git a/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin.png b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin.png Binary files differnew file mode 100644 index 0000000..91b3207 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin.png diff --git a/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@2x.png b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@2x.png Binary files differnew file mode 100644 index 0000000..4d29c13 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@2x.png diff --git a/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@3x.png b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@3x.png Binary files differnew file mode 100644 index 0000000..9c18c0c --- /dev/null +++ b/Hotline/Assets.xcassets/Account Admin.imageset/Account Admin@3x.png diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json b/Hotline/Assets.xcassets/Account Admin.imageset/Contents.json index 8147f45..c07952d 100644 --- a/Hotline/Assets.xcassets/Message Board Post.imageset/Contents.json +++ b/Hotline/Assets.xcassets/Account Admin.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "Message Board Post.png", + "filename" : "Account Admin.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Message Board Post@2x.png", + "filename" : "Account Admin@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Message Board Post@3x.png", + "filename" : "Account Admin@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Hotline/Assets.xcassets/Account Default.imageset/Account Default.png b/Hotline/Assets.xcassets/Account Default.imageset/Account Default.png Binary files differnew file mode 100644 index 0000000..16505a3 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Default.imageset/Account Default.png diff --git a/Hotline/Assets.xcassets/Account Default.imageset/Account Default@2x.png b/Hotline/Assets.xcassets/Account Default.imageset/Account Default@2x.png Binary files differnew file mode 100644 index 0000000..cd6aaac --- /dev/null +++ b/Hotline/Assets.xcassets/Account Default.imageset/Account Default@2x.png diff --git a/Hotline/Assets.xcassets/Account Default.imageset/Account Default@3x.png b/Hotline/Assets.xcassets/Account Default.imageset/Account Default@3x.png Binary files differnew file mode 100644 index 0000000..7a9b898 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Default.imageset/Account Default@3x.png diff --git a/Hotline/Assets.xcassets/Account Default.imageset/Contents.json b/Hotline/Assets.xcassets/Account Default.imageset/Contents.json new file mode 100644 index 0000000..024f924 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Default.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Account Default.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Account Default@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Account Default@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty.png b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty.png Binary files differnew file mode 100644 index 0000000..23216e0 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty.png diff --git a/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@2x.png b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@2x.png Binary files differnew file mode 100644 index 0000000..ab37f9e --- /dev/null +++ b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@2x.png diff --git a/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@3x.png b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@3x.png Binary files differnew file mode 100644 index 0000000..5648140 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Empty.imageset/Account Empty@3x.png diff --git a/Hotline/Assets.xcassets/Account Empty.imageset/Contents.json b/Hotline/Assets.xcassets/Account Empty.imageset/Contents.json new file mode 100644 index 0000000..b4aabb1 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Empty.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Account Empty.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Account Empty@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Account Empty@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved.png b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved.png Binary files differnew file mode 100644 index 0000000..b0c3697 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved.png diff --git a/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@2x.png b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@2x.png Binary files differnew file mode 100644 index 0000000..16a7e81 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@2x.png diff --git a/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@3x.png b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@3x.png Binary files differnew file mode 100644 index 0000000..d703022 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Unsaved.imageset/Account Unsaved@3x.png diff --git a/Hotline/Assets.xcassets/Account Unsaved.imageset/Contents.json b/Hotline/Assets.xcassets/Account Unsaved.imageset/Contents.json new file mode 100644 index 0000000..907d263 --- /dev/null +++ b/Hotline/Assets.xcassets/Account Unsaved.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "Account Unsaved.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Account Unsaved@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Account Unsaved@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png Binary files differdeleted file mode 100644 index 3d7fae1..0000000 --- a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post.png +++ /dev/null diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png Binary files differdeleted file mode 100644 index 1ccc659..0000000 --- a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@2x.png +++ /dev/null diff --git a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png b/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png Binary files differdeleted file mode 100644 index 98bd367..0000000 --- a/Hotline/Assets.xcassets/Message Board Post.imageset/Message Board Post@3x.png +++ /dev/null diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png Binary files differindex 1b154db..eec1604 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle.png diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png Binary files differindex 7583460..f37924c 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@2x.png diff --git a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png Binary files differindex f3adb80..dc8b6df 100644 --- a/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png +++ b/Hotline/Assets.xcassets/News Bundle.imageset/News Bundle@3x.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category.png b/Hotline/Assets.xcassets/News Category.imageset/News Category.png Binary files differindex bf20da6..2d21b2e 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png b/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png Binary files differindex a2a61a0..db98b49 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category@2x.png diff --git a/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png b/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png Binary files differindex 5a6876e..f0b8850 100644 --- a/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png +++ b/Hotline/Assets.xcassets/News Category.imageset/News Category@3x.png diff --git a/Hotline/Assets.xcassets/Section Board.imageset/Section Board.png b/Hotline/Assets.xcassets/Section Board.imageset/Section Board.png Binary files differindex 6ebd353..b04621b 100644 --- a/Hotline/Assets.xcassets/Section Board.imageset/Section Board.png +++ b/Hotline/Assets.xcassets/Section Board.imageset/Section Board.png diff --git a/Hotline/Assets.xcassets/Section Board.imageset/Section Board@2x.png b/Hotline/Assets.xcassets/Section Board.imageset/Section Board@2x.png Binary files differindex 731fcfe..225ad88 100644 --- a/Hotline/Assets.xcassets/Section Board.imageset/Section Board@2x.png +++ b/Hotline/Assets.xcassets/Section Board.imageset/Section Board@2x.png diff --git a/Hotline/Assets.xcassets/Section Board.imageset/Section Board@3x.png b/Hotline/Assets.xcassets/Section Board.imageset/Section Board@3x.png Binary files differindex 754ce9b..f07f136 100644 --- a/Hotline/Assets.xcassets/Section Board.imageset/Section Board@3x.png +++ b/Hotline/Assets.xcassets/Section Board.imageset/Section Board@3x.png diff --git a/Hotline/Assets.xcassets/Section News.imageset/Section News.png b/Hotline/Assets.xcassets/Section News.imageset/Section News.png Binary files differindex 9285bf7..1e9f8e7 100644 --- a/Hotline/Assets.xcassets/Section News.imageset/Section News.png +++ b/Hotline/Assets.xcassets/Section News.imageset/Section News.png diff --git a/Hotline/Assets.xcassets/Section News.imageset/Section News@2x.png b/Hotline/Assets.xcassets/Section News.imageset/Section News@2x.png Binary files differindex b7479d6..cad57f8 100644 --- a/Hotline/Assets.xcassets/Section News.imageset/Section News@2x.png +++ b/Hotline/Assets.xcassets/Section News.imageset/Section News@2x.png diff --git a/Hotline/Assets.xcassets/Section News.imageset/Section News@3x.png b/Hotline/Assets.xcassets/Section News.imageset/Section News@3x.png Binary files differindex 1af6a13..8e9567b 100644 --- a/Hotline/Assets.xcassets/Section News.imageset/Section News@3x.png +++ b/Hotline/Assets.xcassets/Section News.imageset/Section News@3x.png diff --git a/Hotline/Assets.xcassets/User Admin.imageset/Contents.json b/Hotline/Assets.xcassets/User Admin.imageset/Contents.json new file mode 100644 index 0000000..e1d19f0 --- /dev/null +++ b/Hotline/Assets.xcassets/User Admin.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "User Admin.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "User Admin@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "User Admin@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Hotline/Assets.xcassets/User Admin.imageset/User Admin.png b/Hotline/Assets.xcassets/User Admin.imageset/User Admin.png Binary files differnew file mode 100644 index 0000000..deb0fe1 --- /dev/null +++ b/Hotline/Assets.xcassets/User Admin.imageset/User Admin.png diff --git a/Hotline/Assets.xcassets/User Admin.imageset/User Admin@2x.png b/Hotline/Assets.xcassets/User Admin.imageset/User Admin@2x.png Binary files differnew file mode 100644 index 0000000..0698f46 --- /dev/null +++ b/Hotline/Assets.xcassets/User Admin.imageset/User Admin@2x.png diff --git a/Hotline/Assets.xcassets/User Admin.imageset/User Admin@3x.png b/Hotline/Assets.xcassets/User Admin.imageset/User Admin@3x.png Binary files differnew file mode 100644 index 0000000..09e17d2 --- /dev/null +++ b/Hotline/Assets.xcassets/User Admin.imageset/User Admin@3x.png diff --git a/Hotline/Assets.xcassets/User.imageset/User.png b/Hotline/Assets.xcassets/User.imageset/User.png Binary files differindex 6a1a8c3..c867a66 100644 --- a/Hotline/Assets.xcassets/User.imageset/User.png +++ b/Hotline/Assets.xcassets/User.imageset/User.png diff --git a/Hotline/Assets.xcassets/User.imageset/User@2x.png b/Hotline/Assets.xcassets/User.imageset/User@2x.png Binary files differindex 4c025f7..03536ff 100644 --- a/Hotline/Assets.xcassets/User.imageset/User@2x.png +++ b/Hotline/Assets.xcassets/User.imageset/User@2x.png diff --git a/Hotline/Assets.xcassets/User.imageset/User@3x.png b/Hotline/Assets.xcassets/User.imageset/User@3x.png Binary files differindex 58f9167..1bf8f58 100644 --- a/Hotline/Assets.xcassets/User.imageset/User@3x.png +++ b/Hotline/Assets.xcassets/User.imageset/User@3x.png diff --git a/Hotline/macOS/AccountManagerView.swift b/Hotline/macOS/AccountManagerView.swift index 1ada9f3..57682cc 100644 --- a/Hotline/macOS/AccountManagerView.swift +++ b/Hotline/macOS/AccountManagerView.swift @@ -7,87 +7,84 @@ struct AccountManagerView: View { @State private var selection: HotlineAccount? @State private var loading: Bool = true - @State var pendingName: String = "" - @State var pendingLogin: String = "" - @State var pendingPassword: String = "" - @State var pendingAccess = HotlineUserAccessOptions.defaultAccess + @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 { - NavigationSplitView(){ - if loading == false { - List(accounts, id: \.self, selection: $selection) { account in - HStack { - if account.access.contains(.canDisconnectUsers) { - Image(nsImage: Hotline.getClassicIcon(192)!) - .frame(width: 16, height: 16) - .padding(.leading, 4) - Text(account.login) - } - else if account.access.rawValue == 0 { - Image(nsImage: Hotline.getClassicIcon(190)!) - .frame(width: 16, height: 16) - .padding(.leading, 4) - Text(account.login) - } - else if account.persisted == false { - HStack { - Image(nsImage: Hotline.getClassicIcon(191)!) - .frame(width: 16, height: 16) - .padding(.leading, 4) - Text(account.login) - .italic() - } - } else { - Image(nsImage: Hotline.getClassicIcon(193)!) - .frame(width: 16, height: 16) - .padding(.leading, 4) - Text(account.login) - } - } + HStack(spacing: 0) { + ZStack { + accountList + if loading { + ProgressView() } - .sheet(item: $toDelete ) { item in - Form { - 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) - .toolbar { - ToolbarItem(placement: .cancellationAction) { - Button("Cancel") { - toDelete = nil - } - } - - ToolbarItem(placement: .primaryAction) { - Button("Delete"){ - guard toDelete != nil else { - return - } - model.client.sendDeleteUser(login: toDelete!.login) - accounts = accounts.filter { $0.login != toDelete!.login } - self.toDelete = nil - self.selection = nil - } - } - } + } + if selection != nil { + accountDetails + } + else { + ZStack(alignment: .center) { + Text("No Account Selected") + .font(.title) + .foregroundStyle(.secondary) + .multilineTextAlignment(.center) + .padding() } + .frame(maxWidth: .infinity) } - } detail: { - if let selection { + } + .environment(\.defaultMinListRowHeight, 34) + .listStyle(.inset) + .alternatingRowBackgrounds(.enabled) + .task { + if loading { + accounts = await model.getAccounts() + loading = false + } + } + .toolbar { + ToolbarItem(placement: .primaryAction) { + Button { + let newAccount = HotlineAccount("unnamed", "unnamed", HotlineUserAccessOptions.defaultAccess) + + pendingPassword = HotlineAccount.randomPassword() + accounts.append(newAccount) + selection = newAccount + } label: { + Label("New Account", systemImage: "plus") + } + .help("Create a new account") + .disabled(model.access?.contains(.canCreateUsers) != true) + } + + ToolbarItem(placement: .destructiveAction) { + Button { + toDelete = selection + } label: { + Label("Delete Account", systemImage: "trash") + } + .help("Delete account") + .disabled(selection == nil || model.access?.contains(.canDeleteUsers) != true) + } + } + } + + var accountDetails: some View { + VStack(alignment: .center, spacing: 0) { + ScrollView(.vertical) { Form { - Group { - TextField("Name", text: $pendingName) + Section { + TextField(text: $pendingName) { + Text("Name") + } TextField("Login", text: $pendingLogin) - .disabled(selection.persisted == true) - if selection.persisted == true { + .disabled(selection?.persisted == true) + if selection?.persisted == true { SecureField("Password", text: $pendingPassword) } else { TextField("Password", text: $pendingPassword) @@ -192,77 +189,43 @@ struct AccountManagerView: View { .disabled(model.access?.contains(.canModifyUsers) == false) .formStyle(.grouped) .onChange(of: selection) { - pendingName = selection.name - pendingLogin = selection.login - pendingAccess = selection.access - - if selection.persisted { - if selection.password == nil { - pendingPassword = "" - } else { - pendingPassword = placeholderPassword + if let selection { + pendingName = selection.name + pendingLogin = selection.login + pendingAccess = selection.access + + if selection.persisted { + if selection.password == nil { + pendingPassword = "" + } else { + pendingPassword = placeholderPassword + } } } } .onAppear() { - pendingName = selection.name - pendingLogin = selection.login - pendingAccess = selection.access - - if selection.persisted { - if selection.password == nil { - pendingPassword = "" + if let selection { + pendingName = selection.name + pendingLogin = selection.login + pendingAccess = selection.access + + if selection.persisted { + if selection.password == nil { + pendingPassword = "" + } else { + pendingPassword = placeholderPassword + } } else { - pendingPassword = placeholderPassword + pendingPassword = HotlineAccount.randomPassword() } - } else { - pendingPassword = HotlineAccount.randomPassword() } } } - } - .environment(\.defaultMinListRowHeight, 34) - .listStyle(.inset) - .alternatingRowBackgrounds(.enabled) - .task { - if loading { - accounts = await model.getAccounts() - loading = false - } - } - .toolbar { - if model.access?.contains(.canCreateUsers) == true { - ToolbarItem(placement: .primaryAction) { - Button { - let newAccount = HotlineAccount("unnamed", "unnamed", HotlineUserAccessOptions.defaultAccess) - - pendingPassword = HotlineAccount.randomPassword() - accounts.append(newAccount) - selection = newAccount - } label: { - Label("New Account", systemImage: "plus") - } - .help("Create a new account") - } - } + .frame(maxWidth: .infinity) - if model.access?.contains(.canDeleteUsers) == true { - ToolbarItem(placement: .primaryAction) { - Button { - toDelete = selection - } label: { - Label("Delete Account", systemImage: "trash") - } - .help("Delete account") - .disabled(selection == nil) - } - } - } - - Divider() - - VStack(alignment: .trailing) { - HStack(){ + Divider() + + HStack() { Button("Revert") { if let selection { pendingAccess = selection.access @@ -274,7 +237,12 @@ struct AccountManagerView: View { } } } + .controlSize(.large) + .frame(minWidth: 75) .disabled(!self.isSaveable()) +// .padding() + + Spacer() Button("Save"){ guard let selection else { @@ -285,14 +253,20 @@ struct AccountManagerView: View { if selection.persisted == true { if pendingPassword == placeholderPassword { - model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: nil, access: pendingAccess.rawValue) + Task { @MainActor in + model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: nil, access: pendingAccess.rawValue) + } } else { - model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: pendingPassword, access: pendingAccess.rawValue) + Task { @MainActor in + model.client.sendSetUser(name: pendingName, login: pendingLogin, newLogin: nil, password: pendingPassword, access: pendingAccess.rawValue) + } } } else { // Create new existing account - model.client.sendCreateUser(name: pendingName, login: pendingLogin, password: pendingPassword, access: pendingAccess.rawValue) + Task { @MainActor in + model.client.sendCreateUser(name: pendingName, login: pendingLogin, password: pendingPassword, access: pendingAccess.rawValue) + } self.selection?.password = pendingPassword pendingPassword = placeholderPassword } @@ -310,10 +284,90 @@ struct AccountManagerView: View { accounts.sort { $0.login < $1.login } self.selection = account } + .controlSize(.large) + .frame(minWidth: 75) .keyboardShortcut(.defaultAction) .disabled(!self.isSaveable()) } - .frame(height: 40) + .padding() + } + + } + + var accountList: some View { + List(accounts, id: \.self, selection: $selection) { account in + HStack(spacing: 5) { + if account.access.contains(.canDisconnectUsers) { + Image("User Admin") + .frame(width: 16, height: 16) + .opacity(account.persisted ? 1.0 : 0.25) + // .padding(.leading, 4) + Text(account.login) + .foregroundStyle(Color.hotlineRed) + } + else if account.access.rawValue == 0 { + Image("User") + .frame(width: 16, height: 16) + // .padding(.leading, 4) + Text(account.login) + .foregroundStyle(.secondary) + } + // else if account.persisted == false { + // HStack { + // Image("User") + // .frame(width: 16, height: 16) + //// .padding(.leading, 4) + // Text(account.login) + // .italic() + // } + // } + else { + Image("User") + .frame(width: 16, height: 16) + .opacity(account.persisted ? 1.0 : 0.5) + // .padding(.leading, 4) + Text(account.login) + } + } + } + .frame(width: 250) + .sheet(item: $toDelete) { item in + Form { + 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) + .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 } + + } + } + } } } diff --git a/Hotline/macOS/MessageBoardView.swift b/Hotline/macOS/MessageBoardView.swift index ba9968b..f870b0c 100644 --- a/Hotline/macOS/MessageBoardView.swift +++ b/Hotline/macOS/MessageBoardView.swift @@ -40,16 +40,14 @@ struct MessageBoardView: View { .background(Color(nsColor: .textBackgroundColor)) } else { - VStack { + ZStack(alignment: .center) { Text("No Message Board") - .bold() + .font(.title) + .multilineTextAlignment(.center) .foregroundStyle(.secondary) - .font(.title3) - Text("This server has the message board turned off.") - .foregroundStyle(.tertiary) - .font(.system(size: 13)) + .padding() } - .padding() + .frame(maxWidth: .infinity) } } .sheet(isPresented: $composerDisplayed) { diff --git a/Hotline/macOS/NewsItemView.swift b/Hotline/macOS/NewsItemView.swift index 9614663..fc20e61 100644 --- a/Hotline/macOS/NewsItemView.swift +++ b/Hotline/macOS/NewsItemView.swift @@ -85,6 +85,12 @@ struct NewsItemView: View { .foregroundStyle(.secondary) .padding(.trailing, 8) } + else if news.type == .bundle && news.count > 0 { + Text("^[\(news.count) Category](inflect: true)") + .lineLimit(1) + .foregroundStyle(.secondary) + .padding(.trailing, 8) + } // if news.type == .bundle { // Text("\(news.count)") // .lineLimit(1) diff --git a/Hotline/macOS/NewsView.swift b/Hotline/macOS/NewsView.swift index e4f4d21..45cb057 100644 --- a/Hotline/macOS/NewsView.swift +++ b/Hotline/macOS/NewsView.swift @@ -37,16 +37,14 @@ struct NewsView: View { loadingIndicator } else if model.news.isEmpty { - VStack { + ZStack(alignment: .center) { Text("No News") - .bold() + .font(.title) + .multilineTextAlignment(.center) .foregroundStyle(.secondary) - .font(.title3) - Text("This server has no news available.") - .foregroundStyle(.tertiary) - .font(.system(size: 13)) + .padding() } - .padding() + .frame(maxWidth: .infinity) } else { newsBrowser |