Add configurable iPhone widgets
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
import UIKit
|
||||
import WidgetKit
|
||||
|
||||
@MainActor
|
||||
final class AppContext {
|
||||
let core = GotchaCore()
|
||||
let core: GotchaCore
|
||||
private let window: UIWindow
|
||||
private(set) var tabs = UITabBarController()
|
||||
private(set) var navigationControllers: [UINavigationController] = []
|
||||
|
||||
init(window: UIWindow) {
|
||||
self.window = window
|
||||
let storageDirectory = FileManager.default.containerURL(
|
||||
forSecurityApplicationGroupIdentifier: "group.de.rfc1437.gotcha"
|
||||
)?.path
|
||||
core = GotchaCore(storageDirectory: storageDirectory)
|
||||
applyAppearance()
|
||||
}
|
||||
|
||||
@@ -61,6 +66,21 @@ final class AppContext {
|
||||
for (index, root) in replacements {
|
||||
navigationControllers[index].setViewControllers([root], animated: 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
|
||||
default: return false
|
||||
}
|
||||
tabs.selectedIndex = index
|
||||
navigationControllers[index].popToRootViewController(animated: false)
|
||||
return true
|
||||
}
|
||||
|
||||
func didAddServer(index: UInt32) throws {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import UIKit
|
||||
import WidgetKit
|
||||
|
||||
@main
|
||||
final class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
var window: UIWindow?
|
||||
private var context: AppContext?
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
@@ -10,10 +12,26 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
) -> Bool {
|
||||
let window = UIWindow(frame: UIScreen.main.bounds)
|
||||
let context = AppContext(window: window)
|
||||
self.context = context
|
||||
window.rootViewController = context.makeRootController()
|
||||
window.makeKeyAndVisible()
|
||||
self.window = window
|
||||
context.showStartupErrorIfNeeded()
|
||||
if let url = launchOptions?[.url] as? URL {
|
||||
context.route(widgetURL: url)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func application(
|
||||
_ application: UIApplication,
|
||||
open url: URL,
|
||||
options: [UIApplication.OpenURLOptionsKey: Any] = [:]
|
||||
) -> Bool {
|
||||
context?.route(widgetURL: url) ?? false
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
WidgetCenter.shared.reloadAllTimelines()
|
||||
}
|
||||
}
|
||||
|
||||
52
ios/Sources/WidgetIntents.swift
Normal file
52
ios/Sources/WidgetIntents.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
import AppIntents
|
||||
import Foundation
|
||||
|
||||
enum WidgetEnvironment {
|
||||
static let appGroup = "group.de.rfc1437.gotcha"
|
||||
|
||||
static func core() -> GotchaCore {
|
||||
GotchaCore(
|
||||
storageDirectory: FileManager.default.containerURL(
|
||||
forSecurityApplicationGroupIdentifier: appGroup
|
||||
)?.path
|
||||
)
|
||||
}
|
||||
|
||||
static func servers() -> [ServerRow] {
|
||||
core().servers()
|
||||
}
|
||||
|
||||
static func selection(for server: ServerRow) -> String {
|
||||
"\(server.name) · \(server.url)"
|
||||
}
|
||||
|
||||
static func server(for selection: String) -> ServerRow? {
|
||||
servers().first { self.selection(for: $0) == selection }
|
||||
}
|
||||
}
|
||||
|
||||
struct WidgetServerOptionsProvider: DynamicOptionsProvider {
|
||||
func results() async throws -> [String] {
|
||||
WidgetEnvironment.servers().map(WidgetEnvironment.selection)
|
||||
}
|
||||
|
||||
func defaultResult() async -> String? {
|
||||
WidgetEnvironment.servers().first.map(WidgetEnvironment.selection)
|
||||
}
|
||||
}
|
||||
|
||||
struct ActivityWidgetIntent: WidgetConfigurationIntent {
|
||||
static let title: LocalizedStringResource = "Activity Server"
|
||||
static let description = IntentDescription("Choose the server whose recent activity appears.")
|
||||
|
||||
@Parameter(title: "Server", optionsProvider: WidgetServerOptionsProvider())
|
||||
var server: String?
|
||||
}
|
||||
|
||||
struct PullsWidgetIntent: WidgetConfigurationIntent {
|
||||
static let title: LocalizedStringResource = "Pull Request Server"
|
||||
static let description = IntentDescription("Choose the server whose open pull requests appear.")
|
||||
|
||||
@Parameter(title: "Server", optionsProvider: WidgetServerOptionsProvider())
|
||||
var server: String?
|
||||
}
|
||||
Reference in New Issue
Block a user