krz/hutch

an ios client for sourcehut

clone: git clone https://gitbay.org/krz/hutch.git

v2.16.0: Hutch/Views/Repositories/ReferencesListView.swift · raw

 1import SwiftUI
 2
 3struct ReferencesListView: View {
 4    let viewModel: RepositoryDetailViewModel
 5
 6    var body: some View {
 7        List {
 8            if !viewModel.branches.isEmpty {
 9                Section("Branches") {
10                    ForEach(viewModel.branches, id: \.name) { ref in
11                        ReferenceRow(reference: ref, prefix: "refs/heads/")
12                    }
13                }
14            }
15
16            if !viewModel.tags.isEmpty {
17                Section("Tags") {
18                    ForEach(viewModel.tags, id: \.name) { ref in
19                        ReferenceRow(reference: ref, prefix: "refs/tags/")
20                    }
21                }
22            }
23        }
24        .listStyle(.insetGrouped)
25        .overlay {
26            if viewModel.isLoadingRefs, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
27                SRHTLoadingStateView(message: "Loading references…")
28            } else if let error = viewModel.error, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
29                SRHTErrorStateView(
30                    title: "Couldn't Load References",
31                    message: error,
32                    retryAction: { await viewModel.loadReferences() }
33                )
34            } else if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
35                ContentUnavailableView(
36                    "No References",
37                    systemImage: "arrow.triangle.branch",
38                    description: Text("This repository has no branches or tags.")
39                )
40            }
41        }
42        .task {
43            if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
44                await viewModel.loadReferences()
45            }
46        }
47        .refreshable {
48            await viewModel.loadReferences()
49        }
50    }
51}
52
53private struct ReferenceRow: View {
54    let reference: ReferenceDetail
55    let prefix: String
56
57    var body: some View {
58        HStack {
59            Label {
60                VStack(alignment: .leading, spacing: 2) {
61                    Text(shortName)
62                        .font(.body.monospaced())
63                    if let date = reference.date {
64                        Text(date.relativeDescription)
65                            .font(.caption)
66                            .foregroundStyle(.secondary)
67                    }
68                }
69            } icon: {
70                Image(systemName: icon)
71                    .foregroundStyle(iconColor)
72            }
73
74            Spacer()
75
76            Text(String((reference.target ?? "").prefix(8)))
77                .font(.caption.monospaced())
78                .foregroundStyle(.secondary)
79        }
80    }
81
82    private var shortName: String {
83        if reference.name.hasPrefix(prefix) {
84            String(reference.name.dropFirst(prefix.count))
85        } else {
86            reference.name
87        }
88    }
89
90    private var icon: String {
91        prefix.contains("tags") ? "tag" : "arrow.triangle.branch"
92    }
93
94    private var iconColor: Color {
95        prefix.contains("tags") ? .orange : .blue
96    }
97}