TF-296 Fix upload file on browser
This commit is contained in:
@@ -1 +1 @@
|
|||||||
SERVER_URL=http://localhost
|
SERVER_URL=https://dev.open-paas.org
|
||||||
@@ -5,6 +5,7 @@ import 'dart:io';
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
|
import 'package:tmail_ui_user/main/utils/app_logger.dart';
|
||||||
|
|
||||||
class ComposerAPI {
|
class ComposerAPI {
|
||||||
|
|
||||||
@@ -13,15 +14,16 @@ class ComposerAPI {
|
|||||||
ComposerAPI(this._dioClient);
|
ComposerAPI(this._dioClient);
|
||||||
|
|
||||||
Future<UploadResponse> uploadAttachment(UploadRequest uploadRequest) async {
|
Future<UploadResponse> uploadAttachment(UploadRequest uploadRequest) async {
|
||||||
final file = File(uploadRequest.fileInfo.filePath);
|
log('uploadAttachment: fileInfo: ${uploadRequest.fileInfo.props}');
|
||||||
final headerParam = _dioClient.getHeaders();
|
final headerParam = _dioClient.getHeaders();
|
||||||
headerParam[HttpHeaders.contentTypeHeader] = uploadRequest.fileInfo.mimeType;
|
headerParam[HttpHeaders.contentTypeHeader] = uploadRequest.fileInfo.mimeType;
|
||||||
headerParam[HttpHeaders.contentLengthHeader] = file.readAsBytesSync().length;
|
headerParam[HttpHeaders.contentLengthHeader] = uploadRequest.fileInfo.fileSize;
|
||||||
|
|
||||||
final resultJson = await _dioClient.post(
|
final resultJson = await _dioClient.post(
|
||||||
Uri.decodeFull(uploadRequest.uploadUrl.toString()),
|
Uri.decodeFull(uploadRequest.uploadUrl.toString()),
|
||||||
options: Options(headers: headerParam),
|
options: Options(headers: headerParam),
|
||||||
data: file.openRead());
|
data: uploadRequest.fileInfo.readStream);
|
||||||
|
|
||||||
return UploadResponse.fromJson(jsonDecode(resultJson));
|
return UploadResponse.fromJson(jsonDecode(resultJson));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
import 'package:tmail_ui_user/features/base/base_bindings.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/data/datasource/autocomplete_datasource.dart';
|
import 'package:tmail_ui_user/features/composer/data/datasource/autocomplete_datasource.dart';
|
||||||
@@ -121,7 +120,6 @@ class ComposerBindings extends BaseBindings {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void bindingsController() {
|
void bindingsController() {
|
||||||
Get.lazyPut(() => TextEditingController());
|
|
||||||
Get.lazyPut(() => ComposerController(
|
Get.lazyPut(() => ComposerController(
|
||||||
Get.find<SendEmailInteractor>(),
|
Get.find<SendEmailInteractor>(),
|
||||||
Get.find<SaveEmailAddressesInteractor>(),
|
Get.find<SaveEmailAddressesInteractor>(),
|
||||||
@@ -131,7 +129,6 @@ class ComposerBindings extends BaseBindings {
|
|||||||
Get.find<ImagePaths>(),
|
Get.find<ImagePaths>(),
|
||||||
Get.find<Uuid>(),
|
Get.find<Uuid>(),
|
||||||
Get.find<DeviceInfoPlugin>(),
|
Get.find<DeviceInfoPlugin>(),
|
||||||
Get.find<TextEditingController>(),
|
|
||||||
Get.find<LocalFilePickerInteractor>(),
|
Get.find<LocalFilePickerInteractor>(),
|
||||||
Get.find<UploadMultipleAttachmentInteractor>(),
|
Get.find<UploadMultipleAttachmentInteractor>(),
|
||||||
Get.find<SaveEmailAsDraftsInteractor>(),
|
Get.find<SaveEmailAsDraftsInteractor>(),
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import 'package:device_info_plus/device_info_plus.dart';
|
|||||||
import 'package:enough_html_editor/enough_html_editor.dart';
|
import 'package:enough_html_editor/enough_html_editor.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:fk_user_agent/fk_user_agent.dart';
|
import 'package:fk_user_agent/fk_user_agent.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser;
|
import 'package:html_editor_enhanced/html_editor.dart' as HtmlEditorBrowser;
|
||||||
import 'package:http_parser/http_parser.dart';
|
import 'package:http_parser/http_parser.dart';
|
||||||
@@ -64,7 +64,6 @@ class ComposerController extends BaseController {
|
|||||||
final AppToast _appToast;
|
final AppToast _appToast;
|
||||||
final ImagePaths _imagePaths;
|
final ImagePaths _imagePaths;
|
||||||
final Uuid _uuid;
|
final Uuid _uuid;
|
||||||
final TextEditingController subjectEmailInputController;
|
|
||||||
final LocalFilePickerInteractor _localFilePickerInteractor;
|
final LocalFilePickerInteractor _localFilePickerInteractor;
|
||||||
final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor;
|
final UploadMultipleAttachmentInteractor _uploadMultipleAttachmentInteractor;
|
||||||
final DeviceInfoPlugin _deviceInfoPlugin;
|
final DeviceInfoPlugin _deviceInfoPlugin;
|
||||||
@@ -80,6 +79,7 @@ class ComposerController extends BaseController {
|
|||||||
HtmlEditorApi? htmlEditorApi;
|
HtmlEditorApi? htmlEditorApi;
|
||||||
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController();
|
final HtmlEditorBrowser.HtmlEditorController htmlControllerBrowser = HtmlEditorBrowser.HtmlEditorController();
|
||||||
|
|
||||||
|
final subjectEmailInputController = TextEditingController();
|
||||||
final toEmailAddressController = TextEditingController();
|
final toEmailAddressController = TextEditingController();
|
||||||
final ccEmailAddressController = TextEditingController();
|
final ccEmailAddressController = TextEditingController();
|
||||||
final bccEmailAddressController = TextEditingController();
|
final bccEmailAddressController = TextEditingController();
|
||||||
@@ -109,7 +109,6 @@ class ComposerController extends BaseController {
|
|||||||
this._imagePaths,
|
this._imagePaths,
|
||||||
this._uuid,
|
this._uuid,
|
||||||
this._deviceInfoPlugin,
|
this._deviceInfoPlugin,
|
||||||
this.subjectEmailInputController,
|
|
||||||
this._localFilePickerInteractor,
|
this._localFilePickerInteractor,
|
||||||
this._uploadMultipleAttachmentInteractor,
|
this._uploadMultipleAttachmentInteractor,
|
||||||
this._saveEmailAsDraftsInteractor,
|
this._saveEmailAsDraftsInteractor,
|
||||||
@@ -136,12 +135,9 @@ class ComposerController extends BaseController {
|
|||||||
@override
|
@override
|
||||||
void onClose() {
|
void onClose() {
|
||||||
subjectEmailInputController.dispose();
|
subjectEmailInputController.dispose();
|
||||||
|
|
||||||
toEmailAddressController.dispose();
|
toEmailAddressController.dispose();
|
||||||
ccEmailAddressController.dispose();
|
ccEmailAddressController.dispose();
|
||||||
bccEmailAddressController.dispose();
|
bccEmailAddressController.dispose();
|
||||||
|
|
||||||
htmlControllerBrowser.clearFocus();
|
|
||||||
super.onClose();
|
super.onClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,6 +355,8 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sendEmailAction(BuildContext context) async {
|
void sendEmailAction(BuildContext context) async {
|
||||||
|
clearFocusEditor(context);
|
||||||
|
|
||||||
if (isEnableEmailSendButton.value) {
|
if (isEnableEmailSendButton.value) {
|
||||||
final arguments = composerArguments.value;
|
final arguments = composerArguments.value;
|
||||||
if (arguments != null) {
|
if (arguments != null) {
|
||||||
@@ -416,13 +414,25 @@ class ComposerController extends BaseController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void openPickAttachmentMenu(BuildContext context, List<Widget> actionTiles) {
|
void openPickAttachmentMenu(BuildContext context, List<Widget> actionTiles) {
|
||||||
(ContextMenuBuilder(context)
|
clearFocusEditor(context);
|
||||||
..addHeader(
|
|
||||||
(ContextMenuHeaderBuilder(Key('attachment_picker_context_menu_header_builder'))
|
(ContextMenuBuilder(context)
|
||||||
|
..addHeader((ContextMenuHeaderBuilder(Key('attachment_picker_context_menu_header_builder'))
|
||||||
..addLabel(AppLocalizations.of(context).pick_attachments))
|
..addLabel(AppLocalizations.of(context).pick_attachments))
|
||||||
.build())
|
.build())
|
||||||
..addTiles(actionTiles))
|
..addTiles(actionTiles)
|
||||||
.build();
|
..addOnCloseContextMenuAction(() => popBack()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
void openPickAttachmentsForWeb(BuildContext context, RelativeRect? position, List<PopupMenuEntry> popupMenuItems) async {
|
||||||
|
await showMenu(
|
||||||
|
context: context,
|
||||||
|
position: position ?? RelativeRect.fromLTRB(16, 40, 16, 16),
|
||||||
|
color: Colors.white,
|
||||||
|
elevation: 5,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
|
||||||
|
items: popupMenuItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void openFilePickerByType(BuildContext context, FileType fileType) async {
|
void openFilePickerByType(BuildContext context, FileType fileType) async {
|
||||||
@@ -525,7 +535,9 @@ class ComposerController extends BaseController {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveEmailAsDrafts() async {
|
void saveEmailAsDrafts(BuildContext context) async {
|
||||||
|
clearFocusEditor(context);
|
||||||
|
|
||||||
final arguments = composerArguments.value;
|
final arguments = composerArguments.value;
|
||||||
if (arguments != null && Get.context != null) {
|
if (arguments != null && Get.context != null) {
|
||||||
final isChanged = await _isEmailChanged(arguments);
|
final isChanged = await _isEmailChanged(arguments);
|
||||||
@@ -583,7 +595,14 @@ class ComposerController extends BaseController {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
void backToEmailViewAction() {
|
void clearFocusEditor(BuildContext context) {
|
||||||
|
if (!kIsWeb) {
|
||||||
|
htmlEditorApi?.unfocus(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void backToEmailViewAction(BuildContext context) {
|
||||||
|
clearFocusEditor(context);
|
||||||
popBack();
|
popBack();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,13 +25,12 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
onWillPop: () async {
|
onWillPop: () async {
|
||||||
controller.htmlEditorApi?.unfocus(context);
|
controller.saveEmailAsDrafts(context);
|
||||||
controller.saveEmailAsDrafts();
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
controller.htmlEditorApi?.unfocus(context);
|
controller.clearFocusEditor(context);
|
||||||
},
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: AppColor.primaryLightColor,
|
backgroundColor: AppColor.primaryLightColor,
|
||||||
@@ -60,19 +59,20 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
Widget _buildTopBar(BuildContext context) {
|
Widget _buildTopBar(BuildContext context) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 8),
|
||||||
child: Obx(() => (TopBarComposerWidgetBuilder(imagePaths, controller.isEnableEmailSendButton.value)
|
child: Obx(() => (TopBarComposerWidgetBuilder(context, imagePaths, controller.isEnableEmailSendButton.value)
|
||||||
..addSendEmailActionClick(() {
|
..addSendEmailActionClick(() {
|
||||||
controller.htmlEditorApi?.unfocus(context);
|
|
||||||
controller.sendEmailAction(context);
|
controller.sendEmailAction(context);
|
||||||
})
|
})
|
||||||
..addAttachFileActionClick(() {
|
..addAttachFileActionClick((position) {
|
||||||
controller.htmlEditorApi?.unfocus(context);
|
if (kIsWeb) {
|
||||||
controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context));
|
controller.openPickAttachmentsForWeb(context,position, _pickAttachmentsActionTilesForWeb(context));
|
||||||
|
} else {
|
||||||
|
controller.openPickAttachmentMenu(context, _pickAttachmentsActionTiles(context));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
..addBackActionClick(() {
|
..addBackActionClick(() {
|
||||||
controller.htmlEditorApi?.unfocus(context);
|
controller.saveEmailAsDrafts(context);
|
||||||
controller.saveEmailAsDrafts();
|
controller.backToEmailViewAction(context);
|
||||||
controller.backToEmailViewAction();
|
|
||||||
}))
|
}))
|
||||||
.build()),
|
.build()),
|
||||||
);
|
);
|
||||||
@@ -82,7 +82,15 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
return [
|
return [
|
||||||
_pickPhotoAndVideoAction(context),
|
_pickPhotoAndVideoAction(context),
|
||||||
_browseFileAction(context),
|
_browseFileAction(context),
|
||||||
SizedBox(height: 30),
|
SizedBox(height: kIsWeb ? 16 : 30),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PopupMenuEntry> _pickAttachmentsActionTilesForWeb(BuildContext context) {
|
||||||
|
return [
|
||||||
|
PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _pickPhotoAndVideoAction(context)),
|
||||||
|
PopupMenuDivider(height: 0.5),
|
||||||
|
PopupMenuItem(padding: EdgeInsets.symmetric(horizontal: 8), child: _browseFileAction(context)),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,10 +270,11 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
alignment: Alignment.topCenter,
|
alignment: Alignment.topCenter,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
if (kIsWeb) _buildAttachmentsLoadingView(),
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 24),
|
padding: EdgeInsets.only(top: 8, left: 16, right: 16, bottom: 24),
|
||||||
child: _buildComposerEditor(context)),
|
child: _buildComposerEditor(context)),
|
||||||
_buildAttachmentsLoadingView(),
|
if (!kIsWeb) _buildAttachmentsLoadingView(),
|
||||||
_buildAttachments(context),
|
_buildAttachments(context),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -290,7 +299,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
htmlToolbarOptions: HtmlEditorBrowser.HtmlToolbarOptions(
|
htmlToolbarOptions: HtmlEditorBrowser.HtmlToolbarOptions(
|
||||||
toolbarPosition: HtmlEditorBrowser.ToolbarPosition.custom
|
toolbarPosition: HtmlEditorBrowser.ToolbarPosition.custom
|
||||||
),
|
),
|
||||||
otherOptions: HtmlEditorBrowser.OtherOptions(height: 550),
|
otherOptions: HtmlEditorBrowser.OtherOptions(height: 400),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
|
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
|
||||||
@@ -317,7 +326,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
(failure) => SizedBox.shrink(),
|
(failure) => SizedBox.shrink(),
|
||||||
(success) => success is UploadingAttachmentState
|
(success) => success is UploadingAttachmentState
|
||||||
? Center(child: Padding(
|
? Center(child: Padding(
|
||||||
padding: EdgeInsets.only(bottom: controller.attachments.isNotEmpty ? 0 : 24),
|
padding: EdgeInsets.only(bottom: controller.attachments.isNotEmpty ? 0 : 24, top: kIsWeb ? 20 : 0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
|
|
||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
|
||||||
typedef OnBackActionClick = void Function();
|
typedef OnBackActionClick = void Function();
|
||||||
typedef OnSendEmailActionClick = void Function();
|
typedef OnSendEmailActionClick = void Function();
|
||||||
typedef OnAttachFileActionClick = void Function();
|
typedef OnAttachFileActionClick = void Function(RelativeRect? position);
|
||||||
|
|
||||||
class TopBarComposerWidgetBuilder {
|
class TopBarComposerWidgetBuilder {
|
||||||
OnBackActionClick? _onBackActionClick;
|
OnBackActionClick? _onBackActionClick;
|
||||||
OnSendEmailActionClick? _onSendEmailActionClick;
|
OnSendEmailActionClick? _onSendEmailActionClick;
|
||||||
OnAttachFileActionClick? _onAttachFileActionClick;
|
OnAttachFileActionClick? _onAttachFileActionClick;
|
||||||
|
|
||||||
|
final BuildContext _context;
|
||||||
final ImagePaths _imagePaths;
|
final ImagePaths _imagePaths;
|
||||||
final bool _isEnableEmailSendButton;
|
final bool _isEnableEmailSendButton;
|
||||||
|
|
||||||
TopBarComposerWidgetBuilder(this._imagePaths, this._isEnableEmailSendButton);
|
TopBarComposerWidgetBuilder(
|
||||||
|
this._context,
|
||||||
|
this._imagePaths,
|
||||||
|
this._isEnableEmailSendButton,
|
||||||
|
);
|
||||||
|
|
||||||
void addBackActionClick(OnBackActionClick onBackActionClick) {
|
void addBackActionClick(OnBackActionClick onBackActionClick) {
|
||||||
_onBackActionClick = onBackActionClick;
|
_onBackActionClick = onBackActionClick;
|
||||||
@@ -68,14 +74,32 @@ class TopBarComposerWidgetBuilder {
|
|||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
MouseRegion(
|
||||||
key: Key('button_attachment'),
|
cursor: SystemMouseCursors.click,
|
||||||
icon: SvgPicture.asset(_imagePaths.icShare, fit: BoxFit.fill),
|
child: GestureDetector(
|
||||||
onPressed: () {
|
onTap: () {
|
||||||
if (_onAttachFileActionClick != null) {
|
if (!kIsWeb) {
|
||||||
_onAttachFileActionClick!();
|
_onAttachFileActionClick?.call(null);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(right: kIsWeb ? 16 : 0),
|
||||||
|
child: SvgPicture.asset(_imagePaths.icShare, fit: BoxFit.fill),
|
||||||
|
),
|
||||||
|
onTapDown: (detail) {
|
||||||
|
if (kIsWeb) {
|
||||||
|
final screenSize = MediaQuery.of(_context).size;
|
||||||
|
final offset = detail.globalPosition;
|
||||||
|
final position = RelativeRect.fromLTRB(
|
||||||
|
offset.dx,
|
||||||
|
offset.dy,
|
||||||
|
screenSize.width - offset.dx,
|
||||||
|
screenSize.height - offset.dy,
|
||||||
|
);
|
||||||
|
_onAttachFileActionClick?.call(position);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
key: Key('button_send_email'),
|
key: Key('button_send_email'),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import 'package:core/core.dart';
|
import 'package:core/core.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:model/model.dart';
|
import 'package:model/model.dart';
|
||||||
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
|
||||||
|
|
||||||
@@ -11,13 +12,14 @@ class LocalFilePickerInteractor {
|
|||||||
|
|
||||||
Stream<Either<Failure, Success>> execute({FileType fileType = FileType.any}) async* {
|
Stream<Either<Failure, Success>> execute({FileType fileType = FileType.any}) async* {
|
||||||
try {
|
try {
|
||||||
final filesResult = await FilePicker.platform.pickFiles(type: fileType, allowMultiple: true);
|
final filesResult = await FilePicker.platform.pickFiles(type: fileType, allowMultiple: true, withReadStream: true);
|
||||||
if (filesResult != null && filesResult.files.isNotEmpty) {
|
if (filesResult != null && filesResult.files.isNotEmpty) {
|
||||||
final fileInfoResults = filesResult.files
|
final fileInfoResults = filesResult.files
|
||||||
.map((platformFile) => FileInfo(
|
.map((platformFile) => FileInfo(
|
||||||
platformFile.name,
|
platformFile.name,
|
||||||
platformFile.path ?? '',
|
kIsWeb ? '' : platformFile.path ?? '',
|
||||||
platformFile.size)).toList();
|
platformFile.size,
|
||||||
|
readStream: platformFile.readStream)).toList();
|
||||||
yield Right<Failure, Success>(LocalFilePickerSuccess(fileInfoResults));
|
yield Right<Failure, Success>(LocalFilePickerSuccess(fileInfoResults));
|
||||||
} else {
|
} else {
|
||||||
yield Left<Failure, Success>(LocalFilePickerCancel());
|
yield Left<Failure, Success>(LocalFilePickerCancel());
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
|
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:mime/mime.dart';
|
import 'package:mime/mime.dart';
|
||||||
|
|
||||||
class FileInfo with EquatableMixin {
|
class FileInfo with EquatableMixin {
|
||||||
final String fileName;
|
final String fileName;
|
||||||
final String filePath;
|
final String filePath;
|
||||||
final int fileSize;
|
final int fileSize;
|
||||||
|
final Stream<List<int>>? readStream;
|
||||||
|
|
||||||
FileInfo(this.fileName, this.filePath, this.fileSize);
|
FileInfo(this.fileName, this.filePath, this.fileSize, {this.readStream});
|
||||||
|
|
||||||
factory FileInfo.empty() {
|
factory FileInfo.empty() {
|
||||||
return FileInfo('', '', 0);
|
return FileInfo('', '', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get mimeType => lookupMimeType(filePath) ?? 'application/json; charset=UTF-8';
|
String get mimeType => lookupMimeType(kIsWeb ? fileName : filePath) ?? 'application/json; charset=UTF-8';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [fileName, filePath, fileSize];
|
List<Object?> get props => [fileName, filePath, fileSize, readStream];
|
||||||
}
|
}
|
||||||
@@ -130,6 +130,9 @@ dependencies:
|
|||||||
# fk_user_agent
|
# fk_user_agent
|
||||||
fk_user_agent: 2.1.0
|
fk_user_agent: 2.1.0
|
||||||
|
|
||||||
|
# pointer_interceptor
|
||||||
|
pointer_interceptor: 0.9.3
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|||||||
Reference in New Issue
Block a user