TF-475 Fix save a draft email

This commit is contained in:
dab246
2022-05-30 15:35:23 +07:00
committed by Dat H. Pham
parent 8e6f905c43
commit 38bc7d9118
6 changed files with 68 additions and 39 deletions
@@ -32,4 +32,17 @@ extension HtmlExtension on String {
String addBlockQuoteTag() => addBlockTag(
'blockquote',
attribute: 'style=\"margin-left:8px;margin-right:8px;padding-left:12px;padding-right:12px;border-left:5px solid #eee;\"');
String asSignatureHtml() => '--<br><br>$this';
String toSignatureBlock() =>
'<br class="tmail-break-tag"><div class="tmail-signature">${asSignatureHtml()}</div><br class="tmail-break-tag">';
String removeEditorDefaultSpace() {
return replaceAll('<p><br><br><br></p>', '');
}
String addEditorDefaultSpace() {
return '<p><br><br><br></p>';
}
}
@@ -1,6 +1,14 @@
import 'package:core/core.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart';
class SaveEmailAsDraftsLoading extends UIState {
SaveEmailAsDraftsLoading();
@override
List<Object?> get props => [];
}
class SaveEmailAsDraftsSuccess extends UIState {
final Email emailAsDrafts;
@@ -12,6 +12,7 @@ class SaveEmailAsDraftsInteractor {
Stream<Either<Failure, Success>> execute(AccountId accountId, Email email) async* {
try {
yield Right<Failure, Success>(SaveEmailAsDraftsLoading());
final emailAsDrafts = await emailRepository.saveEmailAsDrafts(accountId, email);
if (emailAsDrafts != null) {
yield Right<Failure, Success>(SaveEmailAsDraftsSuccess(emailAsDrafts));
@@ -116,7 +116,7 @@ class ComposerController extends BaseController {
} else {
final content = await htmlEditorApi?.getText() ?? '';
if (_isMobileApp && identitySelected.value?.textSignature?.value.isNotEmpty == true) {
final newContent = '$content<br><br><br>--<br><br><div>${identitySelected.value?.textSignature?.value}</div><br>';
final newContent = '$content${identitySelected.value?.textSignature?.value.toSignatureBlock()}';
log('ComposerController::_generateEmail()_MOBILE: $newContent');
return newContent;
} else {
@@ -143,9 +143,11 @@ class ComposerController extends BaseController {
@override
void onInit() {
super.onInit();
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async {
await FkUserAgent.init();
});
if (!BuildUtils.isWeb) {
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) async {
await FkUserAgent.init();
});
}
}
@override
@@ -161,11 +163,19 @@ class ComposerController extends BaseController {
@override
void onClose() {
if (!BuildUtils.isWeb) {
FkUserAgent.release();
}
super.onClose();
}
@override
void dispose() {
subjectEmailInputController.dispose();
toEmailAddressController.dispose();
ccEmailAddressController.dispose();
bccEmailAddressController.dispose();
super.onClose();
super.dispose();
}
@override
@@ -435,6 +445,7 @@ class ComposerController extends BaseController {
var emailBodyText = await _getEmailBodyText();
log('ComposerController::_generateEmail(): $emailBodyText');
final userAgent = await userAgentPlatform;
log('ComposerController::_generateEmail(): userAgent: $userAgent');
return Email(
generateEmailId,
@@ -708,14 +719,22 @@ class ComposerController extends BaseController {
}
Future<bool> _isEmailChanged(BuildContext context, ComposerArguments arguments) async {
final newEmailBody = (await _getEmailBodyText(changedEmail: true))
.replaceAll('<p><br><br><br></p>', '');
final currentTextInComposer = await _getEmailBodyText(changedEmail: true);
final newEmailBody = currentTextInComposer.removeEditorDefaultSpace();
log('ComposerController::_isEmailChanged(): newEmailBody: $newEmailBody');
var oldEmailBody = '';
final contentEmail = getContentEmail(context);
if (arguments.emailActionType != EmailActionType.compose && contentEmail != null && contentEmail.isNotEmpty) {
oldEmailBody = kIsWeb ? contentEmail : '\n$contentEmail\n';
}
if (BuildUtils.isWeb) {
if (identitySelected.value?.htmlSignature?.value.isNotEmpty == true) {
oldEmailBody = '$oldEmailBody${identitySelected.value?.htmlSignature?.value.toSignatureBlock()}';
} else if (identitySelected.value?.textSignature?.value.isNotEmpty == true) {
oldEmailBody = '$oldEmailBody${identitySelected.value?.textSignature?.value.toSignatureBlock()}';
}
}
log('ComposerController::_isEmailChanged(): oldEmailBody: $oldEmailBody');
final isEmailBodyChanged = !oldEmailBody.trim().isSame(newEmailBody.trim());
log('ComposerController::_isEmailChanged(): isEmailBodyChanged: $isEmailBodyChanged');
@@ -752,7 +771,8 @@ class ComposerController extends BaseController {
return false;
}
void saveEmailAsDrafts(BuildContext context) async {
void saveEmailAsDrafts(BuildContext context, {bool canPop = true}) async {
log('ComposerController::saveEmailAsDrafts():');
clearFocusEditor(context);
final arguments = composerArguments.value;
@@ -763,8 +783,8 @@ class ComposerController extends BaseController {
if (arguments != null && mapDefaultMailboxId.isNotEmpty && userProfile != null && session != null) {
log('ComposerController::saveEmailAsDrafts(): saveEmailAsDrafts START');
final isChanged = await _isEmailChanged(context, arguments);
log('ComposerController::saveEmailAsDrafts(): saveEmailAsDrafts isChanged: $isChanged');
if (isChanged) {
log('ComposerController::saveEmailAsDrafts(): saveEmailAsDrafts isChanged: $isChanged');
final newEmail = await _generateEmail(mapDefaultMailboxId, userProfile, asDrafts: true);
final accountId = session.accounts.keys.first;
final oldEmail = arguments.presentationEmail;
@@ -778,6 +798,12 @@ class ComposerController extends BaseController {
}
}
}
if (BuildUtils.isWeb) {
mailboxDashBoardController.dispatchAction(CloseComposeEmailAction());
} else {
if (canPop) popBack();
}
}
void _getEmailContentAction(ComposerArguments arguments) async {
@@ -819,7 +845,6 @@ class ComposerController extends BaseController {
void clearFocusEditor(BuildContext context) {
if (!kIsWeb) {
htmlEditorApi?.unfocus(context);
htmlControllerBrowser.clearFocus();
}
FocusManager.instance.primaryFocus?.unfocus();
}
@@ -39,7 +39,7 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildComposerViewForMobile(BuildContext context) {
return WillPopScope(
onWillPop: () async {
controller.saveEmailAsDrafts(context);
controller.saveEmailAsDrafts(context, canPop: false);
return true;
},
child: GestureDetector(
@@ -68,7 +68,7 @@ class ComposerView extends GetWidget<ComposerController> {
Widget _buildComposerViewForTablet(BuildContext context) {
return WillPopScope(
onWillPop: () async {
controller.saveEmailAsDrafts(context);
controller.saveEmailAsDrafts(context, canPop: false);
return true;
},
child: GestureDetector(
@@ -119,12 +119,9 @@ class ComposerView extends GetWidget<ComposerController> {
icon: SvgPicture.asset(imagePaths.icClose, width: 30, height: 30, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
iconPadding: EdgeInsets.zero,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposer();
}),
onTap: () => controller.saveEmailAsDrafts(context)),
Expanded(child: _buildTitleComposer(context)),
if (responsiveUtils.isMobile(context))
if (responsiveUtils.isScreenWithShortestSide(context))
buildIconWeb(
icon: SvgPicture.asset(
isEnableSendButton ? imagePaths.icSendMobile : imagePaths.icSendDisable,
@@ -158,10 +155,7 @@ class ComposerView extends GetWidget<ComposerController> {
width: 150,
height: 44,
radius: 10,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposer();
}),
onTap: () => controller.saveEmailAsDrafts(context)),
const SizedBox(width: 12),
buildTextButton(
AppLocalizations.of(context).send,
@@ -487,7 +481,7 @@ class ComposerView extends GetWidget<ComposerController> {
return HtmlEditor(
key: const Key('composer_editor'),
minHeight: 550,
initialContent: '<p><br><br><br></p>',
initialContent: ''.addEditorDefaultSpace(),
onCreated: (editorApi) => controller.htmlEditorApi = editorApi);
} else {
final message = controller.getContentEmail(context);
@@ -91,10 +91,7 @@ class ComposerView extends GetWidget<ComposerController> {
child: buildIconWeb(
icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposerWeb();
}
onTap: () => controller.saveEmailAsDrafts(context)
)),
buildIconWeb(
icon: SvgPicture.asset(imagePaths.icFullScreenComposer, fit: BoxFit.fill),
@@ -174,10 +171,7 @@ class ComposerView extends GetWidget<ComposerController> {
buildIconWeb(
icon: SvgPicture.asset(imagePaths.icCloseMailbox, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposerWeb();
}),
onTap: () => controller.saveEmailAsDrafts(context)),
if (responsiveUtils.isDesktop(context))
Obx(() => buildIconWeb(
icon: SvgPicture.asset(
@@ -210,10 +204,7 @@ class ComposerView extends GetWidget<ComposerController> {
icon: SvgPicture.asset(imagePaths.icClose, width: 30, height: 30, fit: BoxFit.fill),
tooltip: AppLocalizations.of(context).close,
iconPadding: EdgeInsets.zero,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposerWeb();
}),
onTap: () => controller.saveEmailAsDrafts(context)),
Expanded(child: _buildTitleComposer(context)),
buildIconWeb(
icon: SvgPicture.asset(
@@ -248,10 +239,7 @@ class ComposerView extends GetWidget<ComposerController> {
width: 150,
height: 44,
radius: 10,
onTap: () {
controller.saveEmailAsDrafts(context);
controller.closeComposerWeb();
}),
onTap: () => controller.saveEmailAsDrafts(context)),
const SizedBox(width: 12),
buildTextButton(
AppLocalizations.of(context).send,
@@ -518,7 +506,7 @@ class ComposerView extends GetWidget<ComposerController> {
Obx(() {
if (controller.composerArguments.value != null) {
if (controller.composerArguments.value?.emailActionType == EmailActionType.compose) {
final initContent = controller.textEditorWeb ?? '<p><br><br><br></p>';
final initContent = controller.textEditorWeb ?? ''.addEditorDefaultSpace();
return Expanded(child: Padding(
padding: EdgeInsets.symmetric(horizontal: responsiveUtils.isMobile(context) ? 8 : 10),
child: _buildEditor(context, initContent)));