mirror of
https://github.com/NinjaCheetah/RIT-Dining.git
synced 2026-03-05 05:25:29 -05:00
Major sorting/filtering improvements
This update mostly includes improvements related to sorting and filtering the main dining location list, including:
- Favorites! You can mark locations as your favorites by swiping them on the list or pressing the star button on their detail page. Favorites are sorted to the top.
- "Hide Closed Locations" has been moved to a dedicated sort/filter button in the bottom left corner. This looks best on iOS 26+, where it sits nicely to the left of the search bar.
- Added an "Open Locations First" option to sort open locations above closed locations, if you want to know what's open quicker without entirely hiding closed locations.
Other improvements:
- Made most asynchronous code properly async instead of bouncing between DispatchQueue.main.async{} and .sync{}.
- Added a timer to refresh open statuses every 3 seconds while on the main list, so that when the time changes the open statuses will change appropriately. It seemed silly to force you to fetch the data again just to do a quick "hey is current time in range?".
- Made date formatter shared so there aren't 3 separate copies of it.
This commit is contained in:
38
RIT Dining/Data/Favorites.swift
Normal file
38
RIT Dining/Data/Favorites.swift
Normal file
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Favorites.swift
|
||||
// RIT Dining
|
||||
//
|
||||
// Created by Campbell on 9/22/25.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@Observable
|
||||
class Favorites {
|
||||
private var favoriteLocations: Set<Int>
|
||||
private let key = "Favorites"
|
||||
|
||||
init() {
|
||||
let favorites = UserDefaults.standard.array(forKey: key) as? [Int] ?? [Int]()
|
||||
favoriteLocations = Set(favorites)
|
||||
}
|
||||
|
||||
func contains(_ location: DiningLocation) -> Bool {
|
||||
favoriteLocations.contains(location.id)
|
||||
}
|
||||
|
||||
func add(_ location: DiningLocation) {
|
||||
favoriteLocations.insert(location.id)
|
||||
save()
|
||||
}
|
||||
|
||||
func remove(_ location: DiningLocation) {
|
||||
favoriteLocations.remove(location.id)
|
||||
save()
|
||||
}
|
||||
|
||||
func save() {
|
||||
let favorites = Array(favoriteLocations)
|
||||
UserDefaults.standard.set(favorites, forKey: key)
|
||||
}
|
||||
}
|
||||
@@ -244,3 +244,22 @@ func parseLocationInfo(location: DiningLocationParser) -> DiningLocation {
|
||||
visitingChefs: visitingChefs,
|
||||
dailySpecials: dailySpecials)
|
||||
}
|
||||
|
||||
extension DiningLocation {
|
||||
mutating func updateOpenStatus() {
|
||||
var openStatus: OpenStatus = .closed
|
||||
if let diningTimes = diningTimes, !diningTimes.isEmpty {
|
||||
for i in diningTimes.indices {
|
||||
openStatus = parseOpenStatus(openTime: diningTimes[i].openTime, closeTime: diningTimes[i].closeTime)
|
||||
// If the first event pass came back closed, loop again in case a later event has a different status. This is mostly to
|
||||
// accurately catch Gracie's multiple open periods each day.
|
||||
if openStatus != .closed {
|
||||
break
|
||||
}
|
||||
}
|
||||
self.open = openStatus
|
||||
} else {
|
||||
self.open = .closed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ struct DiningLocation: Identifiable, Hashable {
|
||||
let desc: String
|
||||
let mapsUrl: String
|
||||
let diningTimes: [DiningTimes]?
|
||||
let open: OpenStatus
|
||||
var open: OpenStatus
|
||||
let visitingChefs: [VisitingChef]?
|
||||
let dailySpecials: [DailySpecial]?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user