Added deep links for widgets

- Widgets will now open the appropriate DetailView in the app when you tap on them.
  - ...except when they don't. This is still a little buggy. It works correctly when the app is already alive in the background but only works about 75% of the time when the app isn't running yet.
- Unified the loading view into a shared view used in all places requiring loading
This commit is contained in:
2026-01-24 15:11:45 -05:00
parent b51335768f
commit 42b3c35f68
11 changed files with 179 additions and 122 deletions

View File

@@ -13,9 +13,11 @@ import WidgetKit
struct TigerDineApp: App {
// The model needs to be instantiated here so that it's also available in the context of the refresh background task.
@State private var model = DiningModel()
@State private var targetLocationId: Int?
@State private var handledLocationId: Int?
/// Triggers a refresh on the model that will only make network requests if the cache is stale, and then schedules the next refresh.
func handleAppRefresh() async {
private func handleAppRefresh() async {
do {
try await model.getHoursByDayCached()
WidgetCenter.shared.reloadAllTimelines()
@@ -26,10 +28,29 @@ struct TigerDineApp: App {
scheduleNextRefresh()
}
private func parseOpenedURL(url: URL) -> Int? {
guard url.scheme == "tigerdine" else { return nil }
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)!
if components.path == "/location" {
print("opening to a location")
if let queryItems = components.queryItems {
if queryItems.map(\.name).contains("id") {
return Int(queryItems.first(where: { $0.name == "id" })!.value!)
}
}
}
return nil
}
var body: some Scene {
WindowGroup {
ContentView()
ContentView(targetLocationId: $targetLocationId, handledLocationId: $handledLocationId)
.environment(model)
.onOpenURL { url in
targetLocationId = parseOpenedURL(url: url)
handledLocationId = nil
}
}
.backgroundTask(.appRefresh("dev.ninjacheetah.RIT-Dining.refresh")) {
await handleAppRefresh()