From 34cec578adc6c925dce251be7c493ff375f01383 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Sat, 17 Oct 2026 07:01:21 +0200 Subject: [PATCH] Show an empty contributors list as a placeholder with Retry A successful load with no contributors, and the first frame before the load started, rendered an empty form with nothing focusable, stranding the tvOS remote. --- Yattee/Views/Settings/ContributorsView.swift | 22 ++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/Yattee/Views/Settings/ContributorsView.swift b/Yattee/Views/Settings/ContributorsView.swift index 687d1712..79d92775 100644 --- a/Yattee/Views/Settings/ContributorsView.swift +++ b/Yattee/Views/Settings/ContributorsView.swift @@ -13,7 +13,9 @@ struct ContributorsView: View { @Environment(\.appEnvironment) private var appEnvironment @State private var contributors: [GitHubContributor] = [] - @State private var isLoading = false + /// Starts true so the first frame, before `.task` runs, is the spinner and + /// not an empty list. + @State private var isLoading = true @State private var errorMessage: String? var body: some View { @@ -49,6 +51,19 @@ struct ContributorsView: View { .buttonStyle(.borderedProminent) } .frame(maxWidth: .infinity, maxHeight: .infinity) + } else if contributors.isEmpty { + // An empty form has nothing focusable, which strands the tvOS remote. + ContentUnavailableView { + Label(String(localized: "settings.contributors.title"), systemImage: "person.2") + } actions: { + Button(String(localized: "common.retry")) { + Task { + await loadContributors() + } + } + .buttonStyle(.borderedProminent) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) } else { contributorsList } @@ -121,7 +136,10 @@ struct ContributorsView: View { // MARK: - Data Loading private func loadContributors() async { - guard let appEnvironment else { return } + guard let appEnvironment else { + isLoading = false + return + } let api = GitHubAPI(httpClient: appEnvironment.httpClient) isLoading = true