gitbay/Views/Repos/LogView.swift

5411753023a5e2958f17b523903abce380941107
gitbay-ios/gitbay/Views/Repos/LogView.swift history · blame · raw

92 lines · 2938 bytes

 1import SwiftUI
 2
 3struct LogView: View {
 4
 5    @State private var model: LogViewModel
 6
 7    init(client: GitbayClient, repo: String) {
 8        _model = State(initialValue: LogViewModel(client: client, repoPath: repo))
 9    }
10
11    var body: some View {
12        List {
13            ForEach(model.state.value ?? []) { commit in
14                CommitRow(commit: commit)
15            }
16        }
17        .overlay { LoadStateOverlay(state: model.state) }
18        .navigationTitle("History")
19        .navigationBarTitleDisplayMode(.inline)
20        .task { await model.load() }
21        .refreshable { await model.load() }
22    }
23}
24
25struct CommitRow: View {
26    let commit: Commit
27
28    var body: some View {
29        VStack(alignment: .leading, spacing: 4) {
30            Text(commit.subject)
31                .font(.subheadline.weight(.medium))
32                .lineLimit(2)
33            HStack(spacing: 6) {
34                Text(commit.shortSHA)
35                    .font(.caption.monospaced())
36                    .foregroundStyle(.secondary)
37                SignatureBadge(signature: commit.signature)
38                Spacer()
39                Text(commit.authorName)
40                    .font(.caption)
41                    .foregroundStyle(.secondary)
42                    .lineLimit(1)
43                Text(commit.date, format: .relative(presentation: .named))
44                    .font(.caption)
45                    .foregroundStyle(.tertiary)
46            }
47        }
48        .padding(.vertical, 2)
49    }
50}
51
52/// The server's signature verdict, worn as a small badge. The states come
53/// from the registry; the app only chooses glyph and colour.
54struct SignatureBadge: View {
55    let signature: Commit.Signature
56
57    var body: some View {
58        if let (icon, color, text) = presentation {
59            Label {
60                Text(text)
61            } icon: {
62                Image(systemName: icon)
63            }
64            .font(.caption2)
65            .foregroundStyle(color)
66            .labelStyle(.titleAndIcon)
67        }
68    }
69
70    /// Unsigned commits are the norm — no badge at all. Everything else
71    /// says what the server concluded.
72    private var presentation: (String, Color, String)? {
73        switch signature.state {
74        case .unsigned:
75            nil
76        case .verified:
77            ("checkmark.seal.fill", .green, signature.signer ?? "verified")
78        case .signedUnknownKey:
79            ("questionmark.diamond", .secondary, "unknown key")
80        case .signedEmailMismatch:
81            ("exclamationmark.triangle", .orange, "email mismatch")
82        case .signedKeyExpired:
83            ("clock.badge.exclamationmark", .orange, "key expired")
84        case .signedKeyRevoked:
85            ("xmark.seal", .red, "key revoked")
86        case .badSignature:
87            ("xmark.seal.fill", .red, "bad signature")
88        case .unrecognized(let state):
89            ("questionmark.circle", .secondary, state)
90        }
91    }
92}