diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index df5e935..4cff67f 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -23,6 +23,8 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'com.android.application' +apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { @@ -43,7 +45,7 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.example.mobile" + applicationId "com.envelope.envelope" minSdkVersion 20 targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() @@ -65,4 +67,5 @@ flutter { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation platform('com.google.firebase:firebase-bom:31.0.2') } diff --git a/mobile/android/app/google-services.json b/mobile/android/app/google-services.json new file mode 100644 index 0000000..8bd44cb --- /dev/null +++ b/mobile/android/app/google-services.json @@ -0,0 +1,46 @@ +{ + "project_info": { + "project_number": "623758852972", + "project_id": "envelope-32eff", + "storage_bucket": "envelope-32eff.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:623758852972:android:af080c15b69efa00676949", + "android_client_info": { + "package_name": "com.envelope.envelope" + } + }, + "oauth_client": [ + { + "client_id": "623758852972-6ngjav8bc663ld3f04i6naoudlo88roa.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCwGtPho7BUI9AF8In216bDXU87cVpgdu0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "623758852972-6ngjav8bc663ld3f04i6naoudlo88roa.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "623758852972-7jdesrmtt4ccc7qvhpfpstdesf8rto2b.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.envelope.envelope" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/mobile/android/app/src/debug/AndroidManifest.xml b/mobile/android/app/src/debug/AndroidManifest.xml index 4e87af5..f0e79f1 100644 --- a/mobile/android/app/src/debug/AndroidManifest.xml +++ b/mobile/android/app/src/debug/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.envelope.envelope"> diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index c3bfaaa..54b46fd 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,5 @@ + package="com.envelope.envelope"> + package="com.envelope.envelope"> diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle index 4256f91..605b64d 100644 --- a/mobile/android/build.gradle +++ b/mobile/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath 'com.google.gms:google-services:4.3.13' } } diff --git a/mobile/ios/GoogleService-Info.plist b/mobile/ios/GoogleService-Info.plist new file mode 100644 index 0000000..c00408d --- /dev/null +++ b/mobile/ios/GoogleService-Info.plist @@ -0,0 +1,34 @@ + + + + + CLIENT_ID + 623758852972-7jdesrmtt4ccc7qvhpfpstdesf8rto2b.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.623758852972-7jdesrmtt4ccc7qvhpfpstdesf8rto2b + API_KEY + AIzaSyC__tcjbseK6Sc8Db1RzClKWe7FoD7uFLY + GCM_SENDER_ID + 623758852972 + PLIST_VERSION + 1 + BUNDLE_ID + com.envelope.envelope + PROJECT_ID + envelope-32eff + STORAGE_BUCKET + envelope-32eff.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:623758852972:ios:1a410e5ca6d16e3a676949 + + \ No newline at end of file diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 85e330e..8bc256b 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -1,13 +1,72 @@ PODS: + - Firebase/CoreOnly (10.0.0): + - FirebaseCore (= 10.0.0) + - Firebase/Messaging (10.0.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.0.0) + - firebase_core (2.1.1): + - Firebase/CoreOnly (= 10.0.0) + - Flutter + - firebase_messaging (14.0.3): + - Firebase/Messaging (= 10.0.0) + - firebase_core + - Flutter + - FirebaseCore (10.0.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Logger (~> 7.8) + - FirebaseCoreInternal (10.1.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.1.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.0.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.2) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30910.0, >= 2.30908.0) - Flutter (1.0.0) - FMDB (2.7.5): - FMDB/standard (= 2.7.5) - FMDB/standard (2.7.5) + - GoogleDataTransport (9.2.0): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30910.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/AppDelegateSwizzler (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Environment (7.8.0): + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.8.0): + - GoogleUtilities/Environment + - GoogleUtilities/Network (7.8.0): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.8.0)" + - GoogleUtilities/Reachability (7.8.0): + - GoogleUtilities/Logger + - GoogleUtilities/UserDefaults (7.8.0): + - GoogleUtilities/Logger - image_picker_ios (0.0.1): - Flutter - MTBBarcodeScanner (5.0.11) + - nanopb (2.30909.0): + - nanopb/decode (= 2.30909.0) + - nanopb/encode (= 2.30909.0) + - nanopb/decode (2.30909.0) + - nanopb/encode (2.30909.0) - path_provider_ios (0.0.1): - Flutter + - PromisesObjC (2.1.1) - qr_code_scanner (0.2.0): - Flutter - MTBBarcodeScanner @@ -18,6 +77,8 @@ PODS: - FMDB (>= 2.7.5) DEPENDENCIES: + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) - Flutter (from `Flutter`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) @@ -27,10 +88,23 @@ DEPENDENCIES: SPEC REPOS: trunk: + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging - FMDB + - GoogleDataTransport + - GoogleUtilities - MTBBarcodeScanner + - nanopb + - PromisesObjC EXTERNAL SOURCES: + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" Flutter: :path: Flutter image_picker_ios: @@ -45,11 +119,22 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/sqflite/ios" SPEC CHECKSUMS: + Firebase: 1b810f3d0c0532e27a48f1961f8c0400a668a2cf + firebase_core: 5c0bb0ca7d0e70480a68a6e9ad9bf55d1edd5305 + firebase_messaging: 46616a7ded661b632eb7a28846d906849c8b15af + FirebaseCore: 97f48a3a567a72b8d4daa0f03c3aadb78df4e995 + FirebaseCoreInternal: 96d75228e10fd369564da51bd898414eb0f54df5 + FirebaseInstallations: 99d24bac0243cf8b0e96cf5426340d211f0bcc80 + FirebaseMessaging: 8916bf5edb1dbfac74665a181e4d1ab3a78a08a2 Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854 FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + GoogleDataTransport: 1c8145da7117bd68bbbed00cf304edb6a24de00f + GoogleUtilities: 1d20a6ad97ef46f67bbdec158ce00563a671ebb7 image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb + nanopb: b552cce312b6c8484180ef47159bc0f65a1f0431 path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 + PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb qr_code_scanner: bb67d64904c3b9658ada8c402e8b4d406d5d796e shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index a3f5813..3d58784 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -3,12 +3,13 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 45E7864929111AAF004FB7E9 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 45E7864829111AAF004FB7E9 /* GoogleService-Info.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 7C176E8E73493FDFE1D7C309 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CA36B62CB085270A92E728 /* Pods_Runner.framework */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; @@ -34,6 +35,7 @@ 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 = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 45E7864829111AAF004FB7E9 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; 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 = ""; }; @@ -75,6 +77,7 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + 45E7864829111AAF004FB7E9 /* GoogleService-Info.plist */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, @@ -121,7 +124,6 @@ 7D2302AC69A24C6395A4B678 /* Pods-Runner.release.xcconfig */, E1FB47F20CF9808436BCAA60 /* Pods-Runner.profile.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -190,6 +192,7 @@ files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 45E7864929111AAF004FB7E9 /* GoogleService-Info.plist in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); @@ -362,7 +365,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile; + PRODUCT_BUNDLE_IDENTIFIER = com.envelope.envelope; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -490,7 +493,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile; + PRODUCT_BUNDLE_IDENTIFIER = com.envelope.envelope; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -512,7 +515,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.mobile; + PRODUCT_BUNDLE_IDENTIFIER = com.envelope.envelope; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_VERSION = 5.0; diff --git a/mobile/ios/Runner/GoogleService-Info.plist b/mobile/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..c00408d --- /dev/null +++ b/mobile/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,34 @@ + + + + + CLIENT_ID + 623758852972-7jdesrmtt4ccc7qvhpfpstdesf8rto2b.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.623758852972-7jdesrmtt4ccc7qvhpfpstdesf8rto2b + API_KEY + AIzaSyC__tcjbseK6Sc8Db1RzClKWe7FoD7uFLY + GCM_SENDER_ID + 623758852972 + PLIST_VERSION + 1 + BUNDLE_ID + com.envelope.envelope + PROJECT_ID + envelope-32eff + STORAGE_BUCKET + envelope-32eff.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:623758852972:ios:1a410e5ca6d16e3a676949 + + \ No newline at end of file diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart index daa8ffc..996da83 100644 --- a/mobile/lib/main.dart +++ b/mobile/lib/main.dart @@ -1,6 +1,9 @@ +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; +import 'package:overlay_support/overlay_support.dart'; import '/database/models/my_profile.dart'; import '/views/main/home.dart'; @@ -8,22 +11,78 @@ import '/views/authentication/unauthenticated_landing.dart'; import '/views/authentication/login.dart'; import '/views/authentication/signup.dart'; +class PushNotification { + PushNotification({ + this.title, + this.body, + this.dataTitle, + this.dataBody, + }); + + String? title; + String? body; + String? dataTitle; + String? dataBody; +} + void main() async { await dotenv.load(fileName: '.env'); // TODO: Replace this with the prod url when server is deployed MyProfile.setServerUrl(dotenv.env['SERVER_URL'] ?? 'http://localhost:8080/'); - runApp(const MyApp()); + runApp(MyApp()); } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + MyApp({Key? key}) : super(key: key); static const String _title = 'Envelope'; + late final FirebaseMessaging _messaging; + + void registerNotification() async { + await Firebase.initializeApp(); + + _messaging = FirebaseMessaging.instance; + + NotificationSettings settings = await _messaging.requestPermission( + alert: true, + badge: true, + provisional: false, + sound: true, + ); + + if (settings.authorizationStatus != AuthorizationStatus.authorized) { + print('User declined or has not accepted permission'); + return; + } + + print('User granted permission'); + + // For handling the received notifications + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // Parse the message received + PushNotification notification = PushNotification( + title: message.notification?.title, + body: message.notification?.body, + ); + + showSimpleNotification( + Text(notification.title!), + // leading: NotificationBadge(totalNotifications: _totalNotifications), + subtitle: Text(notification.body!), + background: Colors.cyan.shade700, + duration: const Duration(seconds: 2), + ); + }); + } + @override Widget build(BuildContext context) { + + registerNotification(); + return MaterialApp( title: _title, routes: { diff --git a/mobile/lib/views/main/home.dart b/mobile/lib/views/main/home.dart index 087d159..adc4935 100644 --- a/mobile/lib/views/main/home.dart +++ b/mobile/lib/views/main/home.dart @@ -1,11 +1,11 @@ -import 'package:Envelope/database/repositories/conversations_repository.dart'; -import 'package:Envelope/database/repositories/friends_repository.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '/database/models/conversations.dart'; import '/database/models/friends.dart'; import '/database/models/my_profile.dart'; +import '/database/repositories/conversations_repository.dart'; +import '/database/repositories/friends_repository.dart'; import '/services/conversations_service.dart'; import '/services/friends_service.dart'; import '/services/messages_service.dart'; diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 9567b65..17adaaa 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" asn1lib: dependency: "direct main" description: @@ -36,6 +43,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.1.1" + cloud_firestore_platform_interface: + dependency: transitive + description: + name: cloud_firestore_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.8.3" + cloud_firestore_web: + dependency: transitive + description: + name: cloud_firestore_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.3" collection: dependency: transitive description: @@ -92,6 +113,48 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.1.4" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.1" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.2" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + url: "https://pub.dartlang.org" + source: hosted + version: "14.0.3" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.4" flutter: dependency: "direct main" description: flutter @@ -226,6 +289,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.2" + overlay_support: + dependency: "direct main" + description: + name: overlay_support + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" path: dependency: "direct main" description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index dcb8af8..215aeab 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -27,6 +27,9 @@ dependencies: image_picker: ^0.8.5+3 path_provider: ^2.0.11 mime: ^1.0.2 + firebase_core: ^2.1.1 + firebase_messaging: ^14.0.3 + overlay_support: ^2.0.1 dev_dependencies: flutter_test: