diff --git a/Uplift.xcodeproj/project.pbxproj b/Uplift.xcodeproj/project.pbxproj index 43bec8e..0bdc8b8 100644 --- a/Uplift.xcodeproj/project.pbxproj +++ b/Uplift.xcodeproj/project.pbxproj @@ -104,13 +104,14 @@ 89599A502BD4B4B600DA44DE /* FitnessClassInstance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89599A4F2BD4B4B600DA44DE /* FitnessClassInstance.swift */; }; 896500DC2BB4D33500D822AB /* ClassDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 896500DB2BB4D33500D822AB /* ClassDetailView.swift */; }; 897703662BA2028D00F9992F /* ClassesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 897703652BA2028D00F9992F /* ClassesViewModel.swift */; }; - 897DF9BA2CCDC49B00246B0D /* UpliftAPI in Frameworks */ = {isa = PBXBuildFile; productRef = 897DF9B92CCDC49B00246B0D /* UpliftAPI */; }; + 897DF9BA2CCDC49B00246B0D /* (null) in Frameworks */ = {isa = PBXBuildFile; }; 8983A9A62CFEA077008E84DB /* UpliftAPI in Frameworks */ = {isa = PBXBuildFile; productRef = 8983A9A52CFEA077008E84DB /* UpliftAPI */; }; 89950D8A2B992E8400DFB007 /* ClassesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89950D892B992E8400DFB007 /* ClassesView.swift */; }; 8996FEE02BDF351800F13C67 /* NextSessionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8996FEDF2BDF351800F13C67 /* NextSessionCell.swift */; }; 899B186D2CA5FAFB00FAC061 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 899B186C2CA5FAFB00FAC061 /* ProfileView.swift */; }; 89A652F92D02B00000277A16 /* CapacityRemindersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89A652F62D02B00000277A16 /* CapacityRemindersView.swift */; }; 89A652FA2D02B00000277A16 /* RemindersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89A652F72D02B00000277A16 /* RemindersView.swift */; }; + 89C10D172CCB2F9E007E753F /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 89C10D162CCB2F9E007E753F /* FirebaseMessaging */; }; 89C34AA12CA66E9C00C579A5 /* CapacityRemindersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C34AA02CA66E9000C579A5 /* CapacityRemindersViewModel.swift */; }; 89C8658D2BB4779C00758337 /* ClassCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89C8658C2BB4779C00758337 /* ClassCell.swift */; }; 89CE47422D03F3C700BCB79D /* UpliftAPI in Frameworks */ = {isa = PBXBuildFile; productRef = 89CE47412D03F3C700BCB79D /* UpliftAPI */; }; @@ -216,6 +217,7 @@ 899B186C2CA5FAFB00FAC061 /* ProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = ""; }; 89A652F62D02B00000277A16 /* CapacityRemindersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacityRemindersView.swift; sourceTree = ""; }; 89A652F72D02B00000277A16 /* RemindersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemindersView.swift; sourceTree = ""; }; + 89C10D222CCB459F007E753F /* Uplift.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Uplift.entitlements; sourceTree = ""; }; 89C34AA02CA66E9000C579A5 /* CapacityRemindersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacityRemindersViewModel.swift; sourceTree = ""; }; 89C8658C2BB4779C00758337 /* ClassCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassCell.swift; sourceTree = ""; }; 89E4FAA92CEFEC3000A952B1 /* CapacitySemiCircleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacitySemiCircleView.swift; sourceTree = ""; }; @@ -234,6 +236,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 89C10D172CCB2F9E007E753F /* FirebaseMessaging in Frameworks */, 2EE5F3E42B12EDB6008E0299 /* ApolloAPI in Frameworks */, 63001AD82CC9AD970082AFFA /* GoogleSignIn in Frameworks */, 2EE5F3E22B12EDB6008E0299 /* Apollo in Frameworks */, @@ -246,7 +249,7 @@ 6338EC5F2CE14B54000BBFD3 /* UpliftAPI in Frameworks */, 2E39D82F2B3BCBA400AD238B /* UpliftAPI in Frameworks */, 6338EC5C2CE149AA000BBFD3 /* UpliftAPI in Frameworks */, - 897DF9BA2CCDC49B00246B0D /* UpliftAPI in Frameworks */, + 897DF9BA2CCDC49B00246B0D /* (null) in Frameworks */, 2E2748D22BCD4EC00023882E /* UpliftAPI in Frameworks */, 63001ADA2CC9AD980082AFFA /* GoogleSignInSwift in Frameworks */, 63A7ABCD2B86B971008D58FB /* UpliftAPI in Frameworks */, @@ -504,6 +507,7 @@ 2E8FE38E2B1278B700B3DC6A /* Uplift */ = { isa = PBXGroup; children = ( + 89C10D222CCB459F007E753F /* Uplift.entitlements */, 2E3838402BB7536700AE15DC /* PrivacyInfo.xcprivacy */, 2E3D6C1D2B12840C00B51BB2 /* Info.plist */, 2E090ECF2B13088800BAE982 /* Configs */, @@ -611,10 +615,9 @@ 636E3D402BBE1EB100B6EFFC /* UpliftAPI */, 636E3D432BBE1F3800B6EFFC /* UpliftAPI */, 2E2748D12BCD4EC00023882E /* UpliftAPI */, - 897DF9B92CCDC49B00246B0D /* UpliftAPI */, + 89C10D162CCB2F9E007E753F /* FirebaseMessaging */, 63001AD72CC9AD970082AFFA /* GoogleSignIn */, 63001AD92CC9AD970082AFFA /* GoogleSignInSwift */, - 897DF9B92CCDC49B00246B0D /* UpliftAPI */, 63001AD72CC9AD970082AFFA /* GoogleSignIn */, 63001AD92CC9AD970082AFFA /* GoogleSignInSwift */, 6338EC5B2CE149AA000BBFD3 /* UpliftAPI */, @@ -1015,9 +1018,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CODE_SIGN_ENTITLEMENTS = Uplift/Uplift.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 39; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = ZGMCXU7X3U; ENABLE_PREVIEWS = YES; @@ -1038,7 +1042,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.1.1; + MARKETING_VERSION = 3.1.2; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = com.cornellappdev.uplift.ios; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1059,9 +1063,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; + CODE_SIGN_ENTITLEMENTS = Uplift/Uplift.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 36; + CURRENT_PROJECT_VERSION = 39; DEVELOPMENT_TEAM = ZGMCXU7X3U; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -1081,7 +1086,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.1.1; + MARKETING_VERSION = 3.1.2; OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = com.cornellappdev.uplift.ios; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1266,13 +1271,13 @@ isa = XCSwiftPackageProductDependency; productName = UpliftAPI; }; - 897DF9B92CCDC49B00246B0D /* UpliftAPI */ = { + 8983A9A52CFEA077008E84DB /* UpliftAPI */ = { isa = XCSwiftPackageProductDependency; productName = UpliftAPI; }; - 8983A9A52CFEA077008E84DB /* UpliftAPI */ = { + 89C10D162CCB2F9E007E753F /* FirebaseMessaging */ = { isa = XCSwiftPackageProductDependency; - productName = UpliftAPI; + productName = FirebaseMessaging; }; 89CE47412D03F3C700BCB79D /* UpliftAPI */ = { isa = XCSwiftPackageProductDependency; diff --git a/Uplift/Core/UpliftApp.swift b/Uplift/Core/UpliftApp.swift index f7713bb..9c1ec9d 100644 --- a/Uplift/Core/UpliftApp.swift +++ b/Uplift/Core/UpliftApp.swift @@ -7,6 +7,8 @@ // import FirebaseCore +import FirebaseMessaging +import FirebaseInstallations import GoogleSignIn import SwiftUI @@ -49,27 +51,78 @@ struct UpliftApp: App { } } } +} - class AppDelegate: NSObject, UIApplicationDelegate { - func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - FirebaseApp.configure() - GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in - if error != nil || user == nil { - // TODO: - Show the app's signed-out state. - } else { - // TODO: - Show the app's signed-in state. - } +class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate { + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + FirebaseApp.configure() + + GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in + if error != nil || user == nil { + // TODO: - Show the app's signed-out state. + } else { + // TODO: - Show the app's signed-in state. + } + } + + // Configure Firebase Cloud Messaging + Messaging.messaging().delegate = self + + // Configure push notifications + UNUserNotificationCenter.current().delegate = self + + let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] + UNUserNotificationCenter.current().requestAuthorization( + options: authOptions, + completionHandler: { _, _ in } + ) + + application.registerForRemoteNotifications() + + return true + } + + func application(_ app: UIApplication, + open url: URL, + options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { + GIDSignIn.sharedInstance.handle(url) + } + + func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { + print("Unable to register for remote notifications: \(error.localizedDescription)") + } + + func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { + let tokenString = deviceToken.map { String(format: "%02x", $0) }.joined() + print("APNs token retrieved: \(tokenString)") + + // Passes the APNs token to Firebase Cloud Messaging (FCM) + Messaging.messaging().apnsToken = deviceToken + } +} + +extension AppDelegate: MessagingDelegate { + func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { + print("Firebase registration token: \(fcmToken ?? "")") + + Messaging.messaging().token { token, error in + if let error = error { + print("Error fetching FCM registration token: \(error)") + } else if let token = token { + print("FCM registration token: \(token)") } - return true } - func application(_ app: UIApplication, - open url: URL, - options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - GIDSignIn.sharedInstance.handle(url) + Task { + do { + let id = try await Installations.installations().installationID() + print("Installation ID: \(id)") + } catch { + print("Error fetching id: \(error)") + } } } } diff --git a/Uplift/Info.plist b/Uplift/Info.plist index dec0841..0b16ae3 100644 --- a/Uplift/Info.plist +++ b/Uplift/Info.plist @@ -12,6 +12,8 @@ $(ANNOUNCEMENTS_SCHEME) CFBundleIconName AppIcon + FirebaseAppDelegateProxyEnabled + CFBundleURLTypes @@ -36,6 +38,10 @@ Montserrat-Regular.ttf Montserrat-SemiBold.ttf + UIBackgroundModes + + remote-notification + UPLIFT_DEV_URL $(UPLIFT_DEV_URL) UPLIFT_PROD_URL diff --git a/Uplift/Uplift.entitlements b/Uplift/Uplift.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/Uplift/Uplift.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/Uplift/Views/Supporting/CapacitySemiCircleView.swift b/Uplift/Views/Supporting/CapacitySemiCircleView.swift index 2b0dee4..743b0c1 100644 --- a/Uplift/Views/Supporting/CapacitySemiCircleView.swift +++ b/Uplift/Views/Supporting/CapacitySemiCircleView.swift @@ -19,8 +19,26 @@ struct CapacitySemiCircleView: View { let status: CapacityStatus? let timeUpdated: Date? - @State private var color: Color = Constants.Colors.open - @State private var progress: Double = 0.0 + private var color: Color { + switch status { + case .notBusy: + return Constants.Colors.open + case .slightlyBusy: + return Constants.Colors.orange + case .veryBusy: + return Constants.Colors.red + default: + return Constants.Colors.open + } + } + private var progress: Double { + switch status { + case .notBusy(let double), .slightlyBusy(let double), .veryBusy(let double): + return double + default: + return 0 + } + } // MARK: - UI @@ -93,21 +111,6 @@ struct CapacitySemiCircleView: View { } } .padding(lineWidth / 2) - .onAppear { - switch status { - case .notBusy(let double): - color = Constants.Colors.open - progress = double - case .slightlyBusy(let double): - color = Constants.Colors.orange - progress = double - case .veryBusy(let double): - color = Constants.Colors.red - progress = double - case nil: - break - } - } } }