feat(firebase): add production config and push token refresh listener
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"project_info": {
|
||||||
|
"project_number": "950566980029",
|
||||||
|
"project_id": "sf-platform-pro",
|
||||||
|
"storage_bucket": "sf-platform-pro.firebasestorage.app"
|
||||||
|
},
|
||||||
|
"client": [
|
||||||
|
{
|
||||||
|
"client_info": {
|
||||||
|
"mobilesdk_app_id": "1:950566980029:android:75a7c10b6259d09681aad4",
|
||||||
|
"android_client_info": {
|
||||||
|
"package_name": "com.savefamily.app"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"oauth_client": [],
|
||||||
|
"api_key": [
|
||||||
|
{
|
||||||
|
"current_key": "AIzaSyDkjNdOAK0ype7wgdgiC1BCKV_pP4s_mlA"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"services": {
|
||||||
|
"appinvite_service": {
|
||||||
|
"other_platform_oauth_client": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"configuration_version": "1"
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"env": "production",
|
"env": "production",
|
||||||
"apiBaseUrl": "https://api-neki-b2b.neki.es/gateway/api/",
|
"apiBaseUrl": "https://platform.savefamily.app/gateway/api/",
|
||||||
"apiOrigin": "https://neki-b2b.neki.es",
|
"apiOrigin": "https://api-platform.savefamily.app/",
|
||||||
"wsUrl": "wss://api-neki-b2b.neki.es/websocket"
|
"wsUrl": "wss://api-platform.savefamily.app/websocket"
|
||||||
}
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"sf-platform-pre","appId":"1:535646668726:android:b87245b807258e3e5e6317","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"sf-platform-pre","appId":"1:535646668726:ios:5172d626d02dfe215e6317","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options_dev.dart":{"projectId":"sf-platform-pre","configurations":{"android":"1:535646668726:android:c3a09d6c26f0cdf95e6317","ios":"1:535646668726:ios:524afa641f61d7cb5e6317"}},"lib/firebase_options_staging.dart":{"projectId":"sf-platform-pre","configurations":{"android":"1:535646668726:android:b87245b807258e3e5e6317","ios":"1:535646668726:ios:5172d626d02dfe215e6317"}}}}}}
|
{"flutter":{"platforms":{"android":{"default":{"projectId":"sf-platform-pre","appId":"1:535646668726:android:b87245b807258e3e5e6317","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"sf-platform-pre","appId":"1:535646668726:ios:5172d626d02dfe215e6317","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options_dev.dart":{"projectId":"sf-platform-pre","configurations":{"android":"1:535646668726:android:c3a09d6c26f0cdf95e6317","ios":"1:535646668726:ios:524afa641f61d7cb5e6317"}},"lib/firebase_options_staging.dart":{"projectId":"sf-platform-pre","configurations":{"android":"1:535646668726:android:b87245b807258e3e5e6317","ios":"1:535646668726:ios:5172d626d02dfe215e6317"}},"lib/firebase_options_prod.dart":{"projectId":"sf-platform-pro","configurations":{"android":"1:950566980029:android:75a7c10b6259d09681aad4","ios":"1:950566980029:ios:987b4f0b9e9b897481aad4"}}}}}}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>API_KEY</key>
|
||||||
|
<string>AIzaSyC0_d7Z6uVHHKhaf7JHRROaY6g2mvvpOXU</string>
|
||||||
|
<key>GCM_SENDER_ID</key>
|
||||||
|
<string>950566980029</string>
|
||||||
|
<key>PLIST_VERSION</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>BUNDLE_ID</key>
|
||||||
|
<string>com.savefamily.app</string>
|
||||||
|
<key>PROJECT_ID</key>
|
||||||
|
<string>sf-platform-pro</string>
|
||||||
|
<key>STORAGE_BUCKET</key>
|
||||||
|
<string>sf-platform-pro.firebasestorage.app</string>
|
||||||
|
<key>IS_ADS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_ANALYTICS_ENABLED</key>
|
||||||
|
<false></false>
|
||||||
|
<key>IS_APPINVITE_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_GCM_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>IS_SIGNIN_ENABLED</key>
|
||||||
|
<true></true>
|
||||||
|
<key>GOOGLE_APP_ID</key>
|
||||||
|
<string>1:950566980029:ios:987b4f0b9e9b897481aad4</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -7,6 +7,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
|
|
||||||
import '../config/env/environment_enum.dart';
|
import '../config/env/environment_enum.dart';
|
||||||
import '../firebase_options_dev.dart' as dev_options;
|
import '../firebase_options_dev.dart' as dev_options;
|
||||||
|
import '../firebase_options_prod.dart' as prod_options;
|
||||||
import '../firebase_options_staging.dart' as staging_options;
|
import '../firebase_options_staging.dart' as staging_options;
|
||||||
import 'app_version_check/remote_config_keys.dart';
|
import 'app_version_check/remote_config_keys.dart';
|
||||||
|
|
||||||
@@ -18,12 +19,7 @@ Future<void> setupFirebase(EnvironmentEnum env) async {
|
|||||||
case EnvironmentEnum.staging:
|
case EnvironmentEnum.staging:
|
||||||
options = staging_options.DefaultFirebaseOptions.currentPlatform;
|
options = staging_options.DefaultFirebaseOptions.currentPlatform;
|
||||||
case EnvironmentEnum.production:
|
case EnvironmentEnum.production:
|
||||||
// TODO: replace with prod_options.DefaultFirebaseOptions.currentPlatform
|
options = prod_options.DefaultFirebaseOptions.currentPlatform;
|
||||||
// once the production Firebase project is created.
|
|
||||||
throw UnsupportedError(
|
|
||||||
'Production Firebase project is not configured yet. '
|
|
||||||
'Run `flutterfire configure --project=<prod-project-id>` and import it here.',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await Firebase.initializeApp(options: options);
|
await Firebase.initializeApp(options: options);
|
||||||
@@ -54,7 +50,7 @@ Future<void> setupFirebase(EnvironmentEnum env) async {
|
|||||||
RemoteConfigKeys.latestBuild: 0,
|
RemoteConfigKeys.latestBuild: 0,
|
||||||
RemoteConfigKeys.updateForce: false,
|
RemoteConfigKeys.updateForce: false,
|
||||||
RemoteConfigKeys.updateMessage: '',
|
RemoteConfigKeys.updateMessage: '',
|
||||||
RemoteConfigKeys.updateUrlIos: 'https://apps.apple.com/app/id6759873957',
|
RemoteConfigKeys.updateUrlIos: 'https://apps.apple.com/app/id6759875039',
|
||||||
RemoteConfigKeys.updateUrlAndroid:
|
RemoteConfigKeys.updateUrlAndroid:
|
||||||
'https://play.google.com/store/apps/details?id=com.savefamily.app',
|
'https://play.google.com/store/apps/details?id=com.savefamily.app',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -56,11 +56,6 @@ Future<void> setupNotifications() async {
|
|||||||
_onMessageOpenedApp(initialMessage);
|
_onMessageOpenedApp(initialMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: integrate with backend (Treezor/SaveFamily api).
|
|
||||||
messaging.onTokenRefresh.listen((newToken) {
|
|
||||||
debugPrint('[FCM] token refreshed: $newToken');
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final token = await messaging.getToken();
|
final token = await messaging.getToken();
|
||||||
debugPrint('[FCM] initial token: $token');
|
debugPrint('[FCM] initial token: $token');
|
||||||
|
|||||||
68
apps/mobile_app/lib/firebase_options_prod.dart
Normal file
68
apps/mobile_app/lib/firebase_options_prod.dart
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
// 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_prod.dart';
|
||||||
|
/// // ...
|
||||||
|
/// await Firebase.initializeApp(
|
||||||
|
/// options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
class DefaultFirebaseOptions {
|
||||||
|
static FirebaseOptions get currentPlatform {
|
||||||
|
if (kIsWeb) {
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for web - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
switch (defaultTargetPlatform) {
|
||||||
|
case TargetPlatform.android:
|
||||||
|
return android;
|
||||||
|
case TargetPlatform.iOS:
|
||||||
|
return ios;
|
||||||
|
case TargetPlatform.macOS:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for macos - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
case TargetPlatform.windows:
|
||||||
|
throw UnsupportedError(
|
||||||
|
'DefaultFirebaseOptions have not been configured for windows - '
|
||||||
|
'you can reconfigure this by running the FlutterFire CLI again.',
|
||||||
|
);
|
||||||
|
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 android = FirebaseOptions(
|
||||||
|
apiKey: 'AIzaSyDkjNdOAK0ype7wgdgiC1BCKV_pP4s_mlA',
|
||||||
|
appId: '1:950566980029:android:75a7c10b6259d09681aad4',
|
||||||
|
messagingSenderId: '950566980029',
|
||||||
|
projectId: 'sf-platform-pro',
|
||||||
|
storageBucket: 'sf-platform-pro.firebasestorage.app',
|
||||||
|
);
|
||||||
|
|
||||||
|
static const FirebaseOptions ios = FirebaseOptions(
|
||||||
|
apiKey: 'AIzaSyC0_d7Z6uVHHKhaf7JHRROaY6g2mvvpOXU',
|
||||||
|
appId: '1:950566980029:ios:987b4f0b9e9b897481aad4',
|
||||||
|
messagingSenderId: '950566980029',
|
||||||
|
projectId: 'sf-platform-pro',
|
||||||
|
storageBucket: 'sf-platform-pro.firebasestorage.app',
|
||||||
|
iosBundleId: 'com.savefamily.app',
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:auth/auth.dart';
|
import 'package:auth/auth.dart';
|
||||||
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@@ -72,6 +73,9 @@ class SaveFamilyAppState extends ConsumerState<SaveFamilyApp>
|
|||||||
_walletHeartbeat?.stop();
|
_walletHeartbeat?.stop();
|
||||||
_legacyHeartbeat?.stop();
|
_legacyHeartbeat?.stop();
|
||||||
_webSocket?.disconnect();
|
_webSocket?.disconnect();
|
||||||
|
FirebaseMessaging.instance.deleteToken().catchError((Object e) {
|
||||||
|
debugPrint('[FCM] deleteToken on logout failed: $e');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,6 +128,7 @@ class SaveFamilyAppState extends ConsumerState<SaveFamilyApp>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
SizeUtils.init(context: context);
|
SizeUtils.init(context: context);
|
||||||
|
ref.watch(pushTokenRefreshListenerProvider);
|
||||||
|
|
||||||
return AppUpdateGate(
|
return AppUpdateGate(
|
||||||
child: MaterialApp.router(
|
child: MaterialApp.router(
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export 'src/data/datasource/user_remote_datasource_impl.dart';
|
|||||||
export 'src/data/datasource/notifications_remote_datasource.dart';
|
export 'src/data/datasource/notifications_remote_datasource.dart';
|
||||||
export 'src/data/datasource/notifications_remote_datasource_impl.dart';
|
export 'src/data/datasource/notifications_remote_datasource_impl.dart';
|
||||||
export 'src/providers/notifications_remote_datasource_provider.dart';
|
export 'src/providers/notifications_remote_datasource_provider.dart';
|
||||||
|
export 'src/providers/push_token_refresh_listener_provider.dart';
|
||||||
export 'src/domain/entities/beneficiary_validation_entity.dart';
|
export 'src/domain/entities/beneficiary_validation_entity.dart';
|
||||||
export 'src/domain/entities/transaction_beneficiary_entity.dart';
|
export 'src/domain/entities/transaction_beneficiary_entity.dart';
|
||||||
export 'src/data/models/payout_beneficiary_model.dart';
|
export 'src/data/models/payout_beneficiary_model.dart';
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
|
||||||
|
import 'notifications_remote_datasource_provider.dart';
|
||||||
|
|
||||||
|
final pushTokenRefreshListenerProvider = Provider<void>((ref) {
|
||||||
|
final datasource = ref.watch(notificationsRemoteDatasourceProvider);
|
||||||
|
final subscription = FirebaseMessaging.instance.onTokenRefresh.listen((
|
||||||
|
newToken,
|
||||||
|
) async {
|
||||||
|
try {
|
||||||
|
await datasource.registerPushToken(newToken);
|
||||||
|
debugPrint('[FCM] token refreshed and re-registered: $newToken');
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[FCM] token refresh re-register failed: $e');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ref.onDispose(subscription.cancel);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user