From dc8e60f58911bbc0b48607a7c166bebda18ac80d Mon Sep 17 00:00:00 2001 From: Phuoc Nguyen Date: Wed, 26 Nov 2025 17:46:09 +0700 Subject: [PATCH] fix login and add notifications --- .../Info.plist | 13 + .../NotificationService.swift | 32 +++ ...lNotificationServiceExtension.entitlements | 12 + ios/Podfile | 15 +- ios/Podfile.lock | 58 +++- ios/Runner.xcodeproj/project.pbxproj | 265 ++++++++++++++++++ ios/Runner/Info.plist | 28 +- ios/Runner/Runner.entitlements | 12 + lib/core/network/api_interceptor.dart | 2 +- lib/core/router/app_router.dart | 43 ++- .../presentation/providers/auth_provider.dart | 5 +- lib/main.dart | 54 ++++ pubspec.lock | 8 + pubspec.yaml | 3 +- 14 files changed, 517 insertions(+), 33 deletions(-) create mode 100644 ios/OneSignalNotificationServiceExtension/Info.plist create mode 100644 ios/OneSignalNotificationServiceExtension/NotificationService.swift create mode 100644 ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements create mode 100644 ios/Runner/Runner.entitlements diff --git a/ios/OneSignalNotificationServiceExtension/Info.plist b/ios/OneSignalNotificationServiceExtension/Info.plist new file mode 100644 index 0000000..57421eb --- /dev/null +++ b/ios/OneSignalNotificationServiceExtension/Info.plist @@ -0,0 +1,13 @@ + + + + + NSExtension + + NSExtensionPointIdentifier + com.apple.usernotifications.service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).NotificationService + + + diff --git a/ios/OneSignalNotificationServiceExtension/NotificationService.swift b/ios/OneSignalNotificationServiceExtension/NotificationService.swift new file mode 100644 index 0000000..ab391a3 --- /dev/null +++ b/ios/OneSignalNotificationServiceExtension/NotificationService.swift @@ -0,0 +1,32 @@ +import UserNotifications +import OneSignalExtension + +class NotificationService: UNNotificationServiceExtension { + var contentHandler: ((UNNotificationContent) -> Void)? + var receivedRequest: UNNotificationRequest! + var bestAttemptContent: UNMutableNotificationContent? + + // Note this extension only runs when `mutable_content` is set + // Setting an attachment or action buttons automatically sets the property to true + override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { + self.receivedRequest = request + self.contentHandler = contentHandler + self.bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) + + if let bestAttemptContent = bestAttemptContent { + // DEBUGGING: Uncomment the 2 lines below to check this extension is executing +// print("Running NotificationServiceExtension") +// bestAttemptContent.body = "[Modified] " + bestAttemptContent.body + + OneSignalExtension.didReceiveNotificationExtensionRequest(self.receivedRequest, with: bestAttemptContent, withContentHandler: self.contentHandler) + } + } + + override func serviceExtensionTimeWillExpire() { + // Use this as an opportunity to deliver your "best attempt" at modified content, otherwise the original push payload will be used. + if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { + OneSignalExtension.serviceExtensionTimeWillExpireRequest(self.receivedRequest, with: self.bestAttemptContent) + contentHandler(bestAttemptContent) + } + } +} diff --git a/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements b/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements new file mode 100644 index 0000000..675953d --- /dev/null +++ b/ios/OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements @@ -0,0 +1,12 @@ + + + + + aps-environment + development + com.apple.security.application-groups + + group.com.dbiz.partner.onesignal + + + diff --git a/ios/Podfile b/ios/Podfile index 620e46e..ead9595 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '13.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' @@ -36,8 +36,19 @@ target 'Runner' do end end +# OneSignal Notification Service Extension (OUTSIDE Runner target) +target 'OneSignalNotificationServiceExtension' do + use_frameworks! + pod 'OneSignalXCFramework', '>= 5.0.0', '< 6.0' +end + post_install do |installer| installer.pods_project.targets.each do |target| flutter_additional_ios_build_settings(target) + + # Ensure consistent deployment target + target.build_configurations.each do |config| + config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' + end end -end +end \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d465686..fdfbbf4 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -94,6 +94,55 @@ PODS: - nanopb/encode (= 2.30910.0) - nanopb/decode (2.30910.0) - nanopb/encode (2.30910.0) + - onesignal_flutter (5.3.4): + - Flutter + - OneSignalXCFramework (= 5.2.14) + - OneSignalXCFramework (5.2.14): + - OneSignalXCFramework/OneSignalComplete (= 5.2.14) + - OneSignalXCFramework/OneSignal (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalExtension + - OneSignalXCFramework/OneSignalLiveActivities + - OneSignalXCFramework/OneSignalNotifications + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalOutcomes + - OneSignalXCFramework/OneSignalUser + - OneSignalXCFramework/OneSignalComplete (5.2.14): + - OneSignalXCFramework/OneSignal + - OneSignalXCFramework/OneSignalInAppMessages + - OneSignalXCFramework/OneSignalLocation + - OneSignalXCFramework/OneSignalCore (5.2.14) + - OneSignalXCFramework/OneSignalExtension (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalOutcomes + - OneSignalXCFramework/OneSignalInAppMessages (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalNotifications + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalOutcomes + - OneSignalXCFramework/OneSignalUser + - OneSignalXCFramework/OneSignalLiveActivities (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalUser + - OneSignalXCFramework/OneSignalLocation (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalNotifications + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalUser + - OneSignalXCFramework/OneSignalNotifications (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalExtension + - OneSignalXCFramework/OneSignalOutcomes + - OneSignalXCFramework/OneSignalOSCore (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalOutcomes (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalUser (5.2.14): + - OneSignalXCFramework/OneSignalCore + - OneSignalXCFramework/OneSignalNotifications + - OneSignalXCFramework/OneSignalOSCore + - OneSignalXCFramework/OneSignalOutcomes - open_file_ios (0.0.1): - Flutter - path_provider_foundation (0.0.1): @@ -123,6 +172,8 @@ DEPENDENCIES: - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - integration_test (from `.symlinks/plugins/integration_test/ios`) - mobile_scanner (from `.symlinks/plugins/mobile_scanner/ios`) + - onesignal_flutter (from `.symlinks/plugins/onesignal_flutter/ios`) + - OneSignalXCFramework (< 6.0, >= 5.0.0) - open_file_ios (from `.symlinks/plugins/open_file_ios/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - share_plus (from `.symlinks/plugins/share_plus/ios`) @@ -145,6 +196,7 @@ SPEC REPOS: - MLKitCommon - MLKitVision - nanopb + - OneSignalXCFramework - PromisesObjC - SDWebImage - SwiftyGif @@ -164,6 +216,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/integration_test/ios" mobile_scanner: :path: ".symlinks/plugins/mobile_scanner/ios" + onesignal_flutter: + :path: ".symlinks/plugins/onesignal_flutter/ios" open_file_ios: :path: ".symlinks/plugins/open_file_ios/ios" path_provider_foundation: @@ -198,6 +252,8 @@ SPEC CHECKSUMS: MLKitVision: e858c5f125ecc288e4a31127928301eaba9ae0c1 mobile_scanner: 96e91f2e1fb396bb7df8da40429ba8dfad664740 nanopb: 438bc412db1928dac798aa6fd75726007be04262 + onesignal_flutter: f69ff09eeaf41cea4b7a841de5a61e79e7fd9a5a + OneSignalXCFramework: 7112f3e89563e41ebc23fe807788f11985ac541c open_file_ios: 461db5853723763573e140de3193656f91990d9e path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 @@ -208,6 +264,6 @@ SPEC CHECKSUMS: SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4 url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa -PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e +PODFILE CHECKSUM: 41022e80ca79dfdcc337fcf6a6cca3b7d3cb6958 COCOAPODS: 1.16.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 50c9196..9d171f5 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -10,12 +10,14 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 48D410762ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 48D4106F2ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 58215889146B2DBBD9C81410 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2545A56CA7C5FCC88F0D6DF7 /* Pods_Runner.framework */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; AB1F84BC849C548E4DA2D9A4 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 23D173C6FEE4F53025C06238 /* Pods_RunnerTests.framework */; }; + E88379F7C7DF9A2FA2741EC2 /* Pods_OneSignalNotificationServiceExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FC689749C1B738DA836BE8F2 /* Pods_OneSignalNotificationServiceExtension.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -26,9 +28,27 @@ remoteGlobalIDString = 97C146ED1CF9000F007C117D; remoteInfo = Runner; }; + 48D410742ED7067500A8B931 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 48D4106E2ED7067500A8B931; + remoteInfo = OneSignalNotificationServiceExtension; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 48D4107C2ED7067500A8B931 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + 48D410762ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -43,6 +63,7 @@ /* Begin PBXFileReference section */ 01651DC8E3A322D39483596C /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; + 055EB8AF0F56FE3029E6507E /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.release.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.release.xcconfig"; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 18121E1016DEC4038E74F1F0 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; @@ -51,6 +72,10 @@ 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4720F73E5117230A69E1B4A0 /* Pods-OneSignalNotificationServiceExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.profile.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.profile.xcconfig"; sourceTree = ""; }; + 48D4106A2ED7062D00A8B931 /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 48D4106F2ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = OneSignalNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; + 5B101E50F7EDE4E6F1714DD8 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; path = "Target Support Files/Pods-OneSignalNotificationServiceExtension/Pods-OneSignalNotificationServiceExtension.debug.xcconfig"; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -65,9 +90,43 @@ A2165E7BD4BCB2253391F0B0 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; B234409A1C87269651420659 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; C436CF2D08FCD6AFF7811DE0 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + FC689749C1B738DA836BE8F2 /* Pods_OneSignalNotificationServiceExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OneSignalNotificationServiceExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 48D410772ED7067500A8B931 /* Exceptions for "OneSignalNotificationServiceExtension" folder in "OneSignalNotificationServiceExtension" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = 48D4106E2ED7067500A8B931 /* OneSignalNotificationServiceExtension */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + 48D410702ED7067500A8B931 /* OneSignalNotificationServiceExtension */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 48D410772ED7067500A8B931 /* Exceptions for "OneSignalNotificationServiceExtension" folder in "OneSignalNotificationServiceExtension" target */, + ); + explicitFileTypes = { + }; + explicitFolders = ( + ); + path = OneSignalNotificationServiceExtension; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ + 48D4106C2ED7067500A8B931 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E88379F7C7DF9A2FA2741EC2 /* Pods_OneSignalNotificationServiceExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 61A54C58DE898B1B550583E8 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -111,6 +170,7 @@ children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, + 48D410702ED7067500A8B931 /* OneSignalNotificationServiceExtension */, 97C146EF1CF9000F007C117D /* Products */, 331C8082294A63A400263BE5 /* RunnerTests */, D39C332D04678D8C49EEA401 /* Pods */, @@ -123,6 +183,7 @@ children = ( 97C146EE1CF9000F007C117D /* Runner.app */, 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + 48D4106F2ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex */, ); name = Products; sourceTree = ""; @@ -130,6 +191,7 @@ 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( + 48D4106A2ED7062D00A8B931 /* Runner.entitlements */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, @@ -151,6 +213,9 @@ C436CF2D08FCD6AFF7811DE0 /* Pods-RunnerTests.debug.xcconfig */, 01651DC8E3A322D39483596C /* Pods-RunnerTests.release.xcconfig */, 18121E1016DEC4038E74F1F0 /* Pods-RunnerTests.profile.xcconfig */, + 5B101E50F7EDE4E6F1714DD8 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */, + 055EB8AF0F56FE3029E6507E /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */, + 4720F73E5117230A69E1B4A0 /* Pods-OneSignalNotificationServiceExtension.profile.xcconfig */, ); path = Pods; sourceTree = ""; @@ -160,6 +225,7 @@ children = ( 2545A56CA7C5FCC88F0D6DF7 /* Pods_Runner.framework */, 23D173C6FEE4F53025C06238 /* Pods_RunnerTests.framework */, + FC689749C1B738DA836BE8F2 /* Pods_OneSignalNotificationServiceExtension.framework */, ); name = Frameworks; sourceTree = ""; @@ -186,11 +252,33 @@ productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 48D4106E2ED7067500A8B931 /* OneSignalNotificationServiceExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = 48D410782ED7067500A8B931 /* Build configuration list for PBXNativeTarget "OneSignalNotificationServiceExtension" */; + buildPhases = ( + D2C3589E1C02A832F759D563 /* [CP] Check Pods Manifest.lock */, + 48D4106B2ED7067500A8B931 /* Sources */, + 48D4106C2ED7067500A8B931 /* Frameworks */, + 48D4106D2ED7067500A8B931 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 48D410702ED7067500A8B931 /* OneSignalNotificationServiceExtension */, + ); + name = OneSignalNotificationServiceExtension; + productName = OneSignalNotificationServiceExtension; + productReference = 48D4106F2ED7067500A8B931 /* OneSignalNotificationServiceExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( 6FF008E9F6081D18F1331B43 /* [CP] Check Pods Manifest.lock */, + 48D4107C2ED7067500A8B931 /* Embed Foundation Extensions */, 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, @@ -203,6 +291,7 @@ buildRules = ( ); dependencies = ( + 48D410752ED7067500A8B931 /* PBXTargetDependency */, ); name = Runner; productName = Runner; @@ -216,6 +305,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { @@ -223,6 +313,9 @@ CreatedOnToolsVersion = 14.0; TestTargetID = 97C146ED1CF9000F007C117D; }; + 48D4106E2ED7067500A8B931 = { + CreatedOnToolsVersion = 16.4; + }; 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; LastSwiftMigration = 1100; @@ -244,6 +337,7 @@ targets = ( 97C146ED1CF9000F007C117D /* Runner */, 331C8080294A63A400263BE5 /* RunnerTests */, + 48D4106E2ED7067500A8B931 /* OneSignalNotificationServiceExtension */, ); }; /* End PBXProject section */ @@ -256,6 +350,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 48D4106D2ED7067500A8B931 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -379,6 +480,28 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; + D2C3589E1C02A832F759D563 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-OneSignalNotificationServiceExtension-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -390,6 +513,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 48D4106B2ED7067500A8B931 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -407,6 +537,11 @@ target = 97C146ED1CF9000F007C117D /* Runner */; targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; }; + 48D410752ED7067500A8B931 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 48D4106E2ED7067500A8B931 /* OneSignalNotificationServiceExtension */; + targetProxy = 48D410742ED7067500A8B931 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -487,6 +622,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 9R5X2DM2C8; ENABLE_BITCODE = NO; @@ -554,6 +690,123 @@ }; name = Profile; }; + 48D410792ED7067500A8B931 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B101E50F7EDE4E6F1714DD8 /* Pods-OneSignalNotificationServiceExtension.debug.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 9R5X2DM2C8; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.dbiz.partner.OneSignalNotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 48D4107A2ED7067500A8B931 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 055EB8AF0F56FE3029E6507E /* Pods-OneSignalNotificationServiceExtension.release.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 9R5X2DM2C8; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.dbiz.partner.OneSignalNotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 48D4107B2ED7067500A8B931 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4720F73E5117230A69E1B4A0 /* Pods-OneSignalNotificationServiceExtension.profile.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_ENTITLEMENTS = OneSignalNotificationServiceExtension/OneSignalNotificationServiceExtension.entitlements; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 9R5X2DM2C8; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = OneSignalNotificationServiceExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = OneSignalNotificationServiceExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.dbiz.partner.OneSignalNotificationServiceExtension; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Profile; + }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -671,6 +924,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 9R5X2DM2C8; ENABLE_BITCODE = NO; @@ -695,6 +949,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = 9R5X2DM2C8; ENABLE_BITCODE = NO; @@ -725,6 +980,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 48D410782ED7067500A8B931 /* Build configuration list for PBXNativeTarget "OneSignalNotificationServiceExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 48D410792ED7067500A8B931 /* Debug */, + 48D4107A2ED7067500A8B931 /* Release */, + 48D4107B2ED7067500A8B931 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 20bc755..8d8cb20 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleDisplayName @@ -22,18 +24,26 @@ ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) + ITSAppUsesNonExemptEncryption + LSRequiresIPhoneOS + NSCameraUsageDescription + Ứng dụng cần quyền truy cập camera để quét mã QR và chụp ảnh giấy tờ xác thực (CCCD/CMND, chứng chỉ hành nghề) + NSMicrophoneUsageDescription + Ứng dụng cần quyền truy cập microphone để ghi âm video nếu cần + NSPhotoLibraryUsageDescription + Ứng dụng cần quyền truy cập thư viện ảnh để chọn ảnh giấy tờ xác thực và mã QR từ thiết bị của bạn + UIApplicationSupportsIndirectInputEvents + + UIBackgroundModes + + remote-notification + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main - NSCameraUsageDescription - Ứng dụng cần quyền truy cập camera để quét mã QR và chụp ảnh giấy tờ xác thực (CCCD/CMND, chứng chỉ hành nghề) - NSPhotoLibraryUsageDescription - Ứng dụng cần quyền truy cập thư viện ảnh để chọn ảnh giấy tờ xác thực và mã QR từ thiết bị của bạn - NSMicrophoneUsageDescription - Ứng dụng cần quyền truy cập microphone để ghi âm video nếu cần UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -47,11 +57,5 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - - ITSAppUsesNonExemptEncryption - diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..675953d --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,12 @@ + + + + + aps-environment + development + com.apple.security.application-groups + + group.com.dbiz.partner.onesignal + + + diff --git a/lib/core/network/api_interceptor.dart b/lib/core/network/api_interceptor.dart index d3f7a9d..57388ec 100644 --- a/lib/core/network/api_interceptor.dart +++ b/lib/core/network/api_interceptor.dart @@ -569,7 +569,7 @@ Future authInterceptor(Ref ref, Dio dio) async { @riverpod LoggingInterceptor loggingInterceptor(Ref ref) { // Only enable logging in debug mode - const bool isDebug = true; // TODO: Replace with kDebugMode from Flutter + const bool isDebug = false; // TODO: Replace with kDebugMode from Flutter return LoggingInterceptor( enableRequestLogging: false, diff --git a/lib/core/router/app_router.dart b/lib/core/router/app_router.dart index f6f8d2c..ccfd821 100644 --- a/lib/core/router/app_router.dart +++ b/lib/core/router/app_router.dart @@ -65,14 +65,21 @@ final routerProvider = Provider((ref) { redirect: (context, state) { final isLoading = authState.isLoading; final isLoggedIn = authState.value != null; - final isOnSplashPage = state.matchedLocation == RouteNames.splash; - final isOnLoginPage = state.matchedLocation == RouteNames.login; - final isOnForgotPasswordPage = - state.matchedLocation == RouteNames.forgotPassword; - final isOnRegisterPage = state.matchedLocation == RouteNames.register; - final isOnBusinessUnitPage = - state.matchedLocation == RouteNames.businessUnitSelection; - final isOnOtpPage = state.matchedLocation == RouteNames.otpVerification; + final currentPath = state.matchedLocation; + final targetPath = state.uri.toString(); + + // Log redirect attempts for debugging + print('🔄 Router redirect check:'); + print(' Current: $currentPath'); + print(' Target: $targetPath'); + print(' isLoading: $isLoading, isLoggedIn: $isLoggedIn'); + + final isOnSplashPage = currentPath == RouteNames.splash; + final isOnLoginPage = currentPath == RouteNames.login; + final isOnForgotPasswordPage = currentPath == RouteNames.forgotPassword; + final isOnRegisterPage = currentPath == RouteNames.register; + final isOnBusinessUnitPage = currentPath == RouteNames.businessUnitSelection; + final isOnOtpPage = currentPath == RouteNames.otpVerification; final isOnAuthPage = isOnLoginPage || isOnForgotPasswordPage || @@ -82,25 +89,35 @@ final routerProvider = Provider((ref) { // While loading auth state, show splash screen if (isLoading) { - return RouteNames.splash; + if (!isOnSplashPage) { + print(' ➡️ Redirecting to splash (loading)'); + return RouteNames.splash; + } + print(' ✓ Already on splash (loading)'); + return null; } // After loading, redirect from splash to appropriate page - if (isOnSplashPage && !isLoading) { - return isLoggedIn ? RouteNames.home : RouteNames.login; + if (isOnSplashPage) { + final destination = isLoggedIn ? RouteNames.home : RouteNames.login; + print(' ➡️ Redirecting from splash to $destination'); + return destination; } // If not logged in and not on auth/splash pages, redirect to login - if (!isLoggedIn && !isOnAuthPage && !isOnSplashPage) { + if (!isLoggedIn && !isOnAuthPage) { + print(' ➡️ Redirecting to login (not authenticated)'); return RouteNames.login; } // If logged in and on login page, redirect to home if (isLoggedIn && isOnLoginPage) { + print(' ➡️ Redirecting to home (already logged in)'); return RouteNames.home; } // No redirect needed + print(' ✓ No redirect needed'); return null; }, @@ -549,7 +566,7 @@ final routerProvider = Provider((ref) { ), // Debug logging (disable in production) - debugLogDiagnostics: true, + debugLogDiagnostics: false, // Using custom logs instead ); }); diff --git a/lib/features/auth/presentation/providers/auth_provider.dart b/lib/features/auth/presentation/providers/auth_provider.dart index 5598cb4..33066a3 100644 --- a/lib/features/auth/presentation/providers/auth_provider.dart +++ b/lib/features/auth/presentation/providers/auth_provider.dart @@ -88,10 +88,8 @@ class Auth extends _$Auth { @override Future build() async { // Simple initialization - just check if user is logged in - // Don't call getSession() here to avoid ref disposal issues + // Do this ONCE on app startup and don't rebuild try { - final secureStorage = ref.read(secureStorageProvider); - // Check if "Remember Me" was enabled final rememberMe = await _localDataSource.getRememberMe(); @@ -101,6 +99,7 @@ class Auth extends _$Auth { } // Check if we have a stored session + final secureStorage = ref.read(secureStorageProvider); final sid = await secureStorage.read(key: 'frappe_sid'); final userId = await secureStorage.read(key: 'frappe_user_id'); final fullName = await secureStorage.read(key: 'frappe_full_name'); diff --git a/lib/main.dart b/lib/main.dart index 617f4cc..8cacf52 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:onesignal_flutter/onesignal_flutter.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:worker/app.dart'; @@ -29,6 +30,10 @@ void main() async { // Initialize app with error handling await _initializeApp(); + + // Enable verbose logging for debugging (remove in production) + + } /// Initialize all app dependencies with comprehensive error handling @@ -40,6 +45,55 @@ Future _initializeApp() async { // Initialize core dependencies in parallel for faster startup await Future.wait([_initializeHive(), _initializeSharedPreferences()]); + // Initialize OneSignal with verbose logging for debugging + OneSignal.Debug.setLogLevel(OSLogLevel.verbose); + + // Initialize with your OneSignal App ID + OneSignal.initialize("778ca22d-c719-4ec8-86cb-a6b911166066"); + + debugPrint('🔔 OneSignal initialized'); + + // Add observer BEFORE requesting permission to catch the subscription event + OneSignal.User.pushSubscription.addObserver((state) { + debugPrint('🔔 Push subscription state changed:'); + debugPrint(' Previous - optedIn: ${state.previous.optedIn}, id: ${state.previous.id}'); + debugPrint(' Current - optedIn: ${state.current.optedIn}, id: ${state.current.id}'); + debugPrint(' Subscription ID: ${state.current.id}'); + debugPrint(' Push Token: ${state.current.token}'); + + // Save subscription info when available + if (state.current.id != null) { + debugPrint('🔔 ✅ Device successfully subscribed!'); + } + }); + + // Add notification permission observer + OneSignal.Notifications.addPermissionObserver((isGranted) { + debugPrint('🔔 Notification permission changed: $isGranted'); + }); + + // Request permission - TRUE to show the native permission prompt + final accepted = await OneSignal.Notifications.requestPermission(true); + debugPrint('🔔 Permission request result: $accepted'); + + // Give OneSignal SDK time to complete initialization and server registration + // This is necessary because the subscription happens asynchronously + await Future.delayed(const Duration(seconds: 2)); + + // Check current subscription status after initialization completes + final optedIn = OneSignal.User.pushSubscription.optedIn; + final id = OneSignal.User.pushSubscription.id; + final token = OneSignal.User.pushSubscription.token; + + debugPrint('🔔 Current subscription status (after delay):'); + debugPrint(' Opted In: $optedIn'); + debugPrint(' Subscription ID: $id'); + debugPrint(' Push Token: $token'); + + if (id == null) { + debugPrint('🔔 ⚠️ Subscription ID is still null - check device connectivity and OneSignal app ID'); + } + // Run the app with Riverpod ProviderScope runApp(const ProviderScope(child: WorkerApp())); } catch (error, stackTrace) { diff --git a/pubspec.lock b/pubspec.lock index 8205081..70718df 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -964,6 +964,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + onesignal_flutter: + dependency: "direct main" + description: + name: onesignal_flutter + sha256: b5bb43bf496ddb5e3975ba54c6477cc2d1fcd18fb3698f195d2e0bfd376ddafd + url: "https://pub.dev" + source: hosted + version: "5.3.4" open_file: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 414a7cc..0c51038 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.1+15 +version: 1.0.1+16 environment: sdk: ^3.10.0 @@ -78,6 +78,7 @@ dependencies: shared_preferences: ^2.2.3 flutter_secure_storage: ^9.2.4 + onesignal_flutter: ^5.3.4 # Navigation go_router: ^14.6.2