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..070597d 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
+
+
+
+
+
+
+
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 70693e4..c1c9fd9 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,5 +1,7 @@
import UIKit
import Flutter
+import Firebase
+
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
@@ -7,6 +9,7 @@ import Flutter
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
+ 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..e326d8f 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -13,7 +13,7 @@
CFBundleInfoDictionaryVersion
6.0
CFBundleName
- mohem_flutter_app
+ MOHEMM
CFBundlePackageType
APPL
CFBundleShortVersionString
@@ -46,10 +46,14 @@
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,6 +73,13 @@
UIViewControllerBasedStatusBarAppearance
+ com.apple.developer.nfc.readersession.felica.systemcodes
+
+ 0000
+
+ ITSAppUsesNonExemptEncryption
+
+
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 87e684e..b4c0a2c 100644
--- a/lib/api/chat/chat_api_client.dart
+++ b/lib/api/chat/chat_api_client.dart
@@ -30,10 +30,13 @@ class ChatApiClient {
{
"employeeNumber": AppState().memberInformationList!.eMPLOYEENUMBER.toString(),
"password": "FxIu26rWIKoF8n6mpbOmAjDLphzFGmpG",
+ "isMobile": true,
+ "deviceToken": AppState().getDeviceToken,
},
);
+
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/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 e43c774..731a45e 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;
@@ -70,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;
@@ -173,4 +179,13 @@ class AppState {
}
bool cancelRequestTrancsection = true;
+
+
+ String? _deviceNotificationToken;
+
+ String? get deviceNotificationToken => _deviceNotificationToken;
+
+ set deviceNotificationToken(String? deviceNotificationToken) {
+ _deviceNotificationToken = deviceNotificationToken;
+ }
}
diff --git a/lib/classes/consts.dart b/lib/classes/consts.dart
index 56ddde6..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/classes/notifications.dart b/lib/classes/notifications.dart
new file mode 100644
index 0000000..b7d7988
--- /dev/null
+++ b/lib/classes/notifications.dart
@@ -0,0 +1,59 @@
+import 'dart:convert';
+import 'dart:io';
+import 'package:firebase_messaging/firebase_messaging.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/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/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart
index 460a338..71d7ccb 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;
+ 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;
+ }
+ }
+
+ 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..a72e12b 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,9 +253,13 @@ 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(),
+ 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,
@@ -275,11 +279,7 @@ 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 b4ccb0a..1a91636 100644
--- a/lib/ui/landing/dashboard_screen.dart
+++ b/lib/ui/landing/dashboard_screen.dart
@@ -60,7 +60,7 @@ class _DashboardScreenState extends State with WidgetsBindingOb
data = Provider.of(context, listen: false);
marathonProvider = Provider.of(context, listen: false);
cProvider = Provider.of(context, listen: false);
-
+ _bHubCon();
_onRefresh();
});
}
@@ -101,7 +101,6 @@ class _DashboardScreenState extends State with WidgetsBindingOb
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..6253002 100644
--- a/lib/ui/login/login_screen.dart
+++ b/lib/ui/login/login_screen.dart
@@ -12,12 +12,15 @@ 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';
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/lib/widgets/mark_attendance_widget.dart b/lib/widgets/mark_attendance_widget.dart
index dfe3b79..6b89c42 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);
+
+ if (Platform.isIOS) {
+ if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
+ isConnected = true;
+ } else {
+ isConnected = false;
+ }
+ }
+
if (isConnected) {
if (Platform.isIOS) {
await closeWifiRequest();
diff --git a/pubspec.yaml b/pubspec.yaml
index 3167dcd..189128d 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
@@ -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