summaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/RepositoryDetailView.swift
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-03-17 23:19:43 -0500
committerChristian Cleberg <[email protected]>2026-03-17 23:19:43 -0500
commit32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5 (patch)
treeee36d421d704e508d5617d803b4c8cbdb4804fe1 /Hutch/Views/Repositories/RepositoryDetailView.swift
parent8f2057c53e9009c2529c9c4849c914666c0e4b40 (diff)
downloadhutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.gz
hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.tar.bz2
hutch-32ad6cab8d58d99ebd8a28e8fa6e6f4e587cb1e5.zip
v1.0
Diffstat (limited to 'Hutch/Views/Repositories/RepositoryDetailView.swift')
-rw-r--r--Hutch/Views/Repositories/RepositoryDetailView.swift107
1 files changed, 107 insertions, 0 deletions
diff --git a/Hutch/Views/Repositories/RepositoryDetailView.swift b/Hutch/Views/Repositories/RepositoryDetailView.swift
new file mode 100644
index 0000000..9044e56
--- /dev/null
+++ b/Hutch/Views/Repositories/RepositoryDetailView.swift
@@ -0,0 +1,107 @@
+import SwiftUI
+
+struct RepositoryDetailView: View {
+ var repository: RepositorySummary
+ var onDeleted: (() -> Void)?
+
+ @Environment(AppState.self) private var appState
+ @Environment(\.dismiss) private var dismiss
+ @State private var viewModel: RepositoryDetailViewModel?
+ @State private var selectedTab: RepositoryDetailViewModel.Tab = .summary
+ @State private var showSettings = false
+ @State private var displayName: String
+
+ init(repository: RepositorySummary, onDeleted: (() -> Void)? = nil) {
+ self.repository = repository
+ self.onDeleted = onDeleted
+ self._displayName = State(initialValue: repository.name)
+ }
+
+ var body: some View {
+ if repository.service == .hg {
+ HgRepositoryDetailView(repository: repository, onDeleted: onDeleted)
+ } else {
+ Group {
+ if let viewModel {
+ detailContent(viewModel)
+ } else {
+ SRHTLoadingStateView(message: "Loading repository…")
+ }
+ }
+ .navigationTitle(displayName)
+ .navigationBarTitleDisplayMode(.inline)
+ .toolbar {
+ ToolbarItemGroup(placement: .topBarTrailing) {
+ SRHTShareButton(url: SRHTWebURL.repository(repository), target: .repository) {
+ Image(systemName: "square.and.arrow.up")
+ }
+
+ Button {
+ showSettings = true
+ } label: {
+ Image(systemName: "gear")
+ }
+ }
+ }
+ .sheet(isPresented: $showSettings) {
+ RepositorySettingsView(
+ repository: repository,
+ branches: viewModel?.branches ?? [],
+ client: appState.client,
+ onRenamed: { newName in
+ displayName = newName
+ },
+ onDeleted: {
+ dismiss()
+ onDeleted?()
+ }
+ )
+ }
+ .task {
+ if viewModel == nil {
+ viewModel = RepositoryDetailViewModel(
+ repository: repository,
+ client: appState.client
+ )
+ }
+ }
+ }
+ }
+
+ @ViewBuilder
+ private func detailContent(_ viewModel: RepositoryDetailViewModel) -> some View {
+ VStack(spacing: 0) {
+ Picker("Tab", selection: $selectedTab) {
+ ForEach(RepositoryDetailViewModel.Tab.allCases, id: \.self) { tab in
+ Text(tab.rawValue).tag(tab)
+ }
+ }
+ .pickerStyle(.segmented)
+ .padding(.horizontal)
+ .padding(.vertical, 8)
+
+ Divider()
+
+ switch selectedTab {
+ case .summary:
+ ReadmeView(viewModel: viewModel)
+ case .tree:
+ FileTreeView(
+ repository: repository,
+ client: appState.client
+ )
+ case .log:
+ CommitLogView(viewModel: viewModel)
+ case .refs:
+ ReferencesListView(viewModel: viewModel)
+ case .artifacts:
+ ArtifactsView(viewModel: viewModel)
+ }
+ }
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
+ .srhtErrorBanner(error: Binding(
+ get: { viewModel.error },
+ set: { viewModel.error = $0 }
+ ))
+ }
+}