summaryrefslogtreecommitdiff
path: root/Hutch/Views/Repositories/ReferencesListView.swift
blob: 0e3be0a433fba619494d9a6cbd88f2dbe7c2eb47 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import SwiftUI

struct ReferencesListView: View {
    let viewModel: RepositoryDetailViewModel

    var body: some View {
        List {
            if !viewModel.branches.isEmpty {
                Section("Branches") {
                    ForEach(viewModel.branches, id: \.name) { ref in
                        ReferenceRow(reference: ref, prefix: "refs/heads/")
                    }
                    .themedRow()
                }
            }

            if !viewModel.tags.isEmpty {
                Section("Tags") {
                    ForEach(viewModel.tags, id: \.name) { ref in
                        ReferenceRow(reference: ref, prefix: "refs/tags/")
                    }
                    .themedRow()
                }
            }
        }
        .themedList()
        .listStyle(.insetGrouped)
        .overlay {
            if viewModel.isLoadingRefs, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
                SRHTLoadingStateView(message: "Loading references…")
            } else if let error = viewModel.error, viewModel.branches.isEmpty, viewModel.tags.isEmpty {
                SRHTErrorStateView(
                    title: "Couldn't Load References",
                    message: error,
                    retryAction: { await viewModel.loadReferences() }
                )
            } else if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
                ContentUnavailableView(
                    "No References",
                    systemImage: "arrow.triangle.branch",
                    description: Text("This repository has no branches or tags.")
                )
            }
        }
        .task {
            if viewModel.branches.isEmpty, viewModel.tags.isEmpty {
                await viewModel.loadReferences()
            }
        }
        .refreshable {
            await viewModel.loadReferences()
        }
    }
}

private struct ReferenceRow: View {
    let reference: ReferenceDetail
    let prefix: String

    var body: some View {
        HStack {
            Label {
                VStack(alignment: .leading, spacing: 2) {
                    Text(shortName)
                        .font(.body.monospaced())
                    if let date = reference.date {
                        Text(date.relativeDescription)
                            .font(.caption)
                            .foregroundStyle(.secondary)
                    }
                }
            } icon: {
                Image(systemName: icon)
                    .foregroundStyle(iconColor)
            }

            Spacer()

            Text(String((reference.target ?? "").prefix(8)))
                .font(.caption.monospaced())
                .foregroundStyle(.secondary)
        }
    }

    private var shortName: String {
        if reference.name.hasPrefix(prefix) {
            String(reference.name.dropFirst(prefix.count))
        } else {
            reference.name
        }
    }

    private var icon: String {
        prefix.contains("tags") ? "tag" : "arrow.triangle.branch"
    }

    private var iconColor: Color {
        prefix.contains("tags") ? .orange : .blue
    }
}