Files
Gotcha/ios/Sources/RepositoryListScreen.swift
2026-08-03 17:54:07 +02:00

138 lines
4.6 KiB
Swift

import UIKit
@MainActor
final class RepositoriesViewController: RefreshingTableViewController {
private let context: AppContext
private let mode: RepositoryPane
private var rows: [RepositoryRow] = []
private var currentPage: UInt32 = 0
init(context: AppContext, mode: RepositoryPane) {
self.context = context
self.mode = mode
super.init()
title = context.core.activeServerName() ?? "Repositories"
}
@available(*, unavailable)
required init?(coder: NSCoder) { fatalError("init(coder:) is not supported") }
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(
image: context.symbol("server.rack"),
primaryAction: UIAction { [weak self] _ in
guard let self else { return }
self.navigationController?.pushViewController(
ServersViewController(context: self.context),
animated: true
)
}
)
loadContent(refreshing: false)
}
override func loadContent(refreshing: Bool) {
loadPage(1, refreshing: refreshing)
}
override func loadMoreContent() {
loadPage(currentPage + 1, refreshing: false)
}
private func loadPage(_ page: UInt32, refreshing: Bool) {
if page == 1 {
resetPagination()
beginLoading(refreshing: refreshing)
}
loadingTask?.cancel()
loadingTask = Task {
do {
let result = try await context.core.repositories(page: page, pane: mode)
rows = result.rows
currentPage = page
finishPagination(hasMore: result.hasMore)
tableView.reloadData()
tableView.backgroundView = rows.isEmpty
? EmptyBackgroundView(
title: "No repositories",
detail: "This account does not own any repositories on this server."
)
: nil
} catch {
if !Task.isCancelled {
show(error: error)
failPagination()
}
}
if page == 1 { endLoading() }
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
rows.count
}
override func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "repository")
?? UITableViewCell(style: .subtitle, reuseIdentifier: "repository")
let row = rows[indexPath.row]
configureTextCell(cell, title: row.name, detail: "\(row.description)\n\(row.meta)")
let button = UIButton(type: .system, primaryAction: UIAction { [weak self] _ in
self?.toggleFavorite(row)
})
button.setImage(context.symbol(row.favorite ? "star.fill" : "star"), for: .normal)
button.tintColor = row.favorite ? .systemYellow : .tertiaryLabel
button.frame.size = CGSize(width: 44, height: 44)
cell.accessoryView = button
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
96
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let row = rows[indexPath.row]
let destination: UIViewController
switch mode {
case .issues:
destination = IssuesViewController(
context: context,
owner: row.owner,
repository: row.name
)
case .commits:
destination = CommitsViewController(
context: context,
owner: row.owner,
repository: row.name
)
case .milestones:
destination = MilestonesViewController(
context: context,
owner: row.owner,
repository: row.name
)
}
navigationController?.pushViewController(destination, animated: true)
}
private func toggleFavorite(_ row: RepositoryRow) {
do {
rows = try context.core.toggleFavorite(
owner: row.owner,
repository: row.name,
pane: mode
)
tableView.reloadData()
} catch {
show(error: error)
}
}
}