From 525079a52fa1e3b092cbfa6359dd398b0fa47ed8 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 1 May 2025 00:47:40 +0800 Subject: [PATCH] :sparkles: Push notification :bricks: Added firebase --- android/app/build.gradle.kts | 3 + android/app/google-services.json | 29 +++++ android/settings.gradle.kts | 3 + firebase.json | 1 + ios/Podfile.lock | 101 ++++++++++++++++++ ios/Runner.xcodeproj/project.pbxproj | 22 ++++ ios/Runner/GoogleService-Info.plist | 30 ++++++ lib/firebase_options.dart | 88 +++++++++++++++ lib/main.dart | 14 ++- lib/screens/auth/login.dart | 21 +++- lib/services/notify.dart | 54 ++++++++++ linux/flutter/generated_plugin_registrant.cc | 4 + linux/flutter/generated_plugins.cmake | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 6 ++ macos/Runner.xcodeproj/project.pbxproj | 4 + macos/Runner/GoogleService-Info.plist | 30 ++++++ pubspec.lock | 64 +++++++++++ pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 6 ++ windows/flutter/generated_plugins.cmake | 2 + 20 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 android/app/google-services.json create mode 100644 firebase.json create mode 100644 ios/Runner/GoogleService-Info.plist create mode 100644 lib/firebase_options.dart create mode 100644 lib/services/notify.dart create mode 100644 macos/Runner/GoogleService-Info.plist diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index ce149b9..fb709ee 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,5 +1,8 @@ plugins { id("com.android.application") + // START: FlutterFire Configuration + id("com.google.gms.google-services") + // END: FlutterFire Configuration id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..60ae7d5 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "961776991058", + "project_id": "solian-0x001", + "storage_bucket": "solian-0x001.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:961776991058:android:a8d3f7995b0b8e86f4188b", + "android_client_info": { + "package_name": "dev.solsynth.solian" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDvFNudXYs29uDtcCv6pFR8h5tXBs90FYk" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index a439442..9e2d35c 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -19,6 +19,9 @@ pluginManagement { plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "8.7.0" apply false + // START: FlutterFire Configuration + id("com.google.gms.google-services") version("4.3.15") apply false + // END: FlutterFire Configuration id("org.jetbrains.kotlin.android") version "1.8.22" apply false } diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..9db83b1 --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:android:a8d3f7995b0b8e86f4188b","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"solian-0x001","configurations":{"android":"1:961776991058:android:a8d3f7995b0b8e86f4188b","ios":"1:961776991058:ios:727229d368cc47e1f4188b","macos":"1:961776991058:ios:727229d368cc47e1f4188b","web":"1:961776991058:web:b91d12f2892a5609f4188b","windows":"1:961776991058:web:3a912c0eb14028e5f4188b"}}}}}} \ No newline at end of file diff --git a/ios/Podfile.lock b/ios/Podfile.lock index aa1211b..d5cb8fe 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -35,6 +35,38 @@ PODS: - file_picker (0.0.1): - DKImagePickerController/PhotoGallery - Flutter + - Firebase/CoreOnly (11.10.0): + - FirebaseCore (~> 11.10.0) + - Firebase/Messaging (11.10.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 11.10.0) + - firebase_core (3.13.0): + - Firebase/CoreOnly (= 11.10.0) + - Flutter + - firebase_messaging (15.2.5): + - Firebase/Messaging (= 11.10.0) + - firebase_core + - Flutter + - FirebaseCore (11.10.0): + - FirebaseCoreInternal (~> 11.10.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Logger (~> 8.0) + - FirebaseCoreInternal (11.10.0): + - "GoogleUtilities/NSData+zlib (~> 8.0)" + - FirebaseInstallations (11.10.0): + - FirebaseCore (~> 11.10.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - PromisesObjC (~> 2.4) + - FirebaseMessaging (11.10.0): + - FirebaseCore (~> 11.10.0) + - FirebaseInstallations (~> 11.0) + - GoogleDataTransport (~> 10.0) + - GoogleUtilities/AppDelegateSwizzler (~> 8.0) + - GoogleUtilities/Environment (~> 8.0) + - GoogleUtilities/Reachability (~> 8.0) + - GoogleUtilities/UserDefaults (~> 8.0) + - nanopb (~> 3.30910.0) - Flutter (1.0.0) - flutter_inappwebview_ios (0.0.1): - Flutter @@ -45,6 +77,36 @@ PODS: - OrderedSet (~> 6.0.3) - flutter_platform_alert (0.0.1): - Flutter + - flutter_udid (0.0.1): + - Flutter + - SAMKeychain + - GoogleDataTransport (10.1.0): + - nanopb (~> 3.30910.0) + - PromisesObjC (~> 2.4) + - GoogleUtilities/AppDelegateSwizzler (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (8.0.2): + - GoogleUtilities/Privacy + - GoogleUtilities/Logger (8.0.2): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (8.0.2): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (8.0.2)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (8.0.2) + - GoogleUtilities/Reachability (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (8.0.2): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy - image_picker_ios (0.0.1): - Flutter - irondash_engine_context (0.0.1): @@ -54,12 +116,19 @@ PODS: - Flutter - media_kit_video (0.0.1): - Flutter + - nanopb (3.30910.0): + - nanopb/decode (= 3.30910.0) + - nanopb/encode (= 3.30910.0) + - nanopb/decode (3.30910.0) + - nanopb/encode (3.30910.0) - OrderedSet (6.0.3) - package_info_plus (0.4.5): - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS + - PromisesObjC (2.4.0) + - SAMKeychain (1.5.3) - SDWebImage (5.21.0): - SDWebImage/Core (= 5.21.0) - SDWebImage/Core (5.21.0) @@ -82,9 +151,12 @@ PODS: DEPENDENCIES: - device_info_plus (from `.symlinks/plugins/device_info_plus/ios`) - file_picker (from `.symlinks/plugins/file_picker/ios`) + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - Flutter (from `Flutter`) - flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`) - flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`) + - flutter_udid (from `.symlinks/plugins/flutter_udid/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`) - Kingfisher (~> 8.0) @@ -103,8 +175,18 @@ SPEC REPOS: trunk: - DKImagePickerController - DKPhotoGallery + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - GoogleDataTransport + - GoogleUtilities - Kingfisher + - nanopb - OrderedSet + - PromisesObjC + - SAMKeychain - SDWebImage - SwiftyGif @@ -113,12 +195,18 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/device_info_plus/ios" file_picker: :path: ".symlinks/plugins/file_picker/ios" + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" Flutter: :path: Flutter flutter_inappwebview_ios: :path: ".symlinks/plugins/flutter_inappwebview_ios/ios" flutter_platform_alert: :path: ".symlinks/plugins/flutter_platform_alert/ios" + flutter_udid: + :path: ".symlinks/plugins/flutter_udid/ios" image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" irondash_engine_context: @@ -149,17 +237,30 @@ SPEC CHECKSUMS: DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60 file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be + Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2 + firebase_core: 2d4534e7b489907dcede540c835b48981d890943 + firebase_messaging: 75bc93a4df25faccad67f6662ae872ac9ae69b64 + FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7 + FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679 + FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3 + FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9 Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99 flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3 + flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9 + GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7 + GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486 Kingfisher: 3204d23de16b5ea53541c44ca5a8efb55741dec3 media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854 media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474 + nanopb: fad817b59e0457d11a5dfbde799381cd727c1275 OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94 package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499 path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868 shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7 sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index e8e0fef..e0f2f4d 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; }; + E7A0B456EF7AAA71D1397081 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9AE244813FCDFAA941430393 /* GoogleService-Info.plist */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -63,6 +64,7 @@ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 9AE244813FCDFAA941430393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; E6B10A9A85BECA2E576C91FF /* 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 = ""; }; F6D834CA86410B09796B312B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -138,6 +140,7 @@ 331C8082294A63A400263BE5 /* RunnerTests */, 91E124CE95BCB4DCD890160D /* Pods */, 498A09270B73B217F0279168 /* Frameworks */, + 9AE244813FCDFAA941430393 /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -200,6 +203,7 @@ 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */, + 5E7D6EF29B671AC7EDBA5649 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -265,6 +269,7 @@ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + E7A0B456EF7AAA71D1397081 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -309,6 +314,23 @@ 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; }; + 5E7D6EF29B671AC7EDBA5649 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; 8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/ios/Runner/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..3a05755 --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8 + GCM_SENDER_ID + 961776991058 + PLIST_VERSION + 1 + BUNDLE_ID + dev.solsynth.solian + PROJECT_ID + solian-0x001 + STORAGE_BUCKET + solian-0x001.firebasestorage.app + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:961776991058:ios:727229d368cc47e1f4188b + + \ No newline at end of file diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..836f56d --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,88 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + return web; + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + return macos; + case TargetPlatform.windows: + return windows; + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions web = FirebaseOptions( + apiKey: 'AIzaSyBKfIQpTouj5rXnlzkEieSlbAzepm4mgJE', + appId: '1:961776991058:web:b91d12f2892a5609f4188b', + messagingSenderId: '961776991058', + projectId: 'solian-0x001', + authDomain: 'solian-0x001.firebaseapp.com', + storageBucket: 'solian-0x001.firebasestorage.app', + measurementId: 'G-XY3HHKG0PE', + ); + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyDvFNudXYs29uDtcCv6pFR8h5tXBs90FYk', + appId: '1:961776991058:android:a8d3f7995b0b8e86f4188b', + messagingSenderId: '961776991058', + projectId: 'solian-0x001', + storageBucket: 'solian-0x001.firebasestorage.app', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8', + appId: '1:961776991058:ios:727229d368cc47e1f4188b', + messagingSenderId: '961776991058', + projectId: 'solian-0x001', + storageBucket: 'solian-0x001.firebasestorage.app', + iosBundleId: 'dev.solsynth.solian', + ); + + static const FirebaseOptions macos = FirebaseOptions( + apiKey: 'AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8', + appId: '1:961776991058:ios:727229d368cc47e1f4188b', + messagingSenderId: '961776991058', + projectId: 'solian-0x001', + storageBucket: 'solian-0x001.firebasestorage.app', + iosBundleId: 'dev.solsynth.solian', + ); + + static const FirebaseOptions windows = FirebaseOptions( + apiKey: 'AIzaSyCfgOdlcr7h8x8j0WKx_S2wXnGkOopq320', + appId: '1:961776991058:web:3a912c0eb14028e5f4188b', + messagingSenderId: '961776991058', + projectId: 'solian-0x001', + authDomain: 'solian-0x001.firebaseapp.com', + storageBucket: 'solian-0x001.firebasestorage.app', + measurementId: 'G-JD1YEG9D6F', + ); +} diff --git a/lib/main.dart b/lib/main.dart index 75de821..9737c50 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,16 +1,20 @@ import 'dart:io'; import 'package:easy_localization/easy_localization.dart' hide TextDirection; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:image_picker_android/image_picker_android.dart'; +import 'package:island/firebase_options.dart'; import 'package:island/pods/config.dart'; +import 'package:island/pods/network.dart'; import 'package:island/pods/theme.dart'; import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:island/pods/userinfo.dart'; import 'package:island/route.dart'; +import 'package:island/services/notify.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:image_picker_platform_interface/image_picker_platform_interface.dart'; @@ -18,6 +22,8 @@ import 'package:image_picker_platform_interface/image_picker_platform_interface. void main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + final prefs = await SharedPreferences.getInstance(); if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) { @@ -68,7 +74,13 @@ class IslandApp extends HookConsumerWidget { // Load userinfo final userNotifier = ref.read(userInfoProvider.notifier); Future(() { - userNotifier.fetchUser(); + userNotifier.fetchUser().then((_) { + final user = ref.watch(userInfoProvider); + if (user.hasValue) { + final apiClient = ref.read(apiClientProvider); + subscribePushNotification(apiClient); + } + }); }); return null; }, []); diff --git a/lib/screens/auth/login.dart b/lib/screens/auth/login.dart index aaac719..36d0fb1 100644 --- a/lib/screens/auth/login.dart +++ b/lib/screens/auth/login.dart @@ -1,14 +1,17 @@ import 'package:animations/animations.dart'; import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_udid/flutter_udid.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:gap/gap.dart'; import 'package:island/models/auth.dart'; import 'package:island/pods/config.dart'; import 'package:island/pods/network.dart'; import 'package:island/pods/userinfo.dart'; +import 'package:island/services/notify.dart'; import 'package:island/widgets/alert.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:lucide_icons/lucide_icons.dart'; @@ -130,7 +133,10 @@ class _LoginCheckScreen extends HookConsumerWidget { ref.invalidate(tokenPairProvider); if (!context.mounted) return; final userNotifier = ref.read(userInfoProvider.notifier); - userNotifier.fetchUser(); + userNotifier.fetchUser().then((_) { + final apiClient = ref.read(apiClientProvider); + subscribePushNotification(apiClient); + }); Navigator.pop(context, true); } catch (err) { showErrorAlert(err); @@ -355,7 +361,18 @@ class _LoginLookupScreen extends HookConsumerWidget { final client = ref.watch(apiClientProvider); final resp = await client.post( '/auth/challenge', - data: {'account': uname}, + data: { + 'account': uname, + 'device_id': await FlutterUdid.consistentUdid, + 'platform': switch (defaultTargetPlatform) { + TargetPlatform.iOS => 2, + TargetPlatform.android => 3, + TargetPlatform.macOS => 4, + TargetPlatform.windows => 5, + TargetPlatform.linux => 6, + _ => 1, + }, + }, ); final result = SnAuthChallenge.fromJson(resp.data); onChallenge(result); diff --git a/lib/services/notify.dart b/lib/services/notify.dart new file mode 100644 index 0000000..4d75d98 --- /dev/null +++ b/lib/services/notify.dart @@ -0,0 +1,54 @@ +import 'dart:developer'; +import 'dart:io'; + +import 'package:dio/dio.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; + +Future subscribePushNotification(Dio apiClient) async { + await FirebaseMessaging.instance.requestPermission( + provisional: true, + alert: true, + badge: true, + sound: true, + ); + + String? deviceToken; + if (kIsWeb) { + deviceToken = await FirebaseMessaging.instance.getToken( + vapidKey: + "BFN2mkqyeI6oi4d2PAV4pfNyG3Jy0FBEblmmPrjmP0r5lHOPrxrcqLIWhM21R_cicF-j4Xhtr1kyDyDgJYRPLgU", + ); + } else if (Platform.isAndroid) { + deviceToken = await FirebaseMessaging.instance.getToken(); + } else if (Platform.isIOS) { + deviceToken = await FirebaseMessaging.instance.getAPNSToken(); + } + + FirebaseMessaging.instance.onTokenRefresh + .listen((fcmToken) { + _putTokenToRemote(apiClient, fcmToken, 1); + }) + .onError((err) { + log("Failed to get firebase cloud messaging push token: $err"); + }); + + if (deviceToken != null) { + _putTokenToRemote( + apiClient, + deviceToken, + !kIsWeb && (Platform.isIOS || Platform.isMacOS) ? 0 : 1, + ); + } +} + +Future _putTokenToRemote( + Dio apiClient, + String token, + int provider, +) async { + await apiClient.put( + "/notifications/subscription", + data: {"provider": provider, "device_token": token}, + ); +} diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index a9e61fe..aebd246 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_platform_alert_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterPlatformAlertPlugin"); flutter_platform_alert_plugin_register_with_registrar(flutter_platform_alert_registrar); + g_autoptr(FlPluginRegistrar) flutter_udid_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterUdidPlugin"); + flutter_udid_plugin_register_with_registrar(flutter_udid_registrar); g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin"); irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 533c9d2..3460c6a 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST bitsdojo_window_linux file_selector_linux flutter_platform_alert + flutter_udid irondash_engine_context media_kit_libs_linux media_kit_video diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index d56d620..b0b8b04 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -9,8 +9,11 @@ import bitsdojo_window_macos import device_info_plus import file_picker import file_selector_macos +import firebase_core +import firebase_messaging import flutter_inappwebview_macos import flutter_platform_alert +import flutter_udid import irondash_engine_context import media_kit_libs_macos_video import media_kit_video @@ -28,8 +31,11 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) InAppWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "InAppWebViewFlutterPlugin")) FlutterPlatformAlertPlugin.register(with: registry.registrar(forPlugin: "FlutterPlatformAlertPlugin")) + FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) IrondashEngineContextPlugin.register(with: registry.registrar(forPlugin: "IrondashEngineContextPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj index 47ddd93..849d4fa 100644 --- a/macos/Runner.xcodeproj/project.pbxproj +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; 81323E2800290FDA28F313ED /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 99A9898F9135B8B94E49BD2B /* Pods_Runner.framework */; }; + B48F10F93F6AB0C5490C5A07 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B48604B824333A68BCFDF84A /* GoogleService-Info.plist */; }; C2C92AFDE3C1A59CFAF66C7C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DEA64C50BF85AF58D10A213 /* Pods_RunnerTests.framework */; }; /* End PBXBuildFile section */ @@ -87,6 +88,7 @@ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; 97CE52E8413D7559BF9A7981 /* 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 = ""; }; 99A9898F9135B8B94E49BD2B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B48604B824333A68BCFDF84A /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; F6041FCC584315C5E2F0D644 /* 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 = ""; }; /* End PBXFileReference section */ @@ -152,6 +154,7 @@ 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, 1E2C06C8D492360A80ECF35F /* Pods */, + B48604B824333A68BCFDF84A /* GoogleService-Info.plist */, ); sourceTree = ""; }; @@ -317,6 +320,7 @@ files = ( 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + B48F10F93F6AB0C5490C5A07 /* GoogleService-Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/macos/Runner/GoogleService-Info.plist b/macos/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..3a05755 --- /dev/null +++ b/macos/Runner/GoogleService-Info.plist @@ -0,0 +1,30 @@ + + + + + API_KEY + AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8 + GCM_SENDER_ID + 961776991058 + PLIST_VERSION + 1 + BUNDLE_ID + dev.solsynth.solian + PROJECT_ID + solian-0x001 + STORAGE_BUCKET + solian-0x001.firebasestorage.app + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:961776991058:ios:727229d368cc47e1f4188b + + \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index 8b153a7..f26bd8b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -9,6 +9,14 @@ packages: url: "https://pub.dev" source: hosted version: "80.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: de9ecbb3ddafd446095f7e833c853aff2fa1682b017921fe63a833f9d6f0e422 + url: "https://pub.dev" + source: hosted + version: "1.3.54" analyzer: dependency: transitive description: @@ -465,6 +473,54 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.3+4" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "017d17d9915670e6117497e640b2859e0b868026ea36bf3a57feb28c3b97debe" + url: "https://pub.dev" + source: hosted + version: "3.13.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf + url: "https://pub.dev" + source: hosted + version: "5.4.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "129a34d1e0fb62e2b488d988a1fc26cc15636357e50944ffee2862efe8929b23" + url: "https://pub.dev" + source: hosted + version: "2.22.0" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: "5f8918848ee0c8eb172fc7698619b2bcd7dda9ade8b93522c6297dd8f9178356" + url: "https://pub.dev" + source: hosted + version: "15.2.5" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "0bbea00680249595fc896e7313a2bd90bd55be6e0abbe8b9a39d81b6b306acb6" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: ffb392ce2a7e8439cd0a9a80e3c702194e73c927e5c7b4f0adf6faa00b245b17 + url: "https://pub.dev" + source: hosted + version: "3.10.5" fixnum: dependency: transitive description: @@ -648,6 +704,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_udid: + dependency: "direct main" + description: + name: flutter_udid + sha256: "166bee5989a58c66b8b62000ea65edccc7c8167bbafdbb08022638db330dd030" + url: "https://pub.dev" + source: hosted + version: "4.0.0" flutter_web_plugins: dependency: transitive description: flutter diff --git a/pubspec.yaml b/pubspec.yaml index fa7d90e..9df4371 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -80,6 +80,9 @@ dependencies: image_picker_android: ^0.8.12+23 super_context_menu: ^0.9.0-dev.6 modal_bottom_sheet: ^3.0.0 + firebase_messaging: ^15.2.5 + flutter_udid: ^4.0.0 + firebase_core: ^3.13.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index c042a7f..c368584 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -8,8 +8,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -22,10 +24,14 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("BitsdojoWindowPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); FlutterInappwebviewWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterInappwebviewWindowsPluginCApi")); FlutterPlatformAlertPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterPlatformAlertPlugin")); + FlutterUdidPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterUdidPluginCApi")); IrondashEngineContextPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("IrondashEngineContextPluginCApi")); MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index ac6339c..7b03623 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -5,8 +5,10 @@ list(APPEND FLUTTER_PLUGIN_LIST bitsdojo_window_windows file_selector_windows + firebase_core flutter_inappwebview_windows flutter_platform_alert + flutter_udid irondash_engine_context media_kit_libs_windows_video media_kit_video