You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

511 lines
22 KiB
Dart

import 'package:audio_waveforms/audio_waveforms.dart';
10 months ago
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/modules/cm_module/views/components/action_button/footer_action_button.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
10 months ago
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
enum ChatState { idle, voiceRecordingStarted, voiceRecordingCompleted }
10 months ago
class ChatPage extends StatefulWidget {
ChatPage({Key? key}) : super(key: key);
@override
_ChatPageState createState() {
return _ChatPageState();
}
}
class _ChatPageState extends State<ChatPage> {
bool isSender = false;
bool isAudioRecording = false;
String? recordedFilePath;
final RecorderController recorderController = RecorderController();
PlayerController playerController = PlayerController();
ChatState chatState = ChatState.idle;
10 months ago
@override
void initState() {
super.initState();
playerController.addListener(() async {
// if (playerController.playerState == PlayerState.playing && playerController.maxDuration == await playerController.getDuration()) {
// await playerController.stopPlayer();
// setState(() {});
// }
});
10 months ago
}
@override
void dispose() {
playerController.dispose();
recorderController.dispose();
10 months ago
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.white10,
10 months ago
appBar: const DefaultAppBar(title: "Req No. 343443"),
body: Column(
children: [
Container(
color: AppColor.neutral50,
constraints: const BoxConstraints(maxHeight: 56),
padding: const EdgeInsets.all(16),
child: Row(
children: [
Text(
"Engineer: Mahmoud Shrouf",
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.white10),
).expanded,
4.width,
Text(
"View All Documents",
style: AppTextStyles.bodyText.copyWith(
color: AppColor.white10,
decoration: TextDecoration.underline,
decorationColor: AppColor.white10,
),
),
],
),
),
Container(
// width: double.infinity,
color: AppColor.neutral100,
child: ListView(
padding: const EdgeInsets.all(16),
children: [
recipientMsgCard(true, "Please let me know what is the issue? Please let me know what is the issue?"),
recipientMsgCard(false, "testing"),
recipientMsgCard(false, "testing testing testing"),
dateCard("Mon 27 Oct"),
senderMsgCard(true, "Please let me know what is the issue? Please let me know what is the issue?"),
senderMsgCard(false, "Please let me know what is the issue?"),
],
)).expanded,
Divider(height: 1, thickness: 1, color: const Color(0xff767676).withOpacity(.11)),
SafeArea(
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 56),
child: Row(
children: [
if (chatState == ChatState.idle) ...[
TextFormField(
cursorColor: AppColor.neutral50,
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50),
minLines: 1,
maxLines: 3,
textInputAction: TextInputAction.none,
keyboardType: TextInputType.multiline,
decoration: InputDecoration(
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
border: InputBorder.none,
errorBorder: InputBorder.none,
contentPadding: const EdgeInsets.only(left: 16, top: 8, bottom: 8),
alignLabelWithHint: true,
filled: true,
constraints: const BoxConstraints(),
suffixIconConstraints: const BoxConstraints(),
hintText: "Type your message here...",
hintStyle: AppTextStyles.bodyText.copyWith(color: const Color(0xffCCCCCC)),
// suffixIcon: Row(
// mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.end,
// mainAxisAlignment: MainAxisAlignment.end,
// children: [
//
// 8.width,
// ],
// )
),
).expanded,
IconButton(
onPressed: () {},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: "chat_attachment".toSvgAsset(width: 24, height: 24),
constraints: const BoxConstraints(),
),
IconButton(
onPressed: () async {
await recorderController.checkPermission();
if (recorderController.hasPermission) {
chatState = ChatState.voiceRecordingStarted;
recorderController.record();
setState(() {});
} else {
"Audio permission denied. Please enable from setting".showToast;
}
// if (!isPermissionGranted) {
// "Audio permission denied. Please enable from setting".showToast;
// return;
// }
},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: "chat_mic".toSvgAsset(width: 24, height: 24),
constraints: const BoxConstraints(),
),
] else if (chatState == ChatState.voiceRecordingStarted) ...[
AudioWaveforms(
size: Size(MediaQuery.of(context).size.width, 56.0),
waveStyle: const WaveStyle(waveColor: AppColor.neutral50, extendWaveform: true, showMiddleLine: false),
padding: const EdgeInsets.only(left: 16),
recorderController: recorderController, // Customize how waveforms looks.
).expanded,
IconButton(
onPressed: () async {
isAudioRecording = false;
await recorderController.pause();
recordedFilePath = await recorderController.stop();
chatState = ChatState.voiceRecordingCompleted;
setState(() {});
},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: Icon(Icons.stop_circle_rounded),
constraints: const BoxConstraints(),
)
] else if (chatState == ChatState.voiceRecordingCompleted) ...[
if (playerController.playerState == PlayerState.playing)
IconButton(
onPressed: () async {
await playerController.pausePlayer();
await playerController.stopPlayer();
setState(() {});
},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: const Icon(Icons.stop_circle_outlined, size: 20),
constraints: const BoxConstraints(),
)
else
IconButton(
onPressed: () async {
await playerController.preparePlayer(path: recordedFilePath!);
await playerController.startPlayer();
setState(() {});
},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: const Icon(Icons.play_circle_fill_rounded, size: 20),
constraints: const BoxConstraints(),
),
AudioFileWaveforms(
playerController: playerController,
waveformData: recorderController.waveData,
enableSeekGesture: false,
continuousWaveform: false,
waveformType: WaveformType.long,
playerWaveStyle: const PlayerWaveStyle(
fixedWaveColor: AppColor.neutral50,
liveWaveColor: AppColor.primary10,
showSeekLine: true,
),
size: Size(MediaQuery.of(context).size.width, 56.0),
).expanded,
IconButton(
onPressed: () async {
await playerController.stopPlayer();
recorderController.reset();
recordedFilePath = null;
chatState = ChatState.idle;
setState(() {});
},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: "delete_icon".toSvgAsset(width: 24, height: 24),
constraints: const BoxConstraints(),
),
],
// if (recordedFilePath == null) ...[
// isAudioRecording
// ? AudioWaveforms(
// size: Size(MediaQuery.of(context).size.width, 56.0),
//
// // enableGesture: true,
//
// waveStyle: const WaveStyle(waveColor: AppColor.neutral50, extendWaveform: true, showMiddleLine: false),
// padding: const EdgeInsets.only(left: 16),
// recorderController: recorderController, // Customize how waveforms looks.
// ).expanded
// : TextFormField(
// cursorColor: AppColor.neutral50,
// style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50),
// minLines: 1,
// maxLines: 3,
// textInputAction: TextInputAction.none,
// keyboardType: TextInputType.multiline,
// decoration: InputDecoration(
// enabledBorder: InputBorder.none,
// focusedBorder: InputBorder.none,
// border: InputBorder.none,
// errorBorder: InputBorder.none,
// contentPadding: const EdgeInsets.only(left: 16, top: 8, bottom: 8),
// alignLabelWithHint: true,
// filled: true,
// constraints: const BoxConstraints(),
// suffixIconConstraints: const BoxConstraints(),
// hintText: "Type your message here...",
// hintStyle: AppTextStyles.bodyText.copyWith(color: const Color(0xffCCCCCC)),
// // suffixIcon: Row(
// // mainAxisSize: MainAxisSize.min,
// // crossAxisAlignment: CrossAxisAlignment.end,
// // mainAxisAlignment: MainAxisAlignment.end,
// // children: [
// //
// // 8.width,
// // ],
// // )
// ),
// ).expanded,
// IconButton(
// onPressed: () {},
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: "chat_attachment".toSvgAsset(width: 24, height: 24),
// constraints: const BoxConstraints(),
// ),
// ],
// if (recordedFilePath == null)
// ...[]
// else ...[
// IconButton(
// onPressed: () async {
// await playerController.preparePlayer(path: recordedFilePath!);
// playerController.startPlayer();
// },
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: const Icon(Icons.play_circle_fill_rounded, size: 20),
// constraints: const BoxConstraints(),
// ),
// AudioFileWaveforms(
// playerController: playerController,
// size: Size(300, 50),
// ).expanded,
// IconButton(
// onPressed: () async {
// playerController.pausePlayer();
// },
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: const Icon(Icons.pause_circle_filled_outlined, size: 20),
// constraints: const BoxConstraints(),
// ),
// IconButton(
// onPressed: () {},
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: "delete".toSvgAsset(width: 24, height: 24),
// constraints: const BoxConstraints(),
// ),
// ],
// if (isAudioRecording && recorderController.isRecording)
// IconButton(
// onPressed: () {},
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: "chat_msg_send".toSvgAsset(width: 24, height: 24),
// constraints: const BoxConstraints(),
// ),
// if (isAudioRecording)
// IconButton(
// onPressed: () async {
// isAudioRecording = false;
// await recorderController.pause();
// recordedFilePath = await recorderController.stop();
// chatState = ChatState.voiceRecordingCompleted;
// setState(() {});
// },
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: Icon(Icons.stop_circle_rounded),
// constraints: const BoxConstraints(),
// )
// else
// IconButton(
// onPressed: () async {
// await recorderController.checkPermission();
// if (recorderController.hasPermission) {
// setState(() {
// isAudioRecording = true;
// });
// recorderController.record();
// } else {
// "Audio permission denied. Please enable from setting".showToast;
// }
// // if (!isPermissionGranted) {
// // "Audio permission denied. Please enable from setting".showToast;
// // return;
// // }
// },
// style: const ButtonStyle(
// tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
// ),
// icon: "chat_mic".toSvgAsset(width: 24, height: 24),
// constraints: const BoxConstraints(),
// ),
10 months ago
IconButton(
onPressed: () {},
style: const ButtonStyle(
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // or .padded
),
icon: "chat_msg_send".toSvgAsset(width: 24, height: 24),
constraints: const BoxConstraints(),
),
8.width,
],
),
),
)
],
),
);
}
Widget dateCard(String date) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
margin: const EdgeInsets.only(top: 16, bottom: 8),
decoration: BoxDecoration(
color: AppColor.neutral50,
borderRadius: BorderRadius.circular(6),
),
child: Text(date, style: AppTextStyles.bodyText2.copyWith(color: AppColor.white10)))
.center;
}
10 months ago
Widget senderMsgCard(bool showHeader, String msg) {
Widget senderHeader = Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Jeniffer Jeniffer Jeniffer(Me)",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
),
8.width,
Container(
height: 26,
width: 26,
decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.grey),
),
],
);
return Align(
alignment: Alignment.centerRight,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (showHeader) ...[senderHeader, 4.height] else 8.height,
Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(right: 26 + 8, left: 26 + 8),
decoration: BoxDecoration(
color: AppColor.white10,
borderRadius: BorderRadius.circular(6),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
msg,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
),
Text(
"2:00 PM",
style: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.neutral50.withOpacity(0.5)),
),
],
)),
],
),
);
}
Widget recipientMsgCard(bool showHeader, String msg) {
Widget recipientHeader = Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 26,
width: 26,
decoration: BoxDecoration(shape: BoxShape.circle, color: Colors.grey),
),
8.width,
Text(
"Mahmoud Shrouf",
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: AppTextStyles.bodyText.copyWith(color: AppColor.neutral50, fontWeight: FontWeight.w600),
)
],
);
return Align(
alignment: Alignment.centerLeft,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (showHeader) ...[recipientHeader, 4.height] else 8.height,
Container(
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.only(left: 26 + 8, right: 26 + 8),
decoration: BoxDecoration(
color: AppColor.primary10,
borderRadius: BorderRadius.circular(6),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
msg,
style: AppTextStyles.bodyText2.copyWith(color: AppColor.white10),
),
Align(
alignment: Alignment.centerRight,
widthFactor: 1,
child: Text(
"2:00 PM",
style: AppTextStyles.textFieldLabelStyle.copyWith(color: AppColor.white10),
),
),
],
)),
10 months ago
],
),
);
}
}