forked from eatvio/eatvio_app
feat(chat): add plan order message widget and enhance chat bubble to support message types
This commit is contained in:
@@ -9,6 +9,7 @@ import 'package:eatvio_app/features/chat/models/chat_message_model.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/bloc/chat_room_cubit/chat_room_cubit.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/widgets/message_action_bottom_sheet.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
@@ -24,7 +25,9 @@ class ChatBubbleWidget extends StatelessWidget {
|
||||
required this.isRead,
|
||||
required this.messageState,
|
||||
required this.messageUuid,
|
||||
required this.userSlug
|
||||
required this.userSlug,
|
||||
this.messageType,
|
||||
this.isConsultant,
|
||||
});
|
||||
|
||||
final DateTime sendTime;
|
||||
@@ -35,6 +38,8 @@ class ChatBubbleWidget extends StatelessWidget {
|
||||
final MessageState messageState;
|
||||
final String messageUuid;
|
||||
final String userSlug;
|
||||
final String? messageType;
|
||||
final bool? isConsultant;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final size = MediaQuery.sizeOf(context);
|
||||
@@ -144,8 +149,8 @@ class ChatBubbleWidget extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
if (mediaData.isNotEmpty && text.isNotEmpty) const SizedBox(height: 8),
|
||||
if (text.isNotEmpty) Text(text, style: TextStyles.textFS13FW400.copyWith(color: appTheme.black, fontSize: 16)),
|
||||
if (mediaData.isNotEmpty && _getDisplayText().isNotEmpty) const SizedBox(height: 8),
|
||||
if (_getDisplayText().isNotEmpty) _buildLinkableText(_getDisplayText()),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -163,4 +168,88 @@ class ChatBubbleWidget extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getDisplayText() {
|
||||
if (messageType == 'plan_order') {
|
||||
if (isConsultant == true) {
|
||||
// Текст для консультанта
|
||||
return '1. Уточните у подопечного его цели и пожелания\n'
|
||||
'2. Согласуйте и выберите дату старта плана\n'
|
||||
'3. Ожидайте уведомления об успешной оплате\n'
|
||||
'4. После оплаты предоставьте необходимые данные, согласно вашему плану питания';
|
||||
} else {
|
||||
// Текст для пользователя
|
||||
return 'Укажите вашу цель в работе с консультантом\n'
|
||||
'Согласуйте удобную дату старта плана, после чего вам будет направлена ссылка на оплату.';
|
||||
}
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
Widget _buildLinkableText(String text) {
|
||||
final urlRegex = RegExp(
|
||||
r'(?:(?:https?|ftp):\/\/)?(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)',
|
||||
caseSensitive: false,
|
||||
);
|
||||
|
||||
final textStyle = TextStyles.textFS13FW400.copyWith(color: appTheme.black, fontSize: 16);
|
||||
final linkStyle = textStyle.copyWith(
|
||||
color: appTheme.blueA400,
|
||||
decoration: TextDecoration.underline,
|
||||
);
|
||||
|
||||
final matches = urlRegex.allMatches(text);
|
||||
if (matches.isEmpty) {
|
||||
return Text(text, style: textStyle);
|
||||
}
|
||||
|
||||
final spans = <TextSpan>[];
|
||||
int lastEnd = 0;
|
||||
|
||||
for (final match in matches) {
|
||||
// Добавляем текст до ссылки
|
||||
if (match.start > lastEnd) {
|
||||
spans.add(TextSpan(
|
||||
text: text.substring(lastEnd, match.start),
|
||||
style: textStyle,
|
||||
));
|
||||
}
|
||||
|
||||
// Добавляем кликабельную ссылку
|
||||
final url = match.group(0)!;
|
||||
final fullUrl = url.startsWith('http://') || url.startsWith('https://') || url.startsWith('ftp://')
|
||||
? url
|
||||
: 'https://$url';
|
||||
|
||||
spans.add(TextSpan(
|
||||
text: url,
|
||||
style: linkStyle,
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
try {
|
||||
final uri = Uri.parse(fullUrl);
|
||||
if (await canLaunchUrl(uri)) {
|
||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||
}
|
||||
} catch (e) {
|
||||
// Игнорируем ошибки открытия ссылок
|
||||
}
|
||||
},
|
||||
));
|
||||
|
||||
lastEnd = match.end;
|
||||
}
|
||||
|
||||
// Добавляем оставшийся текст после последней ссылки
|
||||
if (lastEnd < text.length) {
|
||||
spans.add(TextSpan(
|
||||
text: text.substring(lastEnd),
|
||||
style: textStyle,
|
||||
));
|
||||
}
|
||||
|
||||
return RichText(
|
||||
text: TextSpan(children: spans),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user