From 7bec99537758132432501eabc2d6fdc304ea9339 Mon Sep 17 00:00:00 2001 From: OkaykOrhmn Date: Mon, 18 Nov 2024 16:44:36 +0330 Subject: [PATCH] "Refactored AI chat page and message bar widgets: added file name handling, updated text direction logic, and rearranged UI components." --- lib/views/ai/ai_chat_page.dart | 6 +- lib/views/ai/widgets/ai_message_bar.dart | 235 +++++++++++------------ 2 files changed, 121 insertions(+), 120 deletions(-) diff --git a/lib/views/ai/ai_chat_page.dart b/lib/views/ai/ai_chat_page.dart index ab3bb45..68d767d 100644 --- a/lib/views/ai/ai_chat_page.dart +++ b/lib/views/ai/ai_chat_page.dart @@ -714,6 +714,7 @@ class _AiChatPageState extends State { Container messageFile( BuildContext context, Prompts message, AiChatState state) { + final String fileName = message.fileName ?? message.fileLocal?.name ?? ''; return Container( decoration: BoxDecoration( borderRadius: DesignConfig.mediumBorderRadius, @@ -734,9 +735,12 @@ class _AiChatPageState extends State { SizedBox( width: MediaQuery.sizeOf(context).width, child: MarqueeText( - text: message.fileName.toString(), + text: fileName, style: const TextStyle(fontSize: 14), stop: const Duration(seconds: 3), + textDirection: fileName.startsWithEnglish() + ? TextDirection.ltr + : TextDirection.rtl, ), ), // if (state.file != null && !kIsWeb) diff --git a/lib/views/ai/widgets/ai_message_bar.dart b/lib/views/ai/widgets/ai_message_bar.dart index 016c208..63c5004 100644 --- a/lib/views/ai/widgets/ai_message_bar.dart +++ b/lib/views/ai/widgets/ai_message_bar.dart @@ -379,53 +379,17 @@ class _AiMessageBarState extends State { Expanded( child: state.file != null && state.file!.isRecorded ? audioContainer() - : Directionality( - textDirection: state.message.text - .toString() - .startsWithEnglish() - ? TextDirection.ltr - : TextDirection.rtl, - child: TextFormField( - textInputAction: TextInputAction.newline, - style: Theme.of(context).textTheme.bodyMedium, - 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(); - } - }, - ), - ), + : ValueListenableBuilder( + valueListenable: state.message, + builder: (context, message, child) { + return Directionality( + textDirection: + message.text.toString().startsWithEnglish() + ? TextDirection.ltr + : TextDirection.rtl, + child: edittext(context, state), + ); + }), ), Padding( padding: const EdgeInsets.only(bottom: 8.0), @@ -458,79 +422,112 @@ class _AiMessageBarState extends State { ); } - Padding recorderAndSendButton( - AiChatState state, HistoryAiChatState historyState) { - return Padding( - padding: const EdgeInsets.fromLTRB(12, 0, 12, 8), - child: state.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) || - 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; - } + TextFormField edittext(BuildContext context, AiChatState state) { + return TextFormField( + textInputAction: TextInputAction.newline, + style: Theme.of(context).textTheme.bodyMedium, + minLines: 1, + maxLines: 6, // Set this + keyboardType: TextInputType.multiline, + controller: state.message, - 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: state.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)) - .toIso8601String(), - )); - } else { - state.messages.add(MessageModel( - dateTime: DateTime.now() + 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(), + ), + ); + } + + 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)) .toIso8601String(), - prompts: [ - Prompts( - error: false, - text: state.message.text, - finished: true, - // file: state.file?.path, - // fileName: state.file?.basename, - fileLocal: state.file, - role: 'user', - createdAt: DateTime.now() - .subtract(const Duration(minutes: 210)) - .toIso8601String(), - ) - ])); - } - state.message.clear(); - openAttach = false; - state.update(); - await state.postMessage( - widget.bot, widget.assistantsName != null); - }, - ), + )); + } else { + state.messages.add(MessageModel( + dateTime: DateTime.now() + .subtract(const Duration(minutes: 210)) + .toIso8601String(), + prompts: [ + Prompts( + error: false, + text: message.text, + finished: true, + // file: state.file?.path, + // fileName: state.file?.basename, + fileLocal: state.file, + role: 'user', + createdAt: DateTime.now() + .subtract(const Duration(minutes: 210)) + .toIso8601String(), + ) + ])); + } + state.message.clear(); + openAttach = false; + state.update(); + await state.postMessage( + widget.bot, widget.assistantsName != null); + }, + ), + ), ); } @@ -694,7 +691,7 @@ class _AiMessageBarState extends State { MediaService.onLoadingPickFile(context); FilePickerResult? result = await MediaService.pickPdfFile(); if (result != null) { - String? name = result.files.first.name; + String? name = result.files.single.name; if (kIsWeb) { Uint8List? bytes = @@ -910,7 +907,7 @@ class _AiMessageBarState extends State { SizedBox( height: 24, child: MarqueeText( - text: state.file != null ? state.file!.name! : '', + text: state.file != null ? state.file!.name ?? '' : '', style: const TextStyle(fontSize: 14), stop: const Duration(seconds: 3), ),