Add first-class Actions management (#63)
This commit is contained in:
@@ -19,21 +19,20 @@ final class AppContext {
|
||||
}
|
||||
|
||||
func makeRootController() -> UIViewController {
|
||||
let roots: [UIViewController] = [
|
||||
HomeViewController(context: self),
|
||||
repositoryRoot(mode: .issues),
|
||||
repositoryRoot(mode: .commits),
|
||||
PullsViewController(context: self),
|
||||
repositoryRoot(mode: .milestones),
|
||||
]
|
||||
let items = [
|
||||
("Home", "house", "house.fill"),
|
||||
("Issues", "exclamationmark.circle", "exclamationmark.circle.fill"),
|
||||
("Repos", "books.vertical", "books.vertical.fill"),
|
||||
("PRs", "arrow.triangle.pull", "arrow.triangle.pull"),
|
||||
("Milestones", "flag", "flag.fill"),
|
||||
]
|
||||
navigationControllers = zip(roots, items).map { root, item in
|
||||
rebuildTabs(preservingHomeStack: false)
|
||||
return tabs
|
||||
}
|
||||
|
||||
func applyPrimaryDestinations() {
|
||||
rebuildTabs(preservingHomeStack: true)
|
||||
}
|
||||
|
||||
private func rebuildTabs(preservingHomeStack: Bool) {
|
||||
let destinations = core.settings().primaryDestinations
|
||||
let home = preservingHomeStack ? navigationControllers.first : nil
|
||||
let roots = destinations.map(destinationController)
|
||||
let items = [("Home", "house", "house.fill")] + destinations.map(destinationItem)
|
||||
let destinationNavigations = zip(roots, items.dropFirst()).map { root, item in
|
||||
let navigation = UINavigationController(rootViewController: root)
|
||||
navigation.tabBarItem = UITabBarItem(
|
||||
title: item.0,
|
||||
@@ -42,8 +41,17 @@ final class AppContext {
|
||||
)
|
||||
return navigation
|
||||
}
|
||||
let homeNavigation = home ?? UINavigationController(
|
||||
rootViewController: HomeViewController(context: self)
|
||||
)
|
||||
homeNavigation.tabBarItem = UITabBarItem(
|
||||
title: items[0].0,
|
||||
image: UIImage(systemName: items[0].1),
|
||||
selectedImage: UIImage(systemName: items[0].2)
|
||||
)
|
||||
navigationControllers = [homeNavigation] + destinationNavigations
|
||||
tabs.viewControllers = navigationControllers
|
||||
return tabs
|
||||
(homeNavigation.viewControllers.first as? HomeViewController)?.refreshPrimaryDestinations()
|
||||
}
|
||||
|
||||
func showStartupErrorIfNeeded() {
|
||||
@@ -57,33 +65,50 @@ final class AppContext {
|
||||
}
|
||||
|
||||
func reloadAfterServerChange() {
|
||||
let replacements: [(Int, UIViewController)] = [
|
||||
(0, HomeViewController(context: self)),
|
||||
(1, repositoryRoot(mode: .issues)),
|
||||
(2, repositoryRoot(mode: .commits)),
|
||||
(3, PullsViewController(context: self)),
|
||||
(4, repositoryRoot(mode: .milestones)),
|
||||
]
|
||||
for (index, root) in replacements {
|
||||
navigationControllers[index].setViewControllers([root], animated: false)
|
||||
}
|
||||
rebuildTabs(preservingHomeStack: false)
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
func route(widgetURL: URL) -> Bool {
|
||||
guard widgetURL.scheme == "gotcha" else { return false }
|
||||
let index: Int
|
||||
switch widgetURL.host {
|
||||
case "home": index = 0
|
||||
case "pulls": index = 3
|
||||
case "home":
|
||||
tabs.selectedIndex = 0
|
||||
navigationControllers[0].popToRootViewController(animated: false)
|
||||
case "pulls":
|
||||
if let index = primaryDestinations.firstIndex(of: .pullRequests).map({ $0 + 1 }) {
|
||||
tabs.selectedIndex = index
|
||||
navigationControllers[index].popToRootViewController(animated: false)
|
||||
} else {
|
||||
tabs.selectedIndex = 0
|
||||
navigationControllers[0].pushViewController(
|
||||
PullsViewController(context: self),
|
||||
animated: false
|
||||
)
|
||||
}
|
||||
default: return false
|
||||
}
|
||||
tabs.selectedIndex = index
|
||||
navigationControllers[index].popToRootViewController(animated: false)
|
||||
return true
|
||||
}
|
||||
|
||||
var primaryDestinations: [PrimaryDestination] {
|
||||
core.settings().primaryDestinations
|
||||
}
|
||||
|
||||
var secondaryDestinations: [PrimaryDestination] {
|
||||
PrimaryDestination.allCases.filter { !primaryDestinations.contains($0) }
|
||||
}
|
||||
|
||||
func show(_ destination: PrimaryDestination, from navigation: UINavigationController?) {
|
||||
if let index = primaryDestinations.firstIndex(of: destination).map({ $0 + 1 }) {
|
||||
tabs.selectedIndex = index
|
||||
navigationControllers[index].popToRootViewController(animated: false)
|
||||
} else {
|
||||
navigation?.pushViewController(destinationController(destination), animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
func didAddServer(index: UInt32) throws {
|
||||
try selectServer(index: index)
|
||||
}
|
||||
@@ -154,7 +179,7 @@ final class AppContext {
|
||||
do {
|
||||
try selectServer(index: UInt32(index))
|
||||
} catch {
|
||||
tabs.present(errorAlert(error.localizedDescription), animated: true)
|
||||
tabs.present(errorAlert(errorMessage(error)), animated: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -216,4 +241,54 @@ final class AppContext {
|
||||
}
|
||||
return RepositoriesViewController(context: self, mode: mode)
|
||||
}
|
||||
|
||||
private func destinationController(_ destination: PrimaryDestination) -> UIViewController {
|
||||
switch destination {
|
||||
case .issues: return repositoryRoot(mode: .issues)
|
||||
case .repositories: return repositoryRoot(mode: .commits)
|
||||
case .pullRequests: return PullsViewController(context: self)
|
||||
case .milestones: return repositoryRoot(mode: .milestones)
|
||||
case .actions: return repositoryRoot(mode: .actions)
|
||||
case .serverActivity: return ServerActivityViewController(context: self)
|
||||
}
|
||||
}
|
||||
|
||||
private func destinationItem(_ destination: PrimaryDestination) -> (String, String, String) {
|
||||
switch destination {
|
||||
case .issues: return ("Issues", "exclamationmark.circle", "exclamationmark.circle.fill")
|
||||
case .repositories: return ("Repos", "books.vertical", "books.vertical.fill")
|
||||
case .pullRequests: return ("PRs", "arrow.triangle.pull", "arrow.triangle.pull")
|
||||
case .milestones: return ("Milestones", "flag", "flag.fill")
|
||||
case .actions: return ("Actions", "play.square.stack", "play.square.stack.fill")
|
||||
case .serverActivity: return ("Activity", "person.3", "person.3.fill")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PrimaryDestination: CaseIterable {
|
||||
public static var allCases: [PrimaryDestination] {
|
||||
[.issues, .repositories, .pullRequests, .milestones, .actions, .serverActivity]
|
||||
}
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .issues: return "Issues"
|
||||
case .repositories: return "Repositories"
|
||||
case .pullRequests: return "Pull Requests"
|
||||
case .milestones: return "Milestones"
|
||||
case .actions: return "Actions"
|
||||
case .serverActivity: return "Server Activity"
|
||||
}
|
||||
}
|
||||
|
||||
var symbolName: String {
|
||||
switch self {
|
||||
case .issues: return "exclamationmark.circle"
|
||||
case .repositories: return "books.vertical"
|
||||
case .pullRequests: return "arrow.triangle.pull"
|
||||
case .milestones: return "flag"
|
||||
case .actions: return "play.square.stack"
|
||||
case .serverActivity: return "person.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user