| @@ -1,5 +1,8 @@ | |||
| plugins { | |||
| id "com.android.application" | |||
| // START: FlutterFire Configuration | |||
| id 'com.google.gms.google-services' | |||
| // END: FlutterFire Configuration | |||
| id "kotlin-android" | |||
| // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. | |||
| id "dev.flutter.flutter-gradle-plugin" | |||
| @@ -42,3 +45,5 @@ android { | |||
| flutter { | |||
| source = "../.." | |||
| } | |||
| apply plugin: 'com.google.gms.google-services' | |||
| @@ -0,0 +1,29 @@ | |||
| { | |||
| "project_info": { | |||
| "project_number": "392489806594", | |||
| "project_id": "folad-neiriz", | |||
| "storage_bucket": "folad-neiriz.firebasestorage.app" | |||
| }, | |||
| "client": [ | |||
| { | |||
| "client_info": { | |||
| "mobilesdk_app_id": "1:392489806594:android:76b6661258b6f56f3b301b", | |||
| "android_client_info": { | |||
| "package_name": "com.example.qadirneyriz" | |||
| } | |||
| }, | |||
| "oauth_client": [], | |||
| "api_key": [ | |||
| { | |||
| "current_key": "AIzaSyAuDK456j4fFdNqrzQRDYyWRcB0VkQ2bCY" | |||
| } | |||
| ], | |||
| "services": { | |||
| "appinvite_service": { | |||
| "other_platform_oauth_client": [] | |||
| } | |||
| } | |||
| } | |||
| ], | |||
| "configuration_version": "1" | |||
| } | |||
| @@ -1,10 +1,12 @@ | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android" | |||
| xmlns:tools="http://schemas.android.com/tools"> | |||
| <uses-permission android:name="android.permission.INTERNET"/> | |||
| <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> | |||
| <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> | |||
| <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> | |||
| <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> | |||
| <uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> | |||
| <application | |||
| android:label="Mizban" | |||
| android:name="${applicationName}" | |||
| @@ -18,10 +20,6 @@ | |||
| android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | |||
| android:hardwareAccelerated="true" | |||
| android:windowSoftInputMode="adjustResize"> | |||
| <!-- Specifies an Android theme to apply to this Activity as soon as | |||
| the Android process has started. This theme is visible to the user | |||
| while the Flutter UI initializes. After that, this theme continues | |||
| to determine the Window background behind the Flutter UI. --> | |||
| <meta-data | |||
| android:name="io.flutter.embedding.android.NormalTheme" | |||
| android:resource="@style/NormalTheme" | |||
| @@ -31,11 +29,19 @@ | |||
| <category android:name="android.intent.category.LAUNCHER"/> | |||
| </intent-filter> | |||
| </activity> | |||
| <service | |||
| android:name="io.flutter.plugins.firebase.messaging.FlutterFirebaseMessagingService" | |||
| android:exported="true" | |||
| tools:replace="android:exported"> | |||
| </service> | |||
| <!-- Don't delete the meta-data below. | |||
| This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> | |||
| <meta-data | |||
| android:name="flutterEmbedding" | |||
| android:value="2" /> | |||
| <meta-data | |||
| android:name="com.google.firebase.messaging.default_notification_channel_id" | |||
| android:value="high_importance_channel" /> | |||
| </application> | |||
| <!-- Required to query activities that can process text, see: | |||
| https://developer.android.com/training/package-visibility and | |||
| @@ -19,6 +19,9 @@ pluginManagement { | |||
| plugins { | |||
| id "dev.flutter.flutter-plugin-loader" version "1.0.0" | |||
| id "com.android.application" version "8.1.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 | |||
| } | |||
| @@ -1,5 +1,7 @@ | |||
| import Flutter | |||
| import UIKit | |||
| import Firebase | |||
| import FirebaseMessaging | |||
| @main | |||
| @objc class AppDelegate: FlutterAppDelegate { | |||
| @@ -7,7 +9,55 @@ import UIKit | |||
| _ application: UIApplication, | |||
| didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? | |||
| ) -> Bool { | |||
| // مقداردهی Firebase | |||
| FirebaseApp.configure() | |||
| // ثبت Plugin های Flutter | |||
| GeneratedPluginRegistrant.register(with: self) | |||
| // تنظیمات Notification Center | |||
| UNUserNotificationCenter.current().delegate = self | |||
| Messaging.messaging().delegate = self | |||
| // درخواست مجوز نوتیفیکیشن | |||
| UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in | |||
| if let error = error { | |||
| print("Error requesting notification permissions: \(error)") | |||
| } | |||
| print("Permission granted: \(granted)") | |||
| } | |||
| // ثبت دستگاه برای دریافت Remote Notifications | |||
| application.registerForRemoteNotifications() | |||
| return super.application(application, didFinishLaunchingWithOptions: launchOptions) | |||
| } | |||
| // متد دریافت APNs Token و ارسال آن به Firebase | |||
| override func application( | |||
| _ application: UIApplication, | |||
| didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data | |||
| ) { | |||
| Messaging.messaging().apnsToken = deviceToken | |||
| } | |||
| } | |||
| // افزودن پروتکلهای UNUserNotificationCenterDelegate و MessagingDelegate | |||
| extension AppDelegate: UNUserNotificationCenterDelegate, MessagingDelegate { | |||
| // مدیریت دریافت توکن Firebase | |||
| func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) { | |||
| print("Firebase FCM Token: \(fcmToken ?? "No Token")") | |||
| // اگر نیاز به ارسال توکن به سرور دارید، اینجا انجام دهید. | |||
| } | |||
| // مدیریت پیامهای دریافتشده هنگام باز بودن اپلیکیشن | |||
| func userNotificationCenter( | |||
| _ center: UNUserNotificationCenter, | |||
| willPresent notification: UNNotification, | |||
| withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void | |||
| ) { | |||
| let userInfo = notification.request.content.userInfo | |||
| print("Foreground Notification Received: \(userInfo)") | |||
| completionHandler([.banner, .sound, .badge]) | |||
| } | |||
| } | |||
| @@ -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>AIzaSyDmiLNq_t5wyqDE2VW1wGyt6kArchRvLAQ</string> | |||
| <key>GCM_SENDER_ID</key> | |||
| <string>392489806594</string> | |||
| <key>PLIST_VERSION</key> | |||
| <string>1</string> | |||
| <key>BUNDLE_ID</key> | |||
| <string>com.example.qadirneyriz</string> | |||
| <key>PROJECT_ID</key> | |||
| <string>folad-neiriz</string> | |||
| <key>STORAGE_BUCKET</key> | |||
| <string>folad-neiriz.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:392489806594:ios:feeba2107eb852ec3b301b</string> | |||
| </dict> | |||
| </plist> | |||
| @@ -1,3 +1,5 @@ | |||
| import 'package:firebase_core/firebase_core.dart'; | |||
| import 'package:firebase_messaging/firebase_messaging.dart'; | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:flutter_localizations/flutter_localizations.dart'; | |||
| import 'package:hive_flutter/hive_flutter.dart'; | |||
| @@ -13,9 +15,52 @@ import 'package:qadirneyriz/screens/private_meeting/state.dart'; | |||
| import 'package:qadirneyriz/screens/report/state.dart'; | |||
| import 'package:qadirneyriz/setting/setting.dart'; | |||
| void main() async { | |||
| final FirebaseMessaging messaging = FirebaseMessaging.instance; | |||
| Future<void> initializeApp() async { | |||
| await Firebase.initializeApp(); | |||
| await Hive.initFlutter(); | |||
| await setting.userLocalDb.openBox(); | |||
| await requestNotificationPermission(); | |||
| await getToken(); | |||
| setupMessageListener(); | |||
| } | |||
| Future<void> requestNotificationPermission() async { | |||
| NotificationSettings settings = await messaging.requestPermission( | |||
| alert: true, | |||
| announcement: false, | |||
| badge: true, | |||
| carPlay: false, | |||
| criticalAlert: false, | |||
| provisional: false, | |||
| sound: true, | |||
| ); | |||
| if (settings.authorizationStatus == AuthorizationStatus.authorized) { | |||
| print('User granted permission'); | |||
| } else { | |||
| print('User declined or has not granted permission'); | |||
| } | |||
| } | |||
| Future<void> getToken() async { | |||
| String? token = await messaging.getToken(); | |||
| print("Device Token: $token"); | |||
| // You can send the token to your server here if needed | |||
| } | |||
| void setupMessageListener() { | |||
| FirebaseMessaging.onMessage.listen((RemoteMessage message) { | |||
| print('Message received: ${message.notification?.title}'); | |||
| print('Message body: ${message.notification?.body}'); | |||
| // You can use a Dialog or Toast to display the message here | |||
| }); | |||
| } | |||
| void main() async { | |||
| WidgetsFlutterBinding.ensureInitialized(); | |||
| await initializeApp(); // Initialize Firebase and other services | |||
| runApp( | |||
| MultiProvider( | |||
| providers: [ | |||
| @@ -41,51 +86,46 @@ class MyApp extends StatefulWidget { | |||
| class _MyAppState extends State<MyApp> { | |||
| late AuthState state; | |||
| String language = setting.userLocalDb.getUser().language; | |||
| @override | |||
| void initState() { | |||
| super.initState(); | |||
| Future.delayed(Duration.zero, () async { | |||
| state = Provider.of(context, listen: false); | |||
| state = Provider.of<AuthState>(context, listen: false); | |||
| setState(() { | |||
| language = state.language; | |||
| }); | |||
| }); | |||
| super.initState(); | |||
| } | |||
| // This widget is the root of your application. | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| return Consumer<AuthState>( | |||
| builder: (context, value, child) { | |||
| return MaterialApp.router( | |||
| theme: ThemeData( | |||
| colorScheme: ColorScheme.light( | |||
| // تغییر رنگ اصلی تایم پیکر | |||
| primary: config.ui.mainGreen, | |||
| // تغییر رنگ متن | |||
| ), | |||
| buttonTheme: ButtonThemeData( | |||
| colorScheme: ColorScheme.light( | |||
| primary: Colors.green, // رنگ دکمهها | |||
| ), | |||
| ), | |||
| useMaterial3: true, | |||
| fontFamily: 'Font', | |||
| scaffoldBackgroundColor: Colors.white), | |||
| colorScheme: ColorScheme.light(primary: config.ui.mainGreen), | |||
| buttonTheme: ButtonThemeData( | |||
| colorScheme: ColorScheme.light(primary: Colors.green), | |||
| ), | |||
| useMaterial3: true, | |||
| fontFamily: 'Font', | |||
| scaffoldBackgroundColor: Colors.white, | |||
| ), | |||
| debugShowCheckedModeBanner: false, | |||
| routerDelegate: router.routerDelegate, | |||
| routeInformationParser: router.routeInformationParser, | |||
| routeInformationProvider: router.routeInformationProvider, | |||
| localizationsDelegates: const [ | |||
| AppLocalizations.delegate, // Add this line | |||
| AppLocalizations.delegate, | |||
| GlobalMaterialLocalizations.delegate, | |||
| GlobalWidgetsLocalizations.delegate, | |||
| GlobalCupertinoLocalizations.delegate, | |||
| ], | |||
| locale: Locale(value.language), | |||
| supportedLocales: const [ | |||
| Locale('en'), // English | |||
| Locale('fa'), // Persian | |||
| Locale('en'), | |||
| Locale('fa'), | |||
| ], | |||
| ); | |||
| }, | |||
| @@ -1,6 +1,7 @@ | |||
| import 'package:flutter/material.dart'; | |||
| import 'package:provider/provider.dart'; | |||
| import 'package:qadirneyriz/config/config.dart'; | |||
| import 'package:qadirneyriz/main.dart'; | |||
| import 'package:qadirneyriz/screens/auth/state/state.dart'; | |||
| import 'package:qadirneyriz/utils/enums/status.dart'; | |||
| import 'package:qadirneyriz/utils/tools/tools.dart'; | |||
| @@ -151,8 +152,9 @@ class _LoginScreenState extends State<LoginScreen> { | |||
| isError: true, | |||
| context, | |||
| ); | |||
| } else { | |||
| } else { String? token = await messaging.getToken(); | |||
| final status = await state.login( | |||
| fcm_token: token??'', | |||
| mobile: phoneController.text, | |||
| password: passwordController.text); | |||
| if (status == Status.ready) { | |||
| @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; | |||
| import 'package:go_router/go_router.dart'; | |||
| import 'package:provider/provider.dart'; | |||
| import 'package:qadirneyriz/config/config.dart'; | |||
| import 'package:qadirneyriz/main.dart'; | |||
| import 'package:qadirneyriz/screens/auth/state/state.dart'; | |||
| import 'package:qadirneyriz/utils/enums/status.dart'; | |||
| import 'package:qadirneyriz/utils/timer/apt_simple_timer_with_controller.dart'; | |||
| @@ -182,9 +183,10 @@ class _OtpScreenState extends State<OtpScreen> { | |||
| } | |||
| void otpCheckCode(onSubmitted, AuthState value) async { | |||
| String? token = await messaging.getToken(); | |||
| if (onSubmitted.length == 4) { | |||
| final status = | |||
| await value.login(mobile: widget.phoneNumber, otp: onSubmitted); | |||
| final status = await value.login( | |||
| mobile: widget.phoneNumber, otp: onSubmitted, fcm_token: token ?? ''); | |||
| if (status == Status.ready) { | |||
| context.goNamed('navigate', pathParameters: {'tab': '0'}); | |||
| } else if (status == Status.error) { | |||
| @@ -22,13 +22,16 @@ class AuthState extends ChangeNotifier { | |||
| Map? errorsLogin; | |||
| Future<Status> login( | |||
| {required String mobile, String? password, String? otp}) async { | |||
| {required String mobile, | |||
| String? password, | |||
| String? otp, | |||
| required String fcm_token}) async { | |||
| assert(password != null || otp != null); | |||
| statusLogin = Status.loading; | |||
| notifyListeners(); | |||
| try { | |||
| final result = await authServises.loginApi( | |||
| mobile: mobile, password: password, otp: otp); | |||
| mobile: mobile, password: password, otp: otp, fcm_token: fcm_token); | |||
| if (result == null) { | |||
| statusLogin = Status.error; | |||
| } else { | |||
| @@ -88,6 +91,4 @@ class AuthState extends ChangeNotifier { | |||
| // print(statusSendotp); | |||
| return statusSendotp; | |||
| } | |||
| } | |||
| @@ -38,8 +38,9 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| DateTime now = DateTime.now(); | |||
| String dateMiladi = | |||
| Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)); | |||
| String dateMiladi = setting.userLocalDb.getUser().language == 'fa' | |||
| ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)) | |||
| : DateFormat('yyyy-MM-dd').format(now); | |||
| String dateJalali = Tools.convertToPersianDigits( | |||
| '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}'); | |||
| @@ -123,29 +124,38 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| final meeting = value | |||
| .todayMeetingsModel!.meetings![index]; | |||
| return Padding( | |||
| padding: const EdgeInsets.only( | |||
| right: 5, left: 1), | |||
| child: Stack( | |||
| children: [ | |||
| CustomCardMeeting( | |||
| status: meeting.accepted ?? 0, | |||
| titel: meeting.subject != null | |||
| ? meeting.subject!.subject ?? '' | |||
| : '', | |||
| fromTime: meeting.azHour ?? '', | |||
| toTime: meeting.taHour ?? "", | |||
| location: meeting.location != null | |||
| ? meeting.location!.address ?? '' | |||
| : '', | |||
| date: meeting.dateJalali ?? '', | |||
| cardId: meeting.id ?? 0, | |||
| ), | |||
| Positioned( | |||
| child: Container( | |||
| padding: const EdgeInsets.only( | |||
| right: 5, left: 1), | |||
| child: Stack( | |||
| children: [ | |||
| CustomCardMeeting( | |||
| status: meeting.accepted ?? 0, | |||
| titel: meeting.subject != null | |||
| ? meeting.subject!.subject ?? '' | |||
| : '', | |||
| fromTime: meeting.azHour ?? '', | |||
| toTime: meeting.taHour ?? "", | |||
| location: meeting.location != null | |||
| ? meeting.location!.address ?? | |||
| '' | |||
| : '', | |||
| date: meeting.dateJalali ?? '', | |||
| cardId: meeting.id ?? 0, | |||
| ), | |||
| Positioned( | |||
| left: setting.userLocalDb | |||
| .getUser() | |||
| .language == | |||
| 'fa' | |||
| ? 20 | |||
| : 280, | |||
| top: 20, | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| borderRadius: | |||
| BorderRadius.circular(10), | |||
| color: Colors.green), | |||
| borderRadius: | |||
| BorderRadius.circular(10), | |||
| color: Colors.green, | |||
| ), | |||
| child: Padding( | |||
| padding: | |||
| const EdgeInsets.all(5.0), | |||
| @@ -156,13 +166,11 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| fontSize: 12, | |||
| color: Colors.white), | |||
| ), | |||
| )), | |||
| left: 30, | |||
| top: 20, | |||
| ), | |||
| ], | |||
| ), | |||
| ); | |||
| ), | |||
| ), | |||
| ), | |||
| ], | |||
| )); | |||
| } else { | |||
| // آیتم از لیست `privateMeetings` | |||
| final privateMeeting = value | |||
| @@ -192,6 +200,12 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| toTime: privateMeeting.taHour ?? '', | |||
| ), | |||
| Positioned( | |||
| left: setting.userLocalDb | |||
| .getUser() | |||
| .language == | |||
| 'fa' | |||
| ? 20 | |||
| : 250, | |||
| child: Container( | |||
| decoration: BoxDecoration( | |||
| borderRadius: | |||
| @@ -208,7 +222,6 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| color: Colors.white), | |||
| ), | |||
| )), | |||
| left: 30, | |||
| top: 20, | |||
| ), | |||
| ], | |||
| @@ -343,86 +356,7 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| const SizedBox( | |||
| height: 30, | |||
| ), | |||
| Consumer<HomeState>( | |||
| builder: (context, value, child) { | |||
| switch (value.statusLogOut) { | |||
| case Status.loading: | |||
| return const LoadingWidget(); | |||
| default: | |||
| return Row( | |||
| mainAxisAlignment: | |||
| MainAxisAlignment | |||
| .center, | |||
| crossAxisAlignment: | |||
| CrossAxisAlignment | |||
| .center, | |||
| children: [ | |||
| CustomButton( | |||
| fontSize: 13, | |||
| color: config | |||
| .ui.mainGreen, | |||
| onPressed: () { | |||
| Navigator.pop( | |||
| context); | |||
| }, | |||
| hieght: 50, | |||
| // width: 150, | |||
| text: AppLocalizations | |||
| .of(context)! | |||
| .no, | |||
| ), | |||
| const SizedBox( | |||
| width: 10, | |||
| ), | |||
| CustomButton( | |||
| fontSize: 13, | |||
| hieght: 50, | |||
| // width: 150, | |||
| text: AppLocalizations | |||
| .of(context)! | |||
| .logout, | |||
| textColor: | |||
| Colors.black, | |||
| color: const Color( | |||
| 0xffD0D5ED), | |||
| onPressed: () async { | |||
| final status = | |||
| await value | |||
| .logOut(); | |||
| if (status == | |||
| Status.error) { | |||
| Tools.showCustomSnackBar( | |||
| context, | |||
| text: value | |||
| .messageLogOut ?? | |||
| AppLocalizations.of( | |||
| context)! | |||
| .error, | |||
| isError: | |||
| true); | |||
| } else if (status == | |||
| Status.ready) { | |||
| context | |||
| .pushReplacementNamed( | |||
| 'login'); | |||
| Tools.showCustomSnackBar( | |||
| context, | |||
| text: value | |||
| .messageLogOut ?? | |||
| 'Done successfully', | |||
| isError: | |||
| false); | |||
| } | |||
| }, | |||
| ), | |||
| ], | |||
| ); | |||
| } | |||
| }, | |||
| ), | |||
| logOutButton(), | |||
| const SizedBox( | |||
| height: 40, | |||
| ) | |||
| @@ -458,6 +392,63 @@ class _HomeScreenState extends State<HomeScreen> { | |||
| }, | |||
| ); | |||
| } | |||
| Consumer<HomeState> logOutButton() { | |||
| return Consumer<HomeState>( | |||
| builder: (context, value, child) { | |||
| switch (value.statusLogOut) { | |||
| case Status.loading: | |||
| return const LoadingWidget(); | |||
| default: | |||
| return Row( | |||
| mainAxisAlignment: MainAxisAlignment.center, | |||
| crossAxisAlignment: CrossAxisAlignment.center, | |||
| children: [ | |||
| CustomButton( | |||
| fontSize: 13, | |||
| color: config.ui.mainGreen, | |||
| onPressed: () { | |||
| Navigator.pop(context); | |||
| }, | |||
| hieght: 50, | |||
| // width: 150, | |||
| text: AppLocalizations.of(context)!.no, | |||
| ), | |||
| const SizedBox( | |||
| width: 10, | |||
| ), | |||
| CustomButton( | |||
| fontSize: 13, | |||
| hieght: 50, | |||
| // width: 150, | |||
| text: AppLocalizations.of(context)!.logout, | |||
| textColor: Colors.black, | |||
| color: const Color(0xffD0D5ED), | |||
| onPressed: () async { | |||
| final status = await value.logOut(); | |||
| if (status == Status.error) { | |||
| Tools.showCustomSnackBar(context, | |||
| text: value.messageLogOut ?? | |||
| AppLocalizations.of(context)!.error, | |||
| isError: true); | |||
| } else if (status == Status.ready) { | |||
| setting.userLocalDb.logOut(); | |||
| context.pushReplacementNamed('login'); | |||
| Tools.showCustomSnackBar(context, | |||
| text: value.messageLogOut ?? 'Done successfully', | |||
| isError: false); | |||
| } | |||
| }, | |||
| ), | |||
| ], | |||
| ); | |||
| } | |||
| }, | |||
| ); | |||
| } | |||
| } | |||
| class ItemInGrid extends StatelessWidget { | |||
| @@ -67,8 +67,9 @@ class _MeetingsScreenState extends State<MeetingsScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| DateTime now = DateTime.now(); | |||
| String dateMiladi = | |||
| Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)); | |||
| String dateMiladi = setting.userLocalDb.getUser().language == 'fa' | |||
| ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)) | |||
| : DateFormat('yyyy-MM-dd').format(now); | |||
| String dateJalali = Tools.convertToPersianDigits( | |||
| '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}'); | |||
| // فرمت کردن تاریخ | |||
| @@ -64,8 +64,9 @@ class _PrivateMeetingsScreenState extends State<PrivateMeetingsScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| DateTime now = DateTime.now(); | |||
| String dateMiladi = | |||
| Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)); | |||
| String dateMiladi = setting.userLocalDb.getUser().language == 'fa' | |||
| ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)) | |||
| : DateFormat('yyyy-MM-dd').format(now); | |||
| String dateJalali = Tools.convertToPersianDigits( | |||
| '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}'); | |||
| @@ -315,8 +316,6 @@ class PrivateMeetingWidget extends StatelessWidget { | |||
| return Padding( | |||
| padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), | |||
| child: Container( | |||
| width: 500, | |||
| height: 190, | |||
| child: Column( | |||
| crossAxisAlignment: CrossAxisAlignment.end, | |||
| children: [ | |||
| @@ -30,8 +30,9 @@ class _ReportScreenState extends State<ReportScreen> { | |||
| @override | |||
| Widget build(BuildContext context) { | |||
| DateTime now = DateTime.now(); | |||
| String dateMiladi = | |||
| Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)); | |||
| String dateMiladi = setting.userLocalDb.getUser().language == 'fa' | |||
| ? Tools.convertToPersianDigits(DateFormat('yyyy-MM-dd').format(now)) | |||
| : DateFormat('yyyy-MM-dd').format(now); | |||
| String dateJalali = Tools.convertToPersianDigits( | |||
| '${setting.timeNow.day} ${Tools.getMonthName(setting.timeNow.month)} ${setting.timeNow.year}'); | |||
| // فرمت کردن تاریخ | |||
| @@ -5,15 +5,20 @@ import 'package:qadirneyriz/utils/result/result.dart'; | |||
| class AuthServices { | |||
| Future<Result?> loginApi( | |||
| {required String mobile, String? password, String? otp}) async { | |||
| {required String mobile, | |||
| String? password, | |||
| String? otp, | |||
| required String fcm_token}) async { | |||
| assert(password != null || otp != null); | |||
| try { | |||
| Map<String, String> headers = {"Accept": "application/json"}; | |||
| FormData? formData; | |||
| formData = password != null | |||
| ? FormData.fromMap({"mobile": mobile, "password": password}) | |||
| : FormData.fromMap({"mobile": mobile, "otp": otp}); | |||
| ? FormData.fromMap( | |||
| {"mobile": mobile, "password": password, "device_id": fcm_token}) | |||
| : FormData.fromMap( | |||
| {"mobile": mobile, "otp": otp, "device_id": fcm_token}); | |||
| print('${formData.fields} resData'); | |||
| final res = await Dio().post("${config.network.baseUrl}login", | |||
| data: formData, options: Options(headers: headers)); | |||
| @@ -26,6 +31,7 @@ class AuthServices { | |||
| return Result(isOk: true, message: res.data['msg']); | |||
| } | |||
| } on DioException catch (e) { | |||
| print(e); | |||
| return Result( | |||
| isOk: false, | |||
| errors: e.response!.data['errors'], | |||
| @@ -0,0 +1,40 @@ | |||
| import 'package:firebase_messaging/firebase_messaging.dart'; | |||
| class NotificationService { | |||
| final FirebaseMessaging _messaging = FirebaseMessaging.instance; | |||
| /// درخواست دسترسی به نوتیفیکیشن | |||
| Future<void> requestNotificationPermission() async { | |||
| NotificationSettings settings = await _messaging.requestPermission( | |||
| alert: true, | |||
| announcement: false, | |||
| badge: true, | |||
| carPlay: false, | |||
| criticalAlert: false, | |||
| provisional: false, | |||
| sound: true, | |||
| ); | |||
| if (settings.authorizationStatus == AuthorizationStatus.authorized) { | |||
| print('User granted permission'); | |||
| } else { | |||
| print('User declined or has not granted permission'); | |||
| } | |||
| } | |||
| /// دریافت توکن دستگاه | |||
| Future<void> getToken() async { | |||
| String? token = await _messaging.getToken(); | |||
| print("Device Token: $token"); | |||
| // اینجا میتوانید توکن را به سرور خود ارسال کنید | |||
| } | |||
| /// تنظیم Listener برای دریافت نوتیفیکیشنها | |||
| void setupMessageListener() { | |||
| FirebaseMessaging.onMessage.listen((RemoteMessage message) { | |||
| print('Message received: ${message.notification?.title}'); | |||
| print('Message body: ${message.notification?.body}'); | |||
| // اینجا میتوانید یک Dialog یا Toast برای نمایش پیام استفاده کنید | |||
| }); | |||
| } | |||
| } | |||
| @@ -5,11 +5,15 @@ | |||
| import FlutterMacOS | |||
| import Foundation | |||
| import firebase_core | |||
| import firebase_messaging | |||
| import open_file_mac | |||
| import path_provider_foundation | |||
| import sqflite | |||
| func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { | |||
| FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) | |||
| FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) | |||
| OpenFilePlugin.register(with: registry.registrar(forPlugin: "OpenFilePlugin")) | |||
| PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) | |||
| SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) | |||
| @@ -9,6 +9,14 @@ packages: | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "72.0.0" | |||
| _flutterfire_internals: | |||
| dependency: transitive | |||
| description: | |||
| name: _flutterfire_internals | |||
| sha256: "71c01c1998c40b3af1944ad0a5f374b4e6fef7f3d2df487f3970dbeadaeb25a1" | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "1.3.46" | |||
| _macros: | |||
| dependency: transitive | |||
| description: dart | |||
| @@ -262,6 +270,54 @@ packages: | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "8.1.3" | |||
| firebase_core: | |||
| dependency: "direct main" | |||
| description: | |||
| name: firebase_core | |||
| sha256: "2438a75ad803e818ad3bd5df49137ee619c46b6fc7101f4dbc23da07305ce553" | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "3.8.0" | |||
| firebase_core_platform_interface: | |||
| dependency: transitive | |||
| description: | |||
| name: firebase_core_platform_interface | |||
| sha256: e30da58198a6d4b49d5bce4e852f985c32cb10db329ebef9473db2b9f09ce810 | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "5.3.0" | |||
| firebase_core_web: | |||
| dependency: transitive | |||
| description: | |||
| name: firebase_core_web | |||
| sha256: f967a7138f5d2ffb1ce15950e2a382924239eaa521150a8f144af34e68b3b3e5 | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "2.18.1" | |||
| firebase_messaging: | |||
| dependency: "direct main" | |||
| description: | |||
| name: firebase_messaging | |||
| sha256: "4d0968ecb860d7baa15a6e2af3469ec5b0d959e51c59ce84a52b0f7632a4aa5a" | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "15.1.5" | |||
| firebase_messaging_platform_interface: | |||
| dependency: transitive | |||
| description: | |||
| name: firebase_messaging_platform_interface | |||
| sha256: a2cb3e7d71d40b6612e2d4e0daa0ae759f6a9d07f693f904d14d22aadf70be10 | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "4.5.48" | |||
| firebase_messaging_web: | |||
| dependency: transitive | |||
| description: | |||
| name: firebase_messaging_web | |||
| sha256: "1554e190f0cd9d6fe59f61ae0275ac12006fdb78b07669f1a260d1a9e6de3a1f" | |||
| url: "https://pub.dev" | |||
| source: hosted | |||
| version: "3.9.4" | |||
| fixnum: | |||
| dependency: transitive | |||
| description: | |||
| @@ -34,6 +34,9 @@ dependencies: | |||
| file_picker: ^8.1.3 | |||
| permission_handler: ^11.3.1 | |||
| open_file: ^3.5.9 | |||
| firebase_core: ^3.8.0 | |||
| firebase_messaging: ^15.1.5 | |||
| dev_dependencies: | |||
| flutter_test: | |||
| @@ -6,9 +6,12 @@ | |||
| #include "generated_plugin_registrant.h" | |||
| #include <firebase_core/firebase_core_plugin_c_api.h> | |||
| #include <permission_handler_windows/permission_handler_windows_plugin.h> | |||
| void RegisterPlugins(flutter::PluginRegistry* registry) { | |||
| FirebaseCorePluginCApiRegisterWithRegistrar( | |||
| registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); | |||
| PermissionHandlerWindowsPluginRegisterWithRegistrar( | |||
| registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); | |||
| } | |||
| @@ -3,6 +3,7 @@ | |||
| # | |||
| list(APPEND FLUTTER_PLUGIN_LIST | |||
| firebase_core | |||
| permission_handler_windows | |||
| ) | |||