summaryrefslogtreecommitdiff
path: root/Hutch/Views/Builds
diff options
context:
space:
mode:
authorChristian Cleberg <[email protected]>2026-04-13 19:06:54 -0500
committerChristian Cleberg <[email protected]>2026-04-13 19:06:54 -0500
commita6ad2b9815d72575206bdca860eef9db850cdf1c (patch)
treeb4d5f27aa1655e5e40bab178550d6e2576d7df8b /Hutch/Views/Builds
parent02a44d115b3784231cad640e992d9c18a7f67b40 (diff)
downloadhutch-a6ad2b9815d72575206bdca860eef9db850cdf1c.tar.gz
hutch-a6ad2b9815d72575206bdca860eef9db850cdf1c.tar.bz2
hutch-a6ad2b9815d72575206bdca860eef9db850cdf1c.zip
feat(theme): AMOLED true-black rows via themedRow()
Apply listRowBackground(Color.black) per row in AMOLED mode using ThemedRowStyle and themedRow() across Lists and Forms. Use themedList() for scroll/grouped backgrounds. Treat segmented and clear list rows with isAMOLED-aware listRowBackground where Color.clear was required. Removes reliance on UIKit appearance for list cells on iOS 16+. Implements: https://todo.sr.ht/~ccleberg/hutch/24
Diffstat (limited to 'Hutch/Views/Builds')
-rw-r--r--Hutch/Views/Builds/BuildDetailView.swift25
-rw-r--r--Hutch/Views/Builds/BuildListView.swift14
2 files changed, 38 insertions, 1 deletions
diff --git a/Hutch/Views/Builds/BuildDetailView.swift b/Hutch/Views/Builds/BuildDetailView.swift
index 5895f48..46fb42d 100644
--- a/Hutch/Views/Builds/BuildDetailView.swift
+++ b/Hutch/Views/Builds/BuildDetailView.swift
@@ -176,26 +176,34 @@ struct BuildDetailView: View {
.font(.subheadline.weight(.medium))
}
}
+ .themedRow()
if let note = job.note, !note.isEmpty {
LabeledContent("Note", value: note)
+ .themedRow()
}
if let image = job.image {
LabeledContent("Image", value: image)
+ .themedRow()
}
if !job.tags.isEmpty {
LabeledContent("Tags", value: job.tags.joined(separator: ", "))
+ .themedRow()
}
if let visibility = job.visibility {
LabeledContent("Visibility", value: visibility.rawValue.capitalized)
+ .themedRow()
}
LabeledContent("Owner", value: job.owner.canonicalName)
+ .themedRow()
LabeledContent("Created", value: job.created.relativeDescription)
+ .themedRow()
LabeledContent("Updated", value: job.updated.relativeDescription)
+ .themedRow()
}
if appState.isDebugModeEnabled {
@@ -211,9 +219,11 @@ struct BuildDetailView: View {
url: \(SRHTWebURL.build(jobId: job.id, ownerCanonicalName: job.owner.canonicalName)?.absoluteString ?? "unavailable")
"""
)
+ .themedRow()
if let rawJobResponse = viewModel.rawJobResponse {
DebugTextBlock(title: "Raw Response", content: rawJobResponse)
+ .themedRow()
}
}
}
@@ -237,6 +247,7 @@ struct BuildDetailView: View {
}
}
.disabled(isOpeningRepository)
+ .themedRow()
}
}
@@ -248,6 +259,7 @@ struct BuildDetailView: View {
openURL(url)
}
}
+ .themedRow()
} header: {
Text("Artifacts")
} footer: {
@@ -275,6 +287,7 @@ struct BuildDetailView: View {
}
}
.foregroundStyle(.primary)
+ .themedRow()
} header: {
HStack(spacing: 6) {
TaskStatusIcon(status: task.status)
@@ -299,6 +312,7 @@ struct BuildDetailView: View {
}
}
.disabled(viewModel.isCancelling)
+ .themedRow()
}
}
@@ -319,6 +333,7 @@ struct BuildDetailView: View {
}
}
.disabled(viewModel.isRebuilding)
+ .themedRow()
Button {
showEditResubmitSheet = true
@@ -326,11 +341,13 @@ struct BuildDetailView: View {
Text("Edit & Resubmit")
}
.disabled(viewModel.isSubmittingEditedBuild)
+ .themedRow()
} footer: {
Text("Creates a new build using this job’s saved manifest, tags, note, and visibility.")
}
}
}
+ .themedList()
.task(id: job.id) {
RecentActivityStore.recordBuild(
jobId: job.id,
@@ -463,26 +480,33 @@ private struct EditResubmitBuildSheet: View {
.lineLimit(12...24)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
+ .themedRow()
}
Section("Build Options") {
TextField("Note (optional)", text: $note)
+ .themedRow()
TextField("Tags (comma-separated, optional)", text: $tagsText)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
+ .themedRow()
Picker("Visibility", selection: $visibility) {
Text("Public").tag(Visibility.public)
Text("Unlisted").tag(Visibility.unlisted)
Text("Private").tag(Visibility.private)
}
+ .themedRow()
Toggle("Start build now", isOn: $execute)
+ .themedRow()
Toggle("Allow build secrets", isOn: $secrets)
+ .themedRow()
}
Section {
Text("This submits a new build. “Start build now” and “Allow build secrets” use local defaults because the current job does not include those original values.")
.font(.footnote)
.foregroundStyle(.secondary)
+ .themedRow()
}
if let actionError = viewModel.actionError {
@@ -494,6 +518,7 @@ private struct EditResubmitBuildSheet: View {
.foregroundStyle(.red)
}
.foregroundStyle(.red)
+ .themedRow()
}
}
}
diff --git a/Hutch/Views/Builds/BuildListView.swift b/Hutch/Views/Builds/BuildListView.swift
index f4647e4..fc91ea1 100644
--- a/Hutch/Views/Builds/BuildListView.swift
+++ b/Hutch/Views/Builds/BuildListView.swift
@@ -5,6 +5,7 @@ struct BuildListView: View {
@AppStorage(AppStorageKeys.buildsAutoRefreshInterval) private var autoRefreshRawValue = 0
@AppStorage(AppStorageKeys.buildsRepoFilter) private var savedRepoFilter = ""
@Environment(AppState.self) private var appState
+ @Environment(\.isAMOLEDTheme) private var isAMOLED
@State private var viewModel: BuildListViewModel?
@State private var showSubmitSheet = false
@State private var submittedJobId: Int?
@@ -134,7 +135,7 @@ struct BuildListView: View {
.padding(.top, 6)
.padding(.bottom, 10)
.listRowInsets(EdgeInsets())
- .listRowBackground(Color.clear)
+ .listRowBackground(isAMOLED ? Color.black : Color.clear)
.listRowSeparator(.hidden)
ForEach(viewModel.filteredJobs) { job in
@@ -181,6 +182,7 @@ struct BuildListView: View {
await viewModel.loadMoreIfNeeded(currentItem: job)
}
}
+ .themedRow()
if viewModel.isLoadingMore {
HStack {
@@ -189,6 +191,7 @@ struct BuildListView: View {
Spacer()
}
.listRowSeparator(.hidden)
+ .themedRow()
}
}
}
@@ -279,26 +282,33 @@ private struct SubmitBuildSheet: View {
.lineLimit(12...24)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
+ .themedRow()
}
Section("Build Options") {
TextField("Note (optional)", text: $note)
+ .themedRow()
TextField("Tags (comma-separated, optional)", text: $tagsText)
.textInputAutocapitalization(.never)
.autocorrectionDisabled()
+ .themedRow()
Picker("Visibility", selection: $visibility) {
Text("Public").tag(Visibility.public)
Text("Unlisted").tag(Visibility.unlisted)
Text("Private").tag(Visibility.private)
}
+ .themedRow()
Toggle("Start build now", isOn: $execute)
+ .themedRow()
Toggle("Allow build secrets", isOn: $secrets)
+ .themedRow()
}
Section {
Text("You need a valid builds.sr.ht manifest and a token with BUILDS:RW.")
.font(.footnote)
.foregroundStyle(.secondary)
+ .themedRow()
}
if let error = viewModel.error {
@@ -310,9 +320,11 @@ private struct SubmitBuildSheet: View {
.foregroundStyle(.red)
}
.foregroundStyle(.red)
+ .themedRow()
}
}
}
+ .themedList()
.navigationTitle("Submit Build")
.navigationBarTitleDisplayMode(.inline)
.onDisappear {