Show and clear active filters

This commit is contained in:
Georg Bauer
2026-07-31 17:54:15 +02:00
parent eadbadd3cb
commit de49db0910
6 changed files with 156 additions and 6 deletions

View File

@@ -609,6 +609,10 @@ public protocol GotchaCoreProtocol: AnyObject, Sendable {
func addServer(name: String, url: String, token: String) async throws -> UInt32
func clearIssueFilters(owner: String, repository: String) throws
func clearPullFilters() throws
func commitDiff(owner: String, repository: String, sha: String, path: String) async throws -> DiffPage
func commitFiles(owner: String, repository: String, sha: String) async throws -> [FileRow]
@@ -771,6 +775,24 @@ open func addServer(name: String, url: String, token: String)async throws -> UI
)
}
open func clearIssueFilters(owner: String, repository: String)throws {try rustCallWithError(FfiConverterTypeGotchaError_lift) {
uniffiCallStatus in
uniffi_gotcha_core_fn_method_gotchacore_clear_issue_filters(
self.uniffiCloneHandle(),
FfiConverterString.lower(owner),
FfiConverterString.lower(repository),uniffiCallStatus
)
}
}
open func clearPullFilters()throws {try rustCallWithError(FfiConverterTypeGotchaError_lift) {
uniffiCallStatus in
uniffi_gotcha_core_fn_method_gotchacore_clear_pull_filters(
self.uniffiCloneHandle(),uniffiCallStatus
)
}
}
open func commitDiff(owner: String, repository: String, sha: String, path: String)async throws -> DiffPage {
return
try await uniffiRustCallAsync(
@@ -4015,6 +4037,12 @@ private let initializationResult: InitializationResult = {
if (uniffi_gotcha_core_checksum_method_gotchacore_add_server() != 42705) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_clear_issue_filters() != 11092) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_clear_pull_filters() != 36676) {
return InitializationResult.apiChecksumMismatch
}
if (uniffi_gotcha_core_checksum_method_gotchacore_commit_diff() != 56887) {
return InitializationResult.apiChecksumMismatch
}

View File

@@ -274,6 +274,16 @@ RustBuffer uniffi_gotcha_core_fn_method_gotchacore_active_server_name(uint64_t p
uint64_t uniffi_gotcha_core_fn_method_gotchacore_add_server(uint64_t ptr, RustBuffer name, RustBuffer url, RustBuffer token
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_CLEAR_ISSUE_FILTERS
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_CLEAR_ISSUE_FILTERS
void uniffi_gotcha_core_fn_method_gotchacore_clear_issue_filters(uint64_t ptr, RustBuffer owner, RustBuffer repository, RustCallStatus *_Nonnull out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_CLEAR_PULL_FILTERS
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_CLEAR_PULL_FILTERS
void uniffi_gotcha_core_fn_method_gotchacore_clear_pull_filters(uint64_t ptr, RustCallStatus *_Nonnull out_status
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_COMMIT_DIFF
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_FN_METHOD_GOTCHACORE_COMMIT_DIFF
uint64_t uniffi_gotcha_core_fn_method_gotchacore_commit_diff(uint64_t ptr, RustBuffer owner, RustBuffer repository, RustBuffer sha, RustBuffer path
@@ -715,6 +725,18 @@ uint16_t uniffi_gotcha_core_checksum_method_gotchacore_active_server_name(void
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_ADD_SERVER
uint16_t uniffi_gotcha_core_checksum_method_gotchacore_add_server(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_CLEAR_ISSUE_FILTERS
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_CLEAR_ISSUE_FILTERS
uint16_t uniffi_gotcha_core_checksum_method_gotchacore_clear_issue_filters(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_CLEAR_PULL_FILTERS
#define UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_CLEAR_PULL_FILTERS
uint16_t uniffi_gotcha_core_checksum_method_gotchacore_clear_pull_filters(void
);
#endif
#ifndef UNIFFI_FFIDEF_UNIFFI_GOTCHA_CORE_CHECKSUM_METHOD_GOTCHACORE_COMMIT_DIFF

View File

@@ -129,7 +129,7 @@ final class IssuesViewController: RefreshingTableViewController {
let current = context.core.settings().issueStatus
let status = UIMenu(
title: "Status",
image: context.symbol("circle.lefthalf.filled"),
image: filterMenuImage("circle.lefthalf.filled", active: current != "open"),
options: .singleSelection,
children: ["open", "closed"].map { status in
UIAction(
@@ -154,6 +154,7 @@ final class IssuesViewController: RefreshingTableViewController {
} else {
children.append(UIAction(title: "Loading filters…", attributes: .disabled) { _ in })
}
children.append(clearFiltersMenu())
filterButton.menu = UIMenu(children: children)
filterButton.accessibilityLabel = "Filter issues"
updateFilterTint()
@@ -172,7 +173,7 @@ final class IssuesViewController: RefreshingTableViewController {
}
return UIMenu(
title: "Milestone",
image: context.symbol("flag"),
image: filterMenuImage("flag", active: !selected.isEmpty),
options: .singleSelection,
children: [all] + actions
)
@@ -203,7 +204,7 @@ final class IssuesViewController: RefreshingTableViewController {
}
return UIMenu(
title: "Labels",
image: context.symbol("tag"),
image: filterMenuImage("tag", active: !selected.isEmpty),
children: actions.isEmpty
? [UIAction(title: "No labels", attributes: .disabled) { _ in }]
: actions
@@ -232,6 +233,32 @@ final class IssuesViewController: RefreshingTableViewController {
)
}
private func clearFiltersMenu() -> UIMenu {
UIMenu(
options: .displayInline,
children: [
UIAction(
title: "Clear Filters",
image: context.symbol("xmark.circle"),
attributes: filtersActive ? [] : .disabled
) { [weak self] _ in self?.clearFilters() },
]
)
}
private func clearFilters() {
filterTask?.cancel()
do {
try context.core.clearIssueFilters(owner: owner, repository: repository)
filterOptions?.selectedMilestone = ""
filterOptions?.selectedLabels = []
updateFilterMenu()
loadIssues(refreshing: false)
} catch {
show(error: error)
}
}
private var filtersActive: Bool {
(try? context.core.issueFiltersActive(owner: owner, repository: repository)) ?? false
}
@@ -835,7 +862,7 @@ final class PullsViewController: RefreshingTableViewController {
let current = context.core.settings().pullStatus
let status = UIMenu(
title: "Status",
image: context.symbol("circle.lefthalf.filled"),
image: filterMenuImage("circle.lefthalf.filled", active: current != "open"),
options: .singleSelection,
children: ["open", "closed"].map { status in
UIAction(title: status.capitalized, state: current == status ? .on : .off) {
@@ -856,7 +883,7 @@ final class PullsViewController: RefreshingTableViewController {
let item = navigationItem.rightBarButtonItem ?? UIBarButtonItem(
image: context.symbol("line.3.horizontal.decrease.circle")
)
item.menu = UIMenu(children: [status, milestone])
item.menu = UIMenu(children: [status, milestone, clearFiltersMenu()])
item.accessibilityLabel = "Filter pull requests"
navigationItem.rightBarButtonItem = item
updateFilterTint()
@@ -874,7 +901,7 @@ final class PullsViewController: RefreshingTableViewController {
}
return UIMenu(
title: "Milestone",
image: context.symbol("flag"),
image: filterMenuImage("flag", active: !selected.isEmpty),
options: .singleSelection,
children: [all] + milestones
)
@@ -892,6 +919,31 @@ final class PullsViewController: RefreshingTableViewController {
}
}
private func clearFiltersMenu() -> UIMenu {
UIMenu(
options: .displayInline,
children: [
UIAction(
title: "Clear Filters",
image: context.symbol("xmark.circle"),
attributes: filtersActive ? [] : .disabled
) { [weak self] _ in self?.clearFilters() },
]
)
}
private func clearFilters() {
filterTask?.cancel()
do {
try context.core.clearPullFilters()
filterOptions?.selectedMilestone = ""
updateFilterMenu()
loadPulls(refreshing: false)
} catch {
show(error: error)
}
}
private var filtersActive: Bool {
(try? context.core.pullFiltersActive()) ?? false
}

View File

@@ -201,6 +201,13 @@ func configureTextCell(_ cell: UITableViewCell, title: String, detail: String, i
cell.backgroundColor = .systemBackground
}
func filterMenuImage(_ symbol: String, active: Bool) -> UIImage? {
let image = UIImage(systemName: symbol)
return active
? image?.withTintColor(.systemBlue, renderingMode: .alwaysOriginal)
: image
}
func configureRepositoryContentCell(_ cell: UITableViewCell, row: RepositoryContentRow) {
let directory = row.kind == "dir"
let detail = directory