TF-3034 Prevent duplicate draft warning
This commit is contained in:
@@ -7,12 +7,12 @@ abstract class PlatformInfo {
|
||||
static bool isTestingForWeb = false;
|
||||
|
||||
static bool get isWeb => kIsWeb || isTestingForWeb;
|
||||
static bool get isLinux => !kIsWeb && defaultTargetPlatform == TargetPlatform.linux;
|
||||
static bool get isWindows => !kIsWeb && defaultTargetPlatform == TargetPlatform.windows;
|
||||
static bool get isMacOS => !kIsWeb && defaultTargetPlatform == TargetPlatform.macOS;
|
||||
static bool get isFuchsia => !kIsWeb && defaultTargetPlatform == TargetPlatform.fuchsia;
|
||||
static bool get isIOS => !kIsWeb && defaultTargetPlatform == TargetPlatform.iOS;
|
||||
static bool get isAndroid => !kIsWeb && defaultTargetPlatform == TargetPlatform.android;
|
||||
static bool get isLinux => !isWeb && defaultTargetPlatform == TargetPlatform.linux;
|
||||
static bool get isWindows => !isWeb && defaultTargetPlatform == TargetPlatform.windows;
|
||||
static bool get isMacOS => !isWeb && defaultTargetPlatform == TargetPlatform.macOS;
|
||||
static bool get isFuchsia => !isWeb && defaultTargetPlatform == TargetPlatform.fuchsia;
|
||||
static bool get isIOS => !isWeb && defaultTargetPlatform == TargetPlatform.iOS;
|
||||
static bool get isAndroid => !isWeb && defaultTargetPlatform == TargetPlatform.android;
|
||||
static bool get isMobile => isAndroid || isIOS;
|
||||
static bool get isDesktop => isLinux || isWindows || isMacOS;
|
||||
static bool get isCanvasKit => isRendererCanvasKit;
|
||||
|
||||
@@ -62,6 +62,7 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/list_sha
|
||||
import 'package:tmail_ui_user/features/composer/presentation/mixin/drag_drog_file_mixin.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/create_email_request.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/draggable_email_address.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/saved_email_draft.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/signature_status.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/inline_image.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/prefix_recipient_state.dart';
|
||||
@@ -109,7 +110,6 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
|
||||
final mailboxDashBoardController = Get.find<MailboxDashBoardController>();
|
||||
final networkConnectionController = Get.find<NetworkConnectionController>();
|
||||
final _dynamicUrlInterceptors = Get.find<DynamicUrlInterceptors>();
|
||||
final _beforeReconnectManager = Get.find<BeforeReconnectManager>();
|
||||
|
||||
final composerArguments = Rxn<ComposerArguments>();
|
||||
@@ -199,6 +199,14 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
ButtonState _saveToDraftButtonState = ButtonState.enabled;
|
||||
ButtonState _sendButtonState = ButtonState.enabled;
|
||||
SignatureStatus _identityContentOnOpenPolicy = SignatureStatus.editedAvailable;
|
||||
int? _savedEmailDraftHash;
|
||||
bool _restoringSignatureButton = false;
|
||||
|
||||
@visibleForTesting
|
||||
bool get restoringSignatureButton => _restoringSignatureButton;
|
||||
|
||||
@visibleForTesting
|
||||
int? get savedEmailDraftHash => _savedEmailDraftHash;
|
||||
|
||||
late Worker uploadInlineImageWorker;
|
||||
late Worker dashboardViewStateWorker;
|
||||
@@ -330,6 +338,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
maxWithEditor = null;
|
||||
} else if (success is GetAlwaysReadReceiptSettingSuccess) {
|
||||
hasRequestReadReceipt.value = success.alwaysReadReceiptEnabled;
|
||||
_initEmailDraftHash();
|
||||
} else if (success is RestoreEmailInlineImagesSuccess) {
|
||||
_updateEditorContent(success);
|
||||
}
|
||||
@@ -358,6 +367,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
}
|
||||
} else if (failure is GetAlwaysReadReceiptSettingFailure) {
|
||||
hasRequestReadReceipt.value = false;
|
||||
_initEmailDraftHash();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -732,16 +742,18 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
(identity) => identity.id == identityId);
|
||||
}
|
||||
|
||||
void _initIdentities(ComposerArguments composerArguments) {
|
||||
Future<void> _initIdentities(ComposerArguments composerArguments) async {
|
||||
listFromIdentities.value = composerArguments.identities ?? [];
|
||||
final selectedIdentityFromId = _selectIdentityFromId(
|
||||
composerArguments.selectedIdentityId);
|
||||
if (listFromIdentities.isEmpty) {
|
||||
_getAllIdentities();
|
||||
} else if (selectedIdentityFromId != null) {
|
||||
_selectIdentity(selectedIdentityFromId);
|
||||
await _selectIdentity(selectedIdentityFromId);
|
||||
_initEmailDraftHash();
|
||||
} else if (composerArguments.identities?.isNotEmpty == true) {
|
||||
_selectIdentity(composerArguments.identities!.first);
|
||||
await _selectIdentity(composerArguments.identities!.first);
|
||||
_initEmailDraftHash();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -764,8 +776,10 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
composerArguments.value?.selectedIdentityId);
|
||||
if (selectedIdentityFromId != null) {
|
||||
await _selectIdentity(selectedIdentityFromId);
|
||||
_initEmailDraftHash();
|
||||
} else {
|
||||
await _selectIdentity(listIdentitiesMayDeleted.firstOrNull);
|
||||
_initEmailDraftHash();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1216,7 +1230,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
final session = mailboxDashBoardController.sessionCurrent;
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
if (session != null && accountId != null) {
|
||||
final uploadUri = session.getUploadUri(accountId, jmapUrl: _dynamicUrlInterceptors.jmapUrl);
|
||||
final uploadUri = session.getUploadUri(accountId, jmapUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
uploadController.justUploadAttachmentsAction(
|
||||
uploadFiles: pickedFiles,
|
||||
uploadUri: uploadUri,
|
||||
@@ -1230,50 +1244,41 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
uploadController.deleteFileUploaded(uploadId);
|
||||
}
|
||||
|
||||
Future<bool> _validateEmailChange({
|
||||
required BuildContext context,
|
||||
required EmailActionType emailActionType,
|
||||
PresentationEmail? presentationEmail,
|
||||
Role? mailboxRole,
|
||||
}) async {
|
||||
final newEmailBody = await _getContentInEditor();
|
||||
final oldEmailBody = _initTextEditor ?? '';
|
||||
log('ComposerController::_validateEmailChange: newEmailBody = $newEmailBody | oldEmailBody = $oldEmailBody');
|
||||
final isEmailBodyChanged = !oldEmailBody.trim().isSame(newEmailBody.trim());
|
||||
Future<bool> _validateEmailChange() async {
|
||||
final newDraftHash = await _hashDraftEmail();
|
||||
|
||||
final newEmailSubject = subjectEmail.value ?? '';
|
||||
final oldEmailSubject = emailActionType == EmailActionType.editDraft
|
||||
? presentationEmail?.getEmailTitle().trim() ?? ''
|
||||
: '';
|
||||
final isEmailSubjectChanged = !oldEmailSubject.trim().isSame(newEmailSubject.trim());
|
||||
return _savedEmailDraftHash != newDraftHash;
|
||||
}
|
||||
|
||||
final recipients = presentationEmail
|
||||
?.generateRecipientsEmailAddressForComposer(
|
||||
emailActionType: emailActionType,
|
||||
mailboxRole: mailboxRole
|
||||
) ?? const Tuple3(<EmailAddress>[], <EmailAddress>[], <EmailAddress>[]);
|
||||
Future<int> _hashDraftEmail() async {
|
||||
final emailContent = await _getContentInEditor();
|
||||
|
||||
final newToEmailAddress = listToEmailAddress;
|
||||
final oldToEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value1 : [];
|
||||
final isToEmailAddressChanged = !oldToEmailAddress.isSame(newToEmailAddress);
|
||||
final savedEmailDraft = SavedEmailDraft(
|
||||
subject: subjectEmail.value ?? '',
|
||||
content: emailContent,
|
||||
toRecipients: listToEmailAddress.toSet(),
|
||||
ccRecipients: listCcEmailAddress.toSet(),
|
||||
bccRecipients: listBccEmailAddress.toSet(),
|
||||
identity: identitySelected.value,
|
||||
attachments: uploadController.attachmentsUploaded,
|
||||
hasReadReceipt: hasRequestReadReceipt.value,
|
||||
);
|
||||
|
||||
final newCcEmailAddress = listCcEmailAddress;
|
||||
final oldCcEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value2 : [];
|
||||
final isCcEmailAddressChanged = !oldCcEmailAddress.isSame(newCcEmailAddress);
|
||||
return savedEmailDraft.hashCode;
|
||||
}
|
||||
|
||||
final newBccEmailAddress = listBccEmailAddress;
|
||||
final oldBccEmailAddress = emailActionType == EmailActionType.editDraft ? recipients.value3 : [];
|
||||
final isBccEmailAddressChanged = !oldBccEmailAddress.isSame(newBccEmailAddress);
|
||||
Future<void> _updateSavedEmailDraftHash() async {
|
||||
_savedEmailDraftHash = await _hashDraftEmail();
|
||||
}
|
||||
|
||||
final isAttachmentsChanged = !initialAttachments.isSame(uploadController.attachmentsUploaded.toList());
|
||||
log('ComposerController::_validateChangeEmail: isEmailBodyChanged = $isEmailBodyChanged | isEmailSubjectChanged = $isEmailSubjectChanged | isToEmailAddressChanged = $isToEmailAddressChanged | isCcEmailAddressChanged = $isCcEmailAddressChanged | isBccEmailAddressChanged = $isBccEmailAddressChanged | isAttachmentsChanged = $isAttachmentsChanged');
|
||||
if (isEmailBodyChanged || isEmailSubjectChanged
|
||||
|| isToEmailAddressChanged || isCcEmailAddressChanged
|
||||
|| isBccEmailAddressChanged || isAttachmentsChanged) {
|
||||
return true;
|
||||
Future<void> _initEmailDraftHash() async {
|
||||
if (composerArguments.value?.emailActionType != EmailActionType.compose
|
||||
&& composerArguments.value?.emailActionType != EmailActionType.editDraft
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
return false;
|
||||
_savedEmailDraftHash = await _hashDraftEmail();
|
||||
}
|
||||
|
||||
void handleClickSaveAsDraftsButton(BuildContext context) async {
|
||||
@@ -1306,10 +1311,12 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
_saveToDraftButtonState = ButtonState.enabled;
|
||||
_emailIdEditing = resultState.emailId;
|
||||
mailboxDashBoardController.consumeState(Stream.value(Right<Failure, Success>(resultState)));
|
||||
_updateSavedEmailDraftHash();
|
||||
} else if (resultState is UpdateEmailDraftsSuccess) {
|
||||
_saveToDraftButtonState = ButtonState.enabled;
|
||||
_emailIdEditing = resultState.emailId;
|
||||
mailboxDashBoardController.consumeState(Stream.value(Right<Failure, Success>(resultState)));
|
||||
_updateSavedEmailDraftHash();
|
||||
} else if ((resultState is SaveEmailAsDraftsFailure && resultState.exception is SavingEmailToDraftsCanceledException) ||
|
||||
(resultState is UpdateEmailDraftsFailure && resultState.exception is SavingEmailToDraftsCanceledException)) {
|
||||
_saveToDraftButtonState = ButtonState.enabled;
|
||||
@@ -1437,6 +1444,8 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
final selectedIdentityFromHeader = _selectIdentityFromId(identityIdFromHeader);
|
||||
if (selectedIdentityFromHeader == null) return;
|
||||
identitySelected.value = selectedIdentityFromHeader;
|
||||
|
||||
_initEmailDraftHash();
|
||||
}
|
||||
|
||||
Future<void> restoreCollapsibleButton(String? emailContent) async {
|
||||
@@ -1445,6 +1454,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
final emailDocument = parse(emailContent);
|
||||
final signature = emailDocument.querySelector('div.tmail-signature');
|
||||
if (signature == null) return;
|
||||
_restoringSignatureButton = true;
|
||||
await _applySignature(signature.innerHtml);
|
||||
} catch (e) {
|
||||
logError('ComposerController::_restoreCollapsibleButton: $e');
|
||||
@@ -1793,7 +1803,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
void _handleUploadInlineSuccess(SuccessAttachmentUploadState uploadState) {
|
||||
uploadController.clearUploadInlineViewState();
|
||||
|
||||
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: _dynamicUrlInterceptors.jmapUrl);
|
||||
final baseDownloadUrl = mailboxDashBoardController.sessionCurrent?.getDownloadUrl(jmapUrl: dynamicUrlInterceptors.jmapUrl);
|
||||
final accountId = mailboxDashBoardController.accountId.value;
|
||||
|
||||
if (baseDownloadUrl != null && accountId != null) {
|
||||
@@ -1988,6 +1998,18 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
initTextEditor(text);
|
||||
}
|
||||
_textEditorWeb = text;
|
||||
|
||||
_initEmailDraftHashAfterSignatureButtonRestored(text);
|
||||
}
|
||||
|
||||
void _initEmailDraftHashAfterSignatureButtonRestored(String? emailContent) {
|
||||
if (!_restoringSignatureButton) return;
|
||||
final emailDocument = parse(emailContent);
|
||||
final signatureButton = emailDocument.querySelector('button.tmail-signature-button');
|
||||
if (signatureButton == null) return;
|
||||
|
||||
_restoringSignatureButton = false;
|
||||
_initEmailDraftHash();
|
||||
}
|
||||
|
||||
void initTextEditor(String? text) {
|
||||
@@ -2087,12 +2109,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
return;
|
||||
}
|
||||
|
||||
final isChanged = await _validateEmailChange(
|
||||
context: context,
|
||||
emailActionType: composerArguments.value!.emailActionType,
|
||||
presentationEmail: composerArguments.value!.presentationEmail,
|
||||
mailboxRole: composerArguments.value!.mailboxRole
|
||||
);
|
||||
final isChanged = await _validateEmailChange();
|
||||
|
||||
if (isChanged && context.mounted) {
|
||||
clearFocus(context);
|
||||
@@ -2368,6 +2385,7 @@ class ComposerController extends BaseController with DragDropFileMixin implement
|
||||
void _setUpRequestReadReceiptForDraftEmail(Email? email) {
|
||||
if (email?.hasRequestReadReceipt == true) {
|
||||
hasRequestReadReceipt.value = true;
|
||||
_initEmailDraftHash();
|
||||
} else {
|
||||
_getAlwaysReadReceiptSetting();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
|
||||
class SavedEmailDraft with EquatableMixin {
|
||||
final String content;
|
||||
final String subject;
|
||||
final Set<EmailAddress> toRecipients;
|
||||
final Set<EmailAddress> ccRecipients;
|
||||
final Set<EmailAddress> bccRecipients;
|
||||
final List<Attachment> attachments;
|
||||
final Identity? identity;
|
||||
final bool hasReadReceipt;
|
||||
|
||||
SavedEmailDraft({
|
||||
required this.content,
|
||||
required this.subject,
|
||||
required this.toRecipients,
|
||||
required this.ccRecipients,
|
||||
required this.bccRecipients,
|
||||
required this.attachments,
|
||||
required this.identity,
|
||||
required this.hasReadReceipt,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
content,
|
||||
subject,
|
||||
// Prevent identical Set<EmailAddress>
|
||||
{0: toRecipients},
|
||||
{1: ccRecipients},
|
||||
{2: bccRecipients},
|
||||
attachments,
|
||||
identity,
|
||||
hasReadReceipt
|
||||
];
|
||||
}
|
||||
+1
-1
@@ -1578,7 +1578,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.3"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
name: plugin_platform_interface
|
||||
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
|
||||
|
||||
@@ -270,6 +270,8 @@ dev_dependencies:
|
||||
|
||||
http_mock_adapter: 0.4.2
|
||||
|
||||
plugin_platform_interface: 2.1.8
|
||||
|
||||
dependency_overrides:
|
||||
firebase_core_platform_interface: 4.6.0
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jmap_dart_client/jmap/identities/identity.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/email/attachment.dart';
|
||||
import 'package:tmail_ui_user/features/composer/presentation/model/saved_email_draft.dart';
|
||||
|
||||
void main() {
|
||||
group('saved email draft test', () {
|
||||
test(
|
||||
'should tag toRecipients, ccRecipients and bccRecipients in props',
|
||||
() {
|
||||
// arrange
|
||||
final savedEmailDraft = SavedEmailDraft(
|
||||
subject: 'subject',
|
||||
content: 'content',
|
||||
toRecipients: {EmailAddress('to name', 'to email')},
|
||||
ccRecipients: {EmailAddress('cc name', 'cc email')},
|
||||
bccRecipients: {EmailAddress('bcc name', 'bcc email')},
|
||||
identity: null,
|
||||
attachments: [],
|
||||
hasReadReceipt: false
|
||||
);
|
||||
|
||||
// act
|
||||
final props = savedEmailDraft.props;
|
||||
|
||||
// assert
|
||||
expect(props[2], equals({0: savedEmailDraft.toRecipients}));
|
||||
expect(props[3], equals({1: savedEmailDraft.ccRecipients}));
|
||||
expect(props[4], equals({2: savedEmailDraft.bccRecipients}));
|
||||
});
|
||||
|
||||
test(
|
||||
'should generate different hashcode '
|
||||
'when toRecipients, ccRecipients and bccRecipients are different',
|
||||
() {
|
||||
// arrange
|
||||
const subject = 'subject';
|
||||
const content = 'content';
|
||||
final recipent = EmailAddress('recipent name', 'recipent email');
|
||||
final identity = Identity();
|
||||
final attachments = <Attachment>[];
|
||||
const hasReadReceipt = false;
|
||||
|
||||
final toSavedEmailDraft = SavedEmailDraft(
|
||||
subject: subject,
|
||||
content: content,
|
||||
toRecipients: {recipent},
|
||||
ccRecipients: {},
|
||||
bccRecipients: {},
|
||||
identity: identity,
|
||||
attachments: attachments,
|
||||
hasReadReceipt: hasReadReceipt
|
||||
);
|
||||
|
||||
final ccSavedEmailDraft = SavedEmailDraft(
|
||||
subject: subject,
|
||||
content: content,
|
||||
toRecipients: {},
|
||||
ccRecipients: {recipent},
|
||||
bccRecipients: {},
|
||||
identity: identity,
|
||||
attachments: attachments,
|
||||
hasReadReceipt: hasReadReceipt
|
||||
);
|
||||
|
||||
final bccSavedEmailDraft = SavedEmailDraft(
|
||||
subject: subject,
|
||||
content: content,
|
||||
toRecipients: {},
|
||||
ccRecipients: {},
|
||||
bccRecipients: {recipent},
|
||||
identity: identity,
|
||||
attachments: attachments,
|
||||
hasReadReceipt: hasReadReceipt
|
||||
);
|
||||
|
||||
// act
|
||||
final toProps = toSavedEmailDraft.props;
|
||||
final ccProps = ccSavedEmailDraft.props;
|
||||
final bccProps = bccSavedEmailDraft.props;
|
||||
|
||||
// assert
|
||||
expect(toProps.hashCode, isNot(ccProps.hashCode));
|
||||
expect(ccProps.hashCode, isNot(bccProps.hashCode));
|
||||
expect(bccProps.hashCode, isNot(toProps.hashCode));
|
||||
});
|
||||
|
||||
test(
|
||||
'should generate different hashcode '
|
||||
'when toRecipients is updated',
|
||||
() {
|
||||
// arrange
|
||||
final listToRecipients = {
|
||||
EmailAddress('to name', 'to email')
|
||||
};
|
||||
final savedEmailDraft = SavedEmailDraft(
|
||||
subject: 'subject',
|
||||
content: 'content',
|
||||
toRecipients: listToRecipients,
|
||||
ccRecipients: {EmailAddress('cc name', 'cc email')},
|
||||
bccRecipients: {EmailAddress('bcc name', 'bcc email')},
|
||||
identity: null,
|
||||
attachments: [],
|
||||
hasReadReceipt: false
|
||||
);
|
||||
final hashCodeBeforeChange = savedEmailDraft.hashCode;
|
||||
|
||||
// act
|
||||
listToRecipients.add(EmailAddress('to name 2', 'to email 2'));
|
||||
final hashCodeAfterChange = savedEmailDraft.hashCode;
|
||||
|
||||
// assert
|
||||
expect(hashCodeBeforeChange, isNot(hashCodeAfterChange));
|
||||
});
|
||||
|
||||
test(
|
||||
'should generate same hashcode '
|
||||
'when all properties are the same',
|
||||
() {
|
||||
// arrange
|
||||
final savedEmailDraft = SavedEmailDraft(
|
||||
subject: 'subject',
|
||||
content: 'content',
|
||||
toRecipients: {EmailAddress('to name', 'to email')},
|
||||
ccRecipients: {EmailAddress('cc name', 'cc email')},
|
||||
bccRecipients: {EmailAddress('bcc name', 'bcc email')},
|
||||
identity: null,
|
||||
attachments: [],
|
||||
hasReadReceipt: false
|
||||
);
|
||||
|
||||
final savedEmailDraft2 = SavedEmailDraft(
|
||||
subject: 'subject',
|
||||
content: 'content',
|
||||
toRecipients: {EmailAddress('to name', 'to email')},
|
||||
ccRecipients: {EmailAddress('cc name', 'cc email')},
|
||||
bccRecipients: {EmailAddress('bcc name', 'bcc email')},
|
||||
identity: null,
|
||||
attachments: [],
|
||||
hasReadReceipt: false
|
||||
);
|
||||
|
||||
// assert
|
||||
expect(savedEmailDraft.hashCode, equals(savedEmailDraft2.hashCode));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:rich_text_composer/rich_text_composer.dart';
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
class MockWebViewPlatform extends InAppWebViewPlatform with MockPlatformInterfaceMixin {
|
||||
@override
|
||||
PlatformInAppWebViewWidget createPlatformInAppWebViewWidget(
|
||||
PlatformInAppWebViewWidgetCreationParams params,
|
||||
) => MockWebViewWidget.implementation(params);
|
||||
|
||||
@override
|
||||
PlatformCookieManager createPlatformCookieManager(
|
||||
PlatformCookieManagerCreationParams params,
|
||||
) => MockPlatformCookieManager();
|
||||
}
|
||||
|
||||
class MockPlatformCookieManager extends Fake implements PlatformCookieManager {
|
||||
@override
|
||||
Future<bool> deleteAllCookies() async {
|
||||
return true;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> setCookie({
|
||||
required WebUri url,
|
||||
required String name,
|
||||
required String value,
|
||||
String path = '/',
|
||||
String? domain,
|
||||
int? expiresDate,
|
||||
int? maxAge,
|
||||
bool? isSecure,
|
||||
bool? isHttpOnly,
|
||||
HTTPCookieSameSitePolicy? sameSite,
|
||||
PlatformInAppWebViewController? iosBelow11WebViewController,
|
||||
PlatformInAppWebViewController? webViewController,
|
||||
}) async {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class MockWebViewWidget extends PlatformInAppWebViewWidget {
|
||||
MockWebViewWidget.implementation(super.params) : super.implementation();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
|
||||
@override
|
||||
T controllerFromPlatform<T>(PlatformInAppWebViewController controller) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {}
|
||||
}
|
||||
Reference in New Issue
Block a user