From 32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Tue, 17 Mar 2026 23:19:43 -0500 Subject: v1.0 --- .../Repositories/RepositorySettingsView.swift | 58 +++++++++++++++------- 1 file changed, 41 insertions(+), 17 deletions(-) (limited to 'Hutch/Views/Repositories/RepositorySettingsView.swift') diff --git a/Hutch/Views/Repositories/RepositorySettingsView.swift b/Hutch/Views/Repositories/RepositorySettingsView.swift index 3db434c..5074138 100644 --- a/Hutch/Views/Repositories/RepositorySettingsView.swift +++ b/Hutch/Views/Repositories/RepositorySettingsView.swift @@ -10,6 +10,7 @@ struct RepositorySettingsView: View { @Environment(\.dismiss) private var dismiss @State private var viewModel: RepositorySettingsViewModel? @State private var showDeleteConfirmation = false + @State private var pendingACLDeletion: ACLEntry? var body: some View { NavigationStack { @@ -17,7 +18,7 @@ struct RepositorySettingsView: View { if let viewModel { settingsForm(viewModel) } else { - ProgressView() + SRHTLoadingStateView(message: "Loading settings…") } } .navigationTitle("Settings") @@ -51,13 +52,7 @@ struct RepositorySettingsView: View { accessSection(viewModel) deleteSection(viewModel) } - .alert("Error", isPresented: .constant(viewModel.error != nil)) { - Button("OK") { viewModel.error = nil } - } message: { - if let error = viewModel.error { - Text(error) - } - } + .srhtErrorBanner(error: $vm.error) .alert( "Permanently delete \(repository.owner.canonicalName)/\(repository.name)?", isPresented: $showDeleteConfirmation @@ -75,6 +70,27 @@ struct RepositorySettingsView: View { } message: { Text("This cannot be undone.") } + .alert("Remove Access?", isPresented: Binding( + get: { pendingACLDeletion != nil }, + set: { isPresented in + if !isPresented { + pendingACLDeletion = nil + } + } + )) { + Button("Cancel", role: .cancel) {} + Button("Remove Access", role: .destructive) { + guard let entry = pendingACLDeletion else { return } + Task { + await viewModel.deleteACL(entry) + pendingACLDeletion = nil + } + } + } message: { + if let entry = pendingACLDeletion { + Text("\(entry.entity.canonicalName) will lose \(entry.mode) access to this repository.") + } + } } // MARK: - Info Section @@ -82,6 +98,11 @@ struct RepositorySettingsView: View { @ViewBuilder private func infoSection(_ viewModel: RepositorySettingsViewModel) -> some View { Section("Info") { + LabeledContent("Name") { + Text(repository.name) + .font(.body.monospaced()) + } + TextField("Description", text: Bindable(viewModel).editedDescription, axis: .vertical) .lineLimit(3...6) @@ -107,7 +128,7 @@ struct RepositorySettingsView: View { ProgressView() .frame(maxWidth: .infinity) } else { - Text("Save") + Text("Save Changes") .frame(maxWidth: .infinity) } } @@ -120,7 +141,7 @@ struct RepositorySettingsView: View { @ViewBuilder private func renameSection(_ viewModel: RepositorySettingsViewModel) -> some View { Section { - TextField("Repository Name", text: Bindable(viewModel).editedName) + TextField("New repository name", text: Bindable(viewModel).editedName) .autocorrectionDisabled() .textInputAutocapitalization(.never) @@ -141,7 +162,7 @@ struct RepositorySettingsView: View { ProgressView() .frame(maxWidth: .infinity) } else { - Text("Rename") + Text("Rename Repository") .frame(maxWidth: .infinity) } } @@ -163,7 +184,7 @@ struct RepositorySettingsView: View { Spacer() } } else if viewModel.acls.isEmpty { - Text("No access control entries.") + Text("No access entries yet.") .foregroundStyle(.secondary) } else { ForEach(viewModel.acls) { entry in @@ -174,11 +195,11 @@ struct RepositorySettingsView: View { .font(.caption.monospaced()) .foregroundStyle(.secondary) } - .swipeActions(edge: .trailing, allowsFullSwipe: true) { + .swipeActions(edge: .trailing, allowsFullSwipe: false) { Button(role: .destructive) { - Task { await viewModel.deleteACL(entry) } + pendingACLDeletion = entry } label: { - Label("Delete", systemImage: "trash") + Label("Remove Access", systemImage: "trash") } } } @@ -186,7 +207,7 @@ struct RepositorySettingsView: View { // Add ACL form HStack { - TextField("Username", text: Bindable(viewModel).newACLEntity) + TextField("Username or ~username", text: Bindable(viewModel).newACLEntity) .autocorrectionDisabled() .textInputAutocapitalization(.never) @@ -203,11 +224,14 @@ struct RepositorySettingsView: View { if viewModel.isAddingACL { ProgressView() } else { - Image(systemName: "plus.circle.fill") + Text("Add") } } .disabled(viewModel.isAddingACL || viewModel.newACLEntity.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) } + Text("Add a SourceHut user and choose read-only or read/write access.") + .font(.caption) + .foregroundStyle(.secondary) } header: { Text("Access") } -- cgit v1.2.3