krz/hutch

an ios client for sourcehut

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

v2.8.2: Hutch/Views/Repositories/ArtifactsView.swift · raw

 1import SwiftUI
 2
 3struct ArtifactsView: View {
 4    let viewModel: RepositoryDetailViewModel
 5    @Environment(\.openURL) private var openURL
 6
 7    var body: some View {
 8        List {
 9            ForEach(viewModel.referenceArtifacts) { refArtifacts in
10                Section(refArtifacts.name) {
11                    ForEach(refArtifacts.artifacts) { artifact in
12                        ArtifactRow(artifact: artifact) {
13                            openURL(artifact.url)
14                        }
15                    }
16                }
17            }
18        }
19        .listStyle(.insetGrouped)
20        .overlay {
21            if viewModel.isLoadingArtifacts, viewModel.referenceArtifacts.isEmpty {
22                SRHTLoadingStateView(message: "Loading artifacts…")
23            } else if let error = viewModel.error, viewModel.referenceArtifacts.isEmpty {
24                SRHTErrorStateView(
25                    title: "Couldn't Load Artifacts",
26                    message: error,
27                    retryAction: { await viewModel.loadArtifacts() }
28                )
29            } else if viewModel.referenceArtifacts.isEmpty {
30                ContentUnavailableView(
31                    "No Artifacts",
32                    systemImage: "archivebox",
33                    description: Text("This repository has no release artifacts.")
34                )
35            }
36        }
37        .task {
38            if viewModel.referenceArtifacts.isEmpty {
39                await viewModel.loadArtifacts()
40            }
41        }
42        .refreshable {
43            await viewModel.loadArtifacts()
44        }
45    }
46}
47
48private struct ArtifactRow: View {
49    let artifact: ArtifactInfo
50    let onDownload: () -> Void
51
52    var body: some View {
53        HStack {
54            VStack(alignment: .leading, spacing: 4) {
55                Text(artifact.filename)
56                    .font(.subheadline)
57
58                Text(artifact.size.formattedByteCount)
59                    .font(.caption)
60                    .foregroundStyle(.secondary)
61            }
62
63            Spacer()
64
65            Button {
66                onDownload()
67            } label: {
68                Image(systemName: "arrow.down.circle")
69                    .imageScale(.large)
70            }
71        }
72    }
73}