Skip to content

Commit

Permalink
merging branches
Browse files Browse the repository at this point in the history
  • Loading branch information
adhi0331 committed Dec 8, 2023
2 parents c97bf9d + 7317b46 commit a43886d
Show file tree
Hide file tree
Showing 20 changed files with 766 additions and 162 deletions.
8 changes: 8 additions & 0 deletions ALUM/ALUM.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@
0748208D29712921004AF547 /* ALUM */,
0748208C29712921004AF547 /* Products */,
0799ACEE2A0102E400EEAFA2 /* Recovered References */,
2A06083E2A0E3128007F38D6 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand Down Expand Up @@ -537,6 +538,13 @@
path = Services;
sourceTree = "<group>";
};
2A06083E2A0E3128007F38D6 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
97992B5D29A6E7E200701CC7 /* SignUpPage */ = {
isa = PBXGroup;
children = (
Expand Down
5 changes: 4 additions & 1 deletion ALUM/ALUM/ALUM.entitlements
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
<dict>
<key>aps-environment</key>
<string>development</string>
</dict>
</plist>
98 changes: 90 additions & 8 deletions ALUM/ALUM/ALUMApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,9 @@ import SwiftUI
import FirebaseCore
import FirebaseFirestore
import FirebaseAuth

class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
FirebaseApp.configure()
return true
}
}
import Firebase
import UserNotifications
import FirebaseMessaging

extension View {
func dismissKeyboardOnDrag() -> some View {
Expand All @@ -38,3 +33,90 @@ struct ALUMApp: App {
}
}
}

class AppDelegate: NSObject, UIApplicationDelegate {
let gcmMessageIDKey = "gcm.message_id"
@ObservedObject var currentUser: CurrentUserModel = CurrentUserModel.shared

func application(_ application: UIApplication, didFinishLaunchingWithOptions
launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
FirebaseApp.configure()

Messaging.messaging().delegate = self

if #available(iOS 10.0, *) {
// For iOS 10 display notification (sent via APNS)
UNUserNotificationCenter.current().delegate = self

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: {_, _ in }
)
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}

application.registerForRemoteNotifications()
return true
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}

print(userInfo)

completionHandler(UIBackgroundFetchResult.newData)
}
}

extension AppDelegate: MessagingDelegate {
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
currentUser.fcmToken = fcmToken
}
}

@available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {

// Receive displayed notifications for iOS 10 devices.
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler:
@escaping (UNNotificationPresentationOptions) -> Void) {
let userInfo = notification.request.content.userInfo

if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}

print(userInfo)

// Change this to your preferred presentation option
completionHandler([[.banner, .badge, .sound]])
}

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
Messaging.messaging().apnsToken = deviceToken
}

func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo

if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID from userNotificationCenter didReceive: \(messageID)")
}

print(userInfo)

completionHandler()
}
}
7 changes: 7 additions & 0 deletions ALUM/ALUM/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,12 @@
<string>Metropolis-ExtraBoldItalic.otf</string>
<string>Metropolis-Thin.otf</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
</dict>
</plist>
34 changes: 34 additions & 0 deletions ALUM/ALUM/Models/CurrentUserModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ enum UserRole {
case mentee
}

struct FCMToken: Codable {
var fcmToken: String
}

class CurrentUserModel: ObservableObject {
static let shared = CurrentUserModel()

@Published var fcmToken: String?
@Published var isLoading: Bool
@Published var uid: String?
@Published var role: UserRole?
Expand All @@ -31,6 +36,7 @@ class CurrentUserModel: ObservableObject {
@Published var pairedMenteeId: String?

init() {
self.fcmToken = nil
self.isLoading = true
self.isLoggedIn = false
self.uid = nil
Expand Down Expand Up @@ -61,6 +67,7 @@ class CurrentUserModel: ObservableObject {
self.setCurrentUser(isLoading: false, isLoggedIn: false, uid: nil, role: nil)
} else {
try await self.setFromFirebaseUser(user: user!)
try await sendFcmToken(fcmToken: fcmToken!)
}
} catch {
// in case setFromFirebaseUser fails, just make the user login again
Expand Down Expand Up @@ -153,4 +160,31 @@ class CurrentUserModel: ObservableObject {
}
return userStatus
}

func sendFcmTokenHelper(fcmToken: String) {
Task {
do {
try await sendFcmToken(fcmToken: fcmToken)
} catch {
print("Error in sending FCM Token")
}
}
}

func sendFcmToken(fcmToken: String) async throws {
print(fcmToken)
print(self.uid)
var tokenToSend: FCMToken = FCMToken(fcmToken: fcmToken)
let route = APIRoute.patchUser(userId: self.uid ?? "")
var request = try await route.createURLRequest()
guard let jsonData = try? JSONEncoder().encode(tokenToSend) else {
DispatchQueue.main.async {
CurrentUserModel.shared.showInternalError.toggle()
}
throw AppError.internalError(.jsonParsingError, message: "Failed to Encode Data")
}
request.httpBody = jsonData
let responseData = try await ServiceHelper.shared.sendRequestWithSafety(route: route, request: request)
print("SUCCESS - \(route.label)")
}
}
137 changes: 74 additions & 63 deletions ALUM/ALUM/Services/APIConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ enum APIRoute {
case getMentee(userId: String)
case postMentor
case postMentee
case patchUser(userId: String)
case getCalendly

case getNote(noteId: String)
Expand Down Expand Up @@ -65,87 +66,97 @@ enum APIRoute {
return URLString.sessions
case .postSession:
return URLString.sessions
case .getCalendly:
return URLString.calendly
case .patchUser(let userId):
return [URLString.user, userId].joined(separator: "/")
case .deleteSession(sessionId: let sessionId):
return [URLString.sessions, sessionId].joined(separator: "/")
case .patchSession(sessionId: let sessionId):
return [URLString.sessions, sessionId].joined(separator: "/")
case .getCalendly:
return URLString.calendly
}
}

var method: String {
switch self {
case .getSelf, .getMentee, .getMentor, .getNote, .getSession, .getSessions, .getCalendly:
return "GET"
case .postMentor, .postMentee, .postSession:
return "POST"
case .deleteSession:
return "DELETE"
case .patchNote, .patchSession:
return "PATCH"
}
var method: String {
switch self {
case .getSelf, .getMentee, .getMentor, .getNote, .getSession, .getSessions, .getCalendly:
return "GET"
case .postMentor, .postMentee, .postSession:
return "POST"
case .patchNote, .patchUser, .patchSession:
return "PATCH"
case .deleteSession:
return "DELETE"
}
}

var requireAuth: Bool {
switch self {
case .getSelf, .getMentor, .getMentee, .getNote, .patchNote, .getSession,
.getSessions, .postSession, .getCalendly, .deleteSession,
.patchSession:
return true
case .postMentee, .postMentor:
return false
}
var requireAuth: Bool {
switch self {
case
.getSelf,
.getMentor,
.getMentee,
.getNote,
.patchNote,
.getSession,
.getSessions,
.postSession,
.getCalendly,
.patchUser,
.patchSession,
.deleteSession:
return true
case .postMentee, .postMentor:
return false
}
}

func createURLRequest() async throws -> URLRequest {
return try await ServiceHelper.shared.createRequest(
urlString: self.url,
method: self.method,
requireAuth: self.requireAuth
)
}
func createURLRequest() async throws -> URLRequest {
return try await ServiceHelper.shared.createRequest(
urlString: self.url,
method: self.method,
requireAuth: self.requireAuth
)
}

var label: String {
return "\(self.method) \(self.url)"
}
var label: String {
return "\(self.method) \(self.url)"
}

var successCode: Int {
switch self {
case .getSelf, .getMentor, .getMentee, .getNote, .patchNote,
.getSession, .getSessions, .getCalendly,
.deleteSession, .patchSession:
return 200 // 200 Ok
case .postMentor, .postMentee, .postSession:
return 201 // 201 Created
}
var successCode: Int {
switch self {
case .getSelf, .getMentor, .getMentee, .getNote, .patchNote,
.getSession, .getSessions, .getCalendly, .patchUser, .deleteSession, .patchSession:
return 200 // 200 Ok
case .postMentor, .postMentee, .postSession:
return 201 // 201 Created
}
}

func getAppError(statusCode: Int, message: String) -> AppError {
let labeledMessage = "\(self.label) - \(message)"
let errorMap: [Int: AppError]
func getAppError(statusCode: Int, message: String) -> AppError {
let labeledMessage = "\(self.label) - \(message)"
let errorMap: [Int: AppError]

switch self {
case .getSelf, .getMentor, .getMentee, .getNote, .patchNote,
.getSession, .getSessions, .getCalendly,
.deleteSession, .patchSession:
errorMap = [
401: AppError.actionable(.authenticationError, message: labeledMessage),
400: AppError.internalError(.invalidRequest, message: labeledMessage),
404: AppError.internalError(.invalidRequest, message: labeledMessage)
]
case .postSession:
switch self {
case .getSelf, .getMentor, .getMentee, .getNote, .patchNote,
.getSession, .getSessions, .getCalendly, .patchUser,
.deleteSession, .patchSession:
errorMap = [
401: AppError.actionable(.authenticationError, message: labeledMessage),
400: AppError.internalError(.invalidRequest, message: labeledMessage),
404: AppError.internalError(.invalidRequest, message: labeledMessage)
]
case .postSession:
errorMap = [
400: AppError.internalError(.invalidRequest, message: labeledMessage)
]
case .postMentor, .postMentee:
// message will be displayed to user so no label here
errorMap = [
400: AppError.actionable(.invalidInput, message: message)
]
}

let error = errorMap[statusCode] ?? AppError.internalError(.unknownError, message: labeledMessage)
return error
case .postMentor, .postMentee:
errorMap = [
400: AppError.internalError(.invalidRequest, message: message)
]
}

let error = errorMap[statusCode] ?? AppError.internalError(.unknownError, message: labeledMessage)
return error
}
}
Loading

0 comments on commit a43886d

Please sign in to comment.