"Added file download functionality, modified media service, and updated AI chat page and state with file download feature."
This commit is contained in:
parent
0512e22727
commit
f42171401e
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
},
|
||||
),
|
||||
)
|
||||
]),
|
||||
)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue