Remove in-list spinner + add monitored-repos setting; bump to 2.3
Build iOS App / Build .ipa and publish source (push) Successful in 22s
Build iOS App / Build .ipa and publish source (push) Successful in 22s
- Remove the in-list loading wheel overlay; the landing page just shows the cached list or the 'No open PRs' screen. - Add a 'Monitored repos' setting (Settings > Inbox) that limits the inbox to specific repos, cutting the number of API calls dramatically. Empty = monitor all accessible repos. Bump to 2.3.
This commit is contained in:
1 parent
75f5f3bc64
commit
880cff9e68
6 files changed
+120
-17
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import SwiftUI
|
||||
|
||||
/// Lets the user pick which repos the inbox monitors. Fetches the accessible
|
||||
/// repos from the API and shows a toggle per repo. Empty selection = monitor
|
||||
/// all.
|
||||
struct MonitoredReposView: View {
|
||||
@Binding var selection: [String]
|
||||
@State private var repos: [Repository] = []
|
||||
@State private var isLoading = true
|
||||
@State private var errorMessage: String?
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if isLoading {
|
||||
ProgressView("Loading repos…")
|
||||
} else if let errorMessage {
|
||||
ContentUnavailableView("Couldn't load repos",
|
||||
systemImage: "exclamationmark.triangle",
|
||||
description: Text(errorMessage))
|
||||
} else {
|
||||
List {
|
||||
Section {
|
||||
Button {
|
||||
selection = []
|
||||
} label: {
|
||||
HStack {
|
||||
Text("Monitor all repos")
|
||||
Spacer()
|
||||
if selection.isEmpty {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Section("Monitored") {
|
||||
ForEach(repos) { repo in
|
||||
Button {
|
||||
toggle(repo.fullName)
|
||||
} label: {
|
||||
HStack {
|
||||
Text(repo.fullName)
|
||||
.foregroundColor(.primary)
|
||||
Spacer()
|
||||
if selection.contains(repo.fullName) {
|
||||
Image(systemName: "checkmark")
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Monitored repos")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.task { await load() }
|
||||
}
|
||||
|
||||
private func load() async {
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
defer { isLoading = false }
|
||||
guard let client = SettingsStore.shared.client() else {
|
||||
errorMessage = "Not configured."
|
||||
return
|
||||
}
|
||||
do {
|
||||
repos = try await client.repos()
|
||||
.sorted { $0.fullName < $1.fullName }
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
}
|
||||
}
|
||||
|
||||
private func toggle(_ fullName: String) {
|
||||
if selection.contains(fullName) {
|
||||
selection.removeAll { $0 == fullName }
|
||||
} else {
|
||||
selection.append(fullName)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,12 @@ final class SettingsStore: ObservableObject {
|
||||
didSet { UserDefaults.standard.set(deleteBranchAfterMerge,
|
||||
forKey: "deleteBranchAfterMerge") }
|
||||
}
|
||||
/// Repos to monitor for the inbox. Empty = monitor all accessible repos.
|
||||
/// Stored as full names (e.g. "luis/config-nixos").
|
||||
@Published var monitoredRepos: [String] {
|
||||
didSet { UserDefaults.standard.set(monitoredRepos,
|
||||
forKey: "monitoredRepos") }
|
||||
}
|
||||
|
||||
private init() {
|
||||
instanceURL = KeychainHelper.get("instanceURL") ?? "https://gitea.bueso.eu"
|
||||
@@ -34,6 +40,7 @@ final class SettingsStore: ObservableObject {
|
||||
let raw = UserDefaults.standard.string(forKey: "mergeGateMode")
|
||||
mergeGateMode = MergeGateMode(rawValue: raw ?? "") ?? .warn
|
||||
deleteBranchAfterMerge = UserDefaults.standard.bool(forKey: "deleteBranchAfterMerge")
|
||||
monitoredRepos = UserDefaults.standard.stringArray(forKey: "monitoredRepos") ?? []
|
||||
}
|
||||
|
||||
var isConfigured: Bool {
|
||||
|
||||
@@ -6,6 +6,7 @@ struct SettingsView: View {
|
||||
@State private var token: String
|
||||
@State private var mergeGateMode: MergeGateMode
|
||||
@State private var deleteBranchAfterMerge: Bool
|
||||
@State private var monitoredRepos: [String]
|
||||
@State private var testResult: TestResult?
|
||||
@State private var testing = false
|
||||
@State private var showLogoutConfirm = false
|
||||
@@ -20,6 +21,7 @@ struct SettingsView: View {
|
||||
_token = State(initialValue: SettingsStore.shared.token)
|
||||
_mergeGateMode = State(initialValue: SettingsStore.shared.mergeGateMode)
|
||||
_deleteBranchAfterMerge = State(initialValue: SettingsStore.shared.deleteBranchAfterMerge)
|
||||
_monitoredRepos = State(initialValue: SettingsStore.shared.monitoredRepos)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
@@ -54,6 +56,16 @@ struct SettingsView: View {
|
||||
Toggle("Delete branch after merge", isOn: $deleteBranchAfterMerge)
|
||||
}
|
||||
|
||||
Section {
|
||||
NavigationLink("Monitored repos") {
|
||||
MonitoredReposView(selection: $monitoredRepos)
|
||||
}
|
||||
} header: {
|
||||
Text("Inbox")
|
||||
} footer: {
|
||||
Text("Limit the landing page to specific repos to speed it up. Leave empty to monitor all accessible repos.")
|
||||
}
|
||||
|
||||
Section("Diagnostics") {
|
||||
NavigationLink("View logs") {
|
||||
LogsView()
|
||||
@@ -134,6 +146,7 @@ struct SettingsView: View {
|
||||
SettingsStore.shared.token = token
|
||||
SettingsStore.shared.mergeGateMode = mergeGateMode
|
||||
SettingsStore.shared.deleteBranchAfterMerge = deleteBranchAfterMerge
|
||||
SettingsStore.shared.monitoredRepos = monitoredRepos
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user