Changed icon to new RIT-trademark-free one
Replaced the icon with a more generic tiger pawprint so that I'm not using an RIT trademark, so that I'm prepared for the first App Store release. Also added information about where menu information is being sourced from on the about screen, and fixed a bug where vegetarian/vegan/no beef/no pork toggles would not be written to UserDefaults.
@ -265,7 +265,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "RIT Dining/RIT Dining.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 5GF7GKNTK4;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -300,7 +300,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "RIT Dining/RIT Dining.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 19;
|
||||
CURRENT_PROJECT_VERSION = 20;
|
||||
DEVELOPMENT_TEAM = 5GF7GKNTK4;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
|
||||
@ -1,7 +1,30 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "RIT Dining Temp Logo.png",
|
||||
"filename" : "TigerDine Temp Logo-iOS-Default-1024x1024@1x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "TigerDine Temp Logo-iOS-Dark-1024x1024@1x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "tinted"
|
||||
}
|
||||
],
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
|
||||
|
After Width: | Height: | Size: 2.6 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "RIT Dining Temp Logo.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 140 KiB |
@ -1,7 +1,17 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "RIT Dining Temp Logo.png",
|
||||
"filename" : "TigerDine Temp Logo-iOS-Default-1024x1024@1x.png",
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "TigerDine Temp Logo-iOS-Dark-1024x1024@1x.png",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
||||
|
Before Width: | Height: | Size: 140 KiB |
BIN
RIT Dining/Assets.xcassets/Icon.imageset/TigerDine Temp Logo-iOS-Dark-1024x1024@1x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.6 MiB |
BIN
RIT Dining/Assets.xcassets/Icon.imageset/TigerDine Temp Logo-iOS-Default-1024x1024@1x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
@ -24,9 +24,9 @@ func parseFDMealPlannerMenu(menu: FDMealsParser) -> [FDMenuItem] {
|
||||
// englishAlternateName holds the proper name of the item, but it's blank for some items for some reason. If that's the
|
||||
// case, then we should fall back on componentName, which is less user-friendly but works as a backup.
|
||||
let realName = if recipe.englishAlternateName != "" {
|
||||
recipe.englishAlternateName
|
||||
recipe.englishAlternateName.trimmingCharacters(in: .whitespaces)
|
||||
} else {
|
||||
recipe.componentName
|
||||
recipe.componentName.trimmingCharacters(in: .whitespaces)
|
||||
}
|
||||
let allergens = recipe.allergenName != "" ? recipe.allergenName.components(separatedBy: ",") : []
|
||||
// Get the list of dietary markers (Vegan, Vegetarian, Pork, Beef), and drop "Vegetarian" if "Vegan" is also included since
|
||||
|
||||
@ -7,10 +7,10 @@
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@Observable
|
||||
class MenuDietaryRestrictionsModel {
|
||||
var filteredDietaryMarkers: Set<String> = []
|
||||
class MenuDietaryRestrictionsModel: ObservableObject {
|
||||
var dietaryRestrictions = DietaryRestrictions()
|
||||
var isVegetarian: Bool = false
|
||||
var isVegan: Bool = false
|
||||
@AppStorage("isVegetarian") var isVegetarian: Bool = false
|
||||
@AppStorage("isVegan") var isVegan: Bool = false
|
||||
@AppStorage("noBeef") var noBeef: Bool = false
|
||||
@AppStorage("noPork") var noPork: Bool = false
|
||||
}
|
||||
|
||||
@ -20,36 +20,43 @@ struct AboutView: View {
|
||||
.clipShape(RoundedRectangle(cornerRadius: 20))
|
||||
Text("TigerDine")
|
||||
.font(.title)
|
||||
.fontWeight(.bold)
|
||||
Text("An unofficial RIT Dining app")
|
||||
.font(.subheadline)
|
||||
Text("Version \(appVersionString) (\(buildNumber))")
|
||||
.foregroundStyle(.secondary)
|
||||
.padding(.bottom, 2)
|
||||
VStack(alignment: .leading, spacing: 10) {
|
||||
Text("Dining locations, their descriptions, and their opening hours are sourced from the RIT student-run TigerCenter API. Building occupancy information is sourced from the official RIT maps API.")
|
||||
Text("Dining locations, their descriptions, and their opening hours are sourced from the RIT student-run TigerCenter API. Building occupancy information is sourced from the official RIT maps API. Menu and nutritional information is sourced from the data provided to FD MealPlanner by RIT Dining through the FD MealPlanner API.")
|
||||
Text("This app is not affiliated, associated, authorized, endorsed by, or in any way officially connected with the Rochester Institute of Technology. This app is student created and maintained.")
|
||||
HStack {
|
||||
VStack(alignment: .center, spacing: 8) {
|
||||
HStack(spacing: 8) {
|
||||
Button(action: {
|
||||
openURL(URL(string: "https://github.com/NinjaCheetah/TigerDine")!)
|
||||
}) {
|
||||
Text("Source Code")
|
||||
Label("Source Code", systemImage: "network")
|
||||
}
|
||||
Text("•")
|
||||
.foregroundStyle(.secondary)
|
||||
Button(action: {
|
||||
openURL(URL(string: "https://tigercenter.rit.edu/")!)
|
||||
}) {
|
||||
Text("TigerCenter")
|
||||
Label("TigerCenter", systemImage: "fork.knife.circle")
|
||||
}
|
||||
Text("•")
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
HStack(spacing: 8) {
|
||||
Button(action: {
|
||||
openURL(URL(string: "https://maps.rit.edu/")!)
|
||||
}) {
|
||||
Text("Official RIT Map")
|
||||
Label("Official RIT Map", systemImage: "map")
|
||||
}
|
||||
Button(action: {
|
||||
openURL(URL(string: "https://fdmealplanner.com/")!)
|
||||
}) {
|
||||
Label("FD MealPlanner", systemImage: "menucard")
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.padding()
|
||||
|
||||
@ -15,32 +15,10 @@ struct MenuDietaryRestrictionsSheet: View {
|
||||
NavigationView {
|
||||
Form {
|
||||
Section(header: Text("Diet")) {
|
||||
Toggle(isOn: Binding(
|
||||
get: {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.contains("Beef")
|
||||
},
|
||||
set: { isOn in
|
||||
if isOn {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.insert("Beef")
|
||||
} else {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.remove("Beef")
|
||||
}
|
||||
} )
|
||||
) {
|
||||
Toggle(isOn: $dietaryRestrictionsModel.noBeef) {
|
||||
Text("No Beef")
|
||||
}
|
||||
Toggle(isOn: Binding(
|
||||
get: {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.contains("Pork")
|
||||
},
|
||||
set: { isOn in
|
||||
if isOn {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.insert("Pork")
|
||||
} else {
|
||||
dietaryRestrictionsModel.filteredDietaryMarkers.remove("Pork")
|
||||
}
|
||||
} )
|
||||
) {
|
||||
Toggle(isOn: $dietaryRestrictionsModel.noPork) {
|
||||
Text("No Pork")
|
||||
}
|
||||
Toggle(isOn: $dietaryRestrictionsModel.isVegetarian) {
|
||||
|
||||
@ -65,17 +65,6 @@ struct MenuView: View {
|
||||
|
||||
private var filteredMenuItems: [FDMenuItem] {
|
||||
var newItems = menuItems
|
||||
// Filter out dietary restrictions, starting with pork/beef since those are tagged.
|
||||
if !dietaryRestrictionsModel.filteredDietaryMarkers.isEmpty {
|
||||
newItems = newItems.filter { item in
|
||||
for marker in dietaryRestrictionsModel.filteredDietaryMarkers {
|
||||
if item.dietaryMarkers.contains(marker) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
// Filter out allergens.
|
||||
newItems = newItems.filter { item in
|
||||
if !item.allergens.isEmpty {
|
||||
@ -100,6 +89,17 @@ struct MenuView: View {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Filter out pork/beef.
|
||||
if dietaryRestrictionsModel.noBeef {
|
||||
newItems = newItems.filter { item in
|
||||
item.dietaryMarkers.contains("Beef") == false
|
||||
}
|
||||
}
|
||||
if dietaryRestrictionsModel.noPork {
|
||||
newItems = newItems.filter { item in
|
||||
item.dietaryMarkers.contains("Pork") == false
|
||||
}
|
||||
}
|
||||
// Filter down to search contents.
|
||||
newItems = newItems.filter { item in
|
||||
let searchedLocations = searchText.isEmpty || item.name.localizedCaseInsensitiveContains(searchText)
|
||||
|
||||