chore: update dependencies, adjust minimum SDK version, and refactor date formatting

This commit is contained in:
Vaibhav Surve 2025-08-23 17:19:20 +05:30
parent 911cddf97c
commit 8688e84779
9 changed files with 78 additions and 51 deletions

View File

@ -39,7 +39,7 @@ android {
// Specify your unique Application ID. This identifies your app on Google Play.
applicationId = "com.marco.aiotstage"
// Set minimum and target SDK versions based on Flutter's configuration
minSdk = flutter.minSdkVersion
minSdk = 23
targetSdk = flutter.targetSdkVersion
// Set version code and name based on Flutter's configuration (from pubspec.yaml)
versionCode = flutter.versionCode
@ -81,5 +81,6 @@ flutter {
// Add required dependencies for desugaring
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.4'
}

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip

View File

@ -18,7 +18,7 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.2.1" apply false
id "com.android.application" version "8.6.0" apply false
id "org.jetbrains.kotlin.android" version "1.8.22" apply false
id("com.google.gms.google-services") version "4.4.2" apply false
}

View File

@ -7,7 +7,6 @@ import 'package:marco/helpers/widgets/my_validators.dart';
import 'package:marco/helpers/services/storage/local_storage.dart';
import 'package:marco/helpers/widgets/my_snackbar.dart';
import 'package:marco/helpers/services/app_logger.dart';
import 'package:marco/helpers/services/firebase/firebase_messaging_service.dart';
class LoginController extends MyController {
final MyFormValidator basicValidator = MyFormValidator();
@ -56,17 +55,14 @@ class LoginController extends MyController {
try {
final loginData = basicValidator.getData();
// Get FCM token
final fcmToken = await FirebaseNotificationService().getFcmToken();
loginData['fcmToken'] = fcmToken ?? '';
logSafe("Attempting login for user: ${loginData['username']} with FCM token: ${loginData['fcmToken']}");
logSafe("Attempting login for user: ${loginData['username']}");
final errors = await AuthService.loginUser(loginData);
if (errors != null) {
logSafe("Login failed for user: ${loginData['username']} with errors: $errors", level: LogLevel.warning);
logSafe(
"Login failed for user: ${loginData['username']} with errors: $errors",
level: LogLevel.warning);
showAppSnackbar(
title: "Login Failed",
@ -79,11 +75,24 @@ class LoginController extends MyController {
basicValidator.clearErrors();
} else {
await _handleRememberMe();
// After login success register saved FCM token with server
final fcmToken = await LocalStorage.getFcmToken();
if (fcmToken?.isNotEmpty ?? false) {
final success = await AuthService.registerDeviceToken(fcmToken!);
logSafe(
success
? "✅ FCM token registered after login."
: "⚠️ Failed to register FCM token after login.",
level: LogLevel.warning);
}
logSafe("Login successful for user: ${loginData['username']}");
Get.toNamed('/home');
}
} catch (e, stacktrace) {
logSafe("Exception during login", level: LogLevel.error, error: e, stackTrace: stacktrace);
logSafe("Exception during login",
level: LogLevel.error, error: e, stackTrace: stacktrace);
showAppSnackbar(
title: "Login Error",
message: "An unexpected error occurred",
@ -96,8 +105,10 @@ class LoginController extends MyController {
Future<void> _handleRememberMe() async {
if (isChecked.value) {
await LocalStorage.setToken('username', basicValidator.getController('username')!.text);
await LocalStorage.setToken('password', basicValidator.getController('password')!.text);
await LocalStorage.setToken(
'username', basicValidator.getController('username')!.text);
await LocalStorage.setToken(
'password', basicValidator.getController('password')!.text);
await LocalStorage.setBool('remember_me', true);
} else {
await LocalStorage.removeToken('username');

View File

@ -189,7 +189,7 @@ class AddExpenseController extends GetxController {
);
if (pickedDate != null) {
final now = DateTime.now(); // get current time
final now = DateTime.now();
final finalDateTime = DateTime(
pickedDate.year,
pickedDate.month,
@ -201,7 +201,7 @@ class AddExpenseController extends GetxController {
selectedTransactionDate.value = finalDateTime;
transactionDateController.text =
DateFormat('dd-MM-yyyy HH:mm').format(finalDateTime);
DateFormat('dd MMM yyyy').format(finalDateTime);
}
}

View File

@ -1,5 +1,4 @@
import 'dart:convert';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:googleapis_auth/auth_io.dart';
import 'package:logger/logger.dart';
@ -9,7 +8,7 @@ import 'package:flutter/services.dart' show rootBundle;
import 'package:marco/helpers/services/local_notification_service.dart';
import 'package:marco/helpers/services/storage/local_storage.dart';
import 'package:marco/helpers/services/auth_service.dart';
import 'package:marco/helpers/services/notification_action_handler.dart'; // NEW
import 'package:marco/helpers/services/notification_action_handler.dart';
/// Firebase Notification Service
class FirebaseNotificationService {
@ -20,17 +19,16 @@ class FirebaseNotificationService {
'https://www.googleapis.com/auth/firebase.messaging',
];
/// Initialize Firebase and FCM
/// Initialize FCM (Firebase.initializeApp() should be called once globally)
Future<void> initialize() async {
await Firebase.initializeApp();
_logger.i('✅ Firebase initialized');
_logger.i('✅ FirebaseMessaging initializing...');
await _requestNotificationPermission();
_registerMessageListeners();
_registerTokenRefreshListener();
// Fetch token on app start
await getFcmToken();
// Fetch token on app start (but only register with server if JWT available)
await getFcmToken(registerOnServer: true);
}
/// Request notification permission
@ -45,9 +43,10 @@ class FirebaseNotificationService {
_logger.i('📩 Foreground Notification');
_logNotificationDetails(message);
// Handle UI updates
// Handle custom actions
NotificationActionHandler.handle(message.data);
// Show local notification
if (message.notification != null) {
LocalNotificationService.showNotification(
title: message.notification!.title ?? "No title",
@ -76,24 +75,31 @@ class FirebaseNotificationService {
? '✅ Device token updated on server after refresh.'
: '⚠️ Failed to update device token on server.');
} else {
_logger.w(
'⚠️ JWT not available — will register token after login or refresh.');
_logger.w('⚠️ JWT not available — will retry after login.');
}
});
}
/// Get current token
Future<String?> getFcmToken() async {
/// Get current token (optionally sync to server if logged in)
Future<String?> getFcmToken({bool registerOnServer = false}) async {
try {
final token = await _firebaseMessaging.getToken();
_logger.i('🔑 FCM token: $token');
if (token?.isNotEmpty ?? false) {
await LocalStorage.setFcmToken(token!);
if (registerOnServer) {
final jwt = await LocalStorage.getJwtToken();
if (jwt?.isNotEmpty ?? false) {
final success = await AuthService.registerDeviceToken(token);
_logger.i(success
? '✅ Device token registered on server.'
: '⚠️ Failed to register device token on server.');
} else {
_logger.w('⚠️ JWT not available — skipping server registration.');
}
}
}
return token;
} catch (e, s) {
@ -102,6 +108,17 @@ class FirebaseNotificationService {
}
}
/// Re-register token with server (useful after login)
Future<void> registerTokenAfterLogin() async {
final token = await LocalStorage.getFcmToken();
if (token?.isNotEmpty ?? false) {
final success = await AuthService.registerDeviceToken(token!);
_logger.i(success
? "✅ FCM token registered after login."
: "⚠️ Failed to register FCM token after login.");
}
}
/// Send a test notification using FCM v1 API
Future<void> sendTestNotification(String deviceToken) async {
try {
@ -192,14 +209,12 @@ class FirebaseNotificationService {
}
}
/// Background handler
/// Background handler (required by Firebase)
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
final logger = Logger();
logger
..i('⚡ Handling background notification...')
..i('📦 Data: ${message.data}');
// Pass to helper
NotificationActionHandler.handle(message.data);
}

View File

@ -284,7 +284,7 @@ class ExpenseList extends StatelessWidget {
final expense = expenseList[index];
final formattedDate = DateTimeUtils.convertUtcToLocal(
expense.transactionDate.toIso8601String(),
format: 'dd MMM yyyy, hh:mm a',
format: 'dd MMM yyyy',
);
return Material(

View File

@ -451,7 +451,7 @@ class _InvoiceHeader extends StatelessWidget {
Widget build(BuildContext context) {
final dateString = DateTimeUtils.convertUtcToLocal(
expense.transactionDate.toString(),
format: 'dd-MM-yyyy');
format: 'dd MMM yyyy');
final statusColor = getExpenseStatusColor(expense.status.name,
colorCode: expense.status.color);
return Column(
@ -514,10 +514,10 @@ class _InvoiceDetailsTable extends StatelessWidget {
Widget build(BuildContext context) {
final transactionDate = DateTimeUtils.convertUtcToLocal(
expense.transactionDate.toString(),
format: 'dd-MM-yyyy hh:mm a');
format: 'dd MMM yyyy');
final createdAt = DateTimeUtils.convertUtcToLocal(
expense.createdAt.toString(),
format: 'dd-MM-yyyy hh:mm a');
format: 'dd MMM yyyy');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [

View File

@ -50,17 +50,17 @@ dependencies:
loading_animation_widget: ^1.3.0
flutter_quill: ^10.8.5
intl: ^0.19.0
syncfusion_flutter_core: ^28.1.33
syncfusion_flutter_sliders: ^28.1.33
file_picker: ^9.2.3
syncfusion_flutter_core: ^29.1.40
syncfusion_flutter_sliders: ^29.1.40
file_picker: ^10.3.2
timelines_plus: ^1.0.4
syncfusion_flutter_charts: ^28.1.33
syncfusion_flutter_charts: ^29.1.40
appflowy_board: ^0.1.2
syncfusion_flutter_calendar: ^28.2.6
syncfusion_flutter_maps: ^28.1.33
syncfusion_flutter_calendar: ^29.1.40
syncfusion_flutter_maps: ^29.1.40
http: ^1.2.2
geolocator: ^9.0.1
permission_handler: ^11.3.0
geolocator: ^14.0.2
permission_handler: ^12.0.1
image: ^4.0.17
image_picker: ^1.0.7
logger: ^2.0.2
@ -79,10 +79,10 @@ dependencies:
quill_delta: ^3.0.0-nullsafety.2
connectivity_plus: ^6.1.4
geocoding: ^4.0.0
firebase_core: ^3.14.0
firebase_messaging: ^15.2.7
firebase_core: ^4.0.0
firebase_messaging: ^16.0.0
googleapis_auth: ^2.0.0
device_info_plus: ^10.1.0
device_info_plus: ^11.3.0
flutter_local_notifications: 19.4.0
timeline_tile: ^2.0.0