fix some bugs

This commit is contained in:
OkaykOrhmn 2024-11-17 16:52:37 +03:30
parent a2c8b5ddac
commit 86c03984cd
16 changed files with 504 additions and 408 deletions

View File

@ -57,7 +57,7 @@ android {
applicationId "com.didvan.didvanapp"
minSdkVersion 24
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 31
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}

View File

@ -43,8 +43,10 @@ class Assets {
static String loadingAnimation = '$_baseAnimationsPath/loading.gif';
static String bookmarkAnimation = '$_baseAnimationsPath/bookmark.gif';
static String boxAnimation =
'$_baseAnimationsPath/onlinegiftools-$_themeSuffix.gif';
static String boxAnimationLight =
'$_baseAnimationsPath/onlinegiftools-light.gif';
static String boxAnimationDark =
'$_baseAnimationsPath/onlinegiftools-dark.gif';
static String get businessCategoryIcon =>
'$_baseCategoriesPath/business-$_themeSuffix.svg';

View File

@ -20,7 +20,6 @@ import 'package:didvan/services/notification/notification_service.dart';
import 'package:didvan/utils/my_custom_scroll_behavior.dart';
import 'package:didvan/views/ai/ai_state.dart';
import 'package:didvan/views/ai/bot_assistants_state.dart';
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/tools_state.dart';
import 'package:didvan/views/podcasts/podcasts_state.dart';
@ -180,9 +179,6 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
ChangeNotifierProvider<ToolsState>(
create: (context) => ToolsState(),
),
ChangeNotifierProvider<CreateBotAssistantsState>(
create: (context) => CreateBotAssistantsState(),
),
ChangeNotifierProvider<BotAssistantsState>(
create: (context) => BotAssistantsState(),
),

View File

@ -5,6 +5,7 @@ import 'package:didvan/views/ai/ai_chat_page.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai/bot_assistants_page.dart';
import 'package:didvan/views/ai/create_bot_assistants_page.dart';
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
import 'package:didvan/views/ai/history_ai_chat_page.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/info_page.dart';
@ -322,8 +323,18 @@ class RouteGenerator {
case Routes.botAssistants:
return _createRoute(const BotAssistantsPage());
case Routes.createBotAssistants:
return _createRoute(CreateBotAssistantsPage(
id: settings.arguments as int?,
return _createRoute(ChangeNotifierProvider<CreateBotAssistantsState>(
create: (context) {
final CreateBotAssistantsState pr = CreateBotAssistantsState();
final id = settings.arguments as int?;
if (id != null) {
pr.getAnAssistant(id: id);
}
return pr;
},
child: CreateBotAssistantsPage(
id: settings.arguments as int?,
),
));
case Routes.info:
return _createRoute(const InfoPage());

View File

@ -76,21 +76,10 @@ class _AiState extends State<Ai> {
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.only(bottom: 24),
padding:
const EdgeInsets.only(bottom: 24, top: 32),
child: Column(
children: [
const SizedBox(
height: 24,
),
Icon(
DidvanIcons.ai_solid,
size: MediaQuery.sizeOf(context).width / 5,
color: Theme.of(context).colorScheme.title,
),
DidvanText(
'هوشان',
color: Theme.of(context).colorScheme.title,
),
const SizedBox(
height: 24,
),

View File

@ -19,6 +19,7 @@ import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/utils/extension.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/widgets/ai_message_bar.dart';
@ -342,23 +343,30 @@ class _AiChatPageState extends State<AiChatPage> {
if (!snapshot.hasData) {
return const SizedBox();
}
return Markdown(
data: "${snapshot.data}...",
onTapLink: (text, href, title) {
if (href != null) {
launchUrlString(
href,
mode:
LaunchMode.inAppBrowserView,
);
}
},
selectable: false,
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
styleSheet:
defaultMarkdownStyleSheet);
return Directionality(
textDirection: snapshot.data
.toString()
.startsWithEnglish()
? TextDirection.ltr
: TextDirection.rtl,
child: Markdown(
data: "${snapshot.data}...",
onTapLink: (text, href, title) {
if (href != null) {
launchUrlString(
href,
mode: LaunchMode
.inAppBrowserView,
);
}
},
selectable: false,
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
styleSheet:
defaultMarkdownStyleSheet),
);
},
);
}),
@ -417,20 +425,26 @@ class _AiChatPageState extends State<AiChatPage> {
((message.audio == null ||
(message.audio != null &&
!message.audio!))))
Markdown(
data: message.text.toString(),
onTapLink: (text, href, title) {
if (href != null) {
launchUrlString(
href,
mode: LaunchMode.inAppBrowserView,
);
}
},
selectable: true,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
styleSheet: defaultMarkdownStyleSheet,
Directionality(
textDirection:
message.text.toString().startsWithEnglish()
? TextDirection.ltr
: TextDirection.rtl,
child: Markdown(
data: message.text.toString(),
onTapLink: (text, href, title) {
if (href != null) {
launchUrlString(
href,
mode: LaunchMode.inAppBrowserView,
);
}
},
selectable: true,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
styleSheet: defaultMarkdownStyleSheet,
),
),
Padding(
padding:
@ -438,7 +452,10 @@ class _AiChatPageState extends State<AiChatPage> {
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (message.role.toString().contains('user'))
if (message.role
.toString()
.contains('user') &&
widget.args.assistantsName == null)
PopupMenuButton(
offset: const Offset(0, 46),
onSelected: (value) async {
@ -446,7 +463,12 @@ class _AiChatPageState extends State<AiChatPage> {
Routes.aiChat,
arguments: AiChatArgs(
bot: value,
prompts: message));
prompts: message,
isTool: widget.args.isTool ??
context
.read<
HistoryAiChatState>()
.bots));
},
itemBuilder: (BuildContext context) {
final bots = widget.args.isTool ??

View File

@ -6,7 +6,6 @@ import 'package:didvan/models/ai/bot_assistants_model.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/ai/bot_assistants_state.dart';
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/hoshan_app_bar.dart';
@ -52,22 +51,25 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
(BuildContext context, BotAssistantsState state, Widget? child) =>
CustomScrollView(
slivers: [
const SliverToBoxAdapter(
SliverToBoxAdapter(
child: Center(
child: Padding(
padding: EdgeInsets.only(top: 32, bottom: 24),
padding: const EdgeInsets.only(top: 32, bottom: 24),
child: DidvanText(
'انتخاب بات‌ها',
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xff1B3C59),
color: Theme.of(context).colorScheme.checkFav,
),
),
),
),
if (state.appState != AppState.failed)
SliverToBoxAdapter(
child: switchAssistants(context, state),
child: Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: switchAssistants(context, state),
),
),
SliverStateHandler(
childCount: state.isMyAssistants
@ -101,8 +103,9 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
return Container(
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
decoration: const BoxDecoration(
color: Colors.white, borderRadius: DesignConfig.lowBorderRadius),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: DesignConfig.lowBorderRadius),
child: Column(
children: [
if (state.isMyAssistants)
@ -188,8 +191,8 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 32),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xffe0e0e0)),
color: Colors.white,
border: Border.all(color: Theme.of(context).colorScheme.border),
color: Theme.of(context).colorScheme.surface,
borderRadius: DesignConfig.lowBorderRadius),
child: Column(
children: [
@ -265,10 +268,6 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
child: state.isMyAssistants
? InkWell(
onTap: () async {
context
.read<CreateBotAssistantsState>()
.getAnAssistant(id: assistants.id!);
Navigator.pushNamed(
context, Routes.createBotAssistants,
arguments: assistants.id);
@ -325,8 +324,10 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
title: 'استفاده از دستیار',
onPressed: () => Navigator.pushNamed(context, Routes.aiChat,
arguments: AiChatArgs(
bot: assistants.bot!
.copyWith(id: assistants.id, image: assistants.image),
bot: assistants.bot!.copyWith(
id: assistants.id,
image: assistants.image,
description: assistants.description),
assistantsName: assistants.name)),
)
],
@ -338,8 +339,9 @@ class _BotAssistantsPageState extends State<BotAssistantsPage> {
return Container(
margin: const EdgeInsets.symmetric(horizontal: 32),
padding: const EdgeInsets.all(12),
decoration: const BoxDecoration(
color: Colors.white, borderRadius: DesignConfig.lowBorderRadius),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: DesignConfig.lowBorderRadius),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [

View File

@ -8,7 +8,6 @@ import 'package:cached_network_image/cached_network_image.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/ai/bot_assistants_model.dart';
import 'package:didvan/models/ai/bot_assistants_req_model.dart';
import 'package:didvan/models/ai/bots_model.dart';
import 'package:didvan/models/ai/file_create_assistants_model.dart';
@ -20,7 +19,6 @@ import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/extension.dart';
import 'package:didvan/views/ai/bot_assistants_state.dart';
import 'package:didvan/views/ai/create_bot_assistants_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/switch.dart';
@ -50,27 +48,12 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
borderRadius: DesignConfig.mediumBorderRadius,
borderSide: BorderSide(
width: 1, color: Theme.of(context).colorScheme.disabledText));
late List<BotsModel> allBots = context.read<HistoryAiChatState>().bots;
final List<String> botModels = ['مدل زبانی', 'مدل تصویری'];
// final _formYouTubeKey = GlobalKey<FormState>();
final _formNameKey = GlobalKey<FormState>();
final _formPromptKey = GlobalKey<FormState>();
final _formDescKey = GlobalKey<FormState>();
String name = '';
String prompt = '';
String desc = '';
// String? youtubeLink;
List<String> countOfLink = [''];
List<FileCreateAssistantsModel> files = [];
ValueNotifier<XFile?> image = ValueNotifier(null);
String selectedBotType = 'text';
bool isPrivate = true;
BotAssistants? assistant;
BotsModel? initialBot;
Timer? _timer;
@override
@ -100,7 +83,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
return;
}
final List<XFile> resultFiles = [];
for (var file in files) {
for (var file in state.files) {
if (!file.fromNetwork) {
resultFiles.add(file.file!);
}
@ -109,19 +92,20 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
final success = await state.createAssistants(
id: widget.id,
data: BotAssistantsReqModel(
type: selectedBotType,
name: name,
description: desc,
type: state.selectedBotType,
name: state.name,
description: state.desc,
botId: selectedBotId,
prompt: prompt,
webLinks: countOfLink.first.isEmpty ? null : countOfLink,
prompt: state.prompt,
webLinks:
state.countOfLink.first.isEmpty ? null : state.countOfLink,
// youtubeLink: youtubeLink,
isPrivate: isPrivate,
isPrivate: state.isPrivate,
files: resultFiles,
deleteImage: assistant != null
? assistant!.image == null
: image.value == null,
image: image.value));
deleteImage: state.assistant != null
? state.assistant!.image == null
: state.image.value == null,
image: state.image.value));
if (success) {
context.read<BotAssistantsState>().getMyAssissmant();
context.read<CreateBotAssistantsState>().assistant = null;
@ -135,10 +119,6 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
@override
Widget build(BuildContext context) {
int selectedBotId = selectedBotType == 'text'
? allBots.first.id!
: context.read<CreateBotAssistantsState>().imageBots.first.id!;
return WillPopScope(
onWillPop: () async {
context.read<CreateBotAssistantsState>().assistant = null;
@ -155,34 +135,9 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
),
body: Consumer<CreateBotAssistantsState>(builder: (BuildContext context,
CreateBotAssistantsState state, Widget? child) {
if (assistant == null && state.assistant != null) {
assistant = state.assistant;
name = assistant!.name ?? '';
prompt = assistant!.prompt ?? '';
desc = assistant!.description ?? '';
// youtubeLink = assistant!.;
isPrivate = assistant!.private ?? true;
if (files.isEmpty &&
assistant!.files != null &&
assistant!.files!.isNotEmpty) {
for (var file in assistant!.files!) {
files.add(FileCreateAssistantsModel(
fromNetwork: true, file: null, url: file));
}
}
countOfLink = assistant!.websites ?? [''];
selectedBotType = assistant!.type ?? 'text';
final list = selectedBotType == 'text' ? allBots : state.imageBots;
for (var bot in list) {
if (bot.id == assistant!.botId) {
initialBot = bot;
break;
}
}
}
int selectedBotId = state.selectedBotType == 'text'
? state.allBots.first.id!
: context.read<CreateBotAssistantsState>().imageBots.first.id!;
return state.loading
? Center(
child: SpinKitThreeBounce(
@ -202,9 +157,9 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
width: MediaQuery.sizeOf(context).width,
child: CustomDropdown<String>(
closedHeaderPadding: const EdgeInsets.all(12),
items: botModels,
enabled: assistant == null,
initialItem: botModels[0],
items: state.botModels,
enabled: state.assistant == null,
initialItem: state.botModels[0],
hideSelectedFieldWhenExpanded: false,
decoration: CustomDropdownDecoration(
listItemDecoration: ListItemDecoration(
@ -220,10 +175,9 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
Theme.of(context).colorScheme.surface),
// hintText: "انتخاب کنید",
onChanged: (value) {
setState(() {
final index = botModels.indexOf(value!);
selectedBotType = index == 0 ? 'text' : 'image';
});
final index = state.botModels.indexOf(value!);
state.selectedBotType =
index == 0 ? 'text' : 'image';
},
),
),
@ -231,7 +185,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
height: 24,
),
ValueListenableBuilder(
valueListenable: image,
valueListenable: state.image,
builder: (context, img, _) {
return Row(
mainAxisAlignment:
@ -240,24 +194,24 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
DidvanButton(
width: 120,
style: ButtonStyleMode.flat,
color: image.value != null ||
assistant?.image != null
color: state.image.value != null ||
state.assistant?.image != null
? Theme.of(context).colorScheme.error
: null,
title: image.value != null ||
assistant?.image != null
title: state.image.value != null ||
state.assistant?.image != null
? 'حذف عکس'
: 'انتخاب عکس',
onPressed: () async {
if (image.value != null ||
assistant?.image != null) {
if (assistant != null) {
assistant!.image = null;
if (state.image.value != null ||
state.assistant?.image != null) {
if (state.assistant != null) {
state.assistant!.image = null;
}
image.value = null;
state.image.value = null;
return;
}
image.value =
state.image.value =
await MediaService.pickImage(
source: ImageSource.gallery);
},
@ -273,9 +227,9 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
Image.file(File(img.path))),
)
: SkeletonImage(
imageUrl: assistant != null &&
assistant!.image != null
? assistant!.image!
imageUrl: state.assistant != null &&
state.assistant!.image != null
? state.assistant!.image!
: 'https://via.placeholder.com/70x70',
width: 80,
height: 80,
@ -290,14 +244,14 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
Form(
key: _formNameKey,
child: DidvanTextField(
initialValue: name,
initialValue: state.name,
onChanged: (value) {
name = value;
state.name = value;
if (value.isEmpty) {
return;
}
if (assistant == null) {
if (state.assistant == null) {
_timer?.cancel();
_timer =
Timer(const Duration(seconds: 1), () async {
@ -312,7 +266,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
result = 'نام نباید خالی باشد';
} else if (value.length < 4) {
result = 'نام نباید کمتر از 4 حرف باشد';
} else if (assistant == null &&
} else if (state.assistant == null &&
!state.successName) {
result =
'اسم دیگری انتخاب کنید این اسم موجود است';
@ -359,7 +313,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
Form(
key: _formDescKey,
child: DidvanTextField(
initialValue: desc,
initialValue: state.desc,
// hintText:
// 'به ربات خود بگویید که چگونه رفتار کند و چگونه به پیام‌های کاربر پاسخ دهد. سعی کنید تا حد امکان واضح و مشخص باشید.',
textInputType: TextInputType.multiline,
@ -369,7 +323,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
hasHeight: false,
showLen: true,
onChanged: (value) {
desc = value;
state.desc = value;
},
validator: (value) {
String? result;
@ -396,18 +350,18 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
width: MediaQuery.sizeOf(context).width,
child: CustomDropdown<BotsModel>(
closedHeaderPadding: const EdgeInsets.all(12),
items: selectedBotType == 'text'
? allBots
items: state.selectedBotType == 'text'
? state.allBots
: state.imageBots,
headerBuilder: (context, bot, enabled) =>
botRow(bot, context),
listItemBuilder: (context, bot, isSelected,
onItemSelect) =>
botRow(bot, context),
initialItem: assistant != null
? initialBot
: (selectedBotType == 'text'
? allBots
initialItem: state.assistant != null
? state.initialBot
: (state.selectedBotType == 'text'
? state.allBots
: state.imageBots)
.first,
hideSelectedFieldWhenExpanded: false,
@ -427,9 +381,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
.surface),
// hintText: "انتخاب کنید",
onChanged: (value) {
setState(() {
selectedBotId = value!.id!;
});
selectedBotId = value!.id!;
},
),
),
@ -440,7 +392,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
Form(
key: _formPromptKey,
child: DidvanTextField(
initialValue: prompt,
initialValue: state.prompt,
hintText:
'به ربات خود بگویید که چگونه رفتار کند و چگونه به پیام‌های کاربر پاسخ دهد. سعی کنید تا حد امکان واضح و مشخص باشید.',
textInputType: TextInputType.multiline,
@ -450,7 +402,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
hasHeight: false,
showLen: true,
onChanged: (value) {
prompt = value;
state.prompt = value;
},
validator: (value) {
String? result;
@ -466,15 +418,15 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
const SizedBox(
height: 24,
),
if (assistant == null)
if (state.assistant == null)
Column(
children: [
if (selectedBotType == 'text')
if (state.selectedBotType == 'text')
Column(
children: [
title(
text: 'پایگاه دانش', isRequired: false),
if (files.length != 3)
if (state.files.length != 3)
SizedBox(
height: 48,
child: ElevatedButton(
@ -492,11 +444,21 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
.pickMultiFile();
if (picks != null) {
for (var file in picks.xFiles) {
files.add(
FileCreateAssistantsModel(
fromNetwork: false,
file: file,
url: null));
if (file.path.isDocument() ||
file.path.isAudio()) {
state.files.add(
FileCreateAssistantsModel(
fromNetwork: false,
file: file,
url: null));
} else {
ActionSheetUtils(context)
.showAlert(AlertData(
message:
'باید فایل انتخاب شده صوتی یا Pdf باشد',
aLertType: ALertType
.error));
}
}
}
state.update();
@ -529,107 +491,125 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
MainAxisAlignment.spaceEvenly,
children: [
...List.generate(
files.length,
state.files.length,
(index) {
return Stack(
children: [
Container(
width: MediaQuery.sizeOf(
context)
.width /
5,
height: MediaQuery.sizeOf(
context)
.width /
5,
margin: const EdgeInsets
.symmetric(
horizontal: 8,
vertical: 12),
padding: const EdgeInsets
.all(8),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.disabledBackground,
borderRadius: DesignConfig
.lowBorderRadius),
child: Column(
children: [
Expanded(
child: files[index]
.fromNetwork
? files[index]
.url!
.isImage()
? CachedNetworkImage(
imageUrl:
files[index]
.url!)
: const Icon(
CupertinoIcons
.doc)
: files[index]
.file!
.path
.isImage()
? Image.file(
File(files[
index]
.file!
.path))
: const Icon(
CupertinoIcons
.doc),
),
MarqueeText(
text: files[index]
return SizedBox(
child: Stack(
children: [
Container(
width: MediaQuery
.sizeOf(
context)
.width /
5,
height: MediaQuery.sizeOf(
context)
.width /
5,
margin: const EdgeInsets
.symmetric(
horizontal: 8,
vertical: 12),
padding:
const EdgeInsets.all(
8),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.disabledBackground,
borderRadius: DesignConfig
.lowBorderRadius),
child: Column(
children: [
Expanded(
child: state
.files[
index]
.fromNetwork
? files[index]
.url!
.split('/')
.last
: files[index]
.file!
.name,
textDirection:
TextDirection
.rtl,
style: Theme.of(
context)
.textTheme
.labelSmall!)
],
)),
Positioned(
top: 8,
left: 4,
child: InkWell(
onTap: () {
files.removeAt(index);
state.update();
},
child: Container(
padding:
const EdgeInsets
.all(6),
decoration:
BoxDecoration(
shape: BoxShape
.circle,
color: Theme.of(
context)
.colorScheme
.error),
child: const Icon(
DidvanIcons
.trash_solid,
color: Colors.white,
size: 18,
? state
.files[
index]
.url!
.isImage()
? CachedNetworkImage(
imageUrl: state
.files[
index]
.url!)
: const Icon(
CupertinoIcons
.doc)
: state
.files[
index]
.file!
.path
.isImage()
? Image.file(File(state
.files[
index]
.file!
.path))
: const Icon(
CupertinoIcons
.doc),
),
MarqueeText(
text: state
.files[
index]
.fromNetwork
? state
.files[
index]
.url!
.split(
'/')
.last
: state
.files[
index]
.file!
.name,
textDirection:
TextDirection
.rtl,
style: Theme.of(
context)
.textTheme
.labelSmall!)
],
)),
Positioned(
top: 8,
left: 4,
child: InkWell(
onTap: () {
state.files
.removeAt(index);
state.update();
},
child: Container(
padding:
const EdgeInsets
.all(6),
decoration: BoxDecoration(
shape: BoxShape
.circle,
color: Theme.of(
context)
.colorScheme
.error),
child: const Icon(
DidvanIcons
.trash_solid,
color: Colors.white,
size: 18,
),
),
),
))
],
))
],
),
);
},
)
@ -666,25 +646,24 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
text: 'لینک وب سایت', isRequired: false),
Row(
children: [
if (countOfLink.length > 1)
if (state.countOfLink.length > 1)
DidvanIconButton(
icon:
CupertinoIcons.minus_circle_fill,
onPressed: () {
setState(() {
countOfLink.removeLast();
});
state.countOfLink.removeLast();
state.update();
},
),
if (countOfLink.length != 3)
if (state.countOfLink.length != 3)
DidvanIconButton(
icon: CupertinoIcons.plus_circle_fill,
onPressed: () {
setState(() {
if (countOfLink.last.isNotEmpty) {
countOfLink.add('');
}
});
if (state
.countOfLink.last.isNotEmpty) {
state.countOfLink.add('');
state.update();
}
},
),
],
@ -693,13 +672,18 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
),
ListView.builder(
shrinkWrap: true,
itemCount: countOfLink.length,
itemCount: state.countOfLink.length,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) => Column(
children: [
DidvanTextField(
onChanged: (value) {
countOfLink.insert(index, value);
state.countOfLink[index] = value;
if (state.countOfLink[index].isEmpty &&
state.countOfLink.length != 1) {
state.countOfLink.removeAt(index);
}
state.update();
},
// validator: (value) {},
hintText:
@ -766,10 +750,10 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
width: 64,
height: 48,
child: DidvanSwitch(
value: !isPrivate,
value: !state.isPrivate,
title: '',
onChanged: (value) {
isPrivate = !value;
state.isPrivate = !value;
},
),
),
@ -853,7 +837,7 @@ class _CreateBotAssistantsPageState extends State<CreateBotAssistantsPage> {
),
],
)
: Column(
: Stack(
children: [
DidvanButton(
title:

View File

@ -1,11 +1,17 @@
import 'package:didvan/main.dart';
import 'package:didvan/models/ai/bot_assistants_model.dart';
import 'package:didvan/models/ai/bot_assistants_req_model.dart';
import 'package:didvan/models/ai/bots_model.dart';
import 'package:didvan/models/ai/file_create_assistants_model.dart';
import 'package:didvan/models/ai/tools_model.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/providers/core.dart';
import 'package:didvan/services/network/request.dart';
import 'package:didvan/services/network/request_helper.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:flutter/cupertino.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
class CreateBotAssistantsState extends CoreProvier {
List<BotsModel> imageBots = [];
@ -15,6 +21,21 @@ class CreateBotAssistantsState extends CoreProvier {
bool successName = false;
bool loading = false;
BotAssistants? assistant;
String name = '';
String prompt = '';
String desc = '';
// String? youtubeLink;
late List<BotsModel> allBots =
navigatorKey.currentContext!.read<HistoryAiChatState>().bots;
final List<String> botModels = ['مدل زبانی', 'مدل تصویری'];
BotsModel? initialBot;
List<String> countOfLink = [''];
List<FileCreateAssistantsModel> files = [];
ValueNotifier<XFile?> image = ValueNotifier(null);
String selectedBotType = 'text';
bool isPrivate = true;
void getImageToolsBots() async {
loadingImageBots = true;
@ -77,6 +98,31 @@ class CreateBotAssistantsState extends CoreProvier {
await service.httpGet();
if (service.isSuccess) {
assistant = BotAssistants.fromJson(service.result['bot']);
if (assistant != null) {
name = assistant!.name ?? '';
prompt = assistant!.prompt ?? '';
desc = assistant!.description ?? '';
// youtubeLink = assistant!.;
isPrivate = assistant!.private ?? true;
if (files.isEmpty &&
assistant!.files != null &&
assistant!.files!.isNotEmpty) {
for (var file in assistant!.files!) {
files.add(FileCreateAssistantsModel(
fromNetwork: true, file: null, url: file));
}
}
countOfLink = assistant!.websites ?? [''];
selectedBotType = assistant!.type ?? 'text';
final list = selectedBotType == 'text' ? allBots : imageBots;
for (var bot in list) {
if (bot.id == assistant!.botId) {
initialBot = bot;
break;
}
}
}
appState = AppState.idle;
loading = false;
update();

View File

@ -1,4 +1,5 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/widgets/didvan/divider.dart';
@ -25,14 +26,14 @@ class _InfoPageState extends State<InfoPage> {
body: SingleChildScrollView(
child: Column(
children: [
const Center(
Center(
child: Padding(
padding: EdgeInsets.only(top: 32, bottom: 24),
padding: const EdgeInsets.only(top: 32, bottom: 24),
child: DidvanText(
'آموزش پرامپت نویسی اصولی',
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xff1B3C59),
color: Theme.of(context).colorScheme.checkFav,
),
),
),

View File

@ -1,4 +1,5 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/models/ai/ai_chat_args.dart';
import 'package:didvan/models/ai/tools_model.dart';
import 'package:didvan/routes/routes.dart';
@ -40,7 +41,7 @@ class _ToolScreenState extends State<ToolScreen> {
tool.name!,
fontSize: 20,
fontWeight: FontWeight.bold,
color: const Color(0xff1B3C59),
color: Theme.of(context).colorScheme.checkFav,
),
const SizedBox(height: 8),
Padding(
@ -48,7 +49,7 @@ class _ToolScreenState extends State<ToolScreen> {
child: DidvanText(
tool.guide!,
fontSize: 12,
color: const Color(0xff666666),
color: Theme.of(context).colorScheme.caption,
),
),
const SizedBox(height: 24),
@ -88,7 +89,7 @@ class _ToolScreenState extends State<ToolScreen> {
bot.name!,
fontSize: 16,
fontWeight: FontWeight.bold,
color: const Color(0xff2A282F),
color: Theme.of(context).colorScheme.text,
),
if (bot.description != null)
Column(

View File

@ -1,4 +1,5 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/views/ai/ai_state.dart';
import 'package:didvan/views/ai/tools_state.dart';
@ -32,13 +33,13 @@ class _ToolsScreenState extends State<ToolsScreen> {
: const BouncingScrollPhysics(),
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 46, bottom: 24),
Padding(
padding: const EdgeInsets.only(top: 46, bottom: 24),
child: DidvanText(
'انتخاب بات‌ها',
fontSize: 20,
fontWeight: FontWeight.bold,
color: Color(0xff1B3C59),
color: Theme.of(context).colorScheme.checkFav,
),
),
Consumer<ToolsState>(
@ -68,8 +69,9 @@ class _ToolsScreenState extends State<ToolsScreen> {
child: Container(
decoration: BoxDecoration(
borderRadius: DesignConfig.lowBorderRadius,
color: Theme.of(context).colorScheme.surface,
border: Border.all(
color: const Color(0xffB8B8B8),
color: Theme.of(context).colorScheme.border,
),
),
padding: const EdgeInsets.all(24),
@ -125,7 +127,9 @@ class _ToolsScreenState extends State<ToolsScreen> {
color: Theme.of(context).colorScheme.primary,
),
DidvanText(tool.description!,
fontSize: 12, color: const Color(0xffA8A6AC))
fontSize: 12,
color:
Theme.of(context).colorScheme.caption)
],
),
)

View File

@ -1,6 +1,7 @@
// ignore_for_file: library_private_types_in_public_api, avoid_web_libraries_in_flutter, deprecated_member_use
import 'dart:async';
import 'package:didvan/utils/extension.dart';
import 'package:record/record.dart';
import 'package:universal_html/html.dart' as html;
import 'dart:io';
@ -378,45 +379,52 @@ class _AiMessageBarState extends State<AiMessageBar> {
Expanded(
child: state.file != null && state.file!.isRecorded
? audioContainer()
: TextFormField(
textInputAction: TextInputAction.newline,
style: Theme.of(context).textTheme.bodyMedium,
minLines: 1,
maxLines: 6, // Set this
keyboardType: TextInputType.multiline,
controller: state.message,
: 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, 0),
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(),
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();
}
},
),
onChanged: (value) {
if (value.isEmpty || value.length == 1) {
state.update();
}
},
),
),
Padding(

View File

@ -14,6 +14,7 @@ import 'package:didvan/services/media/media.dart';
import 'package:didvan/services/media/voice.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/utils/extension.dart';
import 'package:didvan/views/ai/ai_chat_state.dart';
import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart';
@ -391,68 +392,81 @@ class _AiMessageBarIOSState extends State<AiMessageBarIOS> {
state.file!.isRecorded
? audioContainer()
: Form(
child: 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
// expands: true, //
// keyboardType: TextInputType.text,
keyboardType:
TextInputType
.multiline,
controller:
state.message,
enabled: !(state
.file !=
null &&
widget.bot
.attachment ==
1),
decoration:
InputDecoration(
border: InputBorder
.none,
hintText:
'بنویسید...',
hintStyle: Theme.of(
textInputAction:
TextInputAction
.newline,
style: 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(),
),
.bodyMedium,
minLines: 1,
maxLines:
6, // Set this
// expands: true, //
// keyboardType: TextInputType.text,
keyboardType:
TextInputType
.multiline,
controller:
state.message,
onChanged: (value) {
messageText.value =
value;
state.update();
},
enabled: !(state
.file !=
null &&
widget.bot
.attachment ==
1),
decoration:
InputDecoration(
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) {
messageText
.value =
value;
state.update();
},
),
)),
),
),

View File

@ -1,5 +1,7 @@
import 'dart:math';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/routes/routes.dart';
@ -7,6 +9,7 @@ import 'package:didvan/views/ai/ai_state.dart';
import 'package:didvan/views/ai/bot_assistants_state.dart';
import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -37,15 +40,17 @@ class HoshanAppBar extends StatelessWidget implements PreferredSizeWidget {
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Row(
Row(
children: [
Icon(
DidvanIcons.ai_solid,
size: 40,
color: Theme.of(context).colorScheme.title,
),
DidvanText(
'هوشان',
fontSize: 14,
color: Theme.of(context).colorScheme.title,
fontWeight: FontWeight.bold,
),
],
@ -60,14 +65,23 @@ class HoshanAppBar extends StatelessWidget implements PreferredSizeWidget {
Navigator.pushNamed(context, Routes.info);
}),
if (withActions)
DidvanIconButton(
icon: DidvanIcons.antenna_light,
size: 32,
onPressed: () {
context.read<BotAssistantsState>().getMyAssissmant();
Stack(
children: [
DidvanIconButton(
icon: DidvanIcons.ai_regular,
size: 32,
onPressed: () {
context.read<BotAssistantsState>().getMyAssissmant();
Navigator.pushNamed(context, Routes.botAssistants);
},
Navigator.pushNamed(context, Routes.botAssistants);
},
),
Icon(
CupertinoIcons.plus,
color: Theme.of(context).colorScheme.primary,
size: 16,
)
],
),
context.watch<AiState>().page != 0 || !withActions
? Transform.rotate(
@ -85,7 +99,9 @@ class HoshanAppBar extends StatelessWidget implements PreferredSizeWidget {
child: Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Image.asset(
Assets.boxAnimation,
DesignConfig.brightness == Brightness.dark
? Assets.boxAnimationDark
: Assets.boxAnimationLight,
width: 38,
height: 38,
),

View File

@ -1414,10 +1414,10 @@ packages:
dependency: transitive
description:
name: vm_service
sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d"
url: "https://pub.dev"
source: hosted
version: "14.2.4"
version: "14.2.5"
wakelock_plus:
dependency: transitive
description: