fixed chatbot ai selector

This commit is contained in:
Mohamad Mahdi Jebeli 2026-02-16 14:40:26 +03:30
parent 575243e959
commit 44421e39d6
4 changed files with 454 additions and 299 deletions

View File

@ -233,11 +233,11 @@ class _OnBoardingPageState extends State<OnBoardingPage> {
children: [
TextSpan(
text: sliders[index].description,
style: AppTextStyles.body3.copyWith(
style: AppTextStyles.body4.copyWith(
color:
Theme.of(context).colorScheme.onSurface))
],
style: AppTextStyles.body3.copyWith(
style: AppTextStyles.body4.copyWith(
color: Theme.of(context).colorScheme.onSurface,
fontWeight: FontWeight.bold)),
textAlign: TextAlign.justify,

View File

@ -1,4 +1,4 @@
// ignore_for_file: deprecated_member_use_from_same_package, use_build_context_synchronously, avoid_print
// ignore_for_file: deprecated_member_use_from_same_package, use_build_context_synchronously, avoid_print, deprecated_member_use, curly_braces_in_flow_control_structures
import 'dart:math';
@ -24,6 +24,7 @@ import 'package:hoshan/data/model/ai/messages_model.dart';
import 'package:hoshan/data/model/ai/send_message_model.dart';
import 'package:hoshan/data/model/chat_args.dart';
import 'package:hoshan/data/model/empty_states_enum.dart';
import 'package:hoshan/data/repository/bot_repository.dart';
import 'package:hoshan/ui/screens/chat/bloc/messages_bloc.dart';
import 'package:hoshan/ui/screens/chat/bloc/related_questions_bloc.dart';
import 'package:hoshan/ui/screens/chat/cubit/receive_message_cubit.dart';
@ -76,6 +77,22 @@ class _ChatPageState extends State<ChatPage> {
ValueNotifier<int?> maxLines = ValueNotifier(5);
late final ValueNotifier<int> selectedBotId =
ValueNotifier(widget.chatArgs.bot.id ?? 1);
final ValueNotifier<bool> isModelSelectionEnabled = ValueNotifier(true);
late final ValueNotifier<int> currentCost =
ValueNotifier(widget.chatArgs.bot.cost ?? 1);
Future<void> _updateCostFromApi(int botId) async {
try {
final botData = await BotRepository.getSingleBot(id: botId);
if (botData.cost != null) {
currentCost.value = botData.cost!;
}
} catch (e) {
if (kDebugMode) {
print('Error fetching bot cost: $e');
}
}
}
void sendRequest(
{required final String? message,
@ -1292,6 +1309,7 @@ class _ChatPageState extends State<ChatPage> {
},
listener: (context, state) {
if (state is ReceiveMessageDone) {
isModelSelectionEnabled.value = false;
context.read<MessagesBloc>().add(AddMessage(message: state.message));
if (state.model.chatId != null) {
if (chatId == null && !isGhost.value) {
@ -1708,26 +1726,55 @@ class _ChatPageState extends State<ChatPage> {
)
],
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondary,
borderRadius: BorderRadius.circular(12)),
child: Row(
children: [
Text(
bot.cost == 0 || bot.cost == null
? 'رایگان'
: bot.cost.toString(),
style: AppTextStyles.body3.copyWith(color: Colors.white),
ValueListenableBuilder<int>(
valueListenable: currentCost,
builder: (context, cost, _) {
return TweenAnimationBuilder<double>(
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
tween: Tween<double>(
begin: cost.toDouble(),
end: cost.toDouble(),
),
const SizedBox(
width: 4,
),
Assets.icon.outline.coin
.svg(color: Colors.white, width: 18, height: 18)
],
),
builder: (context, value, child) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.secondary,
borderRadius: BorderRadius.circular(12)),
child: Row(
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder:
(Widget child, Animation<double> animation) {
return ScaleTransition(
scale: animation,
child: FadeTransition(
opacity: animation,
child: child,
),
);
},
child: Text(
cost == 0 ? 'رایگان' : cost.toString(),
key: ValueKey<int>(cost),
style: AppTextStyles.body3
.copyWith(color: Colors.white),
),
),
const SizedBox(
width: 4,
),
Assets.icon.outline.coin
.svg(color: Colors.white, width: 18, height: 18)
],
),
);
},
);
},
),
],
),
@ -1874,7 +1921,6 @@ class _ChatPageState extends State<ChatPage> {
child: TextField(
controller: messageText,
onChanged: (value) {},
enabled: (bot.deleted !=
null &&
!bot
@ -1896,7 +1942,7 @@ class _ChatPageState extends State<ChatPage> {
.attachment !=
3),
minLines: 1,
maxLines: 6, // Set this
maxLines: 6,
keyboardType:
TextInputType
.multiline,
@ -2062,107 +2108,142 @@ class _ChatPageState extends State<ChatPage> {
children: [
if (bot.tool == null || !bot.tool!)
ValueListenableBuilder(
valueListenable: selectedBotId,
builder: (context, currentBotId, _) {
String botName = currentBotId == 1
? 'ChatGPT'
: currentBotId == 2
? 'Gemini'
: currentBotId == 4
? 'Grok'
: 'Claude';
valueListenable: isModelSelectionEnabled,
builder: (context, isEnabled, _) {
return ValueListenableBuilder(
valueListenable: selectedBotId,
builder: (context, currentBotId, _) {
String botName = currentBotId == 1
? 'ChatGPT'
: currentBotId == 2
? 'Gemini'
: currentBotId == 4
? 'Grok'
: 'Claude';
return PopupMenuButton<int>(
color:
Theme.of(context).colorScheme.surface,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
offset: const Offset(0, -10),
onSelected: (int value) {
print('🤖 Bot selected: $value');
selectedBotId.value = value;
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<int>>[
PopupMenuItem<int>(
value: 1,
child: Text(
'ChatGPT',
style: AppTextStyles.body5.copyWith(
fontWeight: currentBotId == 1
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 2,
child: Text(
'Gemini',
style: AppTextStyles.body5.copyWith(
fontWeight: currentBotId == 2
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 4,
child: Text(
'Grok',
style: AppTextStyles.body5.copyWith(
fontWeight: currentBotId == 4
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 9,
child: Text(
'Claude',
style: AppTextStyles.body5.copyWith(
fontWeight: currentBotId == 9
? FontWeight.bold
: FontWeight.normal,
),
),
),
],
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
botName,
style: AppTextStyles.body6.copyWith(
color: Theme.of(context)
.colorScheme
.primary,
fontWeight: FontWeight.bold,
),
),
const SizedBox(width: 4),
Icon(
Icons.keyboard_arrow_up,
size: 16,
return IgnorePointer(
ignoring: !isEnabled,
child: Opacity(
opacity: isEnabled ? 1.0 : 0.5,
child: PopupMenuButton<int>(
color: Theme.of(context)
.colorScheme
.primary,
.surface,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(12),
),
offset: const Offset(0, -10),
onSelected: (int value) {
print('🤖 Bot selected: $value');
selectedBotId.value = value;
_updateCostFromApi(value);
},
itemBuilder:
(BuildContext context) =>
<PopupMenuEntry<int>>[
PopupMenuItem<int>(
value: 1,
child: Text(
'ChatGPT',
style: AppTextStyles.body5
.copyWith(
fontWeight:
currentBotId == 1
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 2,
child: Text(
'Gemini',
style: AppTextStyles.body5
.copyWith(
fontWeight:
currentBotId == 2
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 4,
child: Text(
'Grok',
style: AppTextStyles.body5
.copyWith(
fontWeight:
currentBotId == 4
? FontWeight.bold
: FontWeight.normal,
),
),
),
PopupMenuItem<int>(
value: 9,
child: Text(
'Claude',
style: AppTextStyles.body5
.copyWith(
fontWeight:
currentBotId == 9
? FontWeight.bold
: FontWeight.normal,
),
),
),
],
child: Container(
padding:
const EdgeInsets.symmetric(
horizontal: 8,
vertical: 4),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(
isEnabled ? 0.1 : 0.05),
borderRadius:
BorderRadius.circular(8),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(
botName,
style: AppTextStyles.body6
.copyWith(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(isEnabled
? 1.0
: 0.5),
fontWeight:
FontWeight.bold,
),
),
const SizedBox(width: 4),
Icon(
Icons.keyboard_arrow_up,
size: 16,
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(isEnabled
? 1.0
: 0.5),
),
],
),
),
),
],
),
),
),
);
},
);
},
),
@ -2240,100 +2321,71 @@ class _ChatPageState extends State<ChatPage> {
const SizedBox(
width: 12,
),
if ((bot.deleted != null && !bot.deleted!))
if (bot.attachmentType != null &&
bot.attachmentType!.isNotEmpty)
ValueListenableBuilder(
valueListenable: visibleAttach,
builder: (context, value, child) {
return AnimatedVisibility(
isVisible: value,
duration:
const Duration(milliseconds: 300),
fadeMode: FadeMode.horizontal,
child: Padding(
padding:
const EdgeInsets.only(left: 12.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
if (bot.attachmentType!
.contains('image'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
icon: Assets.icon.outline
.galleryAdd,
color: Theme.of(context)
.colorScheme
.primary,
iconColor: Colors.white,
onTap: () async {
await BottomSheetHandler(
context)
.showPickImage(
onSelect: (file) {
selectedFile.value =
file;
if (widget
.chatArgs
.bot
.attachment !=
3) {
visibleAttach
.value =
false;
}
},
);
}),
),
if (bot.attachmentType!
.contains('audio'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
icon: Assets
.icon.outline.musicnote,
color: Theme.of(context)
.colorScheme
.primary,
iconColor: Colors.white,
onTap: () async {
final file =
await PickFileService(
ValueListenableBuilder<int>(
valueListenable: selectedBotId,
builder: (context, currentBotId, child) {
// غیرفعال کردن قابلیت ارسال عکس برای بات با id=4 (Grok)
if ((bot.deleted != null && !bot.deleted!) &&
currentBotId != 4) if (bot.attachmentType !=
null &&
bot.attachmentType!.isNotEmpty)
return ValueListenableBuilder(
valueListenable: visibleAttach,
builder: (context, value, child) {
return AnimatedVisibility(
isVisible: value,
duration:
const Duration(milliseconds: 300),
fadeMode: FadeMode.horizontal,
child: Padding(
padding: const EdgeInsets.only(
left: 12.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.end,
children: [
if (bot.attachmentType!
.contains('image'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
icon: Assets.icon
.outline.galleryAdd,
color: Theme.of(context)
.colorScheme
.primary,
iconColor: Colors.white,
onTap: () async {
await BottomSheetHandler(
context)
.getFile(
fileType:
FileType
.audio);
if (file != null) {
selectedFile.value =
file.single;
if (widget.chatArgs.bot
.attachment !=
3) {
visibleAttach.value =
false;
}
}
},
.showPickImage(
onSelect: (file) {
selectedFile
.value = file;
if (widget
.chatArgs
.bot
.attachment !=
3) {
visibleAttach
.value =
false;
}
},
);
}),
),
),
if (bot.attachmentType!
.contains('pdf'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
if (bot.attachmentType!
.contains('audio'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
icon: Assets.icon.outline
.folderAdd,
.musicnote,
color: Theme.of(context)
.colorScheme
.primary,
@ -2345,19 +2397,7 @@ class _ChatPageState extends State<ChatPage> {
.getFile(
fileType:
FileType
.custom,
allowedExtensions: [
'pdf',
'doc',
'docx',
'xls',
'xlsx',
'xlsm',
'xlsb',
'xlt',
'xltx',
'xltm'
]);
.audio);
if (file != null) {
selectedFile.value =
file.single;
@ -2370,31 +2410,91 @@ class _ChatPageState extends State<ChatPage> {
.value = false;
}
}
}),
)
],
),
));
},
),
if ((bot.deleted != null && !bot.deleted!))
if (bot.attachment != 0 &&
bot.attachmentType != null &&
bot.attachmentType!.isNotEmpty &&
bot.attachment != 3)
GestureDetector(
onTap: () {
if (widget.chatArgs.bot.attachment != 3) {
visibleAttach.value =
!visibleAttach.value;
}
},
),
),
if (bot.attachmentType!
.contains('pdf'))
Padding(
padding:
const EdgeInsets.only(
right: 8.0),
child: CircleIconBtn(
icon: Assets.icon
.outline.folderAdd,
color: Theme.of(context)
.colorScheme
.primary,
iconColor: Colors.white,
onTap: () async {
final file = await PickFileService(
context)
.getFile(
fileType:
FileType
.custom,
allowedExtensions: [
'pdf',
'doc',
'docx',
'xls',
'xlsx',
'xlsm',
'xlsb',
'xlt',
'xltx',
'xltm'
]);
if (file != null) {
selectedFile.value =
file.single;
if (widget
.chatArgs
.bot
.attachment !=
3) {
visibleAttach
.value =
false;
}
}
}),
)
],
),
));
},
child: Assets.icon.outline.elementPlus.svg(
width: 24,
height: 24,
color: Theme.of(context)
.colorScheme
.primary)),
);
return const SizedBox.shrink();
},
),
ValueListenableBuilder<int>(
valueListenable: selectedBotId,
builder: (context, currentBotId, child) {
if ((bot.deleted != null && !bot.deleted!) &&
currentBotId != 4) if (bot.attachment !=
0 &&
bot.attachmentType != null &&
bot.attachmentType!.isNotEmpty &&
bot.attachment != 3)
return GestureDetector(
onTap: () {
if (widget.chatArgs.bot.attachment !=
3) {
visibleAttach.value =
!visibleAttach.value;
}
},
child: Assets.icon.outline.elementPlus
.svg(
width: 24,
height: 24,
color: Theme.of(context)
.colorScheme
.primary));
return const SizedBox.shrink();
},
),
],
),
],

View File

@ -57,7 +57,9 @@ class _AddFamilyState extends State<AddFamily> {
final backgroundColor = colorScheme.background;
final surfaceColor = colorScheme.surface;
final onSurface = colorScheme.onSurface;
final borderColor = const Color.fromARGB(255, 207, 206, 205);
final borderColor = isDark
? colorScheme.outline.withOpacity(0.5)
: const Color.fromARGB(255, 207, 206, 205);
final accent = colorScheme.primary;
final success = colorScheme.secondary;
@ -274,6 +276,10 @@ class _AddFamilyState extends State<AddFamily> {
foregroundColor: onSurface,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: isDark
? BorderSide(
color: success.withOpacity(0.3))
: BorderSide.none,
),
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
@ -287,6 +293,7 @@ class _AddFamilyState extends State<AddFamily> {
? CupertinoIcons.minus
: CupertinoIcons.add,
size: 18,
color: isDark ? success : null,
),
const SizedBox(width: 4),
Text(
@ -294,7 +301,7 @@ class _AddFamilyState extends State<AddFamily> {
? 'بستن فرم'
: 'افزودن عضو جدید',
style: AppTextStyles.body5.copyWith(
color: onSurface,
color: isDark ? success : onSurface,
fontWeight: FontWeight.bold),
),
],
@ -373,10 +380,13 @@ class _AddFamilyState extends State<AddFamily> {
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: isDark
? Color.fromARGB(255, 80, 80, 80)
? Color.fromARGB(255, 45, 45, 45)
: Color.fromARGB(255, 252, 252, 252),
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Color.fromARGB(255, 207, 206, 205)),
border: Border.all(
color: isDark
? colorScheme.outline.withOpacity(0.3)
: Color.fromARGB(255, 207, 206, 205)),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.03),
@ -452,7 +462,7 @@ class _AddFamilyState extends State<AddFamily> {
// // ],
// // ),
// ),
const SizedBox(width: 16),
// const SizedBox(width: 16),
InkWell(
onTap: () {
_showDeleteDialog(index);
@ -463,23 +473,7 @@ class _AddFamilyState extends State<AddFamily> {
height: 25,
),
),
const SizedBox(width: 16),
// Container(
// padding:
// const EdgeInsets.symmetric(horizontal: 15, vertical: 9),
// decoration: BoxDecoration(
// color: Color.fromARGB(255, 224, 236, 255),
// borderRadius: BorderRadius.circular(6),
// ),
// child: Text(
// 'در انتظار تایید',
// style: AppTextStyles.body6.copyWith(
// color: colorScheme.primary,
// fontWeight: FontWeight.bold,
// fontSize: 10,
// ),
// ),
// ),
// const SizedBox(width: 16),
],
),
],
@ -492,6 +486,7 @@ class _AddFamilyState extends State<AddFamily> {
final TextEditingController editPhoneController =
TextEditingController(text: member['phone']);
int? editAgeIndex = member['ageIndex'];
final isDark = Theme.of(context).brightness == Brightness.dark;
showDialog(
context: context,
@ -503,7 +498,9 @@ class _AddFamilyState extends State<AddFamily> {
insetPadding: const EdgeInsets.symmetric(horizontal: 16),
child: Container(
decoration: BoxDecoration(
color: const Color.fromARGB(255, 246, 246, 246),
color: isDark
? Theme.of(context).colorScheme.surface
: const Color.fromARGB(255, 246, 246, 246),
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.gray[300]),
),
@ -514,8 +511,10 @@ class _AddFamilyState extends State<AddFamily> {
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 16),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 224, 236, 255),
decoration: BoxDecoration(
color: isDark
? Theme.of(context).colorScheme.surfaceVariant
: const Color.fromARGB(255, 224, 236, 255),
borderRadius:
BorderRadius.vertical(top: Radius.circular(16)),
),
@ -528,13 +527,20 @@ class _AddFamilyState extends State<AddFamily> {
'ویرایش عضو ${_getOrdinal(index + 1)}',
textAlign: TextAlign.right,
style: AppTextStyles.body4.copyWith(
color: Colors.black,
color: isDark
? Theme.of(context)
.colorScheme
.onSurfaceVariant
: Colors.black,
fontWeight: FontWeight.bold,
),
),
InkWell(
onTap: () => Navigator.pop(context),
child: const Icon(CupertinoIcons.clear, size: 20),
child: Icon(CupertinoIcons.clear,
size: 20,
color:
Theme.of(context).colorScheme.onSurface),
)
],
),
@ -542,7 +548,7 @@ class _AddFamilyState extends State<AddFamily> {
),
Container(
height: 2,
color: const Color.fromARGB(255, 30, 29, 27),
color: Theme.of(context).colorScheme.outline,
),
Padding(
padding: const EdgeInsets.all(16),
@ -563,6 +569,9 @@ class _AddFamilyState extends State<AddFamily> {
controller: editPhoneController,
keyboardType: TextInputType.phone,
textDirection: TextDirection.ltr,
style: TextStyle(
color:
Theme.of(context).colorScheme.onSurface),
decoration: InputDecoration(
suffixIcon: Icon(
CupertinoIcons.phone,
@ -693,11 +702,14 @@ class _AddFamilyState extends State<AddFamily> {
void _showDeleteDialog(int index) {
final member = _invitedMembers[index];
final isDark = Theme.of(context).brightness == Brightness.dark;
showDialog(
context: context,
builder: (context) {
return Dialog(
backgroundColor: Colors.white,
backgroundColor:
isDark ? Theme.of(context).colorScheme.surface : Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
@ -714,7 +726,9 @@ class _AddFamilyState extends State<AddFamily> {
InkWell(
onTap: () => Navigator.pop(context),
child: SvgPicture.asset(
'assets/icon/outline/close-circle.svg')),
'assets/icon/outline/close-circle.svg',
color: Theme.of(context).colorScheme.onSurface,
)),
],
),
SvgPicture.asset(
@ -727,14 +741,17 @@ class _AddFamilyState extends State<AddFamily> {
'کاربر حذف شود؟',
style: AppTextStyles.body3.copyWith(
fontWeight: FontWeight.bold,
color: Colors.black,
color: Theme.of(context).colorScheme.onSurface,
),
),
const SizedBox(height: 8),
Text(
'شماره همراه: ${member['phone']}',
style: AppTextStyles.body5.copyWith(
color: AppColors.black[700],
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.7),
fontFamily: 'Dana',
),
),
@ -828,8 +845,11 @@ class _AddFamilyState extends State<AddFamily> {
}
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey[200],
foregroundColor: Colors.black,
backgroundColor: isDark
? Theme.of(context).colorScheme.surfaceVariant
: Colors.grey[200],
foregroundColor:
Theme.of(context).colorScheme.onSurface,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(100),
@ -864,8 +884,11 @@ class _AddFamilyState extends State<AddFamily> {
required int? groupValue,
required ValueChanged<int> onChanged,
}) {
final colorScheme = Theme.of(context).colorScheme;
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final isDark = theme.brightness == Brightness.dark;
final isSelected = groupValue == index;
return InkWell(
onTap: () => onChanged(index),
borderRadius: BorderRadius.circular(8),
@ -873,16 +896,25 @@ class _AddFamilyState extends State<AddFamily> {
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
color: isSelected
? colorScheme.primaryContainer.withOpacity(0.35)
: colorScheme.surfaceVariant,
? (isDark
? colorScheme.primary.withOpacity(0.3)
: colorScheme.primaryContainer.withOpacity(0.35))
: (isDark
? colorScheme.surfaceVariant
: colorScheme.surfaceVariant),
borderRadius: BorderRadius.circular(30),
border: isDark && !isSelected
? Border.all(color: colorScheme.outline.withOpacity(0.3))
: null,
),
child: Text(
title,
textAlign: TextAlign.center,
style: AppTextStyles.body6.copyWith(
color: isSelected
? colorScheme.onPrimaryContainer
? (isDark
? colorScheme.primary
: colorScheme.onPrimaryContainer)
: colorScheme.onSurface.withOpacity(0.7),
fontWeight: FontWeight.bold,
fontSize: 11,
@ -910,10 +942,14 @@ class _AddFamilyState extends State<AddFamily> {
}
Widget _buildInviteCard(int memberNumber) {
final colorScheme = Theme.of(context).colorScheme;
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final isDark = theme.brightness == Brightness.dark;
return Container(
decoration: BoxDecoration(
color: Color.fromARGB(255, 246, 246, 246),
color:
isDark ? colorScheme.surface : Color.fromARGB(255, 246, 246, 246),
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
@ -929,7 +965,9 @@ class _AddFamilyState extends State<AddFamily> {
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
decoration: BoxDecoration(
color: Color.fromARGB(255, 224, 236, 255),
color: isDark
? colorScheme.surfaceVariant
: Color.fromARGB(255, 224, 236, 255),
borderRadius:
const BorderRadius.vertical(top: Radius.circular(16)),
),
@ -937,7 +975,7 @@ class _AddFamilyState extends State<AddFamily> {
'دعوت از عضو ${_getOrdinal(memberNumber)}',
textAlign: TextAlign.right,
style: AppTextStyles.body4.copyWith(
color: Colors.black,
color: isDark ? colorScheme.onSurfaceVariant : Colors.black,
fontWeight: FontWeight.bold,
),
),
@ -963,6 +1001,7 @@ class _AddFamilyState extends State<AddFamily> {
controller: _phoneController,
keyboardType: TextInputType.phone,
textDirection: TextDirection.ltr,
style: TextStyle(color: colorScheme.onSurface),
decoration: InputDecoration(
suffixIcon: Icon(
CupertinoIcons.phone,
@ -972,8 +1011,10 @@ class _AddFamilyState extends State<AddFamily> {
horizontal: 16, vertical: 12),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
borderSide:
BorderSide(color: Color.fromARGB(255, 161, 160, 160)),
borderSide: BorderSide(
color: isDark
? colorScheme.outline.withOpacity(0.5)
: Color.fromARGB(255, 161, 160, 160)),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(16),
@ -1120,8 +1161,11 @@ class _AddFamilyState extends State<AddFamily> {
}
Widget _buildAgeOption({required String title, required int index}) {
final colorScheme = Theme.of(context).colorScheme;
final theme = Theme.of(context);
final colorScheme = theme.colorScheme;
final isDark = theme.brightness == Brightness.dark;
final isSelected = _selectedAgeIndex == index;
return InkWell(
onTap: () {
setState(() {
@ -1133,16 +1177,23 @@ class _AddFamilyState extends State<AddFamily> {
padding: const EdgeInsets.symmetric(vertical: 12),
decoration: BoxDecoration(
color: isSelected
? Color.fromARGB(255, 224, 236, 255)
: Color.fromARGB(255, 233, 232, 231),
? (isDark
? colorScheme.primary.withOpacity(0.3)
: Color.fromARGB(255, 224, 236, 255))
: (isDark
? colorScheme.surfaceVariant
: Color.fromARGB(255, 233, 232, 231)),
borderRadius: BorderRadius.circular(30),
border: isDark && !isSelected
? Border.all(color: colorScheme.outline.withOpacity(0.3))
: null,
),
child: Text(
title,
textAlign: TextAlign.center,
style: AppTextStyles.body6.copyWith(
color: isSelected
? Colors.black
? (isDark ? colorScheme.primary : Colors.black)
: colorScheme.onSurface.withOpacity(0.7),
fontWeight: FontWeight.bold,
fontSize: 11,
@ -1155,6 +1206,8 @@ class _AddFamilyState extends State<AddFamily> {
Widget _buildTopInfoCard(BuildContext context,
{required String title, required String icon}) {
final colorScheme = Theme.of(context).colorScheme;
final isDark = Theme.of(context).brightness == Brightness.dark;
return Column(
children: [
Container(
@ -1163,13 +1216,16 @@ class _AddFamilyState extends State<AddFamily> {
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Color.fromARGB(255, 248, 231, 241),
color: isDark
? colorScheme.surfaceVariant
: Color.fromARGB(255, 248, 231, 241),
),
child: Center(
child: SvgPicture.asset(
icon,
width: 32,
height: 32,
color: isDark ? colorScheme.onSurfaceVariant : null,
),
),
),

View File

@ -259,7 +259,6 @@ class _TtaPageState extends State<VideoChatPage> {
}
final m = mState.messages;
List<List<Messages>> allMessages = groupMessages(m);
// فیلتر کردن گروههایی که حداقل یک پیام با video_url دارند
List<List<Messages>> messages = allMessages.where((group) {
return group.any((msg) =>
msg.content?.any((c) => c.videoUrl != null) ?? false);