Add repository file browser
This commit is contained in:
@@ -502,11 +502,15 @@ final class PullsViewController: RefreshingTableViewController {
|
||||
|
||||
@MainActor
|
||||
final class CommitsViewController: RefreshingTableViewController {
|
||||
private enum Mode: Int { case history, files }
|
||||
|
||||
private let context: AppContext
|
||||
private let owner: String
|
||||
private let repository: String
|
||||
private var page: CommitPage?
|
||||
private var contents: [RepositoryContentRow] = []
|
||||
private var branch: String?
|
||||
private var mode = Mode.history
|
||||
|
||||
init(context: AppContext, owner: String, repository: String) {
|
||||
self.context = context
|
||||
@@ -522,6 +526,11 @@ final class CommitsViewController: RefreshingTableViewController {
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
tableView.register(CommitCell.self, forCellReuseIdentifier: "commit")
|
||||
let modeControl = UISegmentedControl(items: ["History", "Files"])
|
||||
modeControl.selectedSegmentIndex = mode.rawValue
|
||||
modeControl.addTarget(self, action: #selector(modeChanged(_:)), for: .valueChanged)
|
||||
modeControl.accessibilityLabel = "Repository view"
|
||||
navigationItem.titleView = modeControl
|
||||
updateBranchMenu()
|
||||
loadContent(refreshing: false)
|
||||
}
|
||||
@@ -531,16 +540,23 @@ final class CommitsViewController: RefreshingTableViewController {
|
||||
loadingTask?.cancel()
|
||||
loadingTask = Task {
|
||||
do {
|
||||
page = try await context.core.commits(
|
||||
owner: owner,
|
||||
repository: repository,
|
||||
branch: branch
|
||||
)
|
||||
updateBranchMenu()
|
||||
switch mode {
|
||||
case .history:
|
||||
page = try await context.core.commits(
|
||||
owner: owner,
|
||||
repository: repository,
|
||||
branch: branch
|
||||
)
|
||||
updateBranchMenu()
|
||||
case .files:
|
||||
contents = try await context.core.repositoryContents(
|
||||
owner: owner,
|
||||
repository: repository,
|
||||
path: ""
|
||||
)
|
||||
}
|
||||
tableView.reloadData()
|
||||
tableView.backgroundView = page?.commits.isEmpty == true
|
||||
? EmptyBackgroundView(title: "No commits", detail: "This repository has no commit history.")
|
||||
: nil
|
||||
updateEmptyView()
|
||||
} catch {
|
||||
if !Task.isCancelled { show(error: error) }
|
||||
}
|
||||
@@ -549,34 +565,75 @@ final class CommitsViewController: RefreshingTableViewController {
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
page?.commits.count ?? 0
|
||||
mode == .history ? page?.commits.count ?? 0 : contents.count
|
||||
}
|
||||
|
||||
override func tableView(
|
||||
_ tableView: UITableView,
|
||||
cellForRowAt indexPath: IndexPath
|
||||
) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "commit", for: indexPath) as! CommitCell
|
||||
if let page { cell.configure(page.commits[indexPath.row], laneCount: page.laneCount) }
|
||||
return cell
|
||||
switch mode {
|
||||
case .history:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "commit", for: indexPath) as! CommitCell
|
||||
if let page { cell.configure(page.commits[indexPath.row], laneCount: page.laneCount) }
|
||||
return cell
|
||||
case .files:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "repository-content")
|
||||
?? UITableViewCell(style: .subtitle, reuseIdentifier: "repository-content")
|
||||
configureRepositoryContentCell(cell, row: contents[indexPath.row])
|
||||
return cell
|
||||
}
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
86
|
||||
mode == .history ? 86 : UITableView.automaticDimension
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
guard let row = page?.commits[indexPath.row] else { return }
|
||||
navigationController?.pushViewController(
|
||||
FilesViewController(
|
||||
switch mode {
|
||||
case .history:
|
||||
guard let row = page?.commits[indexPath.row] else { return }
|
||||
navigationController?.pushViewController(
|
||||
FilesViewController(
|
||||
context: context,
|
||||
owner: owner,
|
||||
repository: repository,
|
||||
sha: row.sha
|
||||
),
|
||||
animated: true
|
||||
)
|
||||
case .files:
|
||||
showRepositoryContent(
|
||||
contents[indexPath.row],
|
||||
context: context,
|
||||
owner: owner,
|
||||
repository: repository,
|
||||
sha: row.sha
|
||||
),
|
||||
animated: true
|
||||
)
|
||||
navigationController: navigationController
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func modeChanged(_ sender: UISegmentedControl) {
|
||||
guard let mode = Mode(rawValue: sender.selectedSegmentIndex), mode != self.mode else { return }
|
||||
self.mode = mode
|
||||
navigationItem.rightBarButtonItem = nil
|
||||
if mode == .history { updateBranchMenu() }
|
||||
tableView.reloadData()
|
||||
loadContent(refreshing: false)
|
||||
}
|
||||
|
||||
private func updateEmptyView() {
|
||||
switch mode {
|
||||
case .history:
|
||||
tableView.backgroundView = page?.commits.isEmpty == true
|
||||
? EmptyBackgroundView(title: "No commits", detail: "This repository has no commit history.")
|
||||
: nil
|
||||
case .files:
|
||||
tableView.backgroundView = contents.isEmpty
|
||||
? EmptyBackgroundView(title: "No files", detail: "This repository is empty.")
|
||||
: nil
|
||||
}
|
||||
}
|
||||
|
||||
private func updateBranchMenu() {
|
||||
|
||||
Reference in New Issue
Block a user