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

@@ -12,15 +12,8 @@ struct FoodTruckView: View {
@State private var foodTruckEvents: [FoodTruckEvent] = []
@State private var isLoading: Bool = true
@State private var loadFailed: Bool = false
@State private var rotationDegrees: Double = 0
@State private var showingSafari: Bool = false
private var animation: Animation {
.linear
.speed(0.1)
.repeatForever(autoreverses: false)
}
private func doFoodTruckStuff() async {
switch await getFoodTruckPage() {
case .success(let schedule):
@@ -35,34 +28,11 @@ struct FoodTruckView: View {
var body: some View {
if isLoading {
VStack {
if loadFailed {
Image(systemName: "wifi.exclamationmark.circle")
.resizable()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
Text("An error occurred while fetching food truck data. Please check your network connection and try again.")
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
} else {
Image(systemName: "truck.box")
.resizable()
.scaledToFit()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
.rotationEffect(.degrees(rotationDegrees))
.onAppear {
withAnimation(animation) {
rotationDegrees = 360.0
}
}
Text("One moment...")
.foregroundStyle(.secondary)
}
LoadingView(loadFailed: $loadFailed, loadingType: .truck)
}
.task {
await doFoodTruckStuff()
}
.padding()
} else {
ScrollView {
VStack(alignment: .leading) {

View File

@@ -0,0 +1,64 @@
//
// LoadingView.swift
// TigerDine
//
// Created by Campbell on 1/24/26.
//
import SwiftUI
enum LoadingType {
case normal
case truck
}
struct LoadingView: View {
@Binding var loadFailed: Bool
@State var loadingType: LoadingType = .normal
@State private var rotationDegrees: Double = 0
private var animation: Animation {
.linear
.speed(0.1)
.repeatForever(autoreverses: false)
}
private var loadingSymbol: String {
switch loadingType {
case .normal:
return "fork.knife.circle"
case .truck:
return "truck.box"
}
}
var body: some View {
VStack {
if loadFailed {
Image(systemName: "wifi.exclamationmark.circle")
.resizable()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
Text("An error occurred while loading data. Please check your network connection and try again.")
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
} else {
Image(systemName: loadingSymbol)
.resizable()
.scaledToFit()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
.rotationEffect(.degrees(rotationDegrees))
.onAppear {
withAnimation(animation) {
rotationDegrees = 360.0
}
}
Text("Loading...")
.foregroundStyle(.secondary)
}
}
.padding()
}
}

View File

@@ -57,7 +57,7 @@ struct LocationList: View {
var body: some View {
ForEach(filteredLocations, id: \.self) { location in
NavigationLink(destination: DetailView(locationId: location.id)) {
NavigationLink(value: location) {
VStack(alignment: .leading) {
HStack {
Text(location.name)

View File

@@ -14,18 +14,11 @@ struct MenuView: View {
@State private var searchText: String = ""
@State private var isLoading: Bool = true
@State private var loadFailed: Bool = false
@State private var rotationDegrees: Double = 0
@State private var selectedMealPeriod: Int = 0
@State private var openPeriods: [Int] = []
@StateObject private var dietaryRestrictionsModel = MenuDietaryRestrictionsModel()
@State private var showingDietaryRestrictionsSheet: Bool = false
private var animation: Animation {
.linear
.speed(0.1)
.repeatForever(autoreverses: false)
}
func getOpenPeriods() async {
// Only run this if we haven't already gotten the open periods. This is somewhat of a bandaid solution to the issue of
// fetching this information more than once, but hey it works!
@@ -114,33 +107,11 @@ struct MenuView: View {
var body: some View {
if isLoading {
VStack {
if loadFailed {
Image(systemName: "wifi.exclamationmark.circle")
.resizable()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
Text("An error occurred while fetching the menu. Please check your network connection and try again.")
.foregroundStyle(.secondary)
.multilineTextAlignment(.center)
} else {
Image(systemName: "fork.knife.circle")
.resizable()
.frame(width: 75, height: 75)
.foregroundStyle(.accent)
.rotationEffect(.degrees(rotationDegrees))
.onAppear {
withAnimation(animation) {
rotationDegrees = 360.0
}
}
Text("One moment...")
.foregroundStyle(.secondary)
}
LoadingView(loadFailed: $loadFailed)
}
.task {
await getOpenPeriods()
}
.padding()
} else {
VStack {
if !menuItems.isEmpty {
@@ -219,7 +190,6 @@ struct MenuView: View {
}
}
.onChange(of: selectedMealPeriod) {
rotationDegrees = 0
isLoading = true
Task {
await getMenuForPeriod(mealPeriodId: selectedMealPeriod)