TF-32 Add presentation layer of download attachment for android platform

This commit is contained in:
dab246
2021-09-16 09:08:17 +07:00
committed by Dat H. Pham
parent 30dfb5aec6
commit 20f98ce541
18 changed files with 209 additions and 71 deletions
+13 -1
View File
@@ -3,6 +3,7 @@
package="com.linagora.android.tmail"> package="com.linagora.android.tmail">
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
<!-- webviewflutter support minSdk version to at least 19 --> <!-- webviewflutter support minSdk version to at least 19 -->
<!-- flutter_inappwebview support minSdk version to at least 17 --> <!-- flutter_inappwebview support minSdk version to at least 17 -->
@@ -17,7 +18,7 @@
</queries> </queries>
<application <application
android:label="TMail" android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
@@ -48,6 +49,17 @@
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
</activity> </activity>
<provider
android:name="vn.hunghd.flutterdownloader.DownloadedFileProvider"
android:authorities="${applicationId}.flutter_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data <meta-data
@@ -0,0 +1,9 @@
<resources>
<string name="app_name">Team Mail</string>
<string name="flutter_downloader_notification_started">Started</string>
<string name="flutter_downloader_notification_in_progress">In Progress</string>
<string name="flutter_downloader_notification_canceled">Canceled</string>
<string name="flutter_downloader_notification_failed">Failed</string>
<string name="flutter_downloader_notification_complete">Completed</string>
<string name="flutter_downloader_notification_paused">Paused</string>
</resources>
@@ -1,12 +1,17 @@
import 'package:core/core.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart'; import 'package:tmail_ui_user/features/email/data/datasource/email_datasource.dart';
import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart'; import 'package:tmail_ui_user/features/email/data/datasource_impl/email_datasource_impl.dart';
import 'package:tmail_ui_user/features/email/data/network/email_api.dart'; import 'package:tmail_ui_user/features/email/data/network/email_api.dart';
import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart'; import 'package:tmail_ui_user/features/email/data/repository/email_repository_impl.dart';
import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart'; import 'package:tmail_ui_user/features/email/domain/repository/email_repository.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/email_controller.dart'; import 'package:tmail_ui_user/features/email/presentation/email_controller.dart';
import 'package:tmail_ui_user/features/login/data/repository/credential_repository_impl.dart';
import 'package:tmail_ui_user/features/login/domain/repository/credential_repository.dart';
class EmailBindings extends Bindings { class EmailBindings extends Bindings {
@override @override
@@ -20,5 +25,14 @@ class EmailBindings extends Bindings {
Get.put(EmailController( Get.put(EmailController(
Get.find<GetEmailContentInteractor>(), Get.find<GetEmailContentInteractor>(),
Get.find<MarkAsEmailReadInteractor>())); Get.find<MarkAsEmailReadInteractor>()));
Get.lazyPut(() => CredentialRepositoryImpl(Get.find<SharedPreferences>()));
Get.lazyPut<CredentialRepository>(() => Get.find<CredentialRepositoryImpl>());
Get.lazyPut(() => DownloadAttachmentsInteractor(
Get.find<EmailRepository>(),
Get.find<CredentialRepository>()));
Get.put(EmailController(
Get.find<GetEmailContentInteractor>(),
Get.find<DownloadAttachmentsInteractor>(),
Get.find<DeviceManager>()));
} }
} }
@@ -1,16 +1,21 @@
import 'dart:io';
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:tmail_ui_user/features/base/base_controller.dart'; import 'package:tmail_ui_user/features/base/base_controller.dart';
import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/get_email_content_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/download_attachments_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart'; import 'package:tmail_ui_user/features/email/domain/state/mark_as_email_read_state.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart'; import 'package:tmail_ui_user/features/email/domain/usecases/mark_as_email_read_interactor.dart';
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart'; import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart'; import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/mailbox_dashboard_controller.dart';
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/route_navigation.dart'; import 'package:tmail_ui_user/main/routes/route_navigation.dart';
@@ -21,11 +26,18 @@ class EmailController extends BaseController {
final GetEmailContentInteractor _getEmailContentInteractor; final GetEmailContentInteractor _getEmailContentInteractor;
final MarkAsEmailReadInteractor _markAsEmailReadInteractor; final MarkAsEmailReadInteractor _markAsEmailReadInteractor;
final DownloadAttachmentsInteractor _downloadAttachmentsInteractor;
final DeviceManager _deviceManager;
final emailAddressExpandMode = ExpandMode.COLLAPSE.obs; final emailAddressExpandMode = ExpandMode.COLLAPSE.obs;
EmailContent? emailContent; EmailContent? emailContent;
EmailController(this._getEmailContentInteractor, this._markAsEmailReadInteractor); EmailController(this._getEmailContentInteractor, this._markAsEmailReadInteractor);
EmailController(
this._getEmailContentInteractor,
this._downloadAttachmentsInteractor,
this._deviceManager
);
@override @override
void onReady() { void onReady() {
@@ -102,6 +114,46 @@ class EmailController extends BaseController {
backToThreadView(); backToThreadView();
} }
void downloadAttachments(BuildContext context, List<Attachment> attachments) async {
final needRequestPermission = await _deviceManager.isNeedRequestStoragePermissionOnAndroid();
if (Platform.isAndroid && needRequestPermission) {
final status = await Permission.storage.status;
switch (status) {
case PermissionStatus.granted:
_downloadAttachmentsAction(context, attachments);
break;
case PermissionStatus.permanentlyDenied:
_appToast.showToast(AppLocalizations.of(context).you_need_to_grant_files_permission_to_download_attachments);
break;
default: {
final requested = await Permission.storage.request();
switch (requested) {
case PermissionStatus.granted:
_downloadAttachmentsAction(context, attachments);
break;
default:
_appToast.showToast(AppLocalizations.of(context).you_need_to_grant_files_permission_to_download_attachments);
break;
}
}
}
} else {
_downloadAttachmentsAction(context, attachments);
}
}
void _downloadAttachmentsAction(BuildContext context, List<Attachment> attachments) async {
final accountId = mailboxDashBoardController.accountId.value;
if (accountId != null && mailboxDashBoardController.sessionCurrent != null) {
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent!.getDownloadUrl();
await _downloadAttachmentsInteractor.execute(attachments, accountId, baseDownloadUrl)
.then((result) => result.fold(
(failure) => AppLocalizations.of(context).attachment_download_failed,
(success) => AppLocalizations.of(context).attachment_download_successfully));
}
}
bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null bool canComposeEmail() => mailboxDashBoardController.sessionCurrent != null
&& mailboxDashBoardController.userProfile.value != null && mailboxDashBoardController.userProfile.value != null
&& mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox) && mailboxDashBoardController.mapMailboxId.containsKey(PresentationMailbox.roleOutbox)
@@ -141,9 +141,8 @@ class EmailView extends GetWidget {
.onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND)) .onOpenExpandAddressReceiverActionClick(() => emailController.toggleDisplayEmailAddressAction(expandMode: ExpandMode.EXPAND))
.build()), .build()),
_buildLoadingView(), _buildLoadingView(),
SizedBox(height: 16),
_buildListAttachments(context),
_buildListMessageContent(), _buildListMessageContent(),
_buildListAttachments(context),
], ],
) )
); );
@@ -161,14 +160,18 @@ class EmailView extends GetWidget {
key: Key('list_attachment'), key: Key('list_attachment'),
primary: false, primary: false,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.only(bottom: 16), padding: EdgeInsets.only(top: 16),
itemCount: attachments.length, itemCount: attachments.length,
gridDelegate: SliverGridDelegateFixedHeight( gridDelegate: SliverGridDelegateFixedHeight(
height: 60, height: 60,
crossAxisCount: responsiveUtils.isMobile(context) ? 2 : 4, crossAxisCount: responsiveUtils.isMobile(context) ? 2 : 4,
crossAxisSpacing: 16.0, crossAxisSpacing: 16.0,
mainAxisSpacing: 8.0), mainAxisSpacing: 8.0),
itemBuilder: (context, index) => AttachmentFileTileBuilder(imagePaths, attachments[index]).build()) itemBuilder: (context, index) =>
(AttachmentFileTileBuilder(imagePaths, attachments[index])
..onDownloadAttachmentFileActionClick((attachment) =>
emailController.downloadAttachments(context, [attachment])))
.build())
: SizedBox.shrink(); : SizedBox.shrink();
} else { } else {
return SizedBox.shrink(); return SizedBox.shrink();
@@ -191,6 +194,7 @@ class EmailView extends GetWidget {
? ListView.builder( ? ListView.builder(
primary: false, primary: false,
shrinkWrap: true, shrinkWrap: true,
padding: EdgeInsets.only(top: 16),
key: Key('list_message_content'), key: Key('list_message_content'),
itemCount: messageContents.length, itemCount: messageContents.length,
itemBuilder: (context, index) => itemBuilder: (context, index) =>
@@ -1,6 +1,6 @@
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart'; import 'package:model/model.dart';
extension EmailBodyPartExtension on EmailBodyPart { extension EmailBodyPartExtension on EmailBodyPart {
AttachmentFile toAttachmentFile() => AttachmentFile(partId, blobId, size, name, type, cid); Attachment toAttachment() => Attachment(partId, blobId, size, name, type, cid);
} }
@@ -1,7 +1,7 @@
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
import 'package:model/email/email_content.dart'; import 'package:model/email/email_content.dart';
import 'package:tmail_ui_user/features/email/presentation/constants/email_constants.dart'; import 'package:tmail_ui_user/features/email/presentation/constants/email_constants.dart';
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart'; import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart';
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart'; import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
import 'package:tmail_ui_user/features/email/presentation/extensions/email_body_part_extension.dart'; import 'package:tmail_ui_user/features/email/presentation/extensions/email_body_part_extension.dart';
@@ -27,21 +27,21 @@ extension EmailContentExtension on EmailContent {
return listMessageContent; return listMessageContent;
} }
List<AttachmentFile> getListAttachment() { List<Attachment> getListAttachment() {
if (attachments != null) { if (attachments != null) {
return attachments! return attachments!
.where((element) => (element.disposition != null && element.disposition != 'inline')) .where((element) => (element.disposition != null && element.disposition != 'inline'))
.map((item) => item.toAttachmentFile()) .map((item) => item.toAttachment())
.toList(); .toList();
} }
return []; return [];
} }
List<AttachmentFile> getListAttachmentInline() { List<Attachment> getListAttachmentInline() {
if (attachments != null) { if (attachments != null) {
return attachments! return attachments!
.where((element) => element.disposition == 'inline') .where((element) => element.disposition == 'inline')
.map((item) => item.toAttachmentFile()) .map((item) => item.toAttachment())
.toList(); .toList();
} }
return []; return [];
@@ -1,28 +0,0 @@
import 'package:equatable/equatable.dart';
import 'package:http_parser/http_parser.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/core/unsigned_int.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_body_part.dart';
class AttachmentFile with EquatableMixin {
final PartId? partId;
final Id? blobId;
final UnsignedInt? size;
final String? name;
final MediaType? type;
final String? cid;
AttachmentFile(
this.partId,
this.blobId,
this.size,
this.name,
this.type,
this.cid
);
@override
List<Object?> get props => [partId, blobId, size, name, type, cid];
}
@@ -1,8 +1,6 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart';
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart'; import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
import 'package:model/model.dart'; import 'package:model/model.dart';
@@ -15,16 +13,11 @@ class MessageContent with EquatableMixin {
bool hasImageInlineWithCid() => content.contains('cid:'); bool hasImageInlineWithCid() => content.contains('cid:');
String getContentHasInlineAttachment(Session session, AccountId accountId, List<AttachmentFile> attachmentFiles) { String getContentHasInlineAttachment(String baseDownloadUrl, AccountId accountId, List<Attachment> attachments) {
var contentValid = content; var contentValid = content;
attachmentFiles.forEach((attachment) { attachments.forEach((attachment) {
if(attachment.cid != null) { if(attachment.cid != null) {
final urlDownloadImage = session.getDownloadUrl( final urlDownloadImage = attachment.getDownloadUrl(baseDownloadUrl, accountId);
'${accountId.id.value}',
'${attachment.blobId?.value}',
'${attachment.name}',
'${attachment.type?.mimeType}');
contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage'); contentValid = content.replaceAll('cid:${attachment.cid}', '$urlDownloadImage');
} }
}); });
@@ -4,23 +4,21 @@ import 'package:filesize/filesize.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart'; import 'package:model/model.dart';
typedef OnOpenAttachmentFileActionClick = void Function(); typedef OnDownloadAttachmentFileActionClick = void Function(Attachment attachment);
class AttachmentFileTileBuilder { class AttachmentFileTileBuilder {
final ImagePaths _imagePaths; final ImagePaths _imagePaths;
final AttachmentFile _attachmentFile; final Attachment _attachment;
OnOpenAttachmentFileActionClick? _onOpenAttachmentFileActionClick; OnDownloadAttachmentFileActionClick? _onDownloadAttachmentFileActionClick;
AttachmentFileTileBuilder(this._imagePaths, this._attachmentFile); AttachmentFileTileBuilder(this._imagePaths, this._attachment);
AttachmentFileTileBuilder onOpenAttachmentFileActionClick( void onDownloadAttachmentFileActionClick(OnDownloadAttachmentFileActionClick onDownloadAttachmentFileActionClick) {
OnOpenAttachmentFileActionClick onOpenAttachmentFileActionClick) { _onDownloadAttachmentFileActionClick = onDownloadAttachmentFileActionClick;
_onOpenAttachmentFileActionClick = onOpenAttachmentFileActionClick;
return this;
} }
Widget build() { Widget build() {
@@ -38,26 +36,29 @@ class AttachmentFileTileBuilder {
child: MediaQuery( child: MediaQuery(
data: MediaQueryData(padding: EdgeInsets.zero), data: MediaQueryData(padding: EdgeInsets.zero),
child: ListTile( child: ListTile(
contentPadding: EdgeInsets.zero,
focusColor: AppColor.primaryColor,
hoverColor: AppColor.primaryColor,
onTap: () { onTap: () {
if (_onOpenAttachmentFileActionClick != null) { if (_onDownloadAttachmentFileActionClick != null) {
_onOpenAttachmentFileActionClick!(); _onDownloadAttachmentFileActionClick!(_attachment);
}}, }},
leading: Transform( leading: Transform(
transform: Matrix4.translationValues(0.0, 2.0, 0.0), transform: Matrix4.translationValues(14.0, 2.0, 0.0),
child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)), child: SvgPicture.asset(_imagePaths.icAttachmentFile, width: 24, height: 24, fit: BoxFit.fill)),
title: Transform( title: Transform(
transform: Matrix4.translationValues(-18.0, -8.0, 0.0), transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
child: Text( child: Text(
_attachmentFile.name ?? '', _attachment.name ?? '',
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileNameColor, fontWeight: FontWeight.w500), style: TextStyle(fontSize: 12, color: AppColor.attachmentFileNameColor, fontWeight: FontWeight.w500),
)), )),
subtitle: _attachmentFile.size != null && _attachmentFile.size?.value != 0 subtitle: _attachment.size != null && _attachment.size?.value != 0
? Transform( ? Transform(
transform: Matrix4.translationValues(-18.0, -8.0, 0.0), transform: Matrix4.translationValues(-8.0, -8.0, 0.0),
child: Text( child: Text(
filesize(_attachmentFile.size?.value), filesize(_attachment.size?.value),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, color: AppColor.attachmentFileSizeColor))) style: TextStyle(fontSize: 12, color: AppColor.attachmentFileSizeColor)))
@@ -5,14 +5,14 @@ import 'package:flutter/widgets.dart';
import 'package:flutter_widget_from_html/flutter_widget_from_html.dart'; import 'package:flutter_widget_from_html/flutter_widget_from_html.dart';
import 'package:jmap_dart_client/jmap/account_id.dart'; import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:tmail_ui_user/features/email/presentation/model/attachment_file.dart'; import 'package:model/model.dart';
import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart'; import 'package:tmail_ui_user/features/email/presentation/model/message_content.dart';
import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart'; import 'package:tmail_ui_user/features/email/presentation/model/text_format.dart';
class MessageContentTileBuilder { class MessageContentTileBuilder {
final MessageContent messageContent; final MessageContent messageContent;
final List<AttachmentFile> attachmentInlines; final List<Attachment> attachmentInlines;
final Session? session; final Session? session;
final AccountId? accountId; final AccountId? accountId;
final HtmlMessagePurifier htmlMessagePurifier; final HtmlMessagePurifier htmlMessagePurifier;
@@ -51,7 +51,7 @@ class MessageContentTileBuilder {
String getHtmlMessageText() { String getHtmlMessageText() {
final message = (attachmentInlines.isNotEmpty && session != null && accountId != null && messageContent.hasImageInlineWithCid()) final message = (attachmentInlines.isNotEmpty && session != null && accountId != null && messageContent.hasImageInlineWithCid())
? '${messageContent.getContentHasInlineAttachment(session!, accountId!, attachmentInlines)}' ? '${messageContent.getContentHasInlineAttachment(session!.getDownloadUrl(), accountId!, attachmentInlines)}'
: '${messageContent.content}'; : '${messageContent.content}';
final trustAsHtml = htmlMessagePurifier.purifyHtmlMessage( final trustAsHtml = htmlMessagePurifier.purifyHtmlMessage(
+12
View File
@@ -269,5 +269,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"attachment_download_failed": "Attachment download failed",
"@attachment_download_failed": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"attachment_download_successfully": "Attachment downloaded successfully",
"@attachment_download_successfully": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+12
View File
@@ -269,5 +269,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"attachment_download_failed": "Attachment download failed",
"@attachment_download_failed": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"attachment_download_successfully": "Attachment downloaded successfully",
"@attachment_download_successfully": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+13 -1
View File
@@ -1,5 +1,5 @@
{ {
"@@last_modified": "2021-09-15T13:25:41.117609", "@@last_modified": "2021-09-15T23:44:29.035668",
"initializing_data": "Initializing data...", "initializing_data": "Initializing data...",
"@initializing_data": { "@initializing_data": {
"type": "text", "type": "text",
@@ -269,5 +269,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"attachment_download_failed": "Attachment download failed",
"@attachment_download_failed": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"attachment_download_successfully": "Attachment downloaded successfully",
"@attachment_download_successfully": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+12
View File
@@ -269,5 +269,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"attachment_download_failed": "Attachment download failed",
"@attachment_download_failed": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"attachment_download_successfully": "Attachment downloaded successfully",
"@attachment_download_successfully": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
+12
View File
@@ -269,5 +269,17 @@
"type": "text", "type": "text",
"placeholders_order": [], "placeholders_order": [],
"placeholders": {} "placeholders": {}
},
"attachment_download_failed": "Attachment download failed",
"@attachment_download_failed": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
},
"attachment_download_successfully": "Attachment downloaded successfully",
"@attachment_download_successfully": {
"type": "text",
"placeholders_order": [],
"placeholders": {}
} }
} }
@@ -1,5 +1,6 @@
import 'package:core/core.dart'; import 'package:core/core.dart';
import 'package:core/presentation/utils/app_toast.dart'; import 'package:core/presentation/utils/app_toast.dart';
import 'package:device_info/device_info.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@@ -13,6 +14,7 @@ class CoreBindings extends Bindings {
_bindingKeyboardManager(); _bindingKeyboardManager();
_bindingValidator(); _bindingValidator();
_bindingToast(); _bindingToast();
_bindingDeviceManager();
} }
void _bindingAppImagePaths() { void _bindingAppImagePaths() {
@@ -38,4 +40,9 @@ class CoreBindings extends Bindings {
void _bindingToast() { void _bindingToast() {
Get.put(AppToast()); Get.put(AppToast());
} }
void _bindingDeviceManager() {
Get.put(DeviceInfoPlugin());
Get.put(DeviceManager(Get.find<DeviceInfoPlugin>()));
}
} }
@@ -300,5 +300,19 @@ class AppLocalizations {
name: 'an_error_occurred', name: 'an_error_occurred',
); );
} }
String get attachment_download_failed {
return Intl.message(
'Attachment download failed',
name: 'attachment_download_failed',
);
}
String get attachment_download_successfully {
return Intl.message(
'Attachment downloaded successfully',
name: 'attachment_download_successfully',
);
}
} }