From 2663a8b98e0c667ebd9ded09f3afd752968ddee1 Mon Sep 17 00:00:00 2001 From: OkaykOrhmn Date: Thu, 21 Nov 2024 12:05:43 +0330 Subject: [PATCH] "Updated AI models, routes, and UI components, including adding new fields, modifying widget layouts, and adjusting text styles." --- lib/models/ai/bots_model.dart | 3 + lib/models/ai/info_model.dart | 21 ++ lib/routes/route_generator.dart | 9 +- lib/services/network/request_helper.dart | 1 + lib/views/ai/ai_chat_page.dart | 9 +- lib/views/ai/create_bot_assistants_page.dart | 6 +- lib/views/ai/info_page.dart | 327 ++++++++----------- lib/views/ai/info_state.dart | 23 ++ lib/views/ai/tool_screen.dart | 9 +- lib/views/widgets/didvan/text_field.dart | 2 +- lib/views/widgets/skeleton_image.dart | 6 +- 11 files changed, 207 insertions(+), 209 deletions(-) create mode 100644 lib/models/ai/info_model.dart create mode 100644 lib/views/ai/info_state.dart diff --git a/lib/models/ai/bots_model.dart b/lib/models/ai/bots_model.dart index 2e1f08a..d5a63f6 100644 --- a/lib/models/ai/bots_model.dart +++ b/lib/models/ai/bots_model.dart @@ -4,6 +4,7 @@ class BotsModel { String? image; String? responseType; String? description; + String? short; List? attachmentType; int? attachment; bool? editable; @@ -23,6 +24,7 @@ class BotsModel { name = json['name']; image = json['image']; description = json['description']; + short = json['short']; if (json['attachmentType'] != null) { attachmentType = []; json['attachmentType'].forEach((v) { @@ -40,6 +42,7 @@ class BotsModel { data['name'] = name; data['image'] = image; data['description'] = description; + data['short'] = short; if (attachmentType != null) { data['attachmentType'] = attachmentType!.map((v) => v).toList(); } diff --git a/lib/models/ai/info_model.dart b/lib/models/ai/info_model.dart new file mode 100644 index 0000000..a54496c --- /dev/null +++ b/lib/models/ai/info_model.dart @@ -0,0 +1,21 @@ +class InfoModel { + String? url; + String? title; + List? description; + + InfoModel({this.url, this.title, this.description}); + + InfoModel.fromJson(Map json) { + url = json['url']; + title = json['title']; + description = json['description'].cast(); + } + + Map toJson() { + final Map data = {}; + data['url'] = url; + data['title'] = title; + data['description'] = description; + return data; + } +} diff --git a/lib/routes/route_generator.dart b/lib/routes/route_generator.dart index 520068c..9b368b3 100644 --- a/lib/routes/route_generator.dart +++ b/lib/routes/route_generator.dart @@ -9,6 +9,7 @@ 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'; +import 'package:didvan/views/ai/info_state.dart'; import 'package:didvan/views/authentication/authentication.dart'; import 'package:didvan/views/authentication/authentication_state.dart'; import 'package:didvan/views/comments/comments.dart'; @@ -337,7 +338,13 @@ class RouteGenerator { ), )); case Routes.info: - return _createRoute(const InfoPage()); + return _createRoute(ChangeNotifierProvider( + create: (context) { + InfoState infoState = InfoState(); + infoState.getTools(); + return infoState; + }, + child: const InfoPage())); case Routes.web: return _createRoute(WebView( diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart index 6837695..cce8a18 100644 --- a/lib/services/network/request_helper.dart +++ b/lib/services/network/request_helper.dart @@ -230,6 +230,7 @@ class RequestHelper { static String archivedChat(int id) => '$baseUrl/ai/chat/$id/archive'; static String placeholder(int id) => '$baseUrl/ai/chat/$id/placeholder'; static String tools() => '$baseUrl/ai/tool'; + static String info() => '$baseUrl/ai/video'; static String usersAssistants({final bool personal = false}) => '$baseUrl/ai/user/bot${_urlConcatGenerator([ MapEntry('personal', personal), diff --git a/lib/views/ai/ai_chat_page.dart b/lib/views/ai/ai_chat_page.dart index 68d767d..7165cd5 100644 --- a/lib/views/ai/ai_chat_page.dart +++ b/lib/views/ai/ai_chat_page.dart @@ -159,8 +159,13 @@ class _AiChatPageState extends State { horizontal: 20.0), child: Center( child: DidvanText( - widget.args.bot.description ?? - '')), + widget.args.bot.description ?? '', + fontSize: 12, + color: Theme.of(context) + .colorScheme + .caption, + textAlign: TextAlign.justify, + )), ) ], ) diff --git a/lib/views/ai/create_bot_assistants_page.dart b/lib/views/ai/create_bot_assistants_page.dart index 1e3b921..a808e3a 100644 --- a/lib/views/ai/create_bot_assistants_page.dart +++ b/lib/views/ai/create_bot_assistants_page.dart @@ -416,7 +416,7 @@ class _CreateBotAssistantsPageState extends State { textInputType: TextInputType.multiline, minLine: 6, maxLine: 6, - maxLength: 400, + maxLength: 2000, hasHeight: false, showLen: true, onChanged: (value) { @@ -679,6 +679,7 @@ class _CreateBotAssistantsPageState extends State { itemBuilder: (context, index) => Column( children: [ DidvanTextField( + textAlign: TextAlign.left, onChanged: (value) { state.countOfLink[index] = value; if (state.countOfLink[index] @@ -691,8 +692,7 @@ class _CreateBotAssistantsPageState extends State { state.update(); }, // validator: (value) {}, - hintText: - 'https://www.weforum.org/agenda/2024/08', + hintText: 'https://www.weforum.org', ), const SizedBox( height: 8, diff --git a/lib/views/ai/info_page.dart b/lib/views/ai/info_page.dart index fe1605c..09cd770 100644 --- a/lib/views/ai/info_page.dart +++ b/lib/views/ai/info_page.dart @@ -1,12 +1,17 @@ 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/enums.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/views/ai/info_state.dart'; import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/hoshan_app_bar.dart'; import 'package:didvan/views/widgets/video/chat_video_player.dart'; +import 'package:didvan/views/widgets/video/primary_controls.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; +import 'package:provider/provider.dart'; class InfoPage extends StatefulWidget { const InfoPage({Key? key}) : super(key: key); @@ -23,215 +28,141 @@ class _InfoPageState extends State { withActions: false, onBack: () => Navigator.pop(context), ), - body: Column( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: SingleChildScrollView( - physics: const BouncingScrollPhysics(), - child: Column( - children: [ - Center( - child: Padding( - padding: const EdgeInsets.only(top: 32, bottom: 24), - child: DidvanText( - 'آموزش پرامپت نویسی اصولی', - fontSize: 20, - fontWeight: FontWeight.bold, - color: Theme.of(context).colorScheme.checkFav, - ), - ), - ), - const Padding( - padding: EdgeInsets.symmetric(horizontal: 20.0), - child: ClipRRect( - borderRadius: DesignConfig.lowBorderRadius, - child: ChatVideoPlayer( - src: - 'https://flutter.github.io/assets-for-api-docs/assets/videos/bee.mp4', - showOptions: true, - ), - ), - ), - Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Row( - children: [ - DidvanText( - 'آنچه در این ویدیو خواهید دید:', - fontSize: 16, - ), - ], + body: Consumer(builder: (context, state, child) { + if (state.appState == AppState.busy) { + return Center( + child: SpinKitThreeBounce( + size: 46, + color: Theme.of(context).colorScheme.primary, + ), + ); + } + return Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: SingleChildScrollView( + physics: const BouncingScrollPhysics(), + child: Column( + children: [ + Center( + child: Padding( + padding: const EdgeInsets.only(top: 32, bottom: 24), + child: DidvanText( + state.infoModel.title ?? 'آموزش پرامپت نویسی اصولی', + fontSize: 20, + fontWeight: FontWeight.bold, + color: Theme.of(context).colorScheme.checkFav, ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: ClipRRect( + borderRadius: DesignConfig.lowBorderRadius, + child: ChatVideoPlayer( + src: state.infoModel.url ?? '', + showOptions: true, + custome: const PrimaryControls(), + ), + ), + ), + Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Row( children: [ - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'انتخاب کلمات کلیدی مناسب', - fontSize: 14, - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'ساختار و قالب‌بندی پرامپت‌ها', - fontSize: 14, - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'تعیین سبک و استایل در پرامپت', - fontSize: 14, - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'استفاده از جزییات و صفت‌ها', - fontSize: 14, - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'بهینه‌سازی پرامپت‌ها و تکرار', - fontSize: 14, - ), - ], - ), - const SizedBox( - height: 4, - ), - Row( - children: [ - Container( - margin: const EdgeInsets.only(left: 8), - decoration: const ShapeDecoration( - shape: CircleBorder( - side: BorderSide( - width: 3, color: Colors.black)), - ), - ), - const DidvanText( - 'اشتباهات رایج در پرامپت‌نویسی', - fontSize: 14, - ), - ], + DidvanText( + 'آنچه در این ویدیو خواهید دید:', + fontSize: 16, ), ], ), - ) - ], + Padding( + padding: const EdgeInsets.all(8.0), + child: ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: state.infoModel.description!.length, + itemBuilder: (context, index) => summery( + state.infoModel.description?[index] ?? ''), + )) + ], + ), ), - ), - ], - ), - ), - ), - Column( - children: [ - const Padding( - padding: EdgeInsets.symmetric(horizontal: 20.0), - child: DidvanDivider( - verticalPadding: 12, - height: 4, + ], ), ), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Icon( - DidvanIcons.support_solid, - size: 32, + ), + Column( + children: [ + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20.0), + child: DidvanDivider( + verticalPadding: 12, + height: 4, ), - const SizedBox( - width: 8, - ), - const DidvanText('هنوز سوالی دارید؟'), - TextButton( - onPressed: () { - Navigator.of(context).pushNamed( - Routes.direct, - arguments: {'type': 'پشتیبانی اپلیکیشن'}, - ); - }, - child: const DidvanText( - ' پیام به پشتیبانی', - color: Color(0xff007EA7), + ), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Icon( + DidvanIcons.support_solid, + size: 32, ), - ) - ], + const SizedBox( + width: 8, + ), + const DidvanText('هنوز سوالی دارید؟'), + TextButton( + onPressed: () { + Navigator.of(context).pushNamed( + Routes.direct, + arguments: {'type': 'پشتیبانی اپلیکیشن'}, + ); + }, + child: const DidvanText( + ' پیام به پشتیبانی', + color: Color(0xff007EA7), + ), + ) + ], + ), + const SizedBox( + height: 32, + ), + ], + ) + ], + ); + }), + ); + } + + Column summery(String text) { + return Column( + children: [ + Row( + children: [ + Container( + margin: const EdgeInsets.only(left: 8), + decoration: const ShapeDecoration( + shape: CircleBorder( + side: BorderSide(width: 3, color: Colors.black)), ), - const SizedBox( - height: 32, - ), - ], - ) - ], - ), + ), + DidvanText( + text, + fontSize: 14, + ), + ], + ), + const SizedBox( + height: 4, + ), + ], ); } } diff --git a/lib/views/ai/info_state.dart b/lib/views/ai/info_state.dart new file mode 100644 index 0000000..bfd1735 --- /dev/null +++ b/lib/views/ai/info_state.dart @@ -0,0 +1,23 @@ +import 'package:didvan/models/ai/info_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'; + +class InfoState extends CoreProvier { + late InfoModel infoModel; + void getTools() async { + final service = RequestService( + RequestHelper.info(), + ); + await service.httpGet(); + if (service.isSuccess) { + infoModel = InfoModel.fromJson(service.result); + appState = AppState.idle; + update(); + return; + } + appState = AppState.failed; + update(); + } +} diff --git a/lib/views/ai/tool_screen.dart b/lib/views/ai/tool_screen.dart index be8cc1f..2fd99bb 100644 --- a/lib/views/ai/tool_screen.dart +++ b/lib/views/ai/tool_screen.dart @@ -50,6 +50,7 @@ class _ToolScreenState extends State { tool.guide!, fontSize: 12, color: Theme.of(context).colorScheme.caption, + textAlign: TextAlign.justify, ), ), const SizedBox(height: 24), @@ -91,17 +92,19 @@ class _ToolScreenState extends State { fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.text, ), - if (bot.description != null) + if (bot.short != null) Column( children: [ const SizedBox( height: 4, ), DidvanText( - bot.description!, - fontSize: 14, + bot.short!, + fontSize: 12, fontWeight: FontWeight.bold, color: const Color(0xffA8A6AC), + // maxLines: 2, + overflow: TextOverflow.ellipsis, ), ], ) diff --git a/lib/views/widgets/didvan/text_field.dart b/lib/views/widgets/didvan/text_field.dart index 9a8cc91..878f865 100644 --- a/lib/views/widgets/didvan/text_field.dart +++ b/lib/views/widgets/didvan/text_field.dart @@ -120,7 +120,7 @@ class _DidvanTextFieldState extends State { onFieldSubmitted: widget.onSubmitted, onChanged: _onChanged, validator: _validator, - maxLines: widget.maxLine, + maxLines: _hideContent ? 1 : widget.maxLine, minLines: widget.minLine, maxLength: widget.maxLength, obscuringCharacter: '*', diff --git a/lib/views/widgets/skeleton_image.dart b/lib/views/widgets/skeleton_image.dart index fce59a8..accb399 100644 --- a/lib/views/widgets/skeleton_image.dart +++ b/lib/views/widgets/skeleton_image.dart @@ -1,5 +1,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/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; import 'package:didvan/views/widgets/shimmer_placeholder.dart'; @@ -33,7 +34,10 @@ class SkeletonImage extends StatelessWidget { borderRadius: borderRadius ?? BorderRadius.zero, child: CachedNetworkImage( errorWidget: (context, url, error) { - return const Text("مشکلی پیش آمده است"); + return Container( + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.disabledBackground), + child: const Icon(Icons.image_not_supported_outlined)); }, errorListener: (value) {}, fit: BoxFit.cover,