preTesting
This commit is contained in:
@@ -1,8 +1,5 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
// START: FlutterFire Configuration
|
|
||||||
id("com.google.gms.google-services")
|
|
||||||
// END: FlutterFire Configuration
|
|
||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ pluginManagement {
|
|||||||
plugins {
|
plugins {
|
||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "8.7.0" apply false
|
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
|
id("org.jetbrains.kotlin.android") version "1.8.22" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,32 +1,83 @@
|
|||||||
import Flutter
|
import Flutter
|
||||||
import Firebase
|
|
||||||
import FirebaseMessaging
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import UserNotifications
|
||||||
|
|
||||||
|
// Mirrors LockInBroMobile/Services/NotificationService.swift: pure native APNs,
|
||||||
|
// no Firebase. The hex device token is forwarded to Dart over a MethodChannel
|
||||||
|
// (`blindmaster/apns`) which then POSTs it to /register_apns_token.
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate, UNUserNotificationCenterDelegate {
|
||||||
|
private var apnsChannel: FlutterMethodChannel?
|
||||||
|
private var pendingToken: String?
|
||||||
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
// Explicitly register for remote notifications on every launch so iOS always
|
UNUserNotificationCenter.current().delegate = self
|
||||||
// calls didRegisterForRemoteNotificationsWithDeviceToken, ensuring Firebase
|
// Trigger APNs registration on every launch so iOS calls
|
||||||
// receives a fresh APNs token regardless of whether permission was already granted.
|
// didRegisterForRemoteNotificationsWithDeviceToken with a fresh token.
|
||||||
application.registerForRemoteNotifications()
|
application.registerForRemoteNotifications()
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||||
|
|
||||||
|
let registrar = engineBridge.pluginRegistry.registrar(forPlugin: "BlindMasterApns")
|
||||||
|
let channel = FlutterMethodChannel(
|
||||||
|
name: "blindmaster/apns",
|
||||||
|
binaryMessenger: registrar.messenger()
|
||||||
|
)
|
||||||
|
channel.setMethodCallHandler { [weak self] call, result in
|
||||||
|
switch call.method {
|
||||||
|
case "requestPermission":
|
||||||
|
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
|
||||||
|
if let error = error { print("[APNs] permission error: \(error)") }
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
UIApplication.shared.registerForRemoteNotifications()
|
||||||
|
}
|
||||||
|
result(granted)
|
||||||
|
}
|
||||||
|
case "getToken":
|
||||||
|
result(self?.pendingToken)
|
||||||
|
default:
|
||||||
|
result(FlutterMethodNotImplemented)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
apnsChannel = channel
|
||||||
|
|
||||||
|
// If iOS already delivered the token before Dart attached the channel,
|
||||||
|
// flush it now so the upload still happens.
|
||||||
|
if let token = pendingToken {
|
||||||
|
channel.invokeMethod("onToken", arguments: token)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlutterImplicitEngineDelegate can interfere with Firebase's method swizzling,
|
|
||||||
// preventing it from capturing the APNs token. Forward it explicitly instead.
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
|
||||||
) {
|
) {
|
||||||
Messaging.messaging().apnsToken = deviceToken
|
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
|
||||||
|
pendingToken = token
|
||||||
|
apnsChannel?.invokeMethod("onToken", arguments: token)
|
||||||
super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
|
super.application(application, didRegisterForRemoteNotificationsWithDeviceToken: deviceToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFailToRegisterForRemoteNotificationsWithError error: Error
|
||||||
|
) {
|
||||||
|
print("[APNs] registration failed: \(error)")
|
||||||
|
super.application(application, didFailToRegisterForRemoteNotificationsWithError: error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show banners while the app is in the foreground (matches LockInBroMobile).
|
||||||
|
override func userNotificationCenter(
|
||||||
|
_ center: UNUserNotificationCenter,
|
||||||
|
willPresent notification: UNNotification,
|
||||||
|
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
|
||||||
|
) {
|
||||||
|
completionHandler([.banner, .sound, .badge])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
66
lib/BlindMasterResources/apns_service.dart
Normal file
66
lib/BlindMasterResources/apns_service.dart
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
/// Bridge to the native iOS APNs registration in `ios/Runner/AppDelegate.swift`.
|
||||||
|
/// The Swift side captures the device token in
|
||||||
|
/// `didRegisterForRemoteNotificationsWithDeviceToken`, hex-encodes it, and
|
||||||
|
/// pushes it back here over the `blindmaster/apns` MethodChannel. We then POST
|
||||||
|
/// it to `/register_apns_token` so the server can target this device.
|
||||||
|
///
|
||||||
|
/// Mirrors the LockInBroMobile NotificationService flow — Android has no APNs
|
||||||
|
/// equivalent and the backend only supports APNs, so this is a no-op there.
|
||||||
|
class ApnsService {
|
||||||
|
static const _channel = MethodChannel('blindmaster/apns');
|
||||||
|
static bool _handlerInstalled = false;
|
||||||
|
|
||||||
|
/// Wire the channel handler once at startup so a token delivered before the
|
||||||
|
/// first `register()` call (or after, asynchronously) is still uploaded.
|
||||||
|
static void install() {
|
||||||
|
if (_handlerInstalled) return;
|
||||||
|
if (defaultTargetPlatform != TargetPlatform.iOS &&
|
||||||
|
defaultTargetPlatform != TargetPlatform.macOS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_handlerInstalled = true;
|
||||||
|
_channel.setMethodCallHandler((call) async {
|
||||||
|
if (call.method == 'onToken') {
|
||||||
|
final token = call.arguments as String?;
|
||||||
|
if (token == null || token.isEmpty) return;
|
||||||
|
debugPrint('APNS: token received');
|
||||||
|
try {
|
||||||
|
await securePost({'token': token}, 'register_apns_token');
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('APNS: token upload failed: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Request notification permission and upload the cached token if APNs has
|
||||||
|
/// already produced one. Safe to call repeatedly (login + session-restore) —
|
||||||
|
/// the server upserts.
|
||||||
|
static Future<void> register() async {
|
||||||
|
if (defaultTargetPlatform != TargetPlatform.iOS &&
|
||||||
|
defaultTargetPlatform != TargetPlatform.macOS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
install();
|
||||||
|
try {
|
||||||
|
final granted =
|
||||||
|
await _channel.invokeMethod<bool>('requestPermission') ?? false;
|
||||||
|
if (!granted) {
|
||||||
|
debugPrint('APNS: notifications denied — enable in Settings');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final token = await _channel.invokeMethod<String?>('getToken');
|
||||||
|
if (token == null || token.isEmpty) {
|
||||||
|
debugPrint('APNS: token not ready yet — onToken handler will catch it');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await securePost({'token': token}, 'register_apns_token');
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('APNS registration failed: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
|
|
||||||
class FcmService {
|
|
||||||
/// Request permission, fetch the FCM token, and register it with the server.
|
|
||||||
/// Safe to call on every login/session-restore — the server just upserts the value.
|
|
||||||
static Future<void> register() async {
|
|
||||||
debugPrint('FCM: register() called');
|
|
||||||
try {
|
|
||||||
final messaging = FirebaseMessaging.instance;
|
|
||||||
final settings = await messaging.requestPermission(alert: true, badge: true, sound: true);
|
|
||||||
debugPrint('FCM: authorization status: ${settings.authorizationStatus}');
|
|
||||||
if (settings.authorizationStatus == AuthorizationStatus.denied) {
|
|
||||||
debugPrint('FCM: notifications denied — enable in Settings > [App] > Notifications');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await messaging.setForegroundNotificationPresentationOptions(
|
|
||||||
alert: true,
|
|
||||||
badge: true,
|
|
||||||
sound: true,
|
|
||||||
);
|
|
||||||
// On iOS, APNs token must be available before FCM token can be fetched.
|
|
||||||
// getAPNSToken() can block if iOS hasn't finished APNs registration yet,
|
|
||||||
// so cap it with a timeout and retry once after a short delay.
|
|
||||||
if (defaultTargetPlatform == TargetPlatform.iOS ||
|
|
||||||
defaultTargetPlatform == TargetPlatform.macOS) {
|
|
||||||
String? apnsToken = await messaging.getAPNSToken()
|
|
||||||
.timeout(const Duration(seconds: 3), onTimeout: () => null);
|
|
||||||
if (apnsToken == null) {
|
|
||||||
debugPrint('FCM: APNs token not ready, retrying in 5s...');
|
|
||||||
await Future.delayed(const Duration(seconds: 5));
|
|
||||||
apnsToken = await messaging.getAPNSToken()
|
|
||||||
.timeout(const Duration(seconds: 5), onTimeout: () => null);
|
|
||||||
}
|
|
||||||
if (apnsToken == null) {
|
|
||||||
debugPrint('FCM: APNs token unavailable — simulator or APNs not configured');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
debugPrint('FCM: APNs token acquired');
|
|
||||||
}
|
|
||||||
final token = await messaging.getToken();
|
|
||||||
debugPrint('FCM TOKEN: ${token ?? "null — likely running on simulator"}');
|
|
||||||
if (token == null) return;
|
|
||||||
await securePost({'token': token}, 'register_fcm_token');
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint('FCM registration failed: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -13,7 +13,7 @@ String host = local;
|
|||||||
int port = 3000;
|
int port = 3000;
|
||||||
String priv = "$scheme://$host:$port";
|
String priv = "$scheme://$host:$port";
|
||||||
|
|
||||||
String pub = "https://wahwa.com";
|
String pub = "https://blindmaster.wahwa.com";
|
||||||
|
|
||||||
String socketString = pub;
|
String socketString = pub;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
|
import 'package:blind_master/BlindMasterResources/apns_service.dart';
|
||||||
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/Startup/create_user_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/Startup/create_user_screen.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/Startup/forgot_password_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/Startup/forgot_password_screen.dart';
|
||||||
@@ -62,7 +62,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
backgroundColor: Colors.orange[700],
|
backgroundColor: Colors.orange[700],
|
||||||
duration: Duration(seconds: 4),
|
duration: Duration(seconds: 4),
|
||||||
content: Text(
|
content: Text(
|
||||||
"Your account has not been verified. Please check your email from blindmasterapp@wahwa.com and verify your account.",
|
"Your account has not been verified. Please check your email from account-services@blindmaster.wahwa.com and verify your account.",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(fontSize: 15),
|
style: TextStyle(fontSize: 15),
|
||||||
),
|
),
|
||||||
@@ -85,7 +85,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
|||||||
if (token.isEmpty) throw Exception('Token Not Received');
|
if (token.isEmpty) throw Exception('Token Not Received');
|
||||||
final storage = FlutterSecureStorage();
|
final storage = FlutterSecureStorage();
|
||||||
await storage.write(key: 'token', value: token);
|
await storage.write(key: 'token', value: token);
|
||||||
await FcmService.register();
|
await ApnsService.register();
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
|
import 'package:blind_master/BlindMasterResources/apns_service.dart';
|
||||||
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
import 'package:blind_master/BlindMasterResources/secure_transmissions.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/home_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/home_screen.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/Startup/login_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/Startup/login_screen.dart';
|
||||||
@@ -51,7 +51,7 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nextScreen = HomeScreen();
|
nextScreen = HomeScreen();
|
||||||
await FcmService.register();
|
await ApnsService.register();
|
||||||
} else {
|
} else {
|
||||||
nextScreen = LoginScreen();
|
nextScreen = LoginScreen();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class _VerificationWaitingScreenState extends BaseVerificationWaitingScreenState
|
|||||||
String get title => "Verify Your Email";
|
String get title => "Verify Your Email";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get mainMessage => "We've sent a verification link to your email from blindmasterapp@wahwa.com";
|
String get mainMessage => "We've sent a verification link to your email from account-services@blindmaster.wahwa.com";
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get instructionMessage => "Click the link in the email to verify your account. This page will automatically update once verified.";
|
String get instructionMessage => "Click the link in the email to verify your account. This page will automatically update once verified.";
|
||||||
@@ -29,7 +29,7 @@ class _VerificationWaitingScreenState extends BaseVerificationWaitingScreenState
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> checkStatus() async {
|
Future<bool> checkStatus() async {
|
||||||
final uri = Uri.parse('https://wahwa.com').replace(path: 'verification_status');
|
final uri = Uri.parse('https://blindmaster.wahwa.com').replace(path: 'verification_status');
|
||||||
|
|
||||||
final response = await http.get(
|
final response = await http.get(
|
||||||
uri,
|
uri,
|
||||||
@@ -49,7 +49,7 @@ class _VerificationWaitingScreenState extends BaseVerificationWaitingScreenState
|
|||||||
@override
|
@override
|
||||||
Future<void> resendVerification() async {
|
Future<void> resendVerification() async {
|
||||||
final localHour = DateTime.now().hour;
|
final localHour = DateTime.now().hour;
|
||||||
final uri = Uri.parse('https://wahwa.com').replace(path: 'resend_verification');
|
final uri = Uri.parse('https://blindmaster.wahwa.com').replace(path: 'resend_verification');
|
||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
uri,
|
uri,
|
||||||
|
|||||||
@@ -1,88 +0,0 @@
|
|||||||
// 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: 'AIzaSyDnRirxd46eWwUkK9cKi-g0mKaIBY3LODM',
|
|
||||||
appId: '1:956683546941:web:f66e35806267907c121554',
|
|
||||||
messagingSenderId: '956683546941',
|
|
||||||
projectId: 'blindmaster-54055',
|
|
||||||
authDomain: 'blindmaster-54055.firebaseapp.com',
|
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
|
||||||
measurementId: 'G-Y31FSGG3KP',
|
|
||||||
);
|
|
||||||
|
|
||||||
static const FirebaseOptions android = FirebaseOptions(
|
|
||||||
apiKey: 'AIzaSyBJzL-jeo4xa_rQkHymzku_2lIJ6WJ8hoI',
|
|
||||||
appId: '1:956683546941:android:828055a1f543b75f121554',
|
|
||||||
messagingSenderId: '956683546941',
|
|
||||||
projectId: 'blindmaster-54055',
|
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
|
||||||
);
|
|
||||||
|
|
||||||
static const FirebaseOptions ios = FirebaseOptions(
|
|
||||||
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
|
|
||||||
appId: '1:956683546941:ios:1059be0ae683894b121554',
|
|
||||||
messagingSenderId: '956683546941',
|
|
||||||
projectId: 'blindmaster-54055',
|
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
|
||||||
iosBundleId: 'com.adipu.blindMaster',
|
|
||||||
);
|
|
||||||
|
|
||||||
static const FirebaseOptions macos = FirebaseOptions(
|
|
||||||
apiKey: 'AIzaSyAH5KvipSKH5J6dkjd6Ft7ALAqBYANB-Jo',
|
|
||||||
appId: '1:956683546941:ios:1059be0ae683894b121554',
|
|
||||||
messagingSenderId: '956683546941',
|
|
||||||
projectId: 'blindmaster-54055',
|
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
|
||||||
iosBundleId: 'com.adipu.blindMaster',
|
|
||||||
);
|
|
||||||
|
|
||||||
static const FirebaseOptions windows = FirebaseOptions(
|
|
||||||
apiKey: 'AIzaSyDnRirxd46eWwUkK9cKi-g0mKaIBY3LODM',
|
|
||||||
appId: '1:956683546941:web:f5d94d05b6ce6bef121554',
|
|
||||||
messagingSenderId: '956683546941',
|
|
||||||
projectId: 'blindmaster-54055',
|
|
||||||
authDomain: 'blindmaster-54055.firebaseapp.com',
|
|
||||||
storageBucket: 'blindmaster-54055.firebasestorage.app',
|
|
||||||
measurementId: 'G-WR6581J4P4',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,29 +1,20 @@
|
|||||||
import 'package:blind_master/BlindMasterResources/fcm_service.dart';
|
import 'package:blind_master/BlindMasterResources/apns_service.dart';
|
||||||
import 'package:blind_master/BlindMasterScreens/Startup/splash_screen.dart';
|
import 'package:blind_master/BlindMasterScreens/Startup/splash_screen.dart';
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
|
||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'firebase_options.dart'; // generated by: flutterfire configure
|
|
||||||
|
|
||||||
// Handles FCM messages that arrive when the app is terminated or in the background.
|
|
||||||
@pragma('vm:entry-point')
|
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
|
||||||
// The system notification tray handles display automatically — nothing to do here.
|
|
||||||
}
|
|
||||||
|
|
||||||
enum DaysOfWeek {Su, M, Tu, W, Th, F, Sa}
|
enum DaysOfWeek {Su, M, Tu, W, Th, F, Sa}
|
||||||
|
|
||||||
void main() async {
|
void main() {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
// Wire the APNs MethodChannel handler before any UI runs so a token
|
||||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
// delivered by iOS during launch is still picked up.
|
||||||
FirebaseMessaging.instance.onTokenRefresh.listen((_) => FcmService.register());
|
ApnsService.install();
|
||||||
runApp(const MyApp());
|
runApp(const MyApp());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Color> getBackgroundBasedOnTime() {
|
Map<String, Color> getBackgroundBasedOnTime() {
|
||||||
final hour = DateTime.now().hour;
|
final hour = DateTime.now().hour;
|
||||||
|
|
||||||
Color secondaryLight;
|
Color secondaryLight;
|
||||||
Color primary;
|
Color primary;
|
||||||
Color secondaryDark;
|
Color secondaryDark;
|
||||||
@@ -43,7 +34,7 @@ Map<String, Color> getBackgroundBasedOnTime() {
|
|||||||
secondaryLight = const Color.fromARGB(255, 186, 130, 255);
|
secondaryLight = const Color.fromARGB(255, 186, 130, 255);
|
||||||
secondaryDark = const Color.fromARGB(255, 40, 0, 89);
|
secondaryDark = const Color.fromARGB(255, 40, 0, 89);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'primary': primary,
|
'primary': primary,
|
||||||
'secondaryLight': secondaryLight,
|
'secondaryLight': secondaryLight,
|
||||||
@@ -78,4 +69,3 @@ class MyApp extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,6 @@ dependencies:
|
|||||||
flutter_secure_storage: ^9.2.4
|
flutter_secure_storage: ^9.2.4
|
||||||
flutter_xlider: ^3.5.0
|
flutter_xlider: ^3.5.0
|
||||||
socket_io_client: ^3.1.2
|
socket_io_client: ^3.1.2
|
||||||
firebase_core: ^3.0.0
|
|
||||||
firebase_messaging: ^15.0.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user