TF-725 Implement UI/UX for insert image to composer on web

This commit is contained in:
dab246
2022-07-20 16:51:16 +07:00
committed by Dat H. Pham
parent da32cf9a40
commit e6f1ced4cd
13 changed files with 321 additions and 48 deletions
@@ -31,4 +31,12 @@ mixin AppLoaderMixin {
progressColor: AppColor.primaryColor,
));
}
Widget loadingWidgetWithSizeColor({double? size, Color? color}) {
return Center(child: SizedBox(
width: size ?? 24,
height: size ?? 24,
child: CircularProgressIndicator(
color: color ?? AppColor.colorLoading)));
}
}
@@ -3,7 +3,9 @@ import 'package:core/core.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:get/get.dart';
import 'package:tmail_ui_user/features/base/base_bindings.dart';
import 'package:tmail_ui_user/features/composer/data/datasource/composer_datasource.dart';
import 'package:tmail_ui_user/features/composer/data/datasource/contact_datasource.dart';
import 'package:tmail_ui_user/features/composer/data/datasource_impl/composer_datasource_impl.dart';
import 'package:tmail_ui_user/features/composer/data/datasource_impl/contact_datasource_impl.dart';
import 'package:tmail_ui_user/features/composer/data/repository/auto_complete_repository_impl.dart';
import 'package:tmail_ui_user/features/composer/data/repository/composer_repository_impl.dart';
@@ -11,6 +13,7 @@ import 'package:tmail_ui_user/features/composer/data/repository/contact_reposito
import 'package:tmail_ui_user/features/composer/domain/repository/auto_complete_repository.dart';
import 'package:tmail_ui_user/features/composer/domain/repository/composer_repository.dart';
import 'package:tmail_ui_user/features/composer/domain/repository/contact_repository.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_device_contact_suggestions_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart';
@@ -74,6 +77,7 @@ class ComposerBindings extends BaseBindings {
}
Get.lazyPut(() => AttachmentUploadDataSourceImpl(Get.find<FileUploader>()));
Get.lazyPut(() => ComposerDataSourceImpl(Get.find<DownloadClient>()));
Get.lazyPut(() => ContactDataSourceImpl());
Get.lazyPut(() => EmailDataSourceImpl(Get.find<EmailAPI>()));
Get.lazyPut(() => HtmlDataSourceImpl(
@@ -88,6 +92,7 @@ class ComposerBindings extends BaseBindings {
@override
void bindingsDataSource() {
Get.lazyPut<AttachmentUploadDataSource>(() => Get.find<AttachmentUploadDataSourceImpl>());
Get.lazyPut<ComposerDataSource>(() => Get.find<ComposerDataSourceImpl>());
Get.lazyPut<ContactDataSource>(() => Get.find<ContactDataSourceImpl>());
Get.lazyPut<EmailDataSource>(() => Get.find<EmailDataSourceImpl>());
Get.lazyPut<HtmlDataSource>(() => Get.find<HtmlDataSourceImpl>());
@@ -96,7 +101,9 @@ class ComposerBindings extends BaseBindings {
@override
void bindingsRepositoryImpl() {
Get.lazyPut(() => ComposerRepositoryImpl(Get.find<AttachmentUploadDataSource>()));
Get.lazyPut(() => ComposerRepositoryImpl(
Get.find<AttachmentUploadDataSource>(),
Get.find<ComposerDataSource>()));
Get.lazyPut(() => AutoCompleteRepositoryImpl(dataSources));
Get.lazyPut(() => ContactRepositoryImpl(Get.find<ContactDataSource>()));
Get.lazyPut(() => EmailRepositoryImpl(
@@ -132,6 +139,7 @@ class ComposerBindings extends BaseBindings {
Get.lazyPut(() => GetAllIdentitiesInteractor(Get.find<ManageAccountRepository>()));
Get.lazyPut(() => RemoveComposerCacheOnWebInteractor(Get.find<ComposerCacheRepository>()));
Get.lazyPut(() => SaveComposerCacheOnWebInteractor(Get.find<ComposerCacheRepository>()));
Get.lazyPut(() => DownloadImageAsBase64Interactor(Get.find<ComposerRepository>()));
}
@override
@@ -153,6 +161,7 @@ class ComposerBindings extends BaseBindings {
Get.find<RemoveComposerCacheOnWebInteractor>(),
Get.find<SaveComposerCacheOnWebInteractor>(),
Get.find<RichTextWebController>(),
Get.find<DownloadImageAsBase64Interactor>(),
));
}
@@ -27,7 +27,9 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/composer/domain/model/contact_suggestion_source.dart';
import 'package:tmail_ui_user/features/composer/domain/model/email_request.dart';
import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/get_autocomplete_state.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/download_image_as_base64_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/get_autocomplete_with_device_contact_interactor.dart';
import 'package:tmail_ui_user/features/composer/domain/usecases/save_email_as_drafts_interactor.dart';
@@ -36,7 +38,10 @@ import 'package:tmail_ui_user/features/composer/domain/usecases/update_email_dra
import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_web_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/controller/rich_text_mobile_tablet_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/extensions/email_action_type_extension.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/image_source.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/insert_image_dialog_builder.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
@@ -46,6 +51,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller
import 'package:tmail_ui_user/features/manage_account/domain/state/get_all_identities_state.dart';
import 'package:tmail_ui_user/features/manage_account/domain/usecases/get_all_identities_interactor.dart';
import 'package:tmail_ui_user/features/upload/domain/model/upload_task_id.dart';
import 'package:tmail_ui_user/features/upload/domain/state/attachment_upload_state.dart';
import 'package:tmail_ui_user/features/upload/domain/state/local_file_picker_state.dart';
import 'package:tmail_ui_user/features/upload/domain/usecases/local_file_picker_interactor.dart';
import 'package:tmail_ui_user/features/upload/presentation/controller/upload_controller.dart';
@@ -90,6 +96,7 @@ class ComposerController extends BaseController {
final RemoveComposerCacheOnWebInteractor _removeComposerCacheOnWebInteractor;
final SaveComposerCacheOnWebInteractor _saveComposerCacheOnWebInteractor;
final RichTextWebController richTextWebController;
final DownloadImageAsBase64Interactor _downloadImageAsBase64Interactor;
List<EmailAddress> listToEmailAddress = <EmailAddress>[];
List<EmailAddress> listCcEmailAddress = <EmailAddress>[];
@@ -104,6 +111,8 @@ class ComposerController extends BaseController {
List<Attachment> initialAttachments = <Attachment>[];
String? _textEditorWeb;
List<EmailContent>? _emailContents;
double? maxWithEditor;
late Worker uploadInlineImageWorker;
void setTextEditorWeb(String? text) => _textEditorWeb = text;
@@ -159,11 +168,13 @@ class ComposerController extends BaseController {
this._removeComposerCacheOnWebInteractor,
this._saveComposerCacheOnWebInteractor,
this.richTextWebController,
this._downloadImageAsBase64Interactor,
);
@override
void onInit() {
super.onInit();
_listenWorker();
if (!BuildUtils.isWeb) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
await FkUserAgent.init();
@@ -200,6 +211,7 @@ class ComposerController extends BaseController {
toEmailAddressController.dispose();
ccEmailAddressController.dispose();
bccEmailAddressController.dispose();
uploadInlineImageWorker.dispose();
super.dispose();
}
@@ -228,13 +240,22 @@ class ComposerController extends BaseController {
_pickFileSuccess(success);
} else if (success is GetEmailContentSuccess) {
_getEmailContentSuccess(success);
} if (success is GetAllIdentitiesSuccess) {
} else if (success is GetAllIdentitiesSuccess) {
if (success.identities?.isNotEmpty == true) {
listIdentities.value = success.identities!
.where((identity) => identity.mayDelete == true)
.toList();
selectIdentity(listIdentities.first);
}
} else if (success is DownloadImageAsBase64Success) {
richTextWebController.insertImage(
InlineImage(
ImageSource.local,
fileInfo: success.fileInfo,
cid: success.cid,
base64: success.imageAsBase64),
maxWithEditor: maxWithEditor);
maxWithEditor = null;
}
});
}
@@ -251,6 +272,19 @@ class ComposerController extends BaseController {
popBack();
}
void _listenWorker() {
uploadInlineImageWorker = ever(uploadController.uploadInlineViewState, (state) {
log('ComposerController::_listenWorker(): $state');
if (state is Either) {
state.fold((failure) => null, (success) {
if (success is SuccessAttachmentUploadState) {
_handleUploadInlineSuccess(success);
}
});
}
});
}
void _listenBrowserTabRefresh() {
html.window.onBeforeUnload.listen((event) async {
final userProfile = mailboxDashBoardController.userProfile.value;
@@ -497,7 +531,21 @@ class ComposerController extends BaseController {
final generateBlobId = Id(_uuid.v1());
var emailBodyText = await _getEmailBodyText(context);
log('ComposerController::_generateEmail(): $emailBodyText');
final mapContents = await richTextWebController.refactorContentHasInlineImage(
emailBodyText,
uploadController.mapInlineAttachments);
log('ComposerController::_generateEmail(): mapContents: $mapContents');
emailBodyText = mapContents.value1;
final listInlineAttachment = mapContents.value2;
final listInlineEmailBodyPart = listInlineAttachment
.map((attachment) => attachment.toEmailBodyPart(charset: 'base64'))
.toSet();
final attachments = <EmailBodyPart>{};
attachments.addAll(uploadController.generateAttachments() ?? []);
attachments.addAll(listInlineEmailBodyPart);
log('ComposerController::_generateEmail(): listInlineEmailBodyPart: $listInlineEmailBodyPart');
final userAgent = await userAgentPlatform;
log('ComposerController::_generateEmail(): userAgent: $userAgent');
@@ -521,7 +569,7 @@ class ComposerController extends BaseController {
generatePartId: EmailBodyValue(emailBodyText, false, false)
},
headerUserAgent: {IndividualHeaderIdentifier.headerUserAgent : userAgent},
attachments: uploadController.generateAttachments(),
attachments: attachments.isNotEmpty ? attachments : null,
);
}
@@ -623,7 +671,7 @@ class ComposerController extends BaseController {
final email = await _generateEmail(context, mapDefaultMailboxId, userProfile);
final accountId = session.accounts.keys.first;
final sentMailboxId = mapDefaultMailboxId[PresentationMailbox.roleSent];
final submissionCreateId = Id(const Uuid().v1());
final submissionCreateId = Id(_uuid.v1());
mailboxDashBoardController.consumeState(_sendEmailInteractor.execute(
accountId,
@@ -631,6 +679,8 @@ class ComposerController extends BaseController {
emailIdDestroyed: arguments.emailActionType == EmailActionType.edit
? arguments.presentationEmail?.id
: null)));
uploadController.clearInlineFileUploaded();
}
if (kIsWeb) {
@@ -1055,6 +1105,65 @@ class ComposerController extends BaseController {
}
}
void insertImage(BuildContext context, {double? maxWithEditor}) async {
await InsertImageDialogBuilder(
context,
insertActionCallback: (inlineImage) {
log('ComposerController::insertImage(): ${inlineImage.source}|$maxWithEditor');
if (BuildUtils.isWeb) {
this.maxWithEditor = maxWithEditor;
_insertImageOnWeb(inlineImage);
}
}
).show();
}
void _insertImageOnWeb(InlineImage inlineImage) {
if (inlineImage.source == ImageSource.local) {
_uploadInlineAttachmentsAction(inlineImage.fileInfo!);
} else {
richTextWebController.insertImage(inlineImage);
}
}
void _uploadInlineAttachmentsAction(FileInfo pickedFile) async {
if (uploadController.hasEnoughMaxAttachmentSize(listFiles: [pickedFile])) {
final session = mailboxDashBoardController.sessionCurrent;
final accountId = mailboxDashBoardController.accountId.value;
if (session != null && accountId != null) {
final uploadUri = session.getUploadUri(accountId);
uploadController.uploadInlineImage(pickedFile, uploadUri);
}
} else {
if (currentContext != null) {
showConfirmDialogAction(
currentContext!,
AppLocalizations.of(currentContext!).message_dialog_upload_attachments_exceeds_maximum_size(
filesize(mailboxDashBoardController.maxSizeAttachmentsPerEmail?.value ?? 0, 0)),
AppLocalizations.of(currentContext!).got_it,
() => {},
title: AppLocalizations.of(currentContext!).maximum_files_size,
hasCancelButton: false);
}
}
}
void _handleUploadInlineSuccess(SuccessAttachmentUploadState uploadState) {
uploadController.clearUploadInlineViewState();
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl();
final accountId = mailboxDashBoardController.accountId.value;
if (baseDownloadUrl != null && accountId != null) {
final imageUrl = uploadState.attachment.getDownloadUrl(baseDownloadUrl, accountId);
log('ComposerController::_handleUploadInlineSuccess(): imageUrl: $imageUrl');
consumeState(_downloadImageAsBase64Interactor.execute(
imageUrl,
uploadState.attachment.cid!,
uploadState.fileInfo));
}
}
void closeComposer() {
FocusManager.instance.primaryFocus?.unfocus();
popBack();
@@ -3,7 +3,6 @@ import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:enough_html_editor/enough_html_editor.dart';
import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
@@ -11,7 +10,6 @@ import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:model/model.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart';
@@ -412,7 +410,6 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
child: _buildAttachmentsTitle(context,
uploadAttachments,
controller.expandModeAttachments.value)),
_buildAttachmentsLoadingView(),
Padding(
padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16),
child: _buildAttachmentsList(context,
@@ -479,7 +476,6 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
child: _buildAttachmentsTitle(context,
uploadAttachments,
controller.expandModeAttachments.value)),
_buildAttachmentsLoadingView(),
Padding(
padding: const EdgeInsets.only(bottom: 8, left: 16, right: 16),
child: _buildAttachmentsList(context,
@@ -589,19 +585,6 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
});
}
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
return Obx(() => controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) => success is UploadingAttachmentState
? Center(child: Padding(
padding: padding ?? const EdgeInsets.all(10),
child: SizedBox(
width: size ?? 20,
height: size ?? 20,
child: const CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: const SizedBox.shrink()));
}
Widget _buildAttachmentsTitle(
BuildContext context,
List<UploadFileState> uploadFilesState,
@@ -612,7 +595,6 @@ class ComposerView extends GetWidget<ComposerController> with AppLoaderMixin, Ri
Text(
'${AppLocalizations.of(context).attachments} (${filesize(uploadFilesState.totalSize, 0)}):',
style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
_buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16),
const Spacer(),
Material(
type: MaterialType.circle,
@@ -2,7 +2,6 @@ import 'package:core/core.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:file_picker/file_picker.dart';
import 'package:filesize/filesize.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart';
@@ -11,13 +10,14 @@ import 'package:jmap_dart_client/jmap/identities/identity.dart';
import 'package:model/model.dart';
import 'package:pointer_interceptor/pointer_interceptor.dart';
import 'package:tmail_ui_user/features/base/mixin/app_loader_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/state/upload_attachment_state.dart';
import 'package:tmail_ui_user/features/composer/domain/state/download_image_as_base64_state.dart';
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
import 'package:tmail_ui_user/features/composer/presentation/mixin/rich_text_button_mixin.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/rich_text_style_type.dart';
import 'package:tmail_ui_user/features/composer/presentation/model/screen_display_mode.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/attachment_file_composer_builder.dart';
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_input_builder.dart';
import 'package:tmail_ui_user/features/upload/domain/state/attachment_upload_state.dart';
import 'package:tmail_ui_user/features/upload/presentation/extensions/list_upload_file_state_extension.dart';
import 'package:tmail_ui_user/features/upload/presentation/model/upload_file_state.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
@@ -54,14 +54,19 @@ class ComposerView extends GetWidget<ComposerController>
: const SizedBox.shrink()),
_buildEmailAddress(context, constraints),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildSubjectEmail(context)),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: _buildSubjectEmail(context)),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: const EdgeInsets.symmetric(horizontal: 16), child: _buildListButton(context)),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: _buildListButton(context, constraints)),
const Divider(color: AppColor.colorDividerComposer, height: 1),
Expanded(child: Column(
children: [
_buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(),
_buildInlineLoadingView(),
_buildEditorForm(context)
]
)),
@@ -282,7 +287,7 @@ class ComposerView extends GetWidget<ComposerController>
const Divider(color: AppColor.colorDividerComposer, height: 1),
Padding(padding: const EdgeInsets.only(right: 16), child: _buildSubjectEmail(context)),
const Divider(color: AppColor.colorDividerComposer, height: 1),
_buildListButton(context),
_buildListButton(context, constraints),
]),
))
])),
@@ -295,6 +300,7 @@ class ComposerView extends GetWidget<ComposerController>
children: [
_buildAttachmentsWidget(context),
_buildToolbarRichTextWidget(),
_buildInlineLoadingView(),
_buildEditorForm(context)
]
))),
@@ -483,7 +489,7 @@ class ComposerView extends GetWidget<ComposerController>
);
}
Widget _buildListButton(BuildContext context) {
Widget _buildListButton(BuildContext context, BoxConstraints constraints) {
return Transform(
transform: Matrix4.translationValues(-5.0, 0.0, 0.0),
child: Padding(
@@ -499,6 +505,17 @@ class ComposerView extends GetWidget<ComposerController>
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).attach_file,
onTap: () => controller.openFilePickerByType(context, FileType.any)),
const SizedBox(width: 4),
buildIconWeb(
minSize: 40,
iconPadding: EdgeInsets.zero,
icon: SvgPicture.asset(imagePaths.icInsertImage,
color: AppColor.colorTextButton,
fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).insertImage,
onTap: () => controller.insertImage(
context,
maxWithEditor: constraints.maxWidth - 120)),
])
)
);
@@ -604,7 +621,6 @@ class ComposerView extends GetWidget<ComposerController>
)
)
);
// });
}
Widget _buildAttachmentsWidget(BuildContext context) {
@@ -622,7 +638,6 @@ class ComposerView extends GetWidget<ComposerController>
context,
attachments,
controller.expandModeAttachments.value)),
_buildAttachmentsLoadingView(),
Padding(
padding: EdgeInsets.only(
bottom: 8,
@@ -639,19 +654,6 @@ class ComposerView extends GetWidget<ComposerController>
});
}
Widget _buildAttachmentsLoadingView({EdgeInsets? padding, double? size}) {
return Obx(() => controller.viewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) => success is UploadingAttachmentState
? Center(child: Padding(
padding: padding ?? const EdgeInsets.all(10),
child: SizedBox(
width: size ?? 20,
height: size ?? 20,
child: const CupertinoActivityIndicator(color: AppColor.colorTextButton))))
: const SizedBox.shrink()));
}
Widget _buildAttachmentsTitle(
BuildContext context,
List<UploadFileState> uploadFilesState,
@@ -661,7 +663,6 @@ class ComposerView extends GetWidget<ComposerController>
Text(
'${AppLocalizations.of(context).attachments} (${filesize(uploadFilesState.totalSize, 0)}):',
style: const TextStyle(fontSize: 12, color: AppColor.colorHintEmailAddressInput, fontWeight: FontWeight.normal)),
_buildAttachmentsLoadingView(padding: const EdgeInsets.only(left: 16), size: 16),
const Spacer(),
Material(
type: MaterialType.circle,
@@ -746,4 +747,20 @@ class ComposerView extends GetWidget<ComposerController>
),
);
}
Widget _buildInlineLoadingView() {
return Obx(() => controller.uploadController.uploadInlineViewState.value.fold(
(failure) => const SizedBox.shrink(),
(success) {
if (success is UploadingAttachmentUploadState ||
success is DownloadingImageAsBase64) {
return Padding(
padding: const EdgeInsets.all(5),
child: loadingWidgetWithSizeColor(
size: 30,
color: AppColor.primaryColor));
}
return const SizedBox.shrink();
}));
}
}
+43 -1
View File
@@ -1,5 +1,5 @@
{
"@@last_modified": "2022-07-11T12:17:57.489417",
"@@last_modified": "2022-07-18T16:31:40.598846",
"initializing_data": "Initializing data...",
"@initializing_data": {
"type": "text",
@@ -1573,5 +1573,47 @@
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"insertImage": "Insert image",
"@insertImage": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"selectFromFile": "Select from file",
"@selectFromFile": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"chooseImage": "Choose image",
"@chooseImage": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"urlLink": "URL",
"@urlLink": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"insert": "Insert",
"@insert": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"insertImageErrorFileEmpty": "Please either choose an image or enter an image URL",
"@insertImageErrorFileEmpty": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"insertImageErrorDuplicate": "Please input either an image or an image URL, not both",
"@insertImageErrorDuplicate": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
}
}
@@ -1614,4 +1614,49 @@ class AppLocalizations {
'Save & close',
name: 'saveAndClose');
}
String get insertImage {
return Intl.message(
'Insert image',
name: 'insertImage');
}
String get selectFromFile {
return Intl.message(
'Select from file',
name: 'selectFromFile',
);
}
String get chooseImage {
return Intl.message(
'Choose image',
name: 'chooseImage',
);
}
String get urlLink {
return Intl.message(
'URL',
name: 'urlLink',
);
}
String get insert {
return Intl.message(
'Insert',
name: 'insert');
}
String get insertImageErrorFileEmpty {
return Intl.message(
'Please either choose an image or enter an image URL',
name: 'insertImageErrorFileEmpty');
}
String get insertImageErrorDuplicate {
return Intl.message(
'Please input either an image or an image URL, not both',
name: 'insertImageErrorDuplicate');
}
}