From bd10bb4f1d036980d3309781249f53bd04e50422 Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Sun, 8 Jan 2023 16:43:09 +0300 Subject: [PATCH 1/9] Push notifications handler implemented --- lib/api/chat/chat_api_client.dart | 2 + lib/app_state/app_state.dart | 6 ++ lib/classes/push-notification-handler.dart | 59 +++++++++++++++++++ lib/ui/login/login_screen.dart | 9 ++- .../widgets/marathon_details_card.dart | 2 +- lib/widgets/mark_attendance_widget.dart | 9 +++ 6 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 lib/classes/push-notification-handler.dart diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 87e684e..c4bba3a 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -30,6 +30,8 @@ class ChatApiClient { { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "isMobile": true, + "deviceToken": AppState().getDeviceToken, }, ); if (!kReleaseMode) { diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index e43c774..b3a4a32 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -17,6 +17,12 @@ class AppState { factory AppState() => _instance; + String? deviceToken = ""; + + set setDeviceToken(v) => deviceToken = v; + + String? get getDeviceToken => deviceToken; + bool isAuthenticated = false; set setIsAuthenticated(v) => isAuthenticated = v; diff --git a/lib/classes/push-notification-handler.dart b/lib/classes/push-notification-handler.dart new file mode 100644 index 0000000..b95ceb2 --- /dev/null +++ b/lib/classes/push-notification-handler.dart @@ -0,0 +1,59 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; + +// |--> Push Notification Background +Future backgroundMessageHandler(message) async { + print("Firebase backgroundMessageHandler!!!"); +} + +class PushNotificationHandler { + final BuildContext context; + static PushNotificationHandler? _instance; + + PushNotificationHandler(this.context) { + PushNotificationHandler._instance = this; + } + + static PushNotificationHandler getInstance() => _instance!; + + void init() async { + FirebaseMessaging.onMessage.listen((RemoteMessage message) async { + if (Platform.isIOS) { + await Future.delayed(Duration(milliseconds: 3000)).then((value) { + newMessage(message); + }); + } else { + newMessage(message); + } + }); + + FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async { + if (Platform.isIOS) { + await Future.delayed(Duration(milliseconds: 3000)).then((value) { + newMessage(message); + }); + } else { + newMessage(message); + } + }); + + FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) { + print("Push Notification onTokenRefresh: " + fcm_token); + AppState().setDeviceToken = fcm_token; + }); + + FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); + } + + void newMessage(RemoteMessage remoteMessage) async { + print("Remote Message: " + remoteMessage.data.toString()); + if (remoteMessage.data.isEmpty) { + return; + } + } +} diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 7ba82e4..26e9f3e 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:mohem_flutter_app/classes/push-notification-handler.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; @@ -91,8 +92,15 @@ class _LoginScreenState extends State { try { Utils.showLoading(context); await Firebase.initializeApp(); + await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( + alert: true, + badge: true, + sound: true, + ); + PushNotificationHandler(context).init(); _firebaseMessaging = FirebaseMessaging.instance; firebaseToken = await _firebaseMessaging.getToken(); + AppState().setDeviceToken = firebaseToken; loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); if (loginInfo == null) { await checkPrefs(); @@ -171,7 +179,6 @@ class _LoginScreenState extends State { } if (isAppOpenBySystem!) checkFirebaseToken(); } - // username.text = "15444"; return Scaffold( diff --git a/lib/ui/marathon/widgets/marathon_details_card.dart b/lib/ui/marathon/widgets/marathon_details_card.dart index dda7ef8..267d2d3 100644 --- a/lib/ui/marathon/widgets/marathon_details_card.dart +++ b/lib/ui/marathon/widgets/marathon_details_card.dart @@ -57,7 +57,7 @@ class MarathonDetailsCard extends StatelessWidget { children: marathonDetailModel.sponsors!.first.sponsorPrizes! .map( (SponsorPrizes prizes) => - "${AppState().isArabic(context) ? prizes.marathonPrizeAr : prizes.marathonPrizeAr}".toText16(color: MyColors.greenColor, isBold: true).paddingOnly(right: 5), + "${AppState().isArabic(context) ? prizes.marathonPrizeAr : prizes.marathonPrizeEn}".toText16(color: MyColors.greenColor, isBold: true).paddingOnly(right: 5), ) .toList(), ), diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index dfe3b79..59681b7 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -218,6 +218,15 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "", password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); + // + // print("CURRENT SSID: ${await WiFiForIoTPlugin.getSSID()}"); + + if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { + isConnected = true; + } else { + isConnected = false; + } + if (isConnected) { if (Platform.isIOS) { await closeWifiRequest(); From c8f98262669a68dce0cc55377281a5e1a15dd365 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Wed, 18 Jan 2023 11:34:50 +0300 Subject: [PATCH 2/9] Permission Issue --- android/app/src/main/AndroidManifest.xml | 10 ++- ios/Runner/AppDelegate.swift | 9 +++ lib/api/chat/chat_api_client.dart | 11 ++- lib/app_state/app_state.dart | 9 +++ lib/classes/notifications.dart | 61 +++++++++++++++ lib/provider/chat_provider_model.dart | 52 ++++++++++++- lib/ui/chat/chat_bubble.dart | 98 +++++++++++------------- lib/ui/chat/chat_detailed_screen.dart | 12 ++- lib/ui/landing/dashboard_screen.dart | 3 +- lib/ui/login/login_screen.dart | 6 ++ pubspec.yaml | 5 ++ 11 files changed, 211 insertions(+), 65 deletions(-) create mode 100644 lib/classes/notifications.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 30555e1..8331694 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,11 +7,13 @@ + + + + + + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 70693e4..7d74b94 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,5 +1,7 @@ import UIKit import Flutter +import flutter_local_notifications + @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { @@ -7,6 +9,13 @@ import Flutter _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in + GeneratedPluginRegistrant.register(with: registry) + } + + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate + } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 87e684e..efd7af9 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -30,10 +30,19 @@ class ChatApiClient { { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "isMobile": true, + "deviceToken": AppState().deviceNotificationToken }, ); + + print({ + "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "isMobile": true, + "deviceToken": AppState().deviceNotificationToken + }); if (!kReleaseMode) { - logger.i("res: " + response.body); + logger.i("login-res: " + response.body); } if (response.statusCode == 200) { userLoginResponse = user.userAutoLoginModelFromJson(response.body); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index e43c774..8d09d2d 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -173,4 +173,13 @@ class AppState { } bool cancelRequestTrancsection = true; + + + String? _deviceNotificationToken; + + String? get deviceNotificationToken => _deviceNotificationToken; + + set deviceNotificationToken(String? deviceNotificationToken) { + _deviceNotificationToken = deviceNotificationToken; + } } diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart new file mode 100644 index 0000000..26bb70d --- /dev/null +++ b/lib/classes/notifications.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:mohem_flutter_app/app_state/app_state.dart'; +import 'package:mohem_flutter_app/main.dart'; +import 'package:permission_handler/permission_handler.dart'; + +final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); + + +class AppNotifications { + static final AppNotifications _instance = AppNotifications._internal(); + + AppNotifications._internal(); + + factory AppNotifications() => _instance; + + Future requestPermissions() async { + if (Platform.isIOS) { + await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); + } else if (Platform.isAndroid) { + AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); + bool? granted = await androidImplementation?.requestPermission(); + if (granted == false) { + print("-------------------- Permission Granted ------------------------"); + print(granted); + await Permission.notification.request(); + } + } + } + + Future isAndroidPermGranted() async { + if (Platform.isAndroid) { + bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.areNotificationsEnabled() ?? false; + } + } + + void initNotification(String? firebaseToken) async { + // await requestPermissions(); + AppState().deviceNotificationToken = firebaseToken; + // await Permission.notification.isDenied.then((value) { + // if (value) { + // Permission.notification.request(); + // } + // }); + RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage(); + if (initialMessage != null) _handleMessage(initialMessage); + + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + if (message.notification != null) _handleMessage(message); + }); + FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage); + } + + void _handleMessage(RemoteMessage message) { + print("Handle Message"); + logger.w(json.encode(message)); + } +} diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 460a338..c0a16c0 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; - import 'package:audio_waveforms/audio_waveforms.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/cupertino.dart'; @@ -32,6 +31,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:signalr_netcore/hub_connection.dart'; import 'package:signalr_netcore/signalr_client.dart'; import 'package:uuid/uuid.dart'; +import 'package:flutter/material.dart' as Material; class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { ScrollController scrollController = ScrollController(); @@ -66,6 +66,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { List getEmployeeSubordinatesList = []; List teamMembersList = []; + Material.TextDirection textDirection = Material.TextDirection.ltr; + //Chat Home Page Counter int chatUConvCounter = 0; @@ -99,7 +101,7 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { HubConnection hub; HttpConnectionOptions httpOp = HttpConnectionOptions(skipNegotiation: false, logMessageContent: true); hub = HubConnectionBuilder() - .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Web&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) + .withUrl(ApiConsts.chatHubConnectionUrl + "?UserId=${AppState().chatDetails!.response!.id}&source=Desktop&access_token=${AppState().chatDetails!.response!.token}", options: httpOp) .withAutomaticReconnect(retryDelays: [2000, 5000, 10000, 20000]).build(); return hub; } @@ -1409,4 +1411,50 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { isLoading = false; notifyListeners(); } + + void inputBoxDirection(String val) { + if (val.isNotEmpty) { + isTextMsg = true; + } else { + isTextMsg = false; + } + RegExp exp = RegExp("[a-zA-Z]"); + if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") { + textDirection = Material.TextDirection.ltr; + notifyListeners(); + } else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) { + textDirection = Material.TextDirection.rtl; + notifyListeners(); + } + } + + Material.TextDirection getTextDirection(String v) { + String str = v.trim(); + if (str.isEmpty) return Material.TextDirection.ltr; + int firstUnit = str.codeUnitAt(0); + if (firstUnit > 0x0600 && firstUnit < 0x06FF || + firstUnit > 0x0750 && firstUnit < 0x077F || + firstUnit > 0x07C0 && firstUnit < 0x07EA || + firstUnit > 0x0840 && firstUnit < 0x085B || + firstUnit > 0x08A0 && firstUnit < 0x08B4 || + firstUnit > 0x08E3 && firstUnit < 0x08FF || + firstUnit > 0xFB50 && firstUnit < 0xFBB1 || + firstUnit > 0xFBD3 && firstUnit < 0xFD3D || + firstUnit > 0xFD50 && firstUnit < 0xFD8F || + firstUnit > 0xFD92 && firstUnit < 0xFDC7 || + firstUnit > 0xFDF0 && firstUnit < 0xFDFC || + firstUnit > 0xFE70 && firstUnit < 0xFE74 || + firstUnit > 0xFE76 && firstUnit < 0xFEFC || + firstUnit > 0x10800 && firstUnit < 0x10805 || + firstUnit > 0x1B000 && firstUnit < 0x1B0FF || + firstUnit > 0x1D165 && firstUnit < 0x1D169 || + firstUnit > 0x1D16D && firstUnit < 0x1D172 || + firstUnit > 0x1D17B && firstUnit < 0x1D182 || + firstUnit > 0x1D185 && firstUnit < 0x1D18B || + firstUnit > 0x1D1AA && firstUnit < 0x1D1AD || + firstUnit > 0x1D242 && firstUnit < 0x1D244) { + return Material.TextDirection.rtl; + } + return Material.TextDirection.ltr; + } } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 6d1e2eb..1e91a79 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -32,6 +32,8 @@ class ChatBubble extends StatelessWidget { bool isReplied = false; + bool isVoice = false; + int? fileTypeID; String? fileTypeName; @@ -50,6 +52,7 @@ class ChatBubble extends StatelessWidget { isCurrentUser = cItem.currentUserId == AppState().chatDetails!.response!.id ? true : false; isSeen = cItem.isSeen == true ? true : false; isReplied = cItem.userChatReplyResponse != null ? true : false; + // isVoice = cItem.fileTypeId == 13 && cItem.voiceController != null ? true : false; fileTypeID = cItem.fileTypeId; fileTypeName = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeName : ""; fileTypeDescription = cItem.fileTypeResponse != null ? cItem.fileTypeResponse!.fileTypeDescription : ""; @@ -57,18 +60,6 @@ class ChatBubble extends StatelessWidget { userName = AppState().chatDetails!.response!.userName == cItem.currentUserName.toString() ? "You" : cItem.currentUserName.toString(); } - Future getCurrentUrl(String url)async{ - if(Platform.isIOS){ - String a = url.substring(url.indexOf("Documents/") + 10, url.length) ; - Directory dir = await getApplicationDocumentsDirectory(); - a = "${dir.path}/$a"; - return a; - } - else{ - return url; - } - } - void playVoice( BuildContext context, { required SingleUserChatModel data, @@ -91,36 +82,30 @@ class ChatBubble extends StatelessWidget { } else { Utils.showLoading(context); Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? "")); - // try { - File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); - if(sFile.path.isEmpty){ - logger.d("Path Is Emptyyyyyyy"); - }else{ - logger.d("Path Exsists"); - } - data.voice = sFile; - if (Platform.isIOS) { - logger.d("isIOS"); - Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); - await data.voiceController!.seek(duration); - await data.voiceController!.setLoopMode(LoopMode.off); - await data.voiceController!.setVolume(1.0); + // try { + File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); + if (sFile.path.isEmpty) { + logger.d("Path Is Emptyyyyyyy"); + } else { + logger.d("Path Exsists"); + } + data.voice = sFile; + if (Platform.isIOS) { + logger.d("isIOS"); + Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + await data.voiceController!.seek(duration); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.setVolume(1.0); await data.voiceController!.load(); - Utils.hideLoading(context); - data.voiceController!.play(); - } else { - Duration? duration = await data.voiceController!.setFilePath(sFile.path); - await data.voiceController!.setLoopMode(LoopMode.off); - await data.voiceController!.seek(duration); - - Utils.hideLoading(context); - await data.voiceController!.play(); - } - - // } catch (e) { - // Utils.hideLoading(context); - // Utils.showToast(e.toString()); - // } + Utils.hideLoading(context); + data.voiceController!.play(); + } else { + Duration? duration = await data.voiceController!.setFilePath(sFile.path); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.seek(duration); + Utils.hideLoading(context); + await data.voiceController!.play(); + } } } @@ -168,9 +153,12 @@ class ChatBubble extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), - (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "") - .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) - .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + Directionality( + textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""), + child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "") + .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) + .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ), ], ).expanded, if (cItem.userChatReplyResponse != null) @@ -215,7 +203,7 @@ class ChatBubble extends StatelessWidget { // || fileTypeID == 2 ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), - (cItem.contant ?? "").toText12().expanded, + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12().expanded), if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 //|| fileTypeID == 2 ) @@ -269,9 +257,12 @@ class ChatBubble extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ (userName).toText12(color: MyColors.gradiantStartColor, isBold: false).paddingOnly(right: 5, top: 5, bottom: 0, left: 5), - (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "") - .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) - .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + Directionality( + textDirection: provider.getTextDirection(cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : ""), + child: (cItem.userChatReplyResponse != null ? cItem.userChatReplyResponse!.contant.toString() : "") + .toText10(color: isCurrentUser ? MyColors.grey71Color : MyColors.white.withOpacity(0.5), isBold: false, maxlines: 4) + .paddingOnly(right: 5, top: 5, bottom: 8, left: 5), + ), ], ).expanded, if (cItem.userChatReplyResponse != null) @@ -317,7 +308,7 @@ class ChatBubble extends StatelessWidget { // || fileTypeID == 2 ) SvgPicture.asset(provider.getType(fileTypeName ?? ""), height: 30, width: 22, alignment: Alignment.center, fit: BoxFit.cover).paddingOnly(left: 0, right: 10), - (cItem.contant ?? "").toText12(color: Colors.white).expanded, + Directionality(textDirection: provider.getTextDirection(cItem.contant ?? ""), child: (cItem.contant ?? "").toText12(color: Colors.white).expanded), if (fileTypeID == 1 || fileTypeID == 5 || fileTypeID == 7 || fileTypeID == 6 || fileTypeID == 8 //|| fileTypeID == 2 ) @@ -335,6 +326,10 @@ class ChatBubble extends StatelessWidget { ).paddingOnly(right: MediaQuery.of(context).size.width * 0.3); } + Widget voiceMsg(BuildContext context) { + return Container(); + } + Widget showImage({required bool isReplyPreview, required String fileName, required String fileTypeDescription}) { if (cItem.isImageLoaded! && cItem.image != null) { return Image.memory( @@ -455,7 +450,7 @@ class ChatBubble extends StatelessWidget { playVoice(context, data: modelData); }); } else if (processingState != ProcessingState.completed) { - return Icon( + return const Icon( Icons.pause, size: 30, color: MyColors.lightGreenColor, @@ -463,7 +458,7 @@ class ChatBubble extends StatelessWidget { pausePlaying(context, data: modelData); }); } else { - return Icon( + return const Icon( Icons.replay, size: 30, color: MyColors.lightGreenColor, @@ -476,7 +471,6 @@ class ChatBubble extends StatelessWidget { } } -// Feed your own stream of bytes into the player class MyCustomStream extends StreamAudioSource { final Uint8List bytes; diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 3e02d96..1bbae82 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -42,6 +42,7 @@ class _ChatDetailScreenState extends State { final RefreshController _rc = RefreshController(initialRefresh: false); late ChatProviderModel data; ChatDetailedScreenParams? params; + var textDirection = TextDirection.RTL; void getMoreChat() async { if (params != null) { @@ -202,8 +203,7 @@ class _ChatDetailScreenState extends State { WaveBubble( playerController: m.playerController, isPlaying: m.playerController.playerState == PlayerState.playing, - onTap: () { - }, + onTap: () {}, ).expanded else AudioWaveforms( @@ -253,6 +253,7 @@ class _ChatDetailScreenState extends State { Row( children: [ TextField( + textDirection: m.textDirection, controller: m.message, decoration: InputDecoration( hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), @@ -275,11 +276,8 @@ class _ChatDetailScreenState extends State { : null, ), onChanged: (String val) { - if (val.isNotEmpty) { - m.isTextMsg = true; - } else { - m.isTextMsg = false; - } + m.inputBoxDirection(val); + m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); }, ).expanded, diff --git a/lib/ui/landing/dashboard_screen.dart b/lib/ui/landing/dashboard_screen.dart index 98bf976..5d5549d 100644 --- a/lib/ui/landing/dashboard_screen.dart +++ b/lib/ui/landing/dashboard_screen.dart @@ -58,7 +58,7 @@ class _DashboardScreenState extends State { data = Provider.of(context, listen: false); marathonProvider = Provider.of(context, listen: false); cProvider = Provider.of(context, listen: false); - + _bHubCon(); _onRefresh(); }); } @@ -80,7 +80,6 @@ class _DashboardScreenState extends State { void _onRefresh() async { data.initProvider(); - _bHubCon(); // data.getITGNotification().then((value) { // print("--------------------detail_1-----------------"); // print(value!.result!.data!.notificationMasterId); diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 7ba82e4..0028505 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -1,3 +1,4 @@ +import 'dart:convert'; import 'dart:io'; import 'package:easy_localization/easy_localization.dart'; @@ -12,12 +13,14 @@ import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:mohem_flutter_app/classes/notifications.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; +import 'package:mohem_flutter_app/main.dart'; import 'package:mohem_flutter_app/models/check_mobile_app_version_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/models/member_information_list_model.dart'; @@ -25,6 +28,7 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:safe_device/safe_device.dart'; class LoginScreen extends StatefulWidget { @@ -93,6 +97,7 @@ class _LoginScreenState extends State { await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; firebaseToken = await _firebaseMessaging.getToken(); + AppNotifications().initNotification(firebaseToken); loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); if (loginInfo == null) { await checkPrefs(); @@ -154,6 +159,7 @@ class _LoginScreenState extends State { } } + @override Widget build(BuildContext context) { if (isAppOpenBySystem == null) { diff --git a/pubspec.yaml b/pubspec.yaml index 3167dcd..6f277f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,6 +92,7 @@ dependencies: swipe_to: ^1.0.2 flutter_webrtc: ^0.9.16 camera: ^0.10.0+4 + flutter_local_notifications: any #Chat Voice Message Recoding & Play audio_waveforms: ^0.1.5+1 @@ -106,6 +107,10 @@ dependencies: flutter_layout_grid: ^2.0.1 +dependency_overrides: + firebase_core_platform_interface: 4.5.1 + + dev_dependencies: flutter_test: sdk: flutter From a9bf383164c68fa7fecddcdf7993ab68108a267a Mon Sep 17 00:00:00 2001 From: haroon amjad Date: Wed, 18 Jan 2023 12:53:43 +0300 Subject: [PATCH 3/9] Updates & fixes --- android/app/build.gradle | 22 ++++++++++++++----- android/app/src/main/AndroidManifest.xml | 1 + ios/Runner/Info.plist | 16 ++++++++------ .../items_for_sale_api_client.dart | 2 +- lib/api/offers_and_discounts_api_client.dart | 2 +- lib/app_state/app_state.dart | 2 +- lib/classes/consts.dart | 4 ++-- lib/ui/login/login_screen.dart | 9 ++++++++ lib/widgets/mark_attendance_widget.dart | 12 +++++----- pubspec.yaml | 4 ++-- 10 files changed, 49 insertions(+), 25 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 9cd8b0e..198bc87 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -21,6 +21,12 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'com.google.gms.google-services' @@ -44,18 +50,24 @@ android { defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.cloudSolutions.mohemmtest" + applicationId "hmg.cloudSolutions.mohem" minSdkVersion 21 - targetSdkVersion 32 + targetSdkVersion 33 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } buildTypes { release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig signingConfigs.release } } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 30555e1..bd112a0 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ + CFBundleInfoDictionaryVersion 6.0 CFBundleName - mohem_flutter_app + MOHEMM CFBundlePackageType APPL CFBundleShortVersionString @@ -42,10 +42,10 @@ This App requires access to your location to mark your attendance. NSLocationWhenInUseUsageDescription This App requires access to your location to mark your attendance. - NSPhotoLibraryUsageDescription - This app requires photo library access to select image as document & upload it. NSMicrophoneUsageDescription This app requires microphone access to for call. + NSPhotoLibraryUsageDescription + This app requires photo library access to select image as document & upload it. UIBackgroundModes remote-notification @@ -69,13 +69,15 @@ UIViewControllerBasedStatusBarAppearance - com.apple.developer.nfc.readersession.formats - - TAG - com.apple.developer.nfc.readersession.felica.systemcodes 0000 + ITSAppUsesNonExemptEncryption + + com.apple.developer.nfc.readersession.formats + + TAG + diff --git a/lib/api/items_for_sale/items_for_sale_api_client.dart b/lib/api/items_for_sale/items_for_sale_api_client.dart index eae6ffb..a04651e 100644 --- a/lib/api/items_for_sale/items_for_sale_api_client.dart +++ b/lib/api/items_for_sale/items_for_sale_api_client.dart @@ -32,7 +32,7 @@ class ItemsForSaleApiClient { getSaleCategoriesListObj.titleAr = "الجميع"; getSaleCategoriesListObj.isActive = true; getSaleCategoriesListObj.content = - ''; + ' '; getSaleCategoriesList.add(getSaleCategoriesListObj); diff --git a/lib/api/offers_and_discounts_api_client.dart b/lib/api/offers_and_discounts_api_client.dart index 6189612..1d3153c 100644 --- a/lib/api/offers_and_discounts_api_client.dart +++ b/lib/api/offers_and_discounts_api_client.dart @@ -30,7 +30,7 @@ class OffersAndDiscountsApiClient { getSaleCategoriesListObj.categoryNameAr = "الجميع"; getSaleCategoriesListObj.isActive = true; getSaleCategoriesListObj.content = - ''; + ' '; getSaleCategoriesList.add(getSaleCategoriesListObj); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index b3a4a32..6f4e698 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -76,7 +76,7 @@ class AppState { bool get getIsDemoMarathon => _isDemoMarathon; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 3.8, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 3.9, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart index 6679cbb..56b0008 100644 --- a/lib/classes/consts.dart +++ b/lib/classes/consts.dart @@ -3,8 +3,8 @@ import 'package:mohem_flutter_app/ui/marathon/widgets/question_card.dart'; class ApiConsts { //static String baseUrl = "http://10.200.204.20:2801/"; // Local server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server - static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server - // static String baseUrl = "https://hmgwebservices.com"; // Live server + // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT server + static String baseUrl = "https://hmgwebservices.com"; // Live server static String baseUrlServices = baseUrl + "/Services/"; // server // static String baseUrlServices = "https://api.cssynapses.com/tangheem/"; // Live server static String utilitiesRest = baseUrlServices + "Utilities.svc/REST/"; diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 26e9f3e..0d14e99 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -26,6 +26,7 @@ import 'package:mohem_flutter_app/models/member_login_list_model.dart'; import 'package:mohem_flutter_app/models/privilege_list_model.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/input_widget.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:safe_device/safe_device.dart'; class LoginScreen extends StatefulWidget { @@ -92,6 +93,14 @@ class _LoginScreenState extends State { try { Utils.showLoading(context); await Firebase.initializeApp(); + if(Platform.isIOS) { + await FirebaseMessaging.instance.requestPermission(); + } else { + await Permission.notification.request().then((value) { + }).catchError((err) { + print(err); + }); + } await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, diff --git a/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart index 59681b7..6b89c42 100644 --- a/lib/widgets/mark_attendance_widget.dart +++ b/lib/widgets/mark_attendance_widget.dart @@ -218,13 +218,13 @@ class _MarkAttendanceWidgetState extends State { Utils.showLoading(context); bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "", password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false); - // - // print("CURRENT SSID: ${await WiFiForIoTPlugin.getSSID()}"); - if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { - isConnected = true; - } else { - isConnected = false; + if (Platform.isIOS) { + if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) { + isConnected = true; + } else { + isConnected = false; + } } if (isConnected) { diff --git a/pubspec.yaml b/pubspec.yaml index 3167dcd..db3f4ed 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 3.6.0+300060 +version: 3.2.0+300020 environment: sdk: ">=2.16.0 <3.0.0" @@ -40,7 +40,7 @@ dependencies: provider: ^6.0.1 easy_localization: ^3.0.0 http: ^0.13.4 - permission_handler: ^9.2.0 + permission_handler: ^10.2.0 flutter_svg: any sizer: ^2.0.15 local_auth: ^1.1.9 From 7152b0d57bee13d19be15fbc3fa720424c67ca0e Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 19 Jan 2023 11:24:51 +0300 Subject: [PATCH 4/9] Chat Fix --- lib/api/chat/chat_api_client.dart | 4 ++-- lib/app_state/app_state.dart | 2 +- lib/classes/notifications.dart | 22 ++++++++++------------ lib/ui/chat/chat_detailed_screen.dart | 1 - pubspec.yaml | 4 ++-- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index efd7af9..b525efd 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -38,8 +38,8 @@ class ChatApiClient { print({ "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", - "isMobile": true, - "deviceToken": AppState().deviceNotificationToken + // "isMobile": true, + // "deviceToken": AppState().deviceNotificationToken }); if (!kReleaseMode) { logger.i("login-res: " + response.body); diff --git a/lib/app_state/app_state.dart b/lib/app_state/app_state.dart index 8d09d2d..4a2bd7e 100644 --- a/lib/app_state/app_state.dart +++ b/lib/app_state/app_state.dart @@ -70,7 +70,7 @@ class AppState { bool get getIsDemoMarathon => _isDemoMarathon; - final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 3.8, mobileType: Platform.isAndroid ? "android" : "ios"); + final PostParamsModel _postParamsInitConfig = PostParamsModel(channel: 31, versionID: 3.9, mobileType: Platform.isAndroid ? "android" : "ios"); void setPostParamsInitConfig() { isAuthenticated = false; diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 26bb70d..649b757 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -1,13 +1,11 @@ import 'dart:convert'; import 'dart:io'; - import 'package:firebase_messaging/firebase_messaging.dart'; -import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/main.dart'; import 'package:permission_handler/permission_handler.dart'; -final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); +//final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); class AppNotifications { @@ -19,21 +17,21 @@ class AppNotifications { Future requestPermissions() async { if (Platform.isIOS) { - await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); + // await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); } else if (Platform.isAndroid) { - AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); - bool? granted = await androidImplementation?.requestPermission(); - if (granted == false) { - print("-------------------- Permission Granted ------------------------"); - print(granted); - await Permission.notification.request(); - } + // AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); + // bool? granted = await androidImplementation?.requestPermission(); + // if (granted == false) { + // print("-------------------- Permission Granted ------------------------"); + // print(granted); + // await Permission.notification.request(); + // } } } Future isAndroidPermGranted() async { if (Platform.isAndroid) { - bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.areNotificationsEnabled() ?? false; + // bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.areNotificationsEnabled() ?? false; } } diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 1bbae82..da547cf 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -277,7 +277,6 @@ class _ChatDetailScreenState extends State { ), onChanged: (String val) { m.inputBoxDirection(val); - m.userTypingInvoke(currentUser: AppState().chatDetails!.response!.id!, reciptUser: params!.chatUser!.id!); }, ).expanded, diff --git a/pubspec.yaml b/pubspec.yaml index 6f277f5..c343421 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -92,7 +92,7 @@ dependencies: swipe_to: ^1.0.2 flutter_webrtc: ^0.9.16 camera: ^0.10.0+4 - flutter_local_notifications: any + #flutter_local_notifications: any #Chat Voice Message Recoding & Play audio_waveforms: ^0.1.5+1 @@ -108,7 +108,7 @@ dependencies: dependency_overrides: - firebase_core_platform_interface: 4.5.1 + #firebase_core_platform_interface: 4.5.1 dev_dependencies: From 03ae216b695499a99e18fac7de685ce01ca8e893 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 19 Jan 2023 11:31:33 +0300 Subject: [PATCH 5/9] Chat fix --- lib/api/chat/chat_api_client.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index b525efd..b408362 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -29,15 +29,15 @@ class ChatApiClient { "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", - "isMobile": true, - "deviceToken": AppState().deviceNotificationToken + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" + // "isMobile": true, + // "deviceToken": AppState().deviceNotificationToken }, ); print({ "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" // "isMobile": true, // "deviceToken": AppState().deviceNotificationToken }); From f8ae5b0987f8167e42ad333871c66fb19bd8a140 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 19 Jan 2023 15:53:49 +0300 Subject: [PATCH 6/9] mark attendance session expire fixed --- lib/api/chat/chat_api_client.dart | 6 ------ lib/provider/chat_provider_model.dart | 16 ++++++++-------- lib/ui/chat/chat_detailed_screen.dart | 5 ++++- pubspec.yaml | 2 +- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index b408362..210106e 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -35,12 +35,6 @@ class ChatApiClient { }, ); - print({ - "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" - // "isMobile": true, - // "deviceToken": AppState().deviceNotificationToken - }); if (!kReleaseMode) { logger.i("login-res: " + response.body); } diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index c0a16c0..71d7ccb 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1415,17 +1415,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void inputBoxDirection(String val) { if (val.isNotEmpty) { isTextMsg = true; + RegExp exp = RegExp("[a-zA-Z]"); + if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") { + textDirection = Material.TextDirection.ltr; + notifyListeners(); + } else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) { + textDirection = Material.TextDirection.rtl; + notifyListeners(); + } } else { isTextMsg = false; } - RegExp exp = RegExp("[a-zA-Z]"); - if (exp.hasMatch(val.substring(val.length - 1)) && val.substring(val.length - 1) != " ") { - textDirection = Material.TextDirection.ltr; - notifyListeners(); - } else if (val.substring(val.length - 1) != " " && !exp.hasMatch(val.substring(val.length - 1))) { - textDirection = Material.TextDirection.rtl; - notifyListeners(); - } } Material.TextDirection getTextDirection(String v) { diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index da547cf..a72e12b 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -256,7 +256,10 @@ class _ChatDetailScreenState extends State { textDirection: m.textDirection, controller: m.message, decoration: InputDecoration( - hintText: m.isAttachmentMsg ? m.selectedFile.path.split("/").last : LocaleKeys.typeheretoreply.tr(), + hintTextDirection: m.textDirection, + hintText: m.isAttachmentMsg + ? m.selectedFile.path.split("/").last + : m.textDirection.name == "rtl" ? "اكتب هنا للرد" :LocaleKeys.typeheretoreply.tr(), hintStyle: TextStyle(color: m.isAttachmentMsg ? MyColors.darkTextColor : MyColors.grey98Color, fontSize: 14), border: InputBorder.none, focusedBorder: InputBorder.none, diff --git a/pubspec.yaml b/pubspec.yaml index c343421..b3d6c4c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -108,7 +108,7 @@ dependencies: dependency_overrides: - #firebase_core_platform_interface: 4.5.1 + firebase_core_platform_interface: 4.5.1 dev_dependencies: From 33da1a103d23431017e19a20b114b8806e721a0a Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Thu, 19 Jan 2023 16:28:44 +0300 Subject: [PATCH 7/9] mark attendance session expire fixed --- ios/Runner/AppDelegate.swift | 10 ++------ ios/Runner/Info.plist | 14 +++++++----- lib/api/chat/chat_api_client.dart | 6 ++--- lib/classes/notifications.dart | 38 +++++++++++++++---------------- 4 files changed, 32 insertions(+), 36 deletions(-) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index 7d74b94..c1c9fd9 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -1,6 +1,6 @@ import UIKit import Flutter -import flutter_local_notifications +import Firebase @UIApplicationMain @@ -9,13 +9,7 @@ import flutter_local_notifications _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { - FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in - GeneratedPluginRegistrant.register(with: registry) - } - - if #available(iOS 10.0, *) { - UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate - } + FirebaseApp.configure() GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index f8d7b49..15e0a0c 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -42,14 +42,16 @@ This App requires access to your location to mark your attendance. NSLocationWhenInUseUsageDescription This App requires access to your location to mark your attendance. - NSPhotoLibraryUsageDescription - This app requires photo library access to select image as document & upload it. NSMicrophoneUsageDescription This app requires microphone access to for call. + NSPhotoLibraryUsageDescription + This app requires photo library access to select image as document & upload it. UIBackgroundModes remote-notification + FirebaseAppDelegateProxyEnabled + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -69,13 +71,13 @@ UIViewControllerBasedStatusBarAppearance - com.apple.developer.nfc.readersession.formats - - TAG - com.apple.developer.nfc.readersession.felica.systemcodes 0000 + com.apple.developer.nfc.readersession.formats + + TAG + diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index 210106e..3ad0ed7 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -29,9 +29,9 @@ class ChatApiClient { "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" - // "isMobile": true, - // "deviceToken": AppState().deviceNotificationToken + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "isMobile": true, + "deviceToken": AppState().deviceNotificationToken }, ); diff --git a/lib/classes/notifications.dart b/lib/classes/notifications.dart index 649b757..b7d7988 100644 --- a/lib/classes/notifications.dart +++ b/lib/classes/notifications.dart @@ -15,25 +15,25 @@ class AppNotifications { factory AppNotifications() => _instance; - Future requestPermissions() async { - if (Platform.isIOS) { - // await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); - } else if (Platform.isAndroid) { - // AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); - // bool? granted = await androidImplementation?.requestPermission(); - // if (granted == false) { - // print("-------------------- Permission Granted ------------------------"); - // print(granted); - // await Permission.notification.request(); - // } - } - } - - Future isAndroidPermGranted() async { - if (Platform.isAndroid) { - // bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.areNotificationsEnabled() ?? false; - } - } + // Future requestPermissions() async { + // if (Platform.isIOS) { + // await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(alert: true, badge: true, sound: true); + // } else if (Platform.isAndroid) { + // AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation(); + // bool? granted = await androidImplementation?.requestPermission(); + // if (granted == false) { + // print("-------------------- Permission Granted ------------------------"); + // print(granted); + // await Permission.notification.request(); + // } + // } + // } + + // Future isAndroidPermGranted() async { + // if (Platform.isAndroid) { + // bool granted = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.areNotificationsEnabled() ?? false; + // } + // } void initNotification(String? firebaseToken) async { // await requestPermissions(); From 7f9c82d165659d873e117c05231a271a9421382c Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 19 Jan 2023 16:30:58 +0300 Subject: [PATCH 8/9] ChatFix --- lib/api/chat/chat_api_client.dart | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/api/chat/chat_api_client.dart b/lib/api/chat/chat_api_client.dart index b408362..d029866 100644 --- a/lib/api/chat/chat_api_client.dart +++ b/lib/api/chat/chat_api_client.dart @@ -29,18 +29,13 @@ class ChatApiClient { "${ApiConsts.chatLoginTokenUrl}externaluserlogin", { "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" - // "isMobile": true, - // "deviceToken": AppState().deviceNotificationToken + "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG", + "isMobile": true, + "deviceToken": AppState().deviceNotificationToken }, ); - print({ - "employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(), - "password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG" - // "isMobile": true, - // "deviceToken": AppState().deviceNotificationToken - }); + if (!kReleaseMode) { logger.i("login-res: " + response.body); } From 81a060012ee91b4349b8887056e17b8f883bb7f2 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Thu, 19 Jan 2023 16:44:06 +0300 Subject: [PATCH 9/9] Chat Fix --- lib/ui/login/login_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ui/login/login_screen.dart b/lib/ui/login/login_screen.dart index 0ec0bdb..6253002 100644 --- a/lib/ui/login/login_screen.dart +++ b/lib/ui/login/login_screen.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/consts.dart'; +import 'package:mohem_flutter_app/classes/notifications.dart'; import 'package:mohem_flutter_app/classes/push-notification-handler.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; @@ -96,7 +97,6 @@ class _LoginScreenState extends State { await Firebase.initializeApp(); _firebaseMessaging = FirebaseMessaging.instance; firebaseToken = await _firebaseMessaging.getToken(); - AppState().setDeviceToken = firebaseToken; AppNotifications().initNotification(firebaseToken); loginInfo = await LoginApiClient().getMobileLoginInfoNEW(firebaseToken ?? "", Platform.isAndroid ? "android" : "ios"); if (loginInfo == null) {