From 2aea4b6a6088af040d2b2efa1c51c6f21d5503be Mon Sep 17 00:00:00 2001 From: John Choi Date: Wed, 10 Jan 2024 00:31:31 -0500 Subject: [PATCH 01/14] Fixed Issue 64 --- JCAlerts.xcodeproj/project.pbxproj | 8 ++++---- .../controllers/NotificationDetailViewController.swift | 1 + .../PushNotificationDisplayViewController.swift | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 919ea0f..0788840 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -656,7 +656,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2023122902; + CURRENT_PROJECT_VERSION = 2024011001; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -671,7 +671,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = io.github.johnchoi96.JCAlerts; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -689,7 +689,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2023122902; + CURRENT_PROJECT_VERSION = 2024011001; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -704,7 +704,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = io.github.johnchoi96.JCAlerts; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; diff --git a/JCAlerts/controllers/NotificationDetailViewController.swift b/JCAlerts/controllers/NotificationDetailViewController.swift index 464938b..b4f484b 100644 --- a/JCAlerts/controllers/NotificationDetailViewController.swift +++ b/JCAlerts/controllers/NotificationDetailViewController.swift @@ -30,6 +30,7 @@ class NotificationDetailViewController: UIViewController { messageView.text = notificationPayload.message } messageView.layer.cornerRadius = 15 + messageView.isEditable = false let fontSize = UserSettingService.instance.getTextViewFontSize() messageView.font = .systemFont(ofSize: CGFloat(fontSize)) fontSizeStepper.minimumValue = 12 diff --git a/JCAlerts/controllers/PushNotificationDisplayViewController.swift b/JCAlerts/controllers/PushNotificationDisplayViewController.swift index d6182ec..c1e5ac1 100644 --- a/JCAlerts/controllers/PushNotificationDisplayViewController.swift +++ b/JCAlerts/controllers/PushNotificationDisplayViewController.swift @@ -27,6 +27,7 @@ class PushNotificationDisplayViewController: UIViewController { title = "Notification Detail" textView.text = "Loading..." textView.layer.cornerRadius = 15 + textView.isEditable = false let fontSize = UserSettingService.instance.getTextViewFontSize() textView.font = .systemFont(ofSize: CGFloat(fontSize)) fontSizeStepper.minimumValue = 12 From af53b485c6656d12cefbecef739555d4900be0f0 Mon Sep 17 00:00:00 2001 From: John Choi Date: Wed, 10 Jan 2024 01:09:06 -0500 Subject: [PATCH 02/14] WIP: delegation works but cards do not update --- JCAlerts.xcodeproj/project.pbxproj | 12 +++++++---- .../delegates/CloudFirestoreDelegate.swift | 4 ++++ JCAlerts/delegates/SceneDelegate.swift | 3 +++ .../CloudFirestoreDataTriggerService.swift | 21 +++++++++++++++++++ JCAlerts/services/CloudFirestoreService.swift | 9 ++++++++ 5 files changed, 45 insertions(+), 4 deletions(-) create mode 100644 JCAlerts/services/CloudFirestoreDataTriggerService.swift diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 919ea0f..08bb19b 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -68,6 +68,7 @@ D2E412E42B26E2A8003EC53F /* IQKeyboardManagerSwift in Frameworks */ = {isa = PBXBuildFile; productRef = D2E412E32B26E2A8003EC53F /* IQKeyboardManagerSwift */; }; D2E412E72B26E3BD003EC53F /* NotificationCommentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2E412E52B26E3BD003EC53F /* NotificationCommentTableViewCell.swift */; }; D2E412E82B26E3BD003EC53F /* NotificationCommentTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D2E412E62B26E3BD003EC53F /* NotificationCommentTableViewCell.xib */; }; + D2EA7E9D2B4E664000D4F3F9 /* CloudFirestoreDataTriggerService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2EA7E9C2B4E664000D4F3F9 /* CloudFirestoreDataTriggerService.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -122,6 +123,7 @@ D2E412E02B26DF28003EC53F /* NotificationCommentsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCommentsViewController.swift; sourceTree = ""; }; D2E412E52B26E3BD003EC53F /* NotificationCommentTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCommentTableViewCell.swift; sourceTree = ""; }; D2E412E62B26E3BD003EC53F /* NotificationCommentTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NotificationCommentTableViewCell.xib; sourceTree = ""; }; + D2EA7E9C2B4E664000D4F3F9 /* CloudFirestoreDataTriggerService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudFirestoreDataTriggerService.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -283,6 +285,7 @@ D24211B32AED548E005BD72C /* FCMTopicService.swift */, D2984CC92B08436A007B199C /* CloudFirestoreService.swift */, D2E412DE2B26B7FD003EC53F /* UserSettingService.swift */, + D2EA7E9C2B4E664000D4F3F9 /* CloudFirestoreDataTriggerService.swift */, ); path = services; sourceTree = ""; @@ -472,6 +475,7 @@ D2153F772B32B33600F405C8 /* UIExt.swift in Sources */, D2984CD12B084A37007B199C /* NotificationPayload.swift in Sources */, D2984CD42B085321007B199C /* NotificationTableViewCell.swift in Sources */, + D2EA7E9D2B4E664000D4F3F9 /* CloudFirestoreDataTriggerService.swift in Sources */, D2984CCA2B08436A007B199C /* CloudFirestoreService.swift in Sources */, D24211B02AEB5ABF005BD72C /* NotificationSettingsTableViewCell.swift in Sources */, D2153F3B2B2ECDD900F405C8 /* LandingPageView.swift in Sources */, @@ -656,7 +660,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2023122902; + CURRENT_PROJECT_VERSION = 2024011001; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -671,7 +675,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = io.github.johnchoi96.JCAlerts; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; @@ -689,7 +693,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2023122902; + CURRENT_PROJECT_VERSION = 2024011001; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -704,7 +708,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1; + MARKETING_VERSION = 1.2; PRODUCT_BUNDLE_IDENTIFIER = io.github.johnchoi96.JCAlerts; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; diff --git a/JCAlerts/delegates/CloudFirestoreDelegate.swift b/JCAlerts/delegates/CloudFirestoreDelegate.swift index 879233e..70d2c6f 100644 --- a/JCAlerts/delegates/CloudFirestoreDelegate.swift +++ b/JCAlerts/delegates/CloudFirestoreDelegate.swift @@ -19,6 +19,8 @@ protocol CloudFirestoreDelegate { func didFinishLoadingSingleNotification(notificationId: String, notification: NotificationPayload) func didFinishUploadingComment() + + func triggerDataRefresh() } extension CloudFirestoreDelegate { @@ -28,4 +30,6 @@ extension CloudFirestoreDelegate { func didFinishLoadingSingleNotification(notificationId: String, notification: NotificationPayload) {} func didFinishUploadingComment() {} + + func triggerDataRefresh() {} } diff --git a/JCAlerts/delegates/SceneDelegate.swift b/JCAlerts/delegates/SceneDelegate.swift index 38be693..c91645d 100644 --- a/JCAlerts/delegates/SceneDelegate.swift +++ b/JCAlerts/delegates/SceneDelegate.swift @@ -43,6 +43,9 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { func sceneDidBecomeActive(_ scene: UIScene) { // Called when the scene has moved from an inactive state to an active state. // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + + let instance = CloudFirestoreDataTriggerService.instance + instance.triggerDataRefresh() } func sceneWillResignActive(_ scene: UIScene) { diff --git a/JCAlerts/services/CloudFirestoreDataTriggerService.swift b/JCAlerts/services/CloudFirestoreDataTriggerService.swift new file mode 100644 index 0000000..a6b1eb6 --- /dev/null +++ b/JCAlerts/services/CloudFirestoreDataTriggerService.swift @@ -0,0 +1,21 @@ +// +// CloudFirestoreDataTriggerService.swift +// JCAlerts +// +// Created by John Choi on 1/10/24. +// + +import Foundation + +class CloudFirestoreDataTriggerService { + + var delegate: CloudFirestoreDelegate? + + static var instance = CloudFirestoreDataTriggerService() + + private init() {} + + func triggerDataRefresh() { + delegate?.triggerDataRefresh() + } +} diff --git a/JCAlerts/services/CloudFirestoreService.swift b/JCAlerts/services/CloudFirestoreService.swift index 6bd639f..348686f 100644 --- a/JCAlerts/services/CloudFirestoreService.swift +++ b/JCAlerts/services/CloudFirestoreService.swift @@ -29,8 +29,11 @@ class CloudFirestoreService: ObservableObject { private let fcmTopicService = FCMTopicService.instance + private let cloudFirestoreTriggerService = CloudFirestoreDataTriggerService.instance + init() { fcmTopicService.delegate = self + cloudFirestoreTriggerService.delegate = self } func fetchNotificationPayloads() { @@ -176,3 +179,9 @@ extension CloudFirestoreService: FCMTopicDelegate { fetchNotificationPayloads() } } + +extension CloudFirestoreService: CloudFirestoreDelegate { + func triggerDataRefresh() { + fetchNotificationPayloads() + } +} From f15fd159e61634b2b3a82e5d96d689709bbda7af Mon Sep 17 00:00:00 2001 From: John Choi Date: Sun, 14 Jan 2024 01:41:40 -0500 Subject: [PATCH 03/14] Added support for test notification topic --- JCAlerts.xcodeproj/project.pbxproj | 4 +- .../xcschemes/JCAlerts - Prod.xcscheme | 77 +++++++++++++++++++ JCAlerts/delegates/AppDelegate.swift | 20 ++--- JCAlerts/models/firebase/fcm/FCMTopic.swift | 15 ++++ JCAlerts/services/CloudFirestoreService.swift | 11 ++- JCAlerts/services/FCMTopicService.swift | 39 ++++++++-- JCAlerts/services/UserSettingService.swift | 8 ++ 7 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 JCAlerts.xcodeproj/xcshareddata/xcschemes/JCAlerts - Prod.xcscheme diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 08bb19b..9c30f9a 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -660,7 +660,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011001; + CURRENT_PROJECT_VERSION = 2024011401; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -693,7 +693,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011001; + CURRENT_PROJECT_VERSION = 2024011401; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; diff --git a/JCAlerts.xcodeproj/xcshareddata/xcschemes/JCAlerts - Prod.xcscheme b/JCAlerts.xcodeproj/xcshareddata/xcschemes/JCAlerts - Prod.xcscheme new file mode 100644 index 0000000..d2e1640 --- /dev/null +++ b/JCAlerts.xcodeproj/xcshareddata/xcschemes/JCAlerts - Prod.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/JCAlerts/delegates/AppDelegate.swift b/JCAlerts/delegates/AppDelegate.swift index 160d38c..53e11c4 100644 --- a/JCAlerts/delegates/AppDelegate.swift +++ b/JCAlerts/delegates/AppDelegate.swift @@ -138,13 +138,14 @@ extension AppDelegate: UNUserNotificationCenterDelegate { return [] } - // NOTE: comment this block for development - #if !DEBUG does not work at the moment // check if notification is a test notification - let isTestMessage = Bool(userInfo["test-notification"] as! String)! - if isTestMessage { - return [] + if !UserSettingService.instance.isDebugMode { + let isTestMessage = Bool(userInfo["test-notification"] as! String)! + if isTestMessage { + return [] + } } - + // Change this to your preferred presentation option return [.banner, .sound] } @@ -187,11 +188,12 @@ extension AppDelegate: UNUserNotificationCenterDelegate { return .noData } - // NOTE: comment this block for development - #if !DEBUG does not work at the moment // check if notification is a test notification - let isTestMessage = Bool(userInfo["test-notification"] as! String)! - if isTestMessage { - return .noData + if !UserSettingService.instance.isDebugMode { + let isTestMessage = Bool(userInfo["test-notification"] as! String)! + if isTestMessage { + return .noData + } } return .newData } diff --git a/JCAlerts/models/firebase/fcm/FCMTopic.swift b/JCAlerts/models/firebase/fcm/FCMTopic.swift index c39d1a6..b783f14 100644 --- a/JCAlerts/models/firebase/fcm/FCMTopic.swift +++ b/JCAlerts/models/firebase/fcm/FCMTopic.swift @@ -13,6 +13,7 @@ enum FCMTopic: String, CaseIterable { case PETFINDER = "jc-alerts-petfinder" case METALPRICE = "jc-alerts-metalprice" case CFB = "jc-alerts-cfb" + case TEST_NOTIFICATION = "jc-alerts-test" } extension FCMTopic { @@ -27,9 +28,21 @@ extension FCMTopic { return "MetalPrice" case .CFB: return "CFB" + case .TEST_NOTIFICATION: + return "TEST" } } + static func getAllTopic() -> [FCMTopic] { + var allTopic = FCMTopic.allCases + if !UserSettingService.instance.isDebugMode { + allTopic = allTopic.filter { topic in + topic != .TEST_NOTIFICATION + } + } + return allTopic + } + func getTopicValue() -> String { return self.rawValue } @@ -43,6 +56,8 @@ extension FCMTopic { return .METALPRICE } else if string == FCMTopic.CFB.getTopicName() || string == FCMTopic.CFB.getTopicValue() { return .CFB + } else if string == FCMTopic.TEST_NOTIFICATION.getTopicName() || string == FCMTopic.TEST_NOTIFICATION.getTopicValue() { + return .TEST_NOTIFICATION } else { return nil } diff --git a/JCAlerts/services/CloudFirestoreService.swift b/JCAlerts/services/CloudFirestoreService.swift index 348686f..fc02a87 100644 --- a/JCAlerts/services/CloudFirestoreService.swift +++ b/JCAlerts/services/CloudFirestoreService.swift @@ -54,6 +54,10 @@ class CloudFirestoreService: ObservableObject { topic = .METALPRICE case FCMTopic.CFB.getTopicValue(): topic = .CFB + case FCMTopic.TEST_NOTIFICATION.getTopicValue(): + if UserSettingService.instance.isDebugMode { + topic = .TEST_NOTIFICATION + } default: self.logger.error("Invalid topic type") } @@ -77,9 +81,8 @@ class CloudFirestoreService: ObservableObject { let payload = NotificationPayload(id: UUID(), notificationTitle: notificationTitle, notificationSubtitle: notificationSubtitle, notificationId: notificationId, message: message, timestamp: timestamp.utcTimestampToDate(), topic: topic, isHtml: isHtml, isTestMessage: isTestMessage) - // NOTE: comment this block for development - #if !DEBUG does not work at the moment // if on prod, ignore test messages - if payload.isTestMessage { + if !UserSettingService.instance.isDebugMode && payload.isTestMessage { continue } @@ -123,6 +126,10 @@ class CloudFirestoreService: ObservableObject { topic = .METALPRICE case FCMTopic.CFB.getTopicValue(): topic = .CFB + case FCMTopic.TEST_NOTIFICATION.getTopicValue(): + if UserSettingService.instance.isDebugMode { + topic = .TEST_NOTIFICATION + } default: self.logger.error("Invalid topic type") } diff --git a/JCAlerts/services/FCMTopicService.swift b/JCAlerts/services/FCMTopicService.swift index 2e87f2e..dae59c8 100644 --- a/JCAlerts/services/FCMTopicService.swift +++ b/JCAlerts/services/FCMTopicService.swift @@ -14,7 +14,13 @@ class FCMTopicService { private let TOPIC_KEY = "fcm-topics" - private let DEFAULT_FCM_TOPIC = FCMTopic.ALL + private var DEFAULT_FCM_TOPICS: [FCMTopic] + + private var DEFAULT_FCM_TOPICS_STRING: [String] { + DEFAULT_FCM_TOPICS.map { topic in + topic.getTopicValue() + } + } private let fcmInstance = Messaging.messaging() @@ -22,7 +28,13 @@ class FCMTopicService { var delegate: FCMTopicDelegate? - private init() {} + private init() { + DEFAULT_FCM_TOPICS = [] + DEFAULT_FCM_TOPICS.append(.ALL) + if UserSettingService.instance.isDebugMode { + DEFAULT_FCM_TOPICS.append(.TEST_NOTIFICATION) + } + } func subscribe(toTopic topic: FCMTopic) { // save list of topics to UserDefaults @@ -75,7 +87,7 @@ class FCMTopicService { } func getTopicsAsStrings() -> [String] { - return UserDefaults.standard.stringArray(forKey: TOPIC_KEY) ?? [DEFAULT_FCM_TOPIC.getTopicValue()] + return UserDefaults.standard.stringArray(forKey: TOPIC_KEY) ?? DEFAULT_FCM_TOPICS_STRING } func topicIsSubscribed(topic: FCMTopic) -> Bool { @@ -90,20 +102,33 @@ class FCMTopicService { for topic in getTopicsAsStrings() { fcmInstance.subscribe(toTopic: topic) } + if UserSettingService.instance.isDebugMode { + subscribe(toTopic: .TEST_NOTIFICATION) + } else { + unsubscribe(fromTopic: .TEST_NOTIFICATION) + } } private func setTopics(as topicsList: inout [String]) { if topicsList.count == 0 { - topicsList.append(DEFAULT_FCM_TOPIC.getTopicValue()) + for defaultTopic in DEFAULT_FCM_TOPICS_STRING { + topicsList.append(defaultTopic) + } } - if !topicsList.contains(DEFAULT_FCM_TOPIC.getTopicValue()) { - topicsList.insert(DEFAULT_FCM_TOPIC.getTopicValue(), at: 0) + // if topicsList does not contain the default topics + let defaultListSet = Set(DEFAULT_FCM_TOPICS_STRING) + let topicsListSet = Set(topicsList) + let intersection = defaultListSet.intersection(topicsListSet) + let missingTopicSet = defaultListSet.subtracting(intersection) + + for missingTopic in missingTopicSet { + topicsList.insert(missingTopic, at: 0) } UserDefaults.standard.set(topicsList, forKey: TOPIC_KEY) } func subscribeToAllTopic() { - FCMTopic.allCases.forEach { topic in + FCMTopic.getAllTopic().forEach { topic in subscribe(toTopic: topic) } } diff --git a/JCAlerts/services/UserSettingService.swift b/JCAlerts/services/UserSettingService.swift index f1dd9c0..b9f9e7c 100644 --- a/JCAlerts/services/UserSettingService.swift +++ b/JCAlerts/services/UserSettingService.swift @@ -18,6 +18,14 @@ class UserSettingService { private var firstTimeRunning: Bool + var isDebugMode: Bool { + #if DEBUG + true + #else + false + #endif + } + private init() { // check if UserDefaults has username defined if let username = userDefaults.string(forKey: "currentUsername") { From 27d8b782354cdd4e244ee4d362a973cd42e44df7 Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 01:25:11 -0500 Subject: [PATCH 04/14] Refreshes cards when tapping on push notification or entering foreground --- .../services/CloudFirestoreDataTriggerService.swift | 3 +++ JCAlerts/services/CloudFirestoreService.swift | 7 +++---- JCAlerts/swiftuis/home/LandingPageView.swift | 11 +++++------ 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/JCAlerts/services/CloudFirestoreDataTriggerService.swift b/JCAlerts/services/CloudFirestoreDataTriggerService.swift index a6b1eb6..c949701 100644 --- a/JCAlerts/services/CloudFirestoreDataTriggerService.swift +++ b/JCAlerts/services/CloudFirestoreDataTriggerService.swift @@ -13,9 +13,12 @@ class CloudFirestoreDataTriggerService { static var instance = CloudFirestoreDataTriggerService() + var cloudFirestoreService = CloudFirestoreService() + private init() {} func triggerDataRefresh() { delegate?.triggerDataRefresh() + cloudFirestoreService.fetchNotificationPayloads() } } diff --git a/JCAlerts/services/CloudFirestoreService.swift b/JCAlerts/services/CloudFirestoreService.swift index fc02a87..0ba686a 100644 --- a/JCAlerts/services/CloudFirestoreService.swift +++ b/JCAlerts/services/CloudFirestoreService.swift @@ -29,11 +29,8 @@ class CloudFirestoreService: ObservableObject { private let fcmTopicService = FCMTopicService.instance - private let cloudFirestoreTriggerService = CloudFirestoreDataTriggerService.instance - init() { fcmTopicService.delegate = self - cloudFirestoreTriggerService.delegate = self } func fetchNotificationPayloads() { @@ -91,7 +88,9 @@ class CloudFirestoreService: ObservableObject { } self.delegate?.didFinishLoadingAll(notifications: notifications, notificationsDict: notificationDict) - self.trimmedNotificationPayloads = self.getFirstNElements(list: notifications, n: 4) + DispatchQueue.main.async { + self.trimmedNotificationPayloads = self.getFirstNElements(list: notifications, n: 4) + } } } } diff --git a/JCAlerts/swiftuis/home/LandingPageView.swift b/JCAlerts/swiftuis/home/LandingPageView.swift index e0e3af6..bec4e1d 100644 --- a/JCAlerts/swiftuis/home/LandingPageView.swift +++ b/JCAlerts/swiftuis/home/LandingPageView.swift @@ -8,12 +8,8 @@ import SwiftUI struct LandingPageView: View { - @ObservedObject var cfService = CloudFirestoreService() - - init() { - cfService.fetchNotificationPayloads() - } - + @ObservedObject var cfService = CloudFirestoreDataTriggerService.instance.cloudFirestoreService + var body: some View { NavigationView { ScrollView { @@ -48,6 +44,9 @@ struct LandingPageView: View { .navigationBarTitleDisplayMode(.large) } .scrollIndicators(.hidden) + .onAppear() { + cfService.fetchNotificationPayloads() + } } } } From 1e2c75acfdf9e8687bdafd682b2401932af54598 Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 01:33:38 -0500 Subject: [PATCH 05/14] Removed unused delegate function --- JCAlerts/delegates/CloudFirestoreDelegate.swift | 4 ---- JCAlerts/services/CloudFirestoreDataTriggerService.swift | 1 - JCAlerts/services/CloudFirestoreService.swift | 6 ------ 3 files changed, 11 deletions(-) diff --git a/JCAlerts/delegates/CloudFirestoreDelegate.swift b/JCAlerts/delegates/CloudFirestoreDelegate.swift index 70d2c6f..879233e 100644 --- a/JCAlerts/delegates/CloudFirestoreDelegate.swift +++ b/JCAlerts/delegates/CloudFirestoreDelegate.swift @@ -19,8 +19,6 @@ protocol CloudFirestoreDelegate { func didFinishLoadingSingleNotification(notificationId: String, notification: NotificationPayload) func didFinishUploadingComment() - - func triggerDataRefresh() } extension CloudFirestoreDelegate { @@ -30,6 +28,4 @@ extension CloudFirestoreDelegate { func didFinishLoadingSingleNotification(notificationId: String, notification: NotificationPayload) {} func didFinishUploadingComment() {} - - func triggerDataRefresh() {} } diff --git a/JCAlerts/services/CloudFirestoreDataTriggerService.swift b/JCAlerts/services/CloudFirestoreDataTriggerService.swift index c949701..fb7cee7 100644 --- a/JCAlerts/services/CloudFirestoreDataTriggerService.swift +++ b/JCAlerts/services/CloudFirestoreDataTriggerService.swift @@ -18,7 +18,6 @@ class CloudFirestoreDataTriggerService { private init() {} func triggerDataRefresh() { - delegate?.triggerDataRefresh() cloudFirestoreService.fetchNotificationPayloads() } } diff --git a/JCAlerts/services/CloudFirestoreService.swift b/JCAlerts/services/CloudFirestoreService.swift index 0ba686a..3d685ca 100644 --- a/JCAlerts/services/CloudFirestoreService.swift +++ b/JCAlerts/services/CloudFirestoreService.swift @@ -185,9 +185,3 @@ extension CloudFirestoreService: FCMTopicDelegate { fetchNotificationPayloads() } } - -extension CloudFirestoreService: CloudFirestoreDelegate { - func triggerDataRefresh() { - fetchNotificationPayloads() - } -} From dbc49cd1382ced1555a6ef4fead205e5b00e5cac Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 01:36:36 -0500 Subject: [PATCH 06/14] Build number update --- JCAlerts.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 9c30f9a..68facab 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -660,7 +660,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011401; + CURRENT_PROJECT_VERSION = 2024011501; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -693,7 +693,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011401; + CURRENT_PROJECT_VERSION = 2024011501; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; From 40591d78816536acc22d8900f5927b57bbc89057 Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 01:46:55 -0500 Subject: [PATCH 07/14] Removed all print statements --- JCAlerts/delegates/AppDelegate.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/JCAlerts/delegates/AppDelegate.swift b/JCAlerts/delegates/AppDelegate.swift index 53e11c4..0294bc7 100644 --- a/JCAlerts/delegates/AppDelegate.swift +++ b/JCAlerts/delegates/AppDelegate.swift @@ -107,12 +107,12 @@ extension AppDelegate: MessagingDelegate { func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { Messaging.messaging().token { token, error in if let error = error { - print("Error fetching FCM registration token: \(error)") + self.log.error("Error fetching FCM registration token: \(error)") } else if let token = token { - print("FCM registration token: \(token)") + self.log.info("FCM registration token: \(token)") } } - print("Firebase registration token: \(String(describing: fcmToken))") + log.info("Firebase registration token: \(String(describing: fcmToken))") let dataDict: [String: String] = ["token": fcmToken ?? ""] NotificationCenter.default.post( From ffe96b554309276da4205b5c4b3bd548e82e8724 Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 02:05:22 -0500 Subject: [PATCH 08/14] Removed unused delegate --- JCAlerts/services/CloudFirestoreDataTriggerService.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/JCAlerts/services/CloudFirestoreDataTriggerService.swift b/JCAlerts/services/CloudFirestoreDataTriggerService.swift index fb7cee7..b8142b8 100644 --- a/JCAlerts/services/CloudFirestoreDataTriggerService.swift +++ b/JCAlerts/services/CloudFirestoreDataTriggerService.swift @@ -9,8 +9,6 @@ import Foundation class CloudFirestoreDataTriggerService { - var delegate: CloudFirestoreDelegate? - static var instance = CloudFirestoreDataTriggerService() var cloudFirestoreService = CloudFirestoreService() From db6080072a66e00d84fd35313519992761b247fe Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 02:20:38 -0500 Subject: [PATCH 09/14] Added pull to refresh behavior --- JCAlerts/swiftuis/home/LandingPageView.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/JCAlerts/swiftuis/home/LandingPageView.swift b/JCAlerts/swiftuis/home/LandingPageView.swift index bec4e1d..5f4ac05 100644 --- a/JCAlerts/swiftuis/home/LandingPageView.swift +++ b/JCAlerts/swiftuis/home/LandingPageView.swift @@ -48,6 +48,9 @@ struct LandingPageView: View { cfService.fetchNotificationPayloads() } } + .refreshable { + cfService.fetchNotificationPayloads() + } } } From db10630c2e08315366e42f5c9ee865ad088068a6 Mon Sep 17 00:00:00 2001 From: John Choi Date: Mon, 15 Jan 2024 02:56:05 -0500 Subject: [PATCH 10/14] Resource cells added --- JCAlerts.xcodeproj/project.pbxproj | 4 ++++ JCAlerts/swiftuis/settings/SettingsView.swift | 6 +++-- .../settings/cells/ResourceCell.swift | 24 +++++++++++++++++++ JCAlerts/utils/Constants.swift | 6 +++++ 4 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 JCAlerts/swiftuis/settings/cells/ResourceCell.swift diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 68facab..303496e 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -29,6 +29,7 @@ D24211B02AEB5ABF005BD72C /* NotificationSettingsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24211AE2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.swift */; }; D24211B12AEB5ABF005BD72C /* NotificationSettingsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D24211AF2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.xib */; }; D24211B42AED548E005BD72C /* FCMTopicService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24211B32AED548E005BD72C /* FCMTopicService.swift */; }; + D24971442B5517D20049EAD4 /* ResourceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24971432B5517D20049EAD4 /* ResourceCell.swift */; }; D26D5F942AE757B000981481 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26D5F932AE757B000981481 /* SettingsViewController.swift */; }; D26F6C502AD1FADF00AC1D6F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26F6C4F2AD1FADF00AC1D6F /* AppDelegate.swift */; }; D26F6C522AD1FADF00AC1D6F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26F6C512AD1FADF00AC1D6F /* SceneDelegate.swift */; }; @@ -95,6 +96,7 @@ D24211AE2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationSettingsTableViewCell.swift; sourceTree = ""; }; D24211AF2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NotificationSettingsTableViewCell.xib; sourceTree = ""; }; D24211B32AED548E005BD72C /* FCMTopicService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FCMTopicService.swift; sourceTree = ""; }; + D24971432B5517D20049EAD4 /* ResourceCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceCell.swift; sourceTree = ""; }; D26D5F932AE757B000981481 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; D26F6C4C2AD1FADF00AC1D6F /* JCAlerts.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JCAlerts.app; sourceTree = BUILT_PRODUCTS_DIR; }; D26F6C4F2AD1FADF00AC1D6F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -168,6 +170,7 @@ D2153F662B30B2DE00F405C8 /* SettingsViewCell.swift */, D2153F6D2B30B58D00F405C8 /* NotificationCategoryCell.swift */, D21693AA2B3E63F20020BECF /* AppMetadataCell.swift */, + D24971432B5517D20049EAD4 /* ResourceCell.swift */, ); path = cells; sourceTree = ""; @@ -493,6 +496,7 @@ D2984CC82B003333007B199C /* FCMTopic.swift in Sources */, D2984CC22B002E9C007B199C /* PushNotificationDisplayViewController.swift in Sources */, D2153F632B30A4D300F405C8 /* SettingsView.swift in Sources */, + D24971442B5517D20049EAD4 /* ResourceCell.swift in Sources */, D26D5F942AE757B000981481 /* SettingsViewController.swift in Sources */, D2153F6C2B30B57E00F405C8 /* NotificationCategoriesView.swift in Sources */, D21693AB2B3E63F20020BECF /* AppMetadataCell.swift in Sources */, diff --git a/JCAlerts/swiftuis/settings/SettingsView.swift b/JCAlerts/swiftuis/settings/SettingsView.swift index e58465a..2e763d4 100644 --- a/JCAlerts/swiftuis/settings/SettingsView.swift +++ b/JCAlerts/swiftuis/settings/SettingsView.swift @@ -23,8 +23,10 @@ struct SettingsView: View { AppMetadataCell(label: "App Version:", data: K.Device.appVersion ?? "N/A") AppMetadataCell(label: "Build:", data: K.Device.appBuild ?? "N/A") } - - + Section(header: Text("Resources")) { + ResourceCell(label: "Open Source Repository", url: K.Url.githubLink) + ResourceCell(label: "Submit an Issue", url: K.Url.githubNewIssue) + } } .navigationTitle("Settings") .navigationBarTitleDisplayMode(.large) diff --git a/JCAlerts/swiftuis/settings/cells/ResourceCell.swift b/JCAlerts/swiftuis/settings/cells/ResourceCell.swift new file mode 100644 index 0000000..062a4ee --- /dev/null +++ b/JCAlerts/swiftuis/settings/cells/ResourceCell.swift @@ -0,0 +1,24 @@ +// +// ResourceCell.swift +// JCAlerts +// +// Created by John Choi on 1/15/24. +// + +import SwiftUI + +struct ResourceCell: View { + var label: String + var url: URL + + var body: some View { + HStack { + Link(destination: url, label: { + Text(label) + }) + .foregroundStyle(.primary) + Spacer() + Image(systemName: "link.circle") + } + } +} diff --git a/JCAlerts/utils/Constants.swift b/JCAlerts/utils/Constants.swift index 45db531..f6b0385 100644 --- a/JCAlerts/utils/Constants.swift +++ b/JCAlerts/utils/Constants.swift @@ -40,4 +40,10 @@ struct K { static let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String static let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String } + + struct Url { + static let githubLink = URL(string: "https://github.com/johnchoi96/JCAlerts-iOS")! + + static let githubNewIssue = URL(string: "https://github.com/johnchoi96/JCAlerts-iOS/issues/new")! + } } From cd3a3c0b9a2c8196d95d864b10b738363978894d Mon Sep 17 00:00:00 2001 From: John Choi Date: Tue, 16 Jan 2024 03:21:20 -0500 Subject: [PATCH 11/14] Fixed crash issue on Prod, Added tips on first run --- JCAlerts.xcodeproj/project.pbxproj | 32 ++++++++++++++++ JCAlerts/delegates/SceneDelegate.swift | 11 +++++- JCAlerts/services/FCMTopicService.swift | 5 ++- JCAlerts/services/UserSettingService.swift | 14 +++++++ JCAlerts/swiftuis/ContentView.swift | 32 +++++++--------- JCAlerts/swiftuis/settings/SettingsView.swift | 9 ++++- .../tips/home/FirstTimeWelcomeTip.swift | 37 +++++++++++++++++++ .../tips/settings/SettingsPageTip.swift | 30 +++++++++++++++ 8 files changed, 148 insertions(+), 22 deletions(-) create mode 100644 JCAlerts/swiftuis/tips/home/FirstTimeWelcomeTip.swift create mode 100644 JCAlerts/swiftuis/tips/settings/SettingsPageTip.swift diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 303496e..c1cdf4f 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ D24211B12AEB5ABF005BD72C /* NotificationSettingsTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D24211AF2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.xib */; }; D24211B42AED548E005BD72C /* FCMTopicService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24211B32AED548E005BD72C /* FCMTopicService.swift */; }; D24971442B5517D20049EAD4 /* ResourceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24971432B5517D20049EAD4 /* ResourceCell.swift */; }; + D24971472B5662A80049EAD4 /* FirstTimeWelcomeTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24971462B5662A80049EAD4 /* FirstTimeWelcomeTip.swift */; }; + D24971492B5668860049EAD4 /* SettingsPageTip.swift in Sources */ = {isa = PBXBuildFile; fileRef = D24971482B5668860049EAD4 /* SettingsPageTip.swift */; }; D26D5F942AE757B000981481 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26D5F932AE757B000981481 /* SettingsViewController.swift */; }; D26F6C502AD1FADF00AC1D6F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26F6C4F2AD1FADF00AC1D6F /* AppDelegate.swift */; }; D26F6C522AD1FADF00AC1D6F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D26F6C512AD1FADF00AC1D6F /* SceneDelegate.swift */; }; @@ -97,6 +99,8 @@ D24211AF2AEB5ABE005BD72C /* NotificationSettingsTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NotificationSettingsTableViewCell.xib; sourceTree = ""; }; D24211B32AED548E005BD72C /* FCMTopicService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FCMTopicService.swift; sourceTree = ""; }; D24971432B5517D20049EAD4 /* ResourceCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourceCell.swift; sourceTree = ""; }; + D24971462B5662A80049EAD4 /* FirstTimeWelcomeTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstTimeWelcomeTip.swift; sourceTree = ""; }; + D24971482B5668860049EAD4 /* SettingsPageTip.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsPageTip.swift; sourceTree = ""; }; D26D5F932AE757B000981481 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = ""; }; D26F6C4C2AD1FADF00AC1D6F /* JCAlerts.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JCAlerts.app; sourceTree = BUILT_PRODUCTS_DIR; }; D26F6C4F2AD1FADF00AC1D6F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -159,6 +163,7 @@ D2153F642B30A4FE00F405C8 /* ContentView.swift */, D2153F6A2B30B55F00F405C8 /* home */, D2153F692B30B55500F405C8 /* settings */, + D24971452B5662930049EAD4 /* tips */, D2153F712B3107C800F405C8 /* uikits */, ); path = swiftuis; @@ -293,6 +298,31 @@ path = services; sourceTree = ""; }; + D24971452B5662930049EAD4 /* tips */ = { + isa = PBXGroup; + children = ( + D249714A2B566A850049EAD4 /* home */, + D249714B2B566A8D0049EAD4 /* settings */, + ); + path = tips; + sourceTree = ""; + }; + D249714A2B566A850049EAD4 /* home */ = { + isa = PBXGroup; + children = ( + D24971462B5662A80049EAD4 /* FirstTimeWelcomeTip.swift */, + ); + path = home; + sourceTree = ""; + }; + D249714B2B566A8D0049EAD4 /* settings */ = { + isa = PBXGroup; + children = ( + D24971482B5668860049EAD4 /* SettingsPageTip.swift */, + ); + path = settings; + sourceTree = ""; + }; D26F6C432AD1FADF00AC1D6F = { isa = PBXGroup; children = ( @@ -486,6 +516,7 @@ D2E412DD2B26B3E9003EC53F /* NotificationComment.swift in Sources */, D26F6C502AD1FADF00AC1D6F /* AppDelegate.swift in Sources */, D24211A12AE7589D005BD72C /* StringExt.swift in Sources */, + D24971472B5662A80049EAD4 /* FirstTimeWelcomeTip.swift in Sources */, D2153F732B32665B00F405C8 /* UKNotificationDetailView.swift in Sources */, D2E412E12B26DF28003EC53F /* NotificationCommentsViewController.swift in Sources */, D24211B42AED548E005BD72C /* FCMTopicService.swift in Sources */, @@ -505,6 +536,7 @@ D2153F672B30B2DE00F405C8 /* SettingsViewCell.swift in Sources */, D2984CD72B0854E9007B199C /* NotificationDetailViewController.swift in Sources */, D2153F652B30A4FE00F405C8 /* ContentView.swift in Sources */, + D24971492B5668860049EAD4 /* SettingsPageTip.swift in Sources */, D2E412E72B26E3BD003EC53F /* NotificationCommentTableViewCell.swift in Sources */, D2153F752B32A55F00F405C8 /* FCMTopicDelegate.swift in Sources */, D2153F6E2B30B58D00F405C8 /* NotificationCategoryCell.swift in Sources */, diff --git a/JCAlerts/delegates/SceneDelegate.swift b/JCAlerts/delegates/SceneDelegate.swift index c91645d..b69714d 100644 --- a/JCAlerts/delegates/SceneDelegate.swift +++ b/JCAlerts/delegates/SceneDelegate.swift @@ -7,11 +7,14 @@ import UIKit import SwiftUI +import TipKit +import os class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? + private let log = Logger() func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. @@ -19,8 +22,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). guard let windowScene = (scene as? UIWindowScene) else { return } - let rootView = ContentView() + log.info("Running in \(UserSettingService.instance.isDebugMode ? "debug" : "prod") mode") + let rootView = ContentView().task { + if UserSettingService.instance.isDebugMode { + try? Tips.resetDatastore() + } + try? Tips.configure() + } // Check if a window exists, otherwise create one if let window = window { window.rootViewController = UIHostingController(rootView: rootView) diff --git a/JCAlerts/services/FCMTopicService.swift b/JCAlerts/services/FCMTopicService.swift index dae59c8..272f043 100644 --- a/JCAlerts/services/FCMTopicService.swift +++ b/JCAlerts/services/FCMTopicService.swift @@ -49,7 +49,7 @@ class FCMTopicService { fcmInstance.subscribe(toTopic: topic.getTopicValue()) { error in if error != nil { // do something - self.log.info("\(error!)") + self.log.warning("\(error!)") } else { self.log.info("successfully subed") } @@ -69,7 +69,8 @@ class FCMTopicService { } } if index == -1 { - fatalError("Something went wrong while trying to unsubscribe \(topic) topic") + log.warning("Could not find \(topic.getTopicValue()) topic to unsubscribe. Aborting") + return } // remove from the index topics.remove(at: index) diff --git a/JCAlerts/services/UserSettingService.swift b/JCAlerts/services/UserSettingService.swift index b9f9e7c..bd123c0 100644 --- a/JCAlerts/services/UserSettingService.swift +++ b/JCAlerts/services/UserSettingService.swift @@ -27,6 +27,16 @@ class UserSettingService { } private init() { + currentUsername = "" + textViewFontSize = 12 + firstTimeRunning = true + + checkUsername() + checkTextViewFontSize() + checkFirstTimeRunning() + } + + private func checkUsername() { // check if UserDefaults has username defined if let username = userDefaults.string(forKey: "currentUsername") { currentUsername = username @@ -36,7 +46,9 @@ class UserSettingService { currentUsername = uuid userDefaults.setValue(uuid, forKey: "currentUsername") } + } + private func checkTextViewFontSize() { // check if UserDefaults has textViewFontSize defined if userDefaults.integer(forKey: "textViewFontSize") != 0 { textViewFontSize = userDefaults.integer(forKey: "textViewFontSize") @@ -44,7 +56,9 @@ class UserSettingService { textViewFontSize = 14 userDefaults.setValue(textViewFontSize, forKey: "textViewFontSize") } + } + private func checkFirstTimeRunning() { if let firstTime = userDefaults.string(forKey: "firstTimeRunning") { firstTimeRunning = Bool(firstTime)! } else { diff --git a/JCAlerts/swiftuis/ContentView.swift b/JCAlerts/swiftuis/ContentView.swift index 1fcae10..16b5b33 100644 --- a/JCAlerts/swiftuis/ContentView.swift +++ b/JCAlerts/swiftuis/ContentView.swift @@ -6,16 +6,14 @@ // import SwiftUI +import TipKit struct ContentView: View { - @State private var isFirstTimeRunning = UserSettingService.instance.getFirstTimeRunning() - - private let WELCOME_MSG = "Welcome to JCAlerts!" - private let WELCOME_MSG_BODY = """ -For the first time setup, please go to the Settings tab and configure notification subscriptions -""" + + var firstTimeTip = FirstTimeWelcomeTip() var body: some View { + TipView(firstTimeTip) TabView { LandingPageView() .tabItem { @@ -23,26 +21,24 @@ For the first time setup, please go to the Settings tab and configure notificati } SettingsView() + .task { + if UserSettingService.instance.isDebugMode { + try? Tips.resetDatastore() + } + try? Tips.configure() + } .tabItem { Label("Settings", systemImage: "gear") } - } - .alert(WELCOME_MSG, isPresented: $isFirstTimeRunning) { - Button(role: .cancel) { - // handle action - isFirstTimeRunning = false - FCMTopicService.instance.subscribeToAllTopic() - UserSettingService.instance.setFirstTimeRunningToFalse() - } label: { - Text("OK") - } - } message: { - Text(WELCOME_MSG_BODY) } } } #Preview { ContentView() + .task { + try? Tips.resetDatastore() + try? Tips.configure() + } } diff --git a/JCAlerts/swiftuis/settings/SettingsView.swift b/JCAlerts/swiftuis/settings/SettingsView.swift index 2e763d4..1b90b13 100644 --- a/JCAlerts/swiftuis/settings/SettingsView.swift +++ b/JCAlerts/swiftuis/settings/SettingsView.swift @@ -6,6 +6,7 @@ // import SwiftUI +import TipKit struct SettingsView: View { @@ -13,12 +14,15 @@ struct SettingsView: View { "Notification Categories" ] + let notificationCategoryTip = NotificationCategoryTip() + var body: some View { NavigationView { List(items, id: \.self) { item in Section(header: Text("Settings")) { SettingsViewCell(cellLabel: item) } + .popoverTip(notificationCategoryTip) Section(header: Text("App Data")) { AppMetadataCell(label: "App Version:", data: K.Device.appVersion ?? "N/A") AppMetadataCell(label: "Build:", data: K.Device.appBuild ?? "N/A") @@ -30,11 +34,14 @@ struct SettingsView: View { } .navigationTitle("Settings") .navigationBarTitleDisplayMode(.large) - } } } #Preview { SettingsView() + .task { + try? Tips.resetDatastore() + try? Tips.configure() + } } diff --git a/JCAlerts/swiftuis/tips/home/FirstTimeWelcomeTip.swift b/JCAlerts/swiftuis/tips/home/FirstTimeWelcomeTip.swift new file mode 100644 index 0000000..7c65314 --- /dev/null +++ b/JCAlerts/swiftuis/tips/home/FirstTimeWelcomeTip.swift @@ -0,0 +1,37 @@ +// +// FirstTimeWelcomeTip.swift +// JCAlerts +// +// Created by John Choi on 1/16/24. +// + +import Foundation +import TipKit + +struct FirstTimeWelcomeTip: Tip { + + private let WELCOME_MSG = "Welcome to JCAlerts!" + private let WELCOME_MSG_BODY = """ +For the first time setup, please go to the Settings tab and configure notification subscriptions +""" + + var title: Text { + Text(WELCOME_MSG) + } + + var message: Text? { + Text(WELCOME_MSG_BODY) + } + + var image: Image? { + Image(systemName: "hand.wave.fill") + } + + var actions: [Action] { + Action { + invalidate(reason: .tipClosed) + } _: { + Text("Don't Show Again") + } + } +} diff --git a/JCAlerts/swiftuis/tips/settings/SettingsPageTip.swift b/JCAlerts/swiftuis/tips/settings/SettingsPageTip.swift new file mode 100644 index 0000000..c23f9c7 --- /dev/null +++ b/JCAlerts/swiftuis/tips/settings/SettingsPageTip.swift @@ -0,0 +1,30 @@ +// +// NotificationCategoryTip.swift +// JCAlerts +// +// Created by John Choi on 1/16/24. +// + +import Foundation +import TipKit + +struct NotificationCategoryTip: Tip { + + private let MSG = "You can set your notification preferences here." + + var title: Text { + Text(MSG) + } + + var image: Image? { + Image(systemName: "hand.tap.fill") + } + + var actions: [Action] { + Action { + invalidate(reason: .tipClosed) + } _: { + Text("Don't Show Again") + } + } +} From d745142ca902b49ff85201214ee0e010389dfbd4 Mon Sep 17 00:00:00 2001 From: John Choi Date: Tue, 16 Jan 2024 03:21:46 -0500 Subject: [PATCH 12/14] Version change: --- JCAlerts.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index c1cdf4f..9a8f831 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -696,7 +696,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011501; + CURRENT_PROJECT_VERSION = 2024011601; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; @@ -729,7 +729,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = JCAlerts/JCAlerts.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2024011501; + CURRENT_PROJECT_VERSION = 2024011601; DEVELOPMENT_TEAM = 2JDGUK4DRH; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = JCAlerts/Info.plist; From a6c34be34c410699b9fea98add22d3c041f63d6b Mon Sep 17 00:00:00 2001 From: John Choi Date: Tue, 16 Jan 2024 03:43:11 -0500 Subject: [PATCH 13/14] Fixed settingsview list logic --- JCAlerts/swiftuis/settings/SettingsView.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/JCAlerts/swiftuis/settings/SettingsView.swift b/JCAlerts/swiftuis/settings/SettingsView.swift index 1b90b13..bc494bc 100644 --- a/JCAlerts/swiftuis/settings/SettingsView.swift +++ b/JCAlerts/swiftuis/settings/SettingsView.swift @@ -18,9 +18,11 @@ struct SettingsView: View { var body: some View { NavigationView { - List(items, id: \.self) { item in + List { Section(header: Text("Settings")) { - SettingsViewCell(cellLabel: item) + ForEach(items, id: \.self) { item in + SettingsViewCell(cellLabel: item) + } } .popoverTip(notificationCategoryTip) Section(header: Text("App Data")) { From 69c0ee99af725ad93b1009d49093ac5f7f618299 Mon Sep 17 00:00:00 2001 From: John Choi Date: Tue, 16 Jan 2024 03:49:40 -0500 Subject: [PATCH 14/14] Code cleanup --- JCAlerts.xcodeproj/project.pbxproj | 16 ++++++++-------- .../settings/NotificationCategoriesView.swift | 2 +- JCAlerts/swiftuis/settings/SettingsView.swift | 10 ++-------- ...tionCategoryCell.swift => CategoryCell.swift} | 6 +++--- ...ft => NotificationCategorySettingsItem.swift} | 12 +++--------- 5 files changed, 17 insertions(+), 29 deletions(-) rename JCAlerts/swiftuis/settings/cells/{NotificationCategoryCell.swift => CategoryCell.swift} (88%) rename JCAlerts/swiftuis/settings/cells/{SettingsViewCell.swift => NotificationCategorySettingsItem.swift} (52%) diff --git a/JCAlerts.xcodeproj/project.pbxproj b/JCAlerts.xcodeproj/project.pbxproj index 9a8f831..55ca273 100644 --- a/JCAlerts.xcodeproj/project.pbxproj +++ b/JCAlerts.xcodeproj/project.pbxproj @@ -11,9 +11,9 @@ D2153F3B2B2ECDD900F405C8 /* LandingPageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F3A2B2ECDD900F405C8 /* LandingPageView.swift */; }; D2153F632B30A4D300F405C8 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F622B30A4D300F405C8 /* SettingsView.swift */; }; D2153F652B30A4FE00F405C8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F642B30A4FE00F405C8 /* ContentView.swift */; }; - D2153F672B30B2DE00F405C8 /* SettingsViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F662B30B2DE00F405C8 /* SettingsViewCell.swift */; }; + D2153F672B30B2DE00F405C8 /* NotificationCategorySettingsItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F662B30B2DE00F405C8 /* NotificationCategorySettingsItem.swift */; }; D2153F6C2B30B57E00F405C8 /* NotificationCategoriesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F6B2B30B57E00F405C8 /* NotificationCategoriesView.swift */; }; - D2153F6E2B30B58D00F405C8 /* NotificationCategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F6D2B30B58D00F405C8 /* NotificationCategoryCell.swift */; }; + D2153F6E2B30B58D00F405C8 /* CategoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F6D2B30B58D00F405C8 /* CategoryCell.swift */; }; D2153F702B3107C100F405C8 /* UKAlertsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F6F2B3107C100F405C8 /* UKAlertsView.swift */; }; D2153F732B32665B00F405C8 /* UKNotificationDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F722B32665B00F405C8 /* UKNotificationDetailView.swift */; }; D2153F752B32A55F00F405C8 /* FCMTopicDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2153F742B32A55F00F405C8 /* FCMTopicDelegate.swift */; }; @@ -79,9 +79,9 @@ D2153F3A2B2ECDD900F405C8 /* LandingPageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LandingPageView.swift; sourceTree = ""; }; D2153F622B30A4D300F405C8 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; D2153F642B30A4FE00F405C8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - D2153F662B30B2DE00F405C8 /* SettingsViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewCell.swift; sourceTree = ""; }; + D2153F662B30B2DE00F405C8 /* NotificationCategorySettingsItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCategorySettingsItem.swift; sourceTree = ""; }; D2153F6B2B30B57E00F405C8 /* NotificationCategoriesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCategoriesView.swift; sourceTree = ""; }; - D2153F6D2B30B58D00F405C8 /* NotificationCategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationCategoryCell.swift; sourceTree = ""; }; + D2153F6D2B30B58D00F405C8 /* CategoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryCell.swift; sourceTree = ""; }; D2153F6F2B3107C100F405C8 /* UKAlertsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UKAlertsView.swift; sourceTree = ""; }; D2153F722B32665B00F405C8 /* UKNotificationDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UKNotificationDetailView.swift; sourceTree = ""; }; D2153F742B32A55F00F405C8 /* FCMTopicDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FCMTopicDelegate.swift; sourceTree = ""; }; @@ -172,8 +172,8 @@ D2153F682B30B32E00F405C8 /* cells */ = { isa = PBXGroup; children = ( - D2153F662B30B2DE00F405C8 /* SettingsViewCell.swift */, - D2153F6D2B30B58D00F405C8 /* NotificationCategoryCell.swift */, + D2153F662B30B2DE00F405C8 /* NotificationCategorySettingsItem.swift */, + D2153F6D2B30B58D00F405C8 /* CategoryCell.swift */, D21693AA2B3E63F20020BECF /* AppMetadataCell.swift */, D24971432B5517D20049EAD4 /* ResourceCell.swift */, ); @@ -533,13 +533,13 @@ D21693AB2B3E63F20020BECF /* AppMetadataCell.swift in Sources */, D26F6C522AD1FADF00AC1D6F /* SceneDelegate.swift in Sources */, D242119F2AE75893005BD72C /* Constants.swift in Sources */, - D2153F672B30B2DE00F405C8 /* SettingsViewCell.swift in Sources */, + D2153F672B30B2DE00F405C8 /* NotificationCategorySettingsItem.swift in Sources */, D2984CD72B0854E9007B199C /* NotificationDetailViewController.swift in Sources */, D2153F652B30A4FE00F405C8 /* ContentView.swift in Sources */, D24971492B5668860049EAD4 /* SettingsPageTip.swift in Sources */, D2E412E72B26E3BD003EC53F /* NotificationCommentTableViewCell.swift in Sources */, D2153F752B32A55F00F405C8 /* FCMTopicDelegate.swift in Sources */, - D2153F6E2B30B58D00F405C8 /* NotificationCategoryCell.swift in Sources */, + D2153F6E2B30B58D00F405C8 /* CategoryCell.swift in Sources */, D24211AD2AEB57A4005BD72C /* NotificationSettingsViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/JCAlerts/swiftuis/settings/NotificationCategoriesView.swift b/JCAlerts/swiftuis/settings/NotificationCategoriesView.swift index 9221b5f..984cbfc 100644 --- a/JCAlerts/swiftuis/settings/NotificationCategoriesView.swift +++ b/JCAlerts/swiftuis/settings/NotificationCategoriesView.swift @@ -16,7 +16,7 @@ struct NotificationCategoriesView: View { var body: some View { List(notificationTypes, id: \.self) { type in - NotificationCategoryCell(topic: type) + CategoryCell(topic: type) } .navigationTitle("Categories") } diff --git a/JCAlerts/swiftuis/settings/SettingsView.swift b/JCAlerts/swiftuis/settings/SettingsView.swift index bc494bc..9acfa17 100644 --- a/JCAlerts/swiftuis/settings/SettingsView.swift +++ b/JCAlerts/swiftuis/settings/SettingsView.swift @@ -10,21 +10,15 @@ import TipKit struct SettingsView: View { - private let items = [ - "Notification Categories" - ] - let notificationCategoryTip = NotificationCategoryTip() var body: some View { NavigationView { List { Section(header: Text("Settings")) { - ForEach(items, id: \.self) { item in - SettingsViewCell(cellLabel: item) - } + NotificationCategorySettingsItem() + .popoverTip(notificationCategoryTip) } - .popoverTip(notificationCategoryTip) Section(header: Text("App Data")) { AppMetadataCell(label: "App Version:", data: K.Device.appVersion ?? "N/A") AppMetadataCell(label: "Build:", data: K.Device.appBuild ?? "N/A") diff --git a/JCAlerts/swiftuis/settings/cells/NotificationCategoryCell.swift b/JCAlerts/swiftuis/settings/cells/CategoryCell.swift similarity index 88% rename from JCAlerts/swiftuis/settings/cells/NotificationCategoryCell.swift rename to JCAlerts/swiftuis/settings/cells/CategoryCell.swift index 807bb74..9de2d9c 100644 --- a/JCAlerts/swiftuis/settings/cells/NotificationCategoryCell.swift +++ b/JCAlerts/swiftuis/settings/cells/CategoryCell.swift @@ -1,5 +1,5 @@ // -// NotificationCategoryCell.swift +// CategoryCell.swift // JCAlerts // // Created by John Choi on 12/18/23. @@ -8,7 +8,7 @@ import SwiftUI import os -struct NotificationCategoryCell: View { +struct CategoryCell: View { @State var isOn: Bool = false var topic: FCMTopic @@ -39,5 +39,5 @@ struct NotificationCategoryCell: View { } #Preview { - NotificationCategoryCell(topic: .ALL) + CategoryCell(topic: .ALL) } diff --git a/JCAlerts/swiftuis/settings/cells/SettingsViewCell.swift b/JCAlerts/swiftuis/settings/cells/NotificationCategorySettingsItem.swift similarity index 52% rename from JCAlerts/swiftuis/settings/cells/SettingsViewCell.swift rename to JCAlerts/swiftuis/settings/cells/NotificationCategorySettingsItem.swift index dd534f7..bfe211d 100644 --- a/JCAlerts/swiftuis/settings/cells/SettingsViewCell.swift +++ b/JCAlerts/swiftuis/settings/cells/NotificationCategorySettingsItem.swift @@ -1,5 +1,5 @@ // -// SettingsViewCell.swift +// NotificationCategorySettingsItem.swift // JCAlerts // // Created by John Choi on 12/18/23. @@ -7,16 +7,10 @@ import SwiftUI -struct SettingsViewCell: View { - var cellLabel: String - +struct NotificationCategorySettingsItem: View { var body: some View { NavigationLink(destination: NotificationCategoriesView()) { - Text(cellLabel) + Text("Notification Categories") } } } - -#Preview { - SettingsViewCell(cellLabel: "DEMO") -}