333 lines
16 KiB
Dart
333 lines
16 KiB
Dart
import 'dart:io';
|
|
import 'package:audio_waveforms/audio_waveforms.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:taafee_mobile/common/extensions/widget_extension.dart';
|
|
import 'package:taafee_mobile/features/chat/business%20logic%20layer/chat_controller.dart';
|
|
import 'package:taafee_mobile/features/chat/data_layer/model/message.dart';
|
|
import 'package:taafee_mobile/features/home/business_logic_layer/home_controller.dart';
|
|
import '../../../../common/const/const.dart';
|
|
import '../../../../common/widgets/text.dart';
|
|
|
|
class NewVoiceMessage extends StatelessWidget {
|
|
NewVoiceMessage({
|
|
super.key,
|
|
this.dismissibleKey = const Key('sent'),
|
|
required this.messageModel,
|
|
required this.textFieldFocusNode,
|
|
});
|
|
final HomeController homeController = Get.find<HomeController>();
|
|
final ChatController chatController = Get.find<ChatController>();
|
|
final MessageModel messageModel;
|
|
final FocusNode textFieldFocusNode;
|
|
final Key dismissibleKey;
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
PlayerController playerController =
|
|
chatController.getVoicePlayer(messageModel.content).value;
|
|
playerController.onCompletion.listen((event) {
|
|
chatController.updateIsPlaying(messageModel.content, false);
|
|
});
|
|
playerController.onPlayerStateChanged.listen((event) {
|
|
if (event.isPaused || event.isStopped) {
|
|
chatController.updateIsPlaying(messageModel.content, false);
|
|
}
|
|
});
|
|
return Obx(() {
|
|
return Dismissible(
|
|
confirmDismiss: (direction) async {
|
|
chatController.updateReplyModel(messageModel: messageModel);
|
|
if (chatController.isReplying.value == false) {
|
|
chatController.toggleIsReplying();
|
|
}
|
|
|
|
FocusScope.of(context).requestFocus(textFieldFocusNode);
|
|
return false;
|
|
},
|
|
key: dismissibleKey,
|
|
onDismissed: null,
|
|
child: SizedBox(
|
|
width: Get.width * 0.6,
|
|
height: 90,
|
|
child: Container(
|
|
decoration: BoxDecoration(
|
|
borderRadius:
|
|
(messageModel.direction == MessageDirection.received)
|
|
? BorderRadius.circular(10)
|
|
: null,
|
|
color: (messageModel.direction == MessageDirection.received)
|
|
? Colors.white
|
|
: null,
|
|
image: (messageModel.direction == MessageDirection.sent)
|
|
? const DecorationImage(
|
|
image: AssetImage('assets/images/sent message.png'),
|
|
fit: BoxFit.fill)
|
|
: null),
|
|
child: SizedBox(
|
|
width: Get.width,
|
|
height: (messageModel.direction == MessageDirection.received)
|
|
? 100
|
|
: null,
|
|
child: Column(
|
|
crossAxisAlignment:
|
|
(messageModel.direction == MessageDirection.received)
|
|
? CrossAxisAlignment.start
|
|
: CrossAxisAlignment.center,
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Obx(() {
|
|
return Visibility(
|
|
visible: (chatController
|
|
.isLoadingMap.value[messageModel.content] ??
|
|
false),
|
|
child: CircleAvatar(
|
|
radius: 21.3,
|
|
backgroundColor: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? AppColors.borderColor
|
|
: Colors.white,
|
|
child: SizedBox(
|
|
width: 18,
|
|
height: 18,
|
|
child: CircularProgressIndicator(
|
|
color: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? Colors.white
|
|
: AppColors.borderColor,
|
|
),
|
|
),
|
|
).paddingOnly(left: 16, top: 16),
|
|
);
|
|
}),
|
|
Obx(() {
|
|
return Visibility(
|
|
visible: (chatController
|
|
.voiceFiles[messageModel.content] ==
|
|
null &&
|
|
((chatController.isLoadingMap
|
|
.value[messageModel.content] !=
|
|
null)
|
|
? (!chatController.isLoadingMap
|
|
.value[messageModel.content]!)
|
|
: true)),
|
|
child: CircleAvatar(
|
|
radius: 21.3,
|
|
backgroundColor: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? AppColors.borderColor
|
|
: Colors.white,
|
|
child: Icon(
|
|
Icons.download,
|
|
color: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? Colors.white
|
|
: AppColors.borderColor,
|
|
).onTap(() async {
|
|
chatController.updateIsPlaying(
|
|
messageModel.content, false);
|
|
chatController.updateIsLoading(
|
|
messageModel.content, true);
|
|
|
|
File? file = await chatController.getVoiceFile(
|
|
id: messageModel.content);
|
|
chatController.addVoiceFile(
|
|
messageModel.content, file!);
|
|
|
|
await playerController.preparePlayer(
|
|
path: file.path);
|
|
|
|
chatController.updateIsLoading(
|
|
messageModel.content, false);
|
|
}),
|
|
).paddingOnly(left: 16, top: 16),
|
|
);
|
|
}),
|
|
Obx(() {
|
|
return Visibility(
|
|
visible: (chatController
|
|
.isPlayingMap[messageModel.content] ??
|
|
false),
|
|
child: CircleAvatar(
|
|
radius: 21.3,
|
|
backgroundColor: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? AppColors.borderColor
|
|
: Colors.white,
|
|
child: Icon(
|
|
Icons.stop,
|
|
color: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? Colors.white
|
|
: AppColors.borderColor,
|
|
).onTap(() async {
|
|
chatController.updateIsPlaying(
|
|
messageModel.content, false);
|
|
|
|
await playerController.pausePlayer();
|
|
}),
|
|
).paddingOnly(left: 16, top: 16),
|
|
);
|
|
}),
|
|
Obx(() {
|
|
return Visibility(
|
|
visible: ((chatController
|
|
.isPlayingMap[messageModel.content] !=
|
|
null
|
|
? !chatController
|
|
.isPlayingMap[messageModel.content]!
|
|
: true) &&
|
|
chatController.voiceFiles[messageModel.content] !=
|
|
null &&
|
|
((chatController.isLoadingMap
|
|
.value[messageModel.content] !=
|
|
null)
|
|
? (!chatController.isLoadingMap
|
|
.value[messageModel.content]!)
|
|
: true)),
|
|
child: SvgPicture.asset((messageModel.direction ==
|
|
MessageDirection.received)
|
|
? 'assets/icons/play_voice-2.svg'
|
|
: 'assets/icons/play_voice.svg')
|
|
.paddingOnly(top: 16, left: 16)
|
|
.onTap(() async {
|
|
chatController.updateIsPlaying(
|
|
messageModel.content, true);
|
|
await playerController.startPlayer(
|
|
finishMode: FinishMode.pause);
|
|
}),
|
|
);
|
|
}),
|
|
Visibility(
|
|
visible:
|
|
chatController.voiceFiles[messageModel.content] ==
|
|
null,
|
|
child: AudioFileWaveforms(
|
|
playerWaveStyle: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? PlayerWaveStyle(
|
|
backgroundColor: Colors.grey,
|
|
seekLineColor: Colors.grey,
|
|
fixedWaveColor: Colors.grey,
|
|
liveWaveColor: AppColors.primeColor,
|
|
)
|
|
: const PlayerWaveStyle(),
|
|
waveformData: Constants.defaulWaveFormData,
|
|
size: homeController.isArabic.value
|
|
? const Size(139, 30.0)
|
|
: const Size(149, 30.0),
|
|
waveformType: WaveformType.long,
|
|
playerController: playerController,
|
|
).paddingOnly(
|
|
left: homeController.isArabic.value ? 18 : 8,
|
|
),
|
|
),
|
|
Visibility(
|
|
visible:
|
|
(chatController.voiceFiles[messageModel.content] !=
|
|
null),
|
|
child: Builder(builder: (context) {
|
|
try {
|
|
return AudioFileWaveforms(
|
|
playerWaveStyle: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? PlayerWaveStyle(
|
|
backgroundColor: Colors.grey,
|
|
seekLineColor: Colors.grey,
|
|
fixedWaveColor: Colors.grey,
|
|
liveWaveColor: AppColors.primeColor,
|
|
)
|
|
: const PlayerWaveStyle(),
|
|
size: homeController.isArabic.value
|
|
? const Size(139, 30.0)
|
|
: const Size(159, 30.0),
|
|
waveformType: WaveformType.long,
|
|
playerController: playerController,
|
|
enableSeekGesture: false,
|
|
).paddingOnly(
|
|
left: homeController.isArabic.value ? 18 : 8,
|
|
);
|
|
} on Exception {
|
|
return AudioFileWaveforms(
|
|
playerWaveStyle: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? PlayerWaveStyle(
|
|
liveWaveColor: AppColors.primeColor,
|
|
backgroundColor: Colors.grey,
|
|
seekLineColor: Colors.grey,
|
|
fixedWaveColor: Colors.grey,
|
|
)
|
|
: const PlayerWaveStyle(),
|
|
enableSeekGesture: false,
|
|
waveformData: Constants.defaulWaveFormData,
|
|
size: homeController.isArabic.value
|
|
? const Size(139, 30.0)
|
|
: const Size(159, 30.0),
|
|
waveformType: WaveformType.long,
|
|
playerController: playerController,
|
|
).paddingOnly(
|
|
left: homeController.isArabic.value ? 18 : 8,
|
|
);
|
|
}
|
|
}),
|
|
),
|
|
],
|
|
).paddingOnly(
|
|
right: homeController.isArabic.value ? 28 : 0,
|
|
),
|
|
RegularTextWidget(
|
|
messageModel.createdAt.toString().substring(11, 16),
|
|
color: (messageModel.direction == MessageDirection.sent)
|
|
? Colors.white
|
|
: Colors.grey,
|
|
textAlign: TextAlign.right,
|
|
fontSize: 10,
|
|
)
|
|
.align(
|
|
alignment: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? Alignment.bottomLeft
|
|
: Alignment.bottomRight)
|
|
.paddingOnly(
|
|
right: Responsive.isTablet() ? 80 : 40,
|
|
left: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? 22
|
|
: 0,
|
|
top: (messageModel.direction ==
|
|
MessageDirection.received)
|
|
? 8
|
|
: 0,
|
|
),
|
|
if (messageModel.direction == MessageDirection.sent)
|
|
const SizedBox(
|
|
height: 16,
|
|
),
|
|
],
|
|
),
|
|
).align(
|
|
alignment: (messageModel.direction == MessageDirection.received)
|
|
? Alignment.centerLeft
|
|
: Alignment.centerRight),
|
|
).align(
|
|
alignment: (messageModel.direction == MessageDirection.received)
|
|
? Alignment.centerLeft
|
|
: Alignment.centerRight),
|
|
).paddingOnly(
|
|
left: Responsive.isTablet()
|
|
? 0
|
|
: (messageModel.direction == MessageDirection.received)
|
|
? 12
|
|
: 70,
|
|
right: 0),
|
|
).align(
|
|
alignment: (messageModel.direction == MessageDirection.received)
|
|
? Alignment.centerLeft
|
|
: Alignment.centerRight);
|
|
}).paddingOnly(
|
|
bottom: (messageModel.direction == MessageDirection.received) ? 12 : 0);
|
|
}
|
|
}
|