From 54961c875f1ac3234cbf1a38692e2f8fbdd6f66f Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Sun, 1 Jan 2023 16:02:39 +0300 Subject: [PATCH 1/7] Ios Stream Audio --- assets/langs/ar-SA.json | 3 +- assets/langs/en-US.json | 3 +- lib/generated/locale_keys.g.dart | 1 + lib/ui/chat/chat_bubble.dart | 65 ++++++++++++++----- lib/ui/chat/chat_detailed_screen.dart | 1 - lib/ui/chat/chat_home.dart | 2 +- .../search_employee_bottom_sheet.dart | 1 - 7 files changed, 55 insertions(+), 21 deletions(-) diff --git a/assets/langs/ar-SA.json b/assets/langs/ar-SA.json index c7259fd..60b88a8 100644 --- a/assets/langs/ar-SA.json +++ b/assets/langs/ar-SA.json @@ -518,5 +518,6 @@ "winners": "الفائزين!!!", "noUpcoming": "لا يوجد قادم", "fakeLocation": ".لقد تتبعنا أنك تحاول استخدام موقع مزيف! يعتبر هذا مخالفة وقد تم إخطار الموارد البشرية", - "noWinner": "حزين! لم يفز أحد اليوم." + "noWinner": "حزين! لم يفز أحد اليوم.", + "myTeam" : "فريقي" } \ No newline at end of file diff --git a/assets/langs/en-US.json b/assets/langs/en-US.json index f1eac93..10cfbdf 100644 --- a/assets/langs/en-US.json +++ b/assets/langs/en-US.json @@ -518,5 +518,6 @@ "winners": "WINNERS!!!", "noUpcoming": "There is no upcoming", "fakeLocation": "We traced out that you try to use a fake location! This is considered a violation, and HR has been notified.", - "noWinner": "Sad! No one won today." + "noWinner": "Sad! No one won today.", + "myTeam" : "My Team" } \ No newline at end of file diff --git a/lib/generated/locale_keys.g.dart b/lib/generated/locale_keys.g.dart index 1114c23..035d458 100644 --- a/lib/generated/locale_keys.g.dart +++ b/lib/generated/locale_keys.g.dart @@ -505,5 +505,6 @@ abstract class LocaleKeys { static const noUpcoming = 'noUpcoming'; static const fakeLocation = 'fakeLocation'; static const noWinner = 'noWinner'; + static const myTeam = 'myTeam'; } diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 93fea00..ee28c95 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -61,11 +61,17 @@ class ChatBubble extends StatelessWidget { required SingleUserChatModel data, }) async { if (data.voice != null && data.voice!.existsSync()) { - await data.voiceController!.setFilePath(data!.voice!.path); await data.voiceController!.setLoopMode(LoopMode.off); - Duration? duration = await data.voiceController!.load(); - await data.voiceController!.seek(duration); - await data.voiceController!.play(); + if (Platform.isIOS) { + Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(data.voice!.readAsBytesSync())); + await data.voiceController!.seek(duration); + data.voiceController!.play(); + } else { + await data.voiceController!.setFilePath(data!.voice!.path); + Duration? duration = await data.voiceController!.load(); + await data.voiceController!.seek(duration); + await data.voiceController!.play(); + } } else { Utils.showLoading(context); Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? "")); @@ -74,13 +80,19 @@ class ChatBubble extends StatelessWidget { File file = File(path!); await file.readAsBytes(); data.voice = file; - Duration? duration = await data.voiceController!.setFilePath(file.path); - await data.voiceController!.setLoopMode(LoopMode.off); - await data.voiceController!.seek(duration); - await data.voiceController!.setVolume(1.0); - await data.voiceController!.load(); - Utils.hideLoading(context); - await data.voiceController!.play(); + if (Platform.isIOS) { + Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(encodedString)); + await data.voiceController!.seek(duration); + data.voiceController!.play(); + } else { + Duration? duration = await data.voiceController!.setFilePath(file.path); + await data.voiceController!.setLoopMode(LoopMode.off); + await data.voiceController!.seek(duration); + await data.voiceController!.setVolume(1.0); + await data.voiceController!.load(); + Utils.hideLoading(context); + await data.voiceController!.play(); + } } catch (e) { Utils.hideLoading(context); Utils.showToast(e.toString()); @@ -114,7 +126,7 @@ class ChatBubble extends StatelessWidget { Widget currentUser(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ if (isReplied) ClipRRect( borderRadius: BorderRadius.circular(5.0), @@ -200,7 +212,7 @@ class ChatBubble extends StatelessWidget { ), ), ], - ).paddingOnly(top: 11, left: 13, right: 13, bottom: 5).objectContainerView(disablePadding: true).paddingOnly(left: MediaQuery.of(context).size.width * 0.3); + ).paddingOnly(top: 11, left: 13, right: 13, bottom: 5).objectContainerView(disablePadding: true, radius: 10).paddingOnly(left: MediaQuery.of(context).size.width * 0.3); } Widget receiptUser(BuildContext context) { @@ -340,6 +352,7 @@ class ChatBubble extends StatelessWidget { Widget currentWaveBubble(BuildContext context, SingleUserChatModel data) { return Container( margin: const EdgeInsets.all(0), + constraints: const BoxConstraints(), decoration: BoxDecoration( border: Border( left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), @@ -411,7 +424,7 @@ class ChatBubble extends StatelessWidget { child: const CircularProgressIndicator(), ); } else if (playing != true) { - return Icon( + return const Icon( Icons.play_arrow, size: 30, color: MyColors.lightGreenColor, @@ -419,7 +432,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, @@ -427,7 +440,7 @@ class ChatBubble extends StatelessWidget { pausePlaying(context, data: modelData); }); } else { - return Icon( + return const Icon( Icons.replay, size: 30, color: MyColors.lightGreenColor, @@ -439,3 +452,23 @@ class ChatBubble extends StatelessWidget { ); } } + +// Feed your own stream of bytes into the player +class MyCustomStream extends StreamAudioSource { + final Uint8List bytes; + + MyCustomStream(this.bytes); + + @override + Future request([int? start, int? end]) async { + start ??= 0; + end ??= bytes.length; + return StreamAudioResponse( + sourceLength: bytes.length, + contentLength: end - start, + offset: start, + stream: Stream.value(bytes.sublist(start, end)), + contentType: 'audio/aac', + ); + } +} diff --git a/lib/ui/chat/chat_detailed_screen.dart b/lib/ui/chat/chat_detailed_screen.dart index 595dc13..f597fe2 100644 --- a/lib/ui/chat/chat_detailed_screen.dart +++ b/lib/ui/chat/chat_detailed_screen.dart @@ -275,7 +275,6 @@ class _ChatDetailScreenState extends State { : null, ), onChanged: (String val) { - print(val.length); if (val.isNotEmpty) { m.isTextMsg = true; } else { diff --git a/lib/ui/chat/chat_home.dart b/lib/ui/chat/chat_home.dart index 49908dd..bbb3048 100644 --- a/lib/ui/chat/chat_home.dart +++ b/lib/ui/chat/chat_home.dart @@ -83,7 +83,7 @@ class _ChatHomeState extends State { children: [ myTab(LocaleKeys.mychats.tr(), 0), myTab(LocaleKeys.favorite.tr(), 1), - AppState().getempStatusIsManager ? myTab("My Team", 2) : const SizedBox(), + AppState().getempStatusIsManager ? myTab(LocaleKeys.myTeam.tr(), 2) : const SizedBox(), ], ), ), diff --git a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart index d06bfdc..b20674e 100644 --- a/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart +++ b/lib/widgets/bottom_sheets/search_employee_bottom_sheet.dart @@ -136,7 +136,6 @@ class _SearchEmployeeBottomSheetState extends State { @override void dispose() { - print("// TODO: implement dispose"); super.dispose(); provider.chatUsersList = []; provider.pageNo = 1; From 088fd6f318bec4c63a74125ab8a8a7ce6a6287cc Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Sun, 1 Jan 2023 17:03:31 +0300 Subject: [PATCH 2/7] Ios Fix --- lib/provider/chat_provider_model.dart | 24 ++++++++---- lib/ui/chat/chat_bubble.dart | 56 +++++++++++++++++---------- 2 files changed, 52 insertions(+), 28 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 0851392..d4e90a4 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1295,15 +1295,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { return numberStr; } - Future downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async { - String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; - if (!await Directory(dirPath).exists()) { - await Directory(dirPath).create(); - await File('$dirPath/.nomedia').create(); + Future downChatVoice(Uint8List bytes, String ext, SingleUserChatModel data) async { + File file; + try { + String dirPath = '${(await getApplicationDocumentsDirectory()).path}/chat_audios'; + if (!await Directory(dirPath).exists()) { + await Directory(dirPath).create(); + await File('$dirPath/.nomedia').create(); + } + file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}" + ext); + await file.writeAsBytes(bytes); + } catch (e) { + if (kDebugMode) { + print(e); + } + file = File(""); } - File file = File("$dirPath/${data.currentUserId}-${data.targetUserId}-${DateTime.now().microsecondsSinceEpoch}." + ext); - await file.writeAsBytes(bytes); - return file.path; + return file; } void scrollToMsg(SingleUserChatModel data) { diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index ee28c95..764ccea 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -56,47 +56,64 @@ 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, }) async { if (data.voice != null && data.voice!.existsSync()) { - await data.voiceController!.setLoopMode(LoopMode.off); if (Platform.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(); data.voiceController!.play(); } else { await data.voiceController!.setFilePath(data!.voice!.path); Duration? duration = await data.voiceController!.load(); await data.voiceController!.seek(duration); + await data.voiceController!.setLoopMode(LoopMode.off); await data.voiceController!.play(); } } else { Utils.showLoading(context); Uint8List encodedString = await ChatApiClient().downloadURL(fileName: data.contant!, fileTypeDescription: provider.getFileTypeDescription(data.fileTypeResponse!.fileTypeName ?? "")); - try { - String path = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); - File file = File(path!); - await file.readAsBytes(); - data.voice = file; + // try { + File sFile = await provider.downChatVoice(encodedString, data.fileTypeResponse!.fileTypeName ?? "", data); + data.voice = sFile; if (Platform.isIOS) { - Duration? duration = await data.voiceController!.setAudioSource(MyCustomStream(encodedString)); + 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(file.path); + Duration? duration = await data.voiceController!.setFilePath(sFile.path); await data.voiceController!.setLoopMode(LoopMode.off); await data.voiceController!.seek(duration); - await data.voiceController!.setVolume(1.0); - await data.voiceController!.load(); + Utils.hideLoading(context); await data.voiceController!.play(); } - } catch (e) { - Utils.hideLoading(context); - Utils.showToast(e.toString()); - } + + // } catch (e) { + // Utils.hideLoading(context); + // Utils.showToast(e.toString()); + // } } } @@ -126,7 +143,7 @@ class ChatBubble extends StatelessWidget { Widget currentUser(BuildContext context) { return Column( crossAxisAlignment: CrossAxisAlignment.start, - children: [ + children: [ if (isReplied) ClipRRect( borderRadius: BorderRadius.circular(5.0), @@ -212,7 +229,7 @@ class ChatBubble extends StatelessWidget { ), ), ], - ).paddingOnly(top: 11, left: 13, right: 13, bottom: 5).objectContainerView(disablePadding: true, radius: 10).paddingOnly(left: MediaQuery.of(context).size.width * 0.3); + ).paddingOnly(top: 11, left: 13, right: 13, bottom: 5).objectContainerView(disablePadding: true).paddingOnly(left: MediaQuery.of(context).size.width * 0.3); } Widget receiptUser(BuildContext context) { @@ -352,7 +369,6 @@ class ChatBubble extends StatelessWidget { Widget currentWaveBubble(BuildContext context, SingleUserChatModel data) { return Container( margin: const EdgeInsets.all(0), - constraints: const BoxConstraints(), decoration: BoxDecoration( border: Border( left: BorderSide(width: 6, color: isCurrentUser ? MyColors.gradiantStartColor : MyColors.white), @@ -424,7 +440,7 @@ class ChatBubble extends StatelessWidget { child: const CircularProgressIndicator(), ); } else if (playing != true) { - return const Icon( + return Icon( Icons.play_arrow, size: 30, color: MyColors.lightGreenColor, @@ -432,7 +448,7 @@ class ChatBubble extends StatelessWidget { playVoice(context, data: modelData); }); } else if (processingState != ProcessingState.completed) { - return const Icon( + return Icon( Icons.pause, size: 30, color: MyColors.lightGreenColor, @@ -440,7 +456,7 @@ class ChatBubble extends StatelessWidget { pausePlaying(context, data: modelData); }); } else { - return const Icon( + return Icon( Icons.replay, size: 30, color: MyColors.lightGreenColor, From 16ea3b7c663d964d29870742a014959a1c15b4f4 Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 2 Jan 2023 10:46:28 +0300 Subject: [PATCH 3/7] Ios Fix --- lib/provider/chat_provider_model.dart | 8 -------- lib/ui/chat/chat_bubble.dart | 9 ++++++++- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index d4e90a4..a88a08c 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -119,16 +119,8 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void getUserRecentChats() async { - if (chatHubConnection.state != HubConnectionState.Connected) { - getUserAutoLoginToken().whenComplete(() async { - await buildHubConnection(); - getUserRecentChats(); - }); - return; - } ChatUserModel recentChat = await ChatApiClient().getRecentChats(); ChatUserModel favUList = await ChatApiClient().getFavUsers(); - if (favUList.response != null && recentChat.response != null) { favUsersList = favUList.response!; favUsersList.sort( diff --git a/lib/ui/chat/chat_bubble.dart b/lib/ui/chat/chat_bubble.dart index 764ccea..6d1e2eb 100644 --- a/lib/ui/chat/chat_bubble.dart +++ b/lib/ui/chat/chat_bubble.dart @@ -12,6 +12,7 @@ import 'package:mohem_flutter_app/classes/utils.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/main.dart'; import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart'; import 'package:mohem_flutter_app/provider/chat_provider_model.dart'; import 'package:mohem_flutter_app/ui/chat/chat_full_image_preview.dart'; @@ -92,13 +93,19 @@ class ChatBubble extends StatelessWidget { 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); - await data.voiceController!.load(); + await data.voiceController!.load(); Utils.hideLoading(context); data.voiceController!.play(); } else { From 83b8691a311a9d886b18d012a5d9ca73d5b0c6a7 Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 2 Jan 2023 12:16:03 +0300 Subject: [PATCH 4/7] Ios Stream Audio --- lib/provider/chat_provider_model.dart | 32 ++++++++++++++++++++------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index a88a08c..8a91ddd 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1202,19 +1202,35 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { void startRecoding() async { PermissionStatus status = await Permission.microphone.request(); - if (status.isDenied == true) { + if (status.isDenied) { startRecoding(); + } else if (status.isGranted) { + sRecoding(); } else { - isVoiceMsg = true; - recorderController.reset(); - await recorderController.record(path); - _recodeDuration = 0; - _startTimer(); - isRecoding = !isRecoding; - notifyListeners(); + startRecoding(); } } + // else { + // isVoiceMsg = true; + // recorderController.reset(); + // await recorderController.record(path); + // _recodeDuration = 0; + // _startTimer(); + // isRecoding = !isRecoding; + // notifyListeners(); + // } + + void sRecoding() async { + isVoiceMsg = true; + recorderController.reset(); + await recorderController.record(path); + _recodeDuration = 0; + _startTimer(); + isRecoding = !isRecoding; + notifyListeners(); + } + Future _startTimer() async { _timer?.cancel(); _timer = Timer.periodic(const Duration(seconds: 1), (Timer t) async { From 377fd486934c3e8b0779f7d0fb880d6cf53349bf Mon Sep 17 00:00:00 2001 From: Sikander Saleem Date: Mon, 2 Jan 2023 14:47:38 +0300 Subject: [PATCH 5/7] Ios Fix --- lib/provider/chat_provider_model.dart | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index 8a91ddd..d6e3b57 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1201,14 +1201,17 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void startRecoding() async { - PermissionStatus status = await Permission.microphone.request(); - if (status.isDenied) { - startRecoding(); - } else if (status.isGranted) { - sRecoding(); - } else { - startRecoding(); - } + await Permission.microphone.request().then((PermissionStatus status){ + if (status.isPermanentlyDenied) { + // startRecoding(); + } else if (status.isDenied) { + startRecoding(); + } else if (status.isGranted) { + sRecoding(); + } else { + startRecoding(); + }}); + } // else { From dbb13515fcc6806265843c140ec7f8a33df6de9a Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Mon, 2 Jan 2023 15:35:21 +0300 Subject: [PATCH 6/7] Audio Fix --- lib/provider/chat_provider_model.dart | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/provider/chat_provider_model.dart b/lib/provider/chat_provider_model.dart index d6e3b57..53dbade 100644 --- a/lib/provider/chat_provider_model.dart +++ b/lib/provider/chat_provider_model.dart @@ -1201,17 +1201,23 @@ class ChatProviderModel with ChangeNotifier, DiagnosticableTreeMixin { } void startRecoding() async { - await Permission.microphone.request().then((PermissionStatus status){ + // if (await Permission.microphone.request().isGranted) { + // sRecoding(); + // } else { + // Utils.showToast("Permission Issue"); + // openAppSettings(); + // } + await Permission.microphone.request().then((PermissionStatus status) { if (status.isPermanentlyDenied) { - // startRecoding(); + openAppSettings(); } else if (status.isDenied) { - startRecoding(); + openAppSettings(); } else if (status.isGranted) { sRecoding(); } else { startRecoding(); - }}); - + } + }); } // else { From 538fd133aa49bf39895216ee1ca343900efd8e9d Mon Sep 17 00:00:00 2001 From: "Aamir.Muhammad" Date: Tue, 3 Jan 2023 14:35:35 +0300 Subject: [PATCH 7/7] Title Fix On AppBar --- lib/widgets/chat_app_bar_widge.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/widgets/chat_app_bar_widge.dart b/lib/widgets/chat_app_bar_widge.dart index 790840c..25ed34c 100644 --- a/lib/widgets/chat_app_bar_widge.dart +++ b/lib/widgets/chat_app_bar_widge.dart @@ -76,7 +76,7 @@ AppBar ChatAppBarWidget(BuildContext context, if (chatUser!.isTyping!) ("Typing ...").toText10(color: MyColors.textMixColor) else const SizedBox(), ], ), - ) + ).expanded ], ); }),