"Added file download functionality, modified media service, and updated AI chat page and state with file download feature."

This commit is contained in:
OkaykOrhmn 2024-10-03 09:35:26 +03:30
parent 0512e22727
commit f42171401e
4 changed files with 151 additions and 61 deletions

View File

@ -1,4 +1,7 @@
import 'dart:io';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/ai/files_model.dart';
import 'package:didvan/models/requests/studio.dart';
import 'package:didvan/models/studio_details_data.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
@ -11,7 +14,12 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_picker/image_picker.dart';
import 'package:just_audio/just_audio.dart';
import 'package:mime/mime.dart';
import 'package:path/path.dart' as p;
import 'package:file_picker/file_picker.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;
import 'package:universal_html/html.dart' as html;
class MediaService {
static final audioPlayer = AudioPlayer();
@ -141,6 +149,42 @@ class MediaService {
}
}
static Future<String?> downloadFile(String url) async {
final basename = p.basename(url).split('?accessToken=').first;
Directory? dir;
try {
if (Platform.isIOS) {
dir = await getApplicationDocumentsDirectory(); // for iOS
} else {
dir = Directory('/storage/emulated/0/Download/'); // for android
if (!await dir.exists()) dir = (await getExternalStorageDirectory())!;
}
} catch (err) {
print("Cannot get download folder path $err");
}
String path = "${dir?.path}$basename";
File file = File(path);
try {
final http.Response audioResponse = await http.get(Uri.parse(url));
final bytes = audioResponse.bodyBytes;
file.writeAsBytes(bytes);
} catch (e) {
print("Exception$e");
return null;
}
return path;
}
static String downloadFileFromWeb(String url) {
html.AnchorElement anchorElement = html.AnchorElement(href: url);
anchorElement.download = url;
anchorElement.click();
return anchorElement.pathname!;
}
static onLoadingPickFile(BuildContext context) {
ActionSheetUtils(context).openDialog(
barrierDismissible: false,

View File

@ -16,6 +16,9 @@ import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/media/media.dart';
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/views/ai/ai_chat_state.dart';
@ -27,6 +30,7 @@ import 'package:didvan/views/widgets/didvan/icon_button.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:didvan/views/widgets/marquee_text.dart';
import 'package:didvan/views/widgets/skeleton_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
@ -313,13 +317,14 @@ class _AiChatPageState extends State<AiChatPage> {
bottomSheet: Column(
mainAxisSize: MainAxisSize.min,
children: [
Platform.isIOS
? AiMessageBarIOS(
bot: widget.args.bot,
)
: AiMessageBar(
bot: widget.args.bot,
),
// Platform.isIOS
// ? AiMessageBarIOS(
// bot: widget.args.bot,
// )
// :
AiMessageBar(
bot: widget.args.bot,
),
],
)),
),
@ -590,6 +595,39 @@ class _AiChatPageState extends State<AiChatPage> {
),
),
),
if (message.file != null)
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () async {
final url =
'${RequestHelper.baseUrl + message.file.toString()}?accessToken=${RequestService.token}';
final download = kIsWeb
? MediaService
.downloadFileFromWeb(url)
: await MediaService.downloadFile(
url);
AlertData alertData = AlertData(
message: 'دانلود موفقیت آمیز بود',
aLertType: ALertType.success);
if (download == null) {
alertData = AlertData(
message:
'دانلود موفقیت آمیز نبود',
aLertType: ALertType.error);
}
ActionSheetUtils(context)
.showAlert(alertData);
},
child: Icon(
DidvanIcons.download_solid,
size: 18,
color: Theme.of(context)
.colorScheme
.focusedBorder,
),
),
),
if (message.error != null && message.error!)
Padding(
padding: const EdgeInsets.all(8.0),
@ -613,33 +651,41 @@ class _AiChatPageState extends State<AiChatPage> {
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () async {
await Clipboard.setData(ClipboardData(
text: state.messages[mIndex]
.prompts[index].text
.toString()));
Future.delayed(
Duration.zero,
() => ActionSheetUtils(context)
.showAlert(AlertData(
message:
"متن با موفقیت کپی شد",
aLertType:
ALertType.success)),
);
},
child: Icon(
DidvanIcons.copy_regular,
size: 18,
color: Theme.of(context)
.colorScheme
.focusedBorder,
if (state.messages[mIndex].prompts[index]
.text !=
null ||
(state.messages[mIndex].prompts[index]
.text !=
null &&
state.messages[mIndex].prompts[index]
.text!.isNotEmpty))
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () async {
await Clipboard.setData(ClipboardData(
text: state.messages[mIndex]
.prompts[index].text
.toString()));
Future.delayed(
Duration.zero,
() => ActionSheetUtils(context)
.showAlert(AlertData(
message:
"متن با موفقیت کپی شد",
aLertType:
ALertType.success)),
);
},
child: Icon(
DidvanIcons.copy_regular,
size: 18,
color: Theme.of(context)
.colorScheme
.focusedBorder,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(

View File

@ -143,7 +143,7 @@ class AiChatState extends CoreProvier {
messages.last.prompts.add(Prompts(
finished: false,
error: false,
text: '...',
text: '',
role: 'bot',
createdAt: DateTime.now()
.subtract(const Duration(minutes: 210))

View File

@ -281,12 +281,6 @@ class _AiMessageBarState extends State<AiMessageBar> {
.colorScheme
.focused
.withOpacity(0.5)),
child: Center(
child: SpinKitThreeBounce(
color: Theme.of(context).colorScheme.primary,
size: 32,
),
),
),
)
],
@ -310,6 +304,7 @@ class _AiMessageBarState extends State<AiMessageBar> {
Row recorderAndTextMessageHandler(BuildContext context, AiChatState state) {
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: _mRecorder!.isPaused
? [
Expanded(
@ -412,28 +407,33 @@ class _AiMessageBarState extends State<AiMessageBar> {
},
)),
),
attachmentLayout(state, context),
if (widget.bot.attachmentType!.isNotEmpty)
Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
child: MessageBarBtn(
enable: false,
icon: openAttach || state.file != null
? DidvanIcons.close_regular
: Icons.attach_file_outlined,
click: () {
if (_mPlayer!.isPlaying) {
stopPlayer();
}
if (state.file != null) {
state.file = null;
} else {
openAttach = !openAttach;
}
state.update();
},
),
)
Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: Row(children: [
attachmentLayout(state, context),
if (widget.bot.attachmentType!.isNotEmpty)
Padding(
padding: const EdgeInsets.fromLTRB(12, 0, 12, 0),
child: MessageBarBtn(
enable: false,
icon: openAttach || state.file != null
? DidvanIcons.close_regular
: Icons.attach_file_outlined,
click: () {
if (_mPlayer!.isPlaying) {
stopPlayer();
}
if (state.file != null) {
state.file = null;
} else {
openAttach = !openAttach;
}
state.update();
},
),
)
]),
)
],
);
}