"Refactored AI chat page and message bar widgets: added file name handling, updated text direction logic, and rearranged UI components."

This commit is contained in:
OkaykOrhmn 2024-11-18 16:44:36 +03:30
parent 306b85f163
commit 7bec995377
2 changed files with 121 additions and 120 deletions

View File

@ -714,6 +714,7 @@ class _AiChatPageState extends State<AiChatPage> {
Container messageFile( Container messageFile(
BuildContext context, Prompts message, AiChatState state) { BuildContext context, Prompts message, AiChatState state) {
final String fileName = message.fileName ?? message.fileLocal?.name ?? '';
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: DesignConfig.mediumBorderRadius, borderRadius: DesignConfig.mediumBorderRadius,
@ -734,9 +735,12 @@ class _AiChatPageState extends State<AiChatPage> {
SizedBox( SizedBox(
width: MediaQuery.sizeOf(context).width, width: MediaQuery.sizeOf(context).width,
child: MarqueeText( child: MarqueeText(
text: message.fileName.toString(), text: fileName,
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
stop: const Duration(seconds: 3), stop: const Duration(seconds: 3),
textDirection: fileName.startsWithEnglish()
? TextDirection.ltr
: TextDirection.rtl,
), ),
), ),
// if (state.file != null && !kIsWeb) // if (state.file != null && !kIsWeb)

View File

@ -379,53 +379,17 @@ class _AiMessageBarState extends State<AiMessageBar> {
Expanded( Expanded(
child: state.file != null && state.file!.isRecorded child: state.file != null && state.file!.isRecorded
? audioContainer() ? audioContainer()
: Directionality( : ValueListenableBuilder(
textDirection: state.message.text valueListenable: state.message,
.toString() builder: (context, message, child) {
.startsWithEnglish() return Directionality(
? TextDirection.ltr textDirection:
: TextDirection.rtl, message.text.toString().startsWithEnglish()
child: TextFormField( ? TextDirection.ltr
textInputAction: TextInputAction.newline, : TextDirection.rtl,
style: Theme.of(context).textTheme.bodyMedium, child: edittext(context, state),
minLines: 1, );
maxLines: 6, // Set this }),
keyboardType: TextInputType.multiline,
controller: state.message,
enabled: !(state.file != null &&
widget.bot.attachment == 1),
decoration: InputDecoration(
contentPadding:
const EdgeInsets.fromLTRB(12, 12, 12, 12),
border: InputBorder.none,
hintText: 'بنویسید...',
hintStyle: Theme.of(context)
.textTheme
.bodySmall!
.copyWith(
color: Theme.of(context)
.colorScheme
.disabledText),
suffixIcon: state.isEdite
? InkWell(
onTap: () {
state.isEdite = false;
state.update();
},
child: const Icon(
DidvanIcons.close_circle_solid),
)
: const SizedBox(),
),
onChanged: (value) {
if (value.isEmpty || value.length == 1) {
state.update();
}
},
),
),
), ),
Padding( Padding(
padding: const EdgeInsets.only(bottom: 8.0), padding: const EdgeInsets.only(bottom: 8.0),
@ -458,79 +422,112 @@ class _AiMessageBarState extends State<AiMessageBar> {
); );
} }
Padding recorderAndSendButton( TextFormField edittext(BuildContext context, AiChatState state) {
AiChatState state, HistoryAiChatState historyState) { return TextFormField(
return Padding( textInputAction: TextInputAction.newline,
padding: const EdgeInsets.fromLTRB(12, 0, 12, 8), style: Theme.of(context).textTheme.bodyMedium,
child: state.message.text.isEmpty && minLines: 1,
historyState.bot!.attachmentType!.contains('audio') && maxLines: 6, // Set this
state.file == null && keyboardType: TextInputType.multiline,
widget.bot.attachment != 0 controller: state.message,
? MessageBarBtn(
enable: true,
icon: _mRecorder!.isRecording || _mRecorder!.isPaused
? Icons.stop_rounded
: DidvanIcons.mic_regular,
click: getRecorderFn(),
)
: MessageBarBtn(
enable: (state.file != null && state.file!.isRecorded) ||
(widget.bot.attachment == 1) ||
state.message.text.isNotEmpty,
icon: DidvanIcons.send_light,
click: () async {
if ((state.file == null || !state.file!.isRecorded) &&
(widget.bot.attachment != 1) &&
state.message.text.isEmpty) {
return;
}
if (state.messages.isNotEmpty && enabled: !(state.file != null && widget.bot.attachment == 1),
DateTime.parse(state.messages.last.dateTime) decoration: InputDecoration(
.toPersianDateStr() contentPadding: const EdgeInsets.fromLTRB(12, 12, 12, 12),
.contains(DateTime.parse(DateTime.now() border: InputBorder.none,
.subtract(const Duration(minutes: 210)) hintText: 'بنویسید...',
.toIso8601String()) hintStyle: Theme.of(context)
.toPersianDateStr())) { .textTheme
state.messages.last.prompts.add(Prompts( .bodySmall!
error: false, .copyWith(color: Theme.of(context).colorScheme.disabledText),
text: state.message.text, suffixIcon: state.isEdite
// file: state.file?.path, ? InkWell(
// fileName: state.file?.basename, onTap: () {
fileLocal: state.file, state.isEdite = false;
finished: true, state.update();
role: 'user', },
createdAt: DateTime.now() child: const Icon(DidvanIcons.close_circle_solid),
.subtract(const Duration(minutes: 210)) )
.toIso8601String(), : const SizedBox(),
)); ),
} else { );
state.messages.add(MessageModel( }
dateTime: DateTime.now()
recorderAndSendButton(AiChatState state, HistoryAiChatState historyState) {
return ValueListenableBuilder(
valueListenable: state.message,
builder: (context, message, child) => Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 8),
child: message.text.isEmpty &&
historyState.bot!.attachmentType!.contains('audio') &&
state.file == null &&
widget.bot.attachment != 0
? MessageBarBtn(
enable: true,
icon: _mRecorder!.isRecording || _mRecorder!.isPaused
? Icons.stop_rounded
: DidvanIcons.mic_regular,
click: getRecorderFn(),
)
: MessageBarBtn(
enable: (state.file != null && state.file!.isRecorded) ||
(widget.bot.attachment == 1) ||
message.text.isNotEmpty,
icon: DidvanIcons.send_light,
click: () async {
if ((state.file == null || !state.file!.isRecorded) &&
(widget.bot.attachment != 1) &&
message.text.isEmpty) {
return;
}
if (state.messages.isNotEmpty &&
DateTime.parse(state.messages.last.dateTime)
.toPersianDateStr()
.contains(DateTime.parse(DateTime.now()
.subtract(const Duration(minutes: 210))
.toIso8601String())
.toPersianDateStr())) {
state.messages.last.prompts.add(Prompts(
error: false,
text: message.text,
// file: state.file?.path,
// fileName: state.file?.basename,
fileLocal: state.file,
finished: true,
role: 'user',
createdAt: DateTime.now()
.subtract(const Duration(minutes: 210)) .subtract(const Duration(minutes: 210))
.toIso8601String(), .toIso8601String(),
prompts: [ ));
Prompts( } else {
error: false, state.messages.add(MessageModel(
text: state.message.text, dateTime: DateTime.now()
finished: true, .subtract(const Duration(minutes: 210))
// file: state.file?.path, .toIso8601String(),
// fileName: state.file?.basename, prompts: [
fileLocal: state.file, Prompts(
role: 'user', error: false,
createdAt: DateTime.now() text: message.text,
.subtract(const Duration(minutes: 210)) finished: true,
.toIso8601String(), // file: state.file?.path,
) // fileName: state.file?.basename,
])); fileLocal: state.file,
} role: 'user',
state.message.clear(); createdAt: DateTime.now()
openAttach = false; .subtract(const Duration(minutes: 210))
state.update(); .toIso8601String(),
await state.postMessage( )
widget.bot, widget.assistantsName != null); ]));
}, }
), state.message.clear();
openAttach = false;
state.update();
await state.postMessage(
widget.bot, widget.assistantsName != null);
},
),
),
); );
} }
@ -694,7 +691,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
MediaService.onLoadingPickFile(context); MediaService.onLoadingPickFile(context);
FilePickerResult? result = await MediaService.pickPdfFile(); FilePickerResult? result = await MediaService.pickPdfFile();
if (result != null) { if (result != null) {
String? name = result.files.first.name; String? name = result.files.single.name;
if (kIsWeb) { if (kIsWeb) {
Uint8List? bytes = Uint8List? bytes =
@ -910,7 +907,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
SizedBox( SizedBox(
height: 24, height: 24,
child: MarqueeText( child: MarqueeText(
text: state.file != null ? state.file!.name! : '', text: state.file != null ? state.file!.name ?? '' : '',
style: const TextStyle(fontSize: 14), style: const TextStyle(fontSize: 14),
stop: const Duration(seconds: 3), stop: const Duration(seconds: 3),
), ),