import 'dart:async'; import 'dart:typed_data'; import 'package:alp_animated_splashscreen/alp_animated_splashscreen.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; import 'package:in_app_update/in_app_update.dart'; import 'package:nearledaily/constants/color_constants.dart'; import 'package:nearledaily/view/authentication/app_update_view.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'package:webview_flutter_android/webview_flutter_android.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:new_version_plus/new_version_plus.dart'; import 'constants/api_constants.dart'; import 'controllers/account_controller/faq_controller.dart'; import 'controllers/authentication/auth_controller.dart'; import 'controllers/cart_controller/cart.dart'; import 'controllers/dashboard_controller/dashboard_controller.dart'; import 'controllers/intro_controller/intro_screen_controller.dart'; import 'controllers/order_controller/create_order_controller.dart'; import 'controllers/tenant/get_tenant.dart'; import 'controllers/tenant_controller /tenant_list.dart'; import 'helper/firebase_options.dart'; import 'service/bindings.dart'; import 'service/device_info/device_info.dart'; import 'view/home_view.dart'; import 'view/splash_view/splash_view.dart'; @pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); const AndroidInitializationSettings androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); await flutterLocalNotificationsPlugin.initialize( const InitializationSettings(android: androidSettings), ); final androidPlugin = flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>(); await androidPlugin?.createNotificationChannel( const AndroidNotificationChannel( 'nearle_channel', 'Nearle Notifications', importance: Importance.max, ), ); final data = message.data; final title = data['title'] as String?; final body = data['body'] as String?; if (title == null || title.isEmpty) return; await flutterLocalNotificationsPlugin.show( 999, title, body?.isNotEmpty == true ? body : null, NotificationDetails( android: AndroidNotificationDetails( 'nearle_channel', 'Nearle Notifications', importance: Importance.max, priority: Priority.high, fullScreenIntent: true, playSound: true, enableVibration: true, largeIcon: const DrawableResourceAndroidBitmap('nearle_logo.jpeg'), ), ), ); } final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future _setupLocalNotifications() async { const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); const AndroidNotificationChannel channel = AndroidNotificationChannel( 'nearle_channel', 'Nearle Notifications', description: 'High priority notifications', importance: Importance.max, playSound: true, enableVibration: true, ); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); } final RouteObserver> routeObserver = RouteObserver>(); // PRINT CURRENT + STORE VERSION (unchanged) Future _printAndCheckAppVersions() async { try { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final String currentVersion = packageInfo.version; final String buildNumber = packageInfo.buildNumber; final String packageName = packageInfo.packageName; print("=================================================="); print("CURRENT APP VERSION: $currentVersion"); print("BUILD NUMBER: $buildNumber"); print("PACKAGE NAME: $packageName"); print("=================================================="); final prefs = await SharedPreferences.getInstance(); await prefs.setString('currentAppVersion', currentVersion); if (defaultTargetPlatform == TargetPlatform.android) { final newVersion = NewVersionPlus( androidId: "com.nearle.gear", ); final status = await newVersion.getVersionStatus(); if (status != null) { print("PLAY STORE VERSION: ${status.storeVersion}"); print("CAN UPDATE: ${status.canUpdate}"); print("APP STORE LINK: ${status.appStoreLink}"); print("=================================================="); await prefs.setString('storeAppVersion', status.storeVersion); await prefs.setBool('updateAvailable', status.canUpdate); } else { print("Could not fetch Play Store version"); await prefs.setString('storeAppVersion', 'Unknown'); } } } catch (e) { print("Version check error: $e"); } } // FIXED: Now correctly detects real update from Play Store Future _checkForAppUpdate() async { if (defaultTargetPlatform != TargetPlatform.android) return false; try { final newVersion = NewVersionPlus(androidId: "com.nearle.gear"); final status = await newVersion.getVersionStatus(); if (status != null && status.canUpdate) { print("UPDATE DETECTED! Redirecting to AppUpdateView"); print("Current: ${status.localVersion} → Store: ${status.storeVersion}"); return true; // This will now go to AppUpdateView } } catch (e) { print("Version check failed (continuing anyway): $e"); } return false; } void _handleMessage(RemoteMessage message) { print("Notification tapped: ${message.data}"); } class AnimatedSplashWithNavigation extends StatefulWidget { final Widget nextScreen; const AnimatedSplashWithNavigation({super.key, required this.nextScreen}); @override State createState() => _AnimatedSplashWithNavigationState(); } class _AnimatedSplashWithNavigationState extends State { @override void initState() { super.initState(); Future.delayed(const Duration(milliseconds: 5200), () { if (mounted) { Get.offAll(() => widget.nextScreen); } }); } @override Widget build(BuildContext context) { return AnimatedSplashScreen( logo: 'assets/images/splashimg.png', brandname: 'Nearle Daily', backgroundcolor: Colors.white, foregroundcolor: ColorConstants.primaryColor, brandnamecolor: ColorConstants.primaryColor, // companyname: 'Nearle Daily', ); } } Future main() async { WidgetsFlutterBinding.ensureInitialized(); FlutterError.onError = (details) => FlutterError.dumpErrorToConsole(details); await runZonedGuarded(() async { await Firebase.initializeApp(); await _printAndCheckAppVersions(); SystemChrome.setSystemUIOverlayStyle( SystemUiOverlayStyle(statusBarColor: Colors.grey[200]), ); await _setupLocalNotifications(); FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); if (initialMessage != null) _handleMessage(initialMessage); FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); if (!kIsWeb) { await FirebaseMessaging.instance.requestPermission( alert: true, badge: true, sound: true, ); } SharedPreferences prefs = await SharedPreferences.getInstance(); prefs.setBool("firstTime", true); FirebaseMessaging.onMessage.listen((RemoteMessage message) async { final data = message.data; final title = data['title'] ?? message.notification?.title ?? 'Nearle'; final body = data['body'] ?? message.notification?.body ?? ''; final ByteData jpegData = await rootBundle.load('assets/images/nearledaily.png'); final Uint8List jpegBytes = jpegData.buffer.asUint8List(); await flutterLocalNotificationsPlugin.show( DateTime.now().millisecondsSinceEpoch ~/ 1000, title, body, NotificationDetails( android: AndroidNotificationDetails( 'nearle_channel', 'Nearle Notifications', importance: Importance.max, priority: Priority.high, fullScreenIntent: true, playSound: true, enableVibration: true, largeIcon: ByteArrayAndroidBitmap(jpegBytes), ), ), ); }); String? fcmToken = await FirebaseMessaging.instance.getToken(); await prefs.setString('fcmToken', fcmToken ?? ''); if (defaultTargetPlatform == TargetPlatform.android) { final params = PlatformWebViewControllerCreationParams(); AndroidWebViewController(params); } ApiConstants.tenantCustomers = ApiConstants.tenantCustomerLive; ApiConstants.orderedtenantCustomers = ApiConstants.orderedtenantCustomerLive; ApiConstants.login = ApiConstants.loginLive; Get.put(TenantController(), permanent: true); Get.lazyPut(() => AuthController(), fenix: true); Get.lazyPut(() => DashboardController(), fenix: true); Get.lazyPut(() => CartController(), fenix: true); Get.lazyPut(() => BottomNavController(), fenix: true); Get.lazyPut(() => OrderedTenantController(), fenix: true); Get.lazyPut(() => OrderController(), fenix: true); Get.lazyPut(() => FaqController(), fenix: true); Get.lazyPut(() => IntroScreenController(), fenix: true); DeviceInfo deviceInfo = DeviceInfo(); await deviceInfo.getDeviceInfo(); await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); final int? customerId = prefs.getInt('customerId'); final String? contactNo = prefs.getString('contactno'); bool updateAvailable = await _checkForAppUpdate(); // Now works correctly! Widget nextScreen; if (updateAvailable) { nextScreen = const AppUpdateView(); } else if (customerId != null && contactNo != null && contactNo.isNotEmpty) { nextScreen = BottomNavigation(); } else { nextScreen = const SplashScreenView(); } SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.white, // or transparent statusBarIconBrightness: Brightness.dark, // Android statusBarBrightness: Brightness.light, // iOS ), ); runApp(MyApp(startScreen: nextScreen)); }, (error, stack) => print('Error: $error')); } class MyApp extends StatelessWidget { final Widget startScreen; const MyApp({super.key, required this.startScreen}); @override Widget build(BuildContext context) { return GetMaterialApp( debugShowCheckedModeBanner: false, title: 'Nearle Daily', navigatorObservers: [routeObserver], theme: ThemeData( fontFamily: 'Proxima Nova', colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), ), initialBinding: GlobalBinding(), home: AnimatedSplashWithNavigation(nextScreen: startScreen), ); } }