"Updated InfoModel to include pdf field, modified AiChatPage and InfoPage to handle pdf and markdown text, removed flutter_markdown dependency and added markdown_widget dependency."

This commit is contained in:
OkaykOrhmn 2024-11-24 16:09:56 +03:30
parent 24321bbd32
commit 705d9fb8ab
8 changed files with 211 additions and 87 deletions

View File

@ -1,5 +1,6 @@
class InfoModel { class InfoModel {
String? url; String? url;
String? pdf;
String? title; String? title;
List<String>? description; List<String>? description;
@ -7,6 +8,7 @@ class InfoModel {
InfoModel.fromJson(Map<String, dynamic> json) { InfoModel.fromJson(Map<String, dynamic> json) {
url = json['url']; url = json['url'];
pdf = json['pdf'];
title = json['title']; title = json['title'];
description = json['description'].cast<String>(); description = json['description'].cast<String>();
} }
@ -14,6 +16,7 @@ class InfoModel {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};
data['url'] = url; data['url'] = url;
data['pdf'] = pdf;
data['title'] = title; data['title'] = title;
data['description'] = description; data['description'] = description;
return data; return data;

View File

@ -25,6 +25,7 @@ import 'package:didvan/views/ai/history_ai_chat_state.dart';
import 'package:didvan/views/ai/widgets/ai_message_bar.dart'; import 'package:didvan/views/ai/widgets/ai_message_bar.dart';
import 'package:didvan/views/ai/widgets/audio_wave.dart'; import 'package:didvan/views/ai/widgets/audio_wave.dart';
import 'package:didvan/views/ai/widgets/hoshan_drawer.dart'; import 'package:didvan/views/ai/widgets/hoshan_drawer.dart';
import 'package:didvan/views/widgets/didvan/didvan_markdown.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/hoshan_app_bar.dart'; import 'package:didvan/views/widgets/hoshan_app_bar.dart';
import 'package:didvan/views/widgets/marquee_text.dart'; import 'package:didvan/views/widgets/marquee_text.dart';
@ -34,11 +35,9 @@ import 'package:didvan/views/widgets/video/custome_controls.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
class AiChatPage extends StatefulWidget { class AiChatPage extends StatefulWidget {
final AiChatArgs args; final AiChatArgs args;
@ -111,6 +110,7 @@ class _AiChatPageState extends State<AiChatPage> {
withActions: false, withActions: false,
), ),
key: scaffKey, key: scaffKey,
resizeToAvoidBottomInset: true,
drawer: const HoshanDrawer(), drawer: const HoshanDrawer(),
body: state.loading body: state.loading
? Center( ? Center(
@ -278,27 +278,6 @@ class _AiChatPageState extends State<AiChatPage> {
? Duration(seconds: message.duration!) ? Duration(seconds: message.duration!)
: null)); : null));
MarkdownStyleSheet defaultMarkdownStyleSheet = MarkdownStyleSheet(
pPadding: const EdgeInsets.all(0.8),
h1Padding: const EdgeInsets.all(0.8),
h2Padding: const EdgeInsets.all(0.8),
h3Padding: const EdgeInsets.all(0.8),
h4Padding: const EdgeInsets.all(0.8),
h5Padding: const EdgeInsets.all(0.8),
h6Padding: const EdgeInsets.all(0.8),
tablePadding: const EdgeInsets.all(0.8),
blockquotePadding: const EdgeInsets.all(0.8),
listBulletPadding: const EdgeInsets.all(0.8),
tableCellsPadding: const EdgeInsets.all(0.8),
codeblockPadding: const EdgeInsets.all(8),
code: TextStyle(
backgroundColor: Theme.of(context).colorScheme.black,
color: Theme.of(context).colorScheme.white,
),
codeblockDecoration: BoxDecoration(
borderRadius: BorderRadius.circular(4),
color: Theme.of(context).colorScheme.black));
return Padding( return Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 4), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 4),
child: Column( child: Column(
@ -348,29 +327,19 @@ class _AiChatPageState extends State<AiChatPage> {
if (!snapshot.hasData) { if (!snapshot.hasData) {
return const SizedBox(); return const SizedBox();
} }
return Directionality( return Padding(
padding: const EdgeInsets.symmetric(
vertical: 8.0, horizontal: 16),
child: Directionality(
textDirection: snapshot.data textDirection: snapshot.data
.toString() .toString()
.startsWithEnglish() .startsWithEnglish()
? TextDirection.ltr ? TextDirection.ltr
: TextDirection.rtl, : TextDirection.rtl,
child: Markdown( child: DidvanMarkdownText(
data: "${snapshot.data}...", text: "${snapshot.data}...",
onTapLink: (text, href, title) { ),
if (href != null) { ),
launchUrlString(
href,
mode: LaunchMode
.inAppBrowserView,
);
}
},
selectable: false,
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
styleSheet:
defaultMarkdownStyleSheet),
); );
}, },
); );
@ -430,25 +399,18 @@ class _AiChatPageState extends State<AiChatPage> {
((message.audio == null || ((message.audio == null ||
(message.audio != null && (message.audio != null &&
!message.audio!)))) !message.audio!))))
Directionality( Padding(
textDirection: padding: const EdgeInsets.symmetric(
message.text.toString().startsWithEnglish() vertical: 8.0, horizontal: 16),
child: Directionality(
textDirection: message.text
.toString()
.startsWithEnglish()
? TextDirection.ltr ? TextDirection.ltr
: TextDirection.rtl, : TextDirection.rtl,
child: Markdown( child: DidvanMarkdownText(
data: message.text.toString(), text: 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(

View File

@ -4,6 +4,7 @@ import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart'; import 'package:didvan/models/enums.dart';
import 'package:didvan/routes/routes.dart'; import 'package:didvan/routes/routes.dart';
import 'package:didvan/views/ai/info_state.dart'; import 'package:didvan/views/ai/info_state.dart';
import 'package:didvan/views/widgets/didvan/button.dart';
import 'package:didvan/views/widgets/didvan/divider.dart'; import 'package:didvan/views/widgets/didvan/divider.dart';
import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/hoshan_app_bar.dart'; import 'package:didvan/views/widgets/hoshan_app_bar.dart';
@ -13,6 +14,7 @@ import 'package:didvan/views/widgets/video/primary_controls.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher_string.dart';
class InfoPage extends StatefulWidget { class InfoPage extends StatefulWidget {
const InfoPage({Key? key}) : super(key: key); const InfoPage({Key? key}) : super(key: key);
@ -62,17 +64,29 @@ class _InfoPageState extends State<InfoPage> {
), ),
), ),
), ),
if (state.infoModel.url != null)
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0), padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: ClipRRect( child: ClipRRect(
borderRadius: DesignConfig.lowBorderRadius, borderRadius: DesignConfig.lowBorderRadius,
child: ChatVideoPlayer( child: ChatVideoPlayer(
src: state.infoModel.url ?? '', src: state.infoModel.url!,
showOptions: true, showOptions: true,
custome: const PrimaryControls(), custome: const PrimaryControls(),
), ),
), ),
), ),
if (state.infoModel.pdf != null)
Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20, 0),
child: DidvanButton(
title: 'دانلود فایل راهنما',
onPressed: () {
launchUrlString(state.infoModel.pdf!,
mode: LaunchMode.inAppBrowserView);
},
),
),
Padding( Padding(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),
child: Column( child: Column(

View File

@ -488,7 +488,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
.toPersianDateStr())) { .toPersianDateStr())) {
state.messages.last.prompts.add(Prompts( state.messages.last.prompts.add(Prompts(
error: false, error: false,
text: message.text, text: message.text.replaceAll(r"\n", r" \n \n "),
// file: state.file?.path, // file: state.file?.path,
// fileName: state.file?.basename, // fileName: state.file?.basename,
fileLocal: state.file, fileLocal: state.file,
@ -506,7 +506,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
prompts: [ prompts: [
Prompts( Prompts(
error: false, error: false,
text: message.text, text: message.text.replaceAll(r"\n", r" \n \n "),
finished: true, finished: true,
// file: state.file?.path, // file: state.file?.path,
// fileName: state.file?.basename, // fileName: state.file?.basename,

View File

@ -254,7 +254,10 @@ class _AiMessageBarIOSState extends State<AiMessageBarIOS> {
.add(Prompts( .add(Prompts(
error: false, error: false,
text: state text: state
.message.text, .message.text
.replaceAll(
r"\n",
r" \n \n "),
file: state file: state
.file?.path, .file?.path,
fileName: state fileName: state
@ -285,7 +288,10 @@ class _AiMessageBarIOSState extends State<AiMessageBarIOS> {
false, false,
text: state text: state
.message .message
.text, .text
.replaceAll(
r"\n",
r" \n \n "),
finished: finished:
true, true,
file: state file: state

View File

@ -0,0 +1,107 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/utils/extension.dart';
import 'package:flutter/material.dart';
import 'package:markdown_widget/config/configs.dart';
import 'package:markdown_widget/widget/blocks/leaf/heading.dart';
import 'package:markdown_widget/widget/blocks/leaf/paragraph.dart';
import 'package:markdown_widget/widget/markdown.dart';
class DidvanMarkdownText extends StatelessWidget {
final String text;
final Color? color;
final double? width;
const DidvanMarkdownText(
{super.key, required this.text, this.color, this.width});
// onTapLink: (text, href, title) {
// if (href != null) {
// launchUrlString(
// href,
// mode: LaunchMode
// .inAppBrowserView,
// );
// }
// },
// MarkdownStyleSheet defaultMarkdownStyleSheet = MarkdownStyleSheet(
// pPadding: const EdgeInsets.all(0.8),
// h1Padding: const EdgeInsets.all(0.8),
// h2Padding: const EdgeInsets.all(0.8),
// h3Padding: const EdgeInsets.all(0.8),
// h4Padding: const EdgeInsets.all(0.8),
// h5Padding: const EdgeInsets.all(0.8),
// h6Padding: const EdgeInsets.all(0.8),
// tablePadding: const EdgeInsets.all(0.8),
// blockquotePadding: const EdgeInsets.all(0.8),
// listBulletPadding: const EdgeInsets.all(0.8),
// tableCellsPadding: const EdgeInsets.all(0.8),
// codeblockPadding: const EdgeInsets.all(8),
// code: TextStyle(
// backgroundColor: Theme.of(context).colorScheme.black,
// color: Theme.of(context).colorScheme.white,
// ),
// codeblockDecoration: BoxDecoration(
// borderRadius: BorderRadius.circular(4),
// color: Theme.of(context).colorScheme.black));
@override
Widget build(BuildContext context) {
return Directionality(
textDirection:
text.startsWithEnglish() ? TextDirection.ltr : TextDirection.rtl,
child: SizedBox(
width: width,
child: MarkdownWidget(
data: text,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
selectable: true,
config: MarkdownConfig(configs: [
H1Config(
style: MarkdownConfig.defaultConfig.h1.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
H2Config(
style: MarkdownConfig.defaultConfig.h2.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
H3Config(
style: MarkdownConfig.defaultConfig.h3.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
H4Config(
style: MarkdownConfig.defaultConfig.h4.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
H5Config(
style: MarkdownConfig.defaultConfig.h5.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
H6Config(
style: MarkdownConfig.defaultConfig.h6.style.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color)),
PConfig(
textStyle: MarkdownConfig.defaultConfig.p.textStyle.copyWith(
fontFamily: text.startsWithEnglish()
? DesignConfig.fontFamily.replaceAll('-FA', '')
: null,
color: color))
]),
),
),
);
}
}

View File

@ -414,6 +414,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.11.8" version: "1.11.8"
flutter_highlight:
dependency: transitive
description:
name: flutter_highlight
sha256: "7b96333867aa07e122e245c033b8ad622e4e3a42a1a2372cbb098a2541d8782c"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
flutter_html: flutter_html:
dependency: "direct main" dependency: "direct main"
description: description:
@ -459,14 +467,6 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_markdown:
dependency: "direct main"
description:
name: flutter_markdown
sha256: a23c41ee57573e62fc2190a1f36a0480c4d90bde3a8a8d7126e5d5992fb53fb7
url: "https://pub.dev"
source: hosted
version: "0.7.3+1"
flutter_plugin_android_lifecycle: flutter_plugin_android_lifecycle:
dependency: transitive dependency: transitive
description: description:
@ -597,6 +597,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.1" version: "2.3.1"
highlight:
dependency: transitive
description:
name: highlight
sha256: "5353a83ffe3e3eca7df0abfb72dcf3fa66cc56b953728e7113ad4ad88497cf21"
url: "https://pub.dev"
source: hosted
version: "0.7.0"
home_widget: home_widget:
dependency: "direct main" dependency: "direct main"
description: description:
@ -797,6 +805,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.2.2" version: "7.2.2"
markdown_widget:
dependency: "direct main"
description:
name: markdown_widget
sha256: "216dced98962d7699a265344624bc280489d739654585ee881c95563a3252fac"
url: "https://pub.dev"
source: hosted
version: "2.3.2+6"
marquee: marquee:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1125,6 +1141,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.27.7" version: "0.27.7"
scroll_to_index:
dependency: transitive
description:
name: scroll_to_index
sha256: b707546e7500d9f070d63e5acf74fd437ec7eeeb68d3412ef7b0afada0b4f176
url: "https://pub.dev"
source: hosted
version: "3.0.1"
skeleton_text: skeleton_text:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1410,6 +1434,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.2" version: "2.3.2"
visibility_detector:
dependency: transitive
description:
name: visibility_detector
sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420
url: "https://pub.dev"
source: hosted
version: "0.4.0+2"
vm_service: vm_service:
dependency: transitive dependency: transitive
description: description:

View File

@ -87,7 +87,7 @@ dependencies:
video_player: ^2.9.2 video_player: ^2.9.2
chewie: ^1.8.3 chewie: ^1.8.3
typewritertext: ^3.0.8 typewritertext: ^3.0.8
flutter_markdown: ^0.7.3+1 markdown_widget: ^2.3.2+6
file_picker: ^8.0.5 file_picker: ^8.0.5
marquee: ^2.2.3 marquee: ^2.2.3
mime: ^1.0.2 mime: ^1.0.2