From 86bcd9452d3107f68aca085e03e69b02667c0dbb Mon Sep 17 00:00:00 2001 From: Christian Cleberg Date: Sun, 12 Apr 2026 22:06:16 -0500 Subject: feat: polish read-only project views and home integration Refs: https://todo.sr.ht/~ccleberg/hutch/36 Refs: https://todo.sr.ht/~ccleberg/hutch/37 Refs: https://todo.sr.ht/~ccleberg/hutch/38 --- Hutch/Views/Home/HomeView.swift | 68 ++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 22 deletions(-) (limited to 'Hutch/Views/Home/HomeView.swift') diff --git a/Hutch/Views/Home/HomeView.swift b/Hutch/Views/Home/HomeView.swift index 42a6737..426d351 100644 --- a/Hutch/Views/Home/HomeView.swift +++ b/Hutch/Views/Home/HomeView.swift @@ -179,7 +179,7 @@ struct HomeView: View { @ViewBuilder private func projectsSection(_ viewModel: HomeViewModel) -> some View { - if !viewModel.pinnedProjects.isEmpty { + if viewModel.hasPinnedProjects { HomeSectionView("Pinned Projects", isExpanded: $projectsExpanded) { NavigationLink { ProjectsListView() @@ -189,11 +189,27 @@ struct HomeView: View { } .buttonStyle(.plain) } content: { - ForEach(viewModel.pinnedProjects.prefix(projectPreviewLimit)) { project in - NavigationLink { - ProjectDetailView(project: project) - } label: { - HomeProjectRow(project: project) + if viewModel.isLoadingProjects && viewModel.pinnedProjects.isEmpty { + HomeSectionLoadingRow(label: "Loading pinned projects") + } else if let error = viewModel.projectsError, viewModel.pinnedProjects.isEmpty { + HomeSectionMessageRow( + text: "Couldn’t load pinned projects.", + systemImage: "exclamationmark.triangle", + emphasized: true, + accessibilityHint: error + ) + } else if viewModel.pinnedProjects.isEmpty { + HomeSectionMessageRow( + text: "Pinned projects will appear here when they’re available.", + systemImage: "pin" + ) + } else { + ForEach(viewModel.pinnedProjects.prefix(projectPreviewLimit)) { project in + NavigationLink { + ProjectDetailView(project: project) + } label: { + HomeProjectRow(project: project) + } } } } @@ -388,26 +404,34 @@ private struct HomeProjectRow: View { let project: Project var body: some View { - VStack(alignment: .leading, spacing: 4) { - Text(project.name) - .font(.subheadline.weight(.medium)) - .lineLimit(1) + VStack(alignment: .leading, spacing: 8) { + HStack(alignment: .top, spacing: 10) { + VStack(alignment: .leading, spacing: 4) { + Text(project.displayName) + .font(.subheadline.weight(.medium)) + .foregroundStyle(.primary) + .lineLimit(1) - if let description = project.description, !description.isEmpty { - Text(description) - .font(.caption) - .foregroundStyle(.secondary) - .lineLimit(1) - } + if let description = project.displayDescription { + Text(description) + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(2) + } + } - if let summary = project.resourceSummary { - Text(summary) - .font(.caption) - .foregroundStyle(.tertiary) - .lineLimit(1) + Spacer(minLength: 8) + + VisibilityBadge(visibility: project.visibility) } + + Text(project.metadataLine) + .font(.caption) + .foregroundStyle(.secondary) + .lineLimit(1) } - .padding(.vertical, 2) + .contentShape(Rectangle()) + .padding(.vertical, 4) } } -- cgit v1.2.3