TF-2666 Apply new UI for edit recipient card on mobile
Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
@@ -102,6 +102,8 @@ class ThemeUtils {
|
|||||||
fontFamily: ConstantsUI.fontApp,
|
fontFamily: ConstantsUI.fontApp,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
letterSpacing: 0.1,
|
letterSpacing: 0.1,
|
||||||
|
fontSize: 14,
|
||||||
|
height: 20 / 14,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:core/utils/platform_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/smart_interaction_widget.dart';
|
import 'package:tmail_ui_user/features/base/widget/smart_interaction_widget.dart';
|
||||||
@@ -6,12 +7,14 @@ class CardWithSmartInteractionOverlayView extends StatefulWidget {
|
|||||||
final Widget child;
|
final Widget child;
|
||||||
final double overlayWidth;
|
final double overlayWidth;
|
||||||
final Widget Function(VoidCallback onClose) menuBuilder;
|
final Widget Function(VoidCallback onClose) menuBuilder;
|
||||||
|
final VoidCallback? onClearFocusAction;
|
||||||
|
|
||||||
const CardWithSmartInteractionOverlayView({
|
const CardWithSmartInteractionOverlayView({
|
||||||
super.key,
|
super.key,
|
||||||
required this.child,
|
required this.child,
|
||||||
required this.menuBuilder,
|
required this.menuBuilder,
|
||||||
this.overlayWidth = 361,
|
this.overlayWidth = 361,
|
||||||
|
this.onClearFocusAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -52,7 +55,10 @@ class _CardWithSmartInteractionOverlayViewState
|
|||||||
width: widget.overlayWidth,
|
width: widget.overlayWidth,
|
||||||
child: CompositedTransformFollower(
|
child: CompositedTransformFollower(
|
||||||
link: _layerLink,
|
link: _layerLink,
|
||||||
offset: const Offset(0, 40),
|
offset: Offset(
|
||||||
|
0,
|
||||||
|
PlatformInfo.isWeb ? 40 : 50,
|
||||||
|
),
|
||||||
showWhenUnlinked: false,
|
showWhenUnlinked: false,
|
||||||
child: FadeTransition(
|
child: FadeTransition(
|
||||||
opacity: CurvedAnimation(
|
opacity: CurvedAnimation(
|
||||||
@@ -112,6 +118,8 @@ class _CardWithSmartInteractionOverlayViewState
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _togglePopup() {
|
void _togglePopup() {
|
||||||
|
widget.onClearFocusAction?.call();
|
||||||
|
|
||||||
if (_overlayEntry == null) {
|
if (_overlayEntry == null) {
|
||||||
_showPopup();
|
_showPopup();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
)),
|
)),
|
||||||
Obx(() {
|
Obx(() {
|
||||||
if (controller.ccRecipientState.value == PrefixRecipientState.enabled) {
|
if (controller.ccRecipientState.value == PrefixRecipientState.enabled) {
|
||||||
@@ -166,6 +167,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -194,6 +196,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -222,6 +225,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -346,6 +350,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
onEnableAllRecipientsInputAction: controller.handleEnableRecipientsInputAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -369,6 +374,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -392,6 +398,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -414,6 +421,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
onSuggestionEmailAddress: controller.getAutoCompleteSuggestion,
|
||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -148,6 +149,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -174,6 +176,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -199,6 +202,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
@@ -395,6 +399,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -421,6 +426,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -447,6 +453,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -472,6 +479,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
@@ -711,6 +719,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.ccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -737,6 +746,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.bccRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -763,6 +773,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
if (controller.replyToRecipientState.value == PrefixRecipientState.enabled)
|
||||||
RecipientComposerWidget(
|
RecipientComposerWidget(
|
||||||
@@ -788,6 +799,7 @@ class ComposerView extends GetWidget<ComposerController> {
|
|||||||
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
onFocusNextAddressAction: controller.handleFocusNextAddressAction,
|
||||||
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
onRemoveDraggableEmailAddressAction: controller.removeDraggableEmailAddress,
|
||||||
onEditRecipientAction: controller.onEditRecipient,
|
onEditRecipientAction: controller.onEditRecipient,
|
||||||
|
onClearFocusAction: controller.onClearFocusAction,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
|||||||
+13
-35
@@ -7,11 +7,9 @@ import 'package:model/email/prefix_email_address.dart';
|
|||||||
import 'package:model/extensions/email_address_extension.dart';
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
import 'package:model/mailbox/expand_mode.dart';
|
import 'package:model/mailbox/expand_mode.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/composer_controller.dart';
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/context_item_email_address_action_type.dart';
|
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
||||||
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_create_new_rule_filter.dart';
|
import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/extensions/handle_create_new_rule_filter.dart';
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
import 'package:tmail_ui_user/main/routes/route_navigation.dart';
|
|
||||||
|
|
||||||
extension HandleEditRecipientExtension on ComposerController {
|
extension HandleEditRecipientExtension on ComposerController {
|
||||||
void onEditRecipient(
|
void onEditRecipient(
|
||||||
@@ -20,38 +18,12 @@ extension HandleEditRecipientExtension on ComposerController {
|
|||||||
EmailAddress emailAddress,
|
EmailAddress emailAddress,
|
||||||
EmailAddressActionType emailAddressActionType,
|
EmailAddressActionType emailAddressActionType,
|
||||||
) {
|
) {
|
||||||
if (PlatformInfo.isMobile) {
|
_handleEmailAddressActionTypeClick(
|
||||||
clearFocus(context);
|
context,
|
||||||
|
emailAddressActionType,
|
||||||
final contextMenuActions = EmailAddressActionType.values
|
prefix,
|
||||||
.map((action) => ContextItemEmailAddressActionType(
|
emailAddress,
|
||||||
action,
|
);
|
||||||
AppLocalizations.of(context),
|
|
||||||
imagePaths
|
|
||||||
))
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
openBottomSheetContextMenuAction(
|
|
||||||
context: context,
|
|
||||||
itemActions: contextMenuActions,
|
|
||||||
onContextMenuActionClick: (menuAction) {
|
|
||||||
popBack();
|
|
||||||
_handleEmailAddressActionTypeClick(
|
|
||||||
context,
|
|
||||||
menuAction.action,
|
|
||||||
prefix,
|
|
||||||
emailAddress,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_handleEmailAddressActionTypeClick(
|
|
||||||
context,
|
|
||||||
emailAddressActionType,
|
|
||||||
prefix,
|
|
||||||
emailAddress,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleEmailAddressActionTypeClick(
|
void _handleEmailAddressActionTypeClick(
|
||||||
@@ -64,7 +36,7 @@ extension HandleEditRecipientExtension on ComposerController {
|
|||||||
case EmailAddressActionType.copy:
|
case EmailAddressActionType.copy:
|
||||||
_copyEmailAddress(context, emailAddress);
|
_copyEmailAddress(context, emailAddress);
|
||||||
break;
|
break;
|
||||||
case EmailAddressActionType.modify:
|
case EmailAddressActionType.edit:
|
||||||
_modifyEmailAddress(prefix, emailAddress);
|
_modifyEmailAddress(prefix, emailAddress);
|
||||||
break;
|
break;
|
||||||
case EmailAddressActionType.createRule:
|
case EmailAddressActionType.createRule:
|
||||||
@@ -151,4 +123,10 @@ extension HandleEditRecipientExtension on ComposerController {
|
|||||||
emailAddress: emailAddress,
|
emailAddress: emailAddress,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onClearFocusAction() {
|
||||||
|
if (PlatformInfo.isMobile) {
|
||||||
|
htmlEditorApi?.unfocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import 'package:core/presentation/resources/image_paths.dart';
|
|
||||||
import 'package:tmail_ui_user/features/base/widget/context_menu/context_menu_item_action.dart';
|
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
|
||||||
|
|
||||||
class ContextItemEmailAddressActionType
|
|
||||||
extends ContextMenuItemActionRequiredIcon<EmailAddressActionType> {
|
|
||||||
final AppLocalizations appLocalizations;
|
|
||||||
final ImagePaths imagePaths;
|
|
||||||
|
|
||||||
ContextItemEmailAddressActionType(
|
|
||||||
super.action,
|
|
||||||
this.appLocalizations,
|
|
||||||
this.imagePaths,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get actionIcon => action.getContextMenuIcon(imagePaths);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get actionName => action.getContextMenuTitle(appLocalizations);
|
|
||||||
}
|
|
||||||
@@ -4,15 +4,15 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
|||||||
|
|
||||||
enum EmailAddressActionType {
|
enum EmailAddressActionType {
|
||||||
copy,
|
copy,
|
||||||
modify,
|
edit,
|
||||||
createRule;
|
createRule;
|
||||||
|
|
||||||
String getContextMenuTitle(AppLocalizations appLocalizations) {
|
String getContextMenuTitle(AppLocalizations appLocalizations) {
|
||||||
switch(this) {
|
switch(this) {
|
||||||
case EmailAddressActionType.copy:
|
case EmailAddressActionType.copy:
|
||||||
return appLocalizations.copy;
|
return appLocalizations.copy;
|
||||||
case EmailAddressActionType.modify:
|
case EmailAddressActionType.edit:
|
||||||
return appLocalizations.modifyEmailAddress;
|
return appLocalizations.edit;
|
||||||
case EmailAddressActionType.createRule:
|
case EmailAddressActionType.createRule:
|
||||||
return appLocalizations.createARule;
|
return appLocalizations.createARule;
|
||||||
}
|
}
|
||||||
@@ -22,7 +22,7 @@ enum EmailAddressActionType {
|
|||||||
switch(this) {
|
switch(this) {
|
||||||
case EmailAddressActionType.copy:
|
case EmailAddressActionType.copy:
|
||||||
return imagePaths.icCopy;
|
return imagePaths.icCopy;
|
||||||
case EmailAddressActionType.modify:
|
case EmailAddressActionType.edit:
|
||||||
return imagePaths.icEditRule;
|
return imagePaths.icEditRule;
|
||||||
case EmailAddressActionType.createRule:
|
case EmailAddressActionType.createRule:
|
||||||
return imagePaths.icQuickCreatingRule;
|
return imagePaths.icQuickCreatingRule;
|
||||||
|
|||||||
-22
@@ -1,22 +0,0 @@
|
|||||||
import 'package:core/presentation/resources/image_paths.dart';
|
|
||||||
import 'package:tmail_ui_user/features/base/model/popup_menu_item_action.dart';
|
|
||||||
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
|
||||||
|
|
||||||
class PopupMenuItemEmailAddressActionType
|
|
||||||
extends PopupMenuItemActionRequiredIcon<EmailAddressActionType> {
|
|
||||||
final AppLocalizations appLocalizations;
|
|
||||||
final ImagePaths imagePaths;
|
|
||||||
|
|
||||||
PopupMenuItemEmailAddressActionType(
|
|
||||||
super.action,
|
|
||||||
this.appLocalizations,
|
|
||||||
this.imagePaths,
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get actionIcon => action.getContextMenuIcon(imagePaths);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get actionName => action.getContextMenuTitle(appLocalizations);
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,14 @@
|
|||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
|
||||||
import 'package:core/presentation/extensions/string_extension.dart';
|
|
||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/utils/theme_utils.dart';
|
|
||||||
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
|
||||||
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:model/extensions/email_address_extension.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/view/mobile/mobile_edit_recipients_view.dart';
|
||||||
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
import 'package:tmail_ui_user/features/composer/presentation/view/web/desktop_edit_recipients_view.dart';
|
||||||
import 'package:tmail_ui_user/features/base/widget/email_address_with_copy_widget.dart';
|
|
||||||
import 'package:tmail_ui_user/features/base/widget/user_avatar_builder.dart';
|
|
||||||
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
|
||||||
|
|
||||||
class EditRecipientsView extends StatelessWidget {
|
class EditRecipientsView extends StatelessWidget {
|
||||||
final EmailAddress emailAddress;
|
final EmailAddress emailAddress;
|
||||||
final ImagePaths imagePaths;
|
final ImagePaths imagePaths;
|
||||||
|
final bool isMobile;
|
||||||
|
final double width;
|
||||||
final VoidCallback onCopyAction;
|
final VoidCallback onCopyAction;
|
||||||
final VoidCallback onEditAction;
|
final VoidCallback onEditAction;
|
||||||
final VoidCallback onCreateRuleAction;
|
final VoidCallback onCreateRuleAction;
|
||||||
@@ -24,6 +18,8 @@ class EditRecipientsView extends StatelessWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
required this.emailAddress,
|
required this.emailAddress,
|
||||||
required this.imagePaths,
|
required this.imagePaths,
|
||||||
|
required this.isMobile,
|
||||||
|
required this.width,
|
||||||
required this.onCopyAction,
|
required this.onCopyAction,
|
||||||
required this.onEditAction,
|
required this.onEditAction,
|
||||||
required this.onCreateRuleAction,
|
required this.onCreateRuleAction,
|
||||||
@@ -32,135 +28,25 @@ class EditRecipientsView extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return PointerInterceptor(
|
if (isMobile) {
|
||||||
child: Container(
|
return MobileEditRecipientsView(
|
||||||
width: 361,
|
emailAddress: emailAddress,
|
||||||
decoration: BoxDecoration(
|
imagePaths: imagePaths,
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
width: width,
|
||||||
color: Colors.white,
|
onCopyAction: onCopyAction,
|
||||||
boxShadow: [
|
onEditAction: onEditAction,
|
||||||
BoxShadow(
|
onCreateRuleAction: onCreateRuleAction,
|
||||||
color: Colors.black.withOpacity(0.15),
|
);
|
||||||
blurRadius: 8,
|
} else {
|
||||||
spreadRadius: 3,
|
return DesktopEditRecipientsView(
|
||||||
offset: const Offset(0, 4),
|
emailAddress: emailAddress,
|
||||||
),
|
imagePaths: imagePaths,
|
||||||
BoxShadow(
|
width: width,
|
||||||
color: Colors.black.withOpacity(0.3),
|
onCopyAction: onCopyAction,
|
||||||
blurRadius: 3,
|
onEditAction: onEditAction,
|
||||||
offset: const Offset(0, 1),
|
onCreateRuleAction: onCreateRuleAction,
|
||||||
),
|
onCloseAction: onCloseAction,
|
||||||
],
|
);
|
||||||
),
|
}
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsetsDirectional.only(
|
|
||||||
start: 16,
|
|
||||||
end: 16,
|
|
||||||
top: 21,
|
|
||||||
bottom: 21,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
UserAvatarBuilder(
|
|
||||||
username: emailAddress.asString().firstLetterToUpperCase,
|
|
||||||
size: 42,
|
|
||||||
textStyle: ThemeUtils.textStyleInter600().copyWith(
|
|
||||||
fontSize: 16,
|
|
||||||
height: 22 / 16,
|
|
||||||
letterSpacing: -0.41,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
padding: const EdgeInsetsDirectional.only(end: 16),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if (emailAddress.displayName.isNotEmpty)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsetsDirectional.only(end: 24),
|
|
||||||
child: Text(
|
|
||||||
emailAddress.displayName,
|
|
||||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
||||||
color: AppColor.textPrimary,
|
|
||||||
),
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
maxLines: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
EmailAddressWithCopyWidget(
|
|
||||||
label: emailAddress.emailAddress,
|
|
||||||
copyLabelIcon: imagePaths.icCopy,
|
|
||||||
textStyle: ThemeUtils.textStyleBodyBody2(
|
|
||||||
color: AppColor.steelGray400,
|
|
||||||
),
|
|
||||||
copyIconMargin: const EdgeInsetsDirectional.only(
|
|
||||||
start: 7,
|
|
||||||
),
|
|
||||||
copyIconColor: AppColor.steelGray400,
|
|
||||||
onCopyButtonAction: onCopyAction,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child: Container(
|
|
||||||
constraints: const BoxConstraints(minWidth: 127),
|
|
||||||
margin: const EdgeInsetsDirectional.only(end: 8),
|
|
||||||
height: 36,
|
|
||||||
child: ConfirmDialogButton(
|
|
||||||
label: AppLocalizations.of(context).editEmail,
|
|
||||||
backgroundColor: AppColor.primaryMain,
|
|
||||||
textColor: Colors.white,
|
|
||||||
onTapAction: onEditAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Flexible(
|
|
||||||
child: Container(
|
|
||||||
constraints: const BoxConstraints(minWidth: 134),
|
|
||||||
height: 36,
|
|
||||||
child: ConfirmDialogButton(
|
|
||||||
label: AppLocalizations.of(context).createARule,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
textColor: AppColor.primaryMain,
|
|
||||||
borderColor: AppColor.primaryMain,
|
|
||||||
onTapAction: onCreateRuleAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PositionedDirectional(
|
|
||||||
top: 0,
|
|
||||||
end: 0,
|
|
||||||
child: TMailButtonWidget.fromIcon(
|
|
||||||
icon: imagePaths.icCloseDialog,
|
|
||||||
iconSize: 24,
|
|
||||||
iconColor: AppColor.m3Tertiary,
|
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
borderRadius: 24,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
onTapActionCallback: onCloseAction,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,153 @@
|
|||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/extensions/string_extension.dart';
|
||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/utils/theme_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/user_avatar_builder.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/widgets/email_address_action_widget.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
|
class MobileEditRecipientsView extends StatelessWidget {
|
||||||
|
final EmailAddress emailAddress;
|
||||||
|
final ImagePaths imagePaths;
|
||||||
|
final double width;
|
||||||
|
final VoidCallback onCopyAction;
|
||||||
|
final VoidCallback onEditAction;
|
||||||
|
final VoidCallback onCreateRuleAction;
|
||||||
|
|
||||||
|
const MobileEditRecipientsView({
|
||||||
|
super.key,
|
||||||
|
required this.emailAddress,
|
||||||
|
required this.imagePaths,
|
||||||
|
required this.width,
|
||||||
|
required this.onCopyAction,
|
||||||
|
required this.onEditAction,
|
||||||
|
required this.onCreateRuleAction,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PointerInterceptor(
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.15),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 3,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.3),
|
||||||
|
blurRadius: 3,
|
||||||
|
offset: const Offset(0, 1),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
padding: const EdgeInsetsDirectional.only(bottom: 6),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.symmetric(
|
||||||
|
horizontal: 14,
|
||||||
|
vertical: 12,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
UserAvatarBuilder(
|
||||||
|
username: emailAddress.asString().firstLetterToUpperCase,
|
||||||
|
size: 28,
|
||||||
|
textStyle: ThemeUtils.textStyleInter600().copyWith(
|
||||||
|
fontSize: 11,
|
||||||
|
height: 22 / 11,
|
||||||
|
letterSpacing: -0.41,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 16),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (emailAddress.displayName.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 24),
|
||||||
|
child: Text(
|
||||||
|
emailAddress.displayName,
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.titleSmall
|
||||||
|
?.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
emailAddress.emailAddress,
|
||||||
|
style: ThemeUtils.textStyleInter400.copyWith(
|
||||||
|
color: AppColor.steelGray400,
|
||||||
|
fontSize: 11,
|
||||||
|
height: 14 / 11,
|
||||||
|
letterSpacing: 0.0,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
..._buildActions(AppLocalizations.of(context)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildActions(AppLocalizations appLocalizations) {
|
||||||
|
return EmailAddressActionType.values.map((type) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
top: BorderSide(
|
||||||
|
color: AppColor.gray424244.withOpacity(0.12),
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: EmailAddressActionWidget(
|
||||||
|
imagePaths: imagePaths,
|
||||||
|
actionType: type,
|
||||||
|
onClick: _handleEmailAddressActionTypeClick,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleEmailAddressActionTypeClick(EmailAddressActionType actionType) {
|
||||||
|
switch (actionType) {
|
||||||
|
case EmailAddressActionType.copy:
|
||||||
|
onCopyAction();
|
||||||
|
break;
|
||||||
|
case EmailAddressActionType.edit:
|
||||||
|
onEditAction();
|
||||||
|
break;
|
||||||
|
case EmailAddressActionType.createRule:
|
||||||
|
onCreateRuleAction();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/extensions/string_extension.dart';
|
||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/utils/theme_utils.dart';
|
||||||
|
import 'package:core/presentation/views/button/tmail_button_widget.dart';
|
||||||
|
import 'package:core/presentation/views/dialog/confirm_dialog_button.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
|
import 'package:pointer_interceptor/pointer_interceptor.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/email_address_with_copy_widget.dart';
|
||||||
|
import 'package:tmail_ui_user/features/base/widget/user_avatar_builder.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
|
class DesktopEditRecipientsView extends StatelessWidget {
|
||||||
|
final EmailAddress emailAddress;
|
||||||
|
final ImagePaths imagePaths;
|
||||||
|
final double width;
|
||||||
|
final VoidCallback onCopyAction;
|
||||||
|
final VoidCallback onEditAction;
|
||||||
|
final VoidCallback onCreateRuleAction;
|
||||||
|
final VoidCallback onCloseAction;
|
||||||
|
|
||||||
|
const DesktopEditRecipientsView({
|
||||||
|
super.key,
|
||||||
|
required this.emailAddress,
|
||||||
|
required this.imagePaths,
|
||||||
|
required this.width,
|
||||||
|
required this.onCopyAction,
|
||||||
|
required this.onEditAction,
|
||||||
|
required this.onCreateRuleAction,
|
||||||
|
required this.onCloseAction,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return PointerInterceptor(
|
||||||
|
child: Container(
|
||||||
|
width: width,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
|
color: Colors.white,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.15),
|
||||||
|
blurRadius: 8,
|
||||||
|
spreadRadius: 3,
|
||||||
|
offset: const Offset(0, 4),
|
||||||
|
),
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black.withOpacity(0.3),
|
||||||
|
blurRadius: 3,
|
||||||
|
offset: const Offset(0, 1),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(
|
||||||
|
start: 16,
|
||||||
|
end: 16,
|
||||||
|
top: 21,
|
||||||
|
bottom: 21,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
UserAvatarBuilder(
|
||||||
|
username: emailAddress.asString().firstLetterToUpperCase,
|
||||||
|
size: 42,
|
||||||
|
textStyle: ThemeUtils.textStyleInter600().copyWith(
|
||||||
|
fontSize: 16,
|
||||||
|
height: 22 / 16,
|
||||||
|
letterSpacing: -0.41,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 16),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
if (emailAddress.displayName.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsetsDirectional.only(end: 24),
|
||||||
|
child: Text(
|
||||||
|
emailAddress.displayName,
|
||||||
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||||
|
color: AppColor.textPrimary,
|
||||||
|
),
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
EmailAddressWithCopyWidget(
|
||||||
|
label: emailAddress.emailAddress,
|
||||||
|
copyLabelIcon: imagePaths.icCopy,
|
||||||
|
textStyle: ThemeUtils.textStyleBodyBody2(
|
||||||
|
color: AppColor.steelGray400,
|
||||||
|
),
|
||||||
|
copyIconMargin: const EdgeInsetsDirectional.only(
|
||||||
|
start: 7,
|
||||||
|
),
|
||||||
|
copyIconColor: AppColor.steelGray400,
|
||||||
|
onCopyButtonAction: onCopyAction,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(minWidth: 127),
|
||||||
|
margin: const EdgeInsetsDirectional.only(end: 8),
|
||||||
|
height: 36,
|
||||||
|
child: ConfirmDialogButton(
|
||||||
|
label: AppLocalizations.of(context).editEmail,
|
||||||
|
backgroundColor: AppColor.primaryMain,
|
||||||
|
textColor: Colors.white,
|
||||||
|
onTapAction: onEditAction,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Container(
|
||||||
|
constraints: const BoxConstraints(minWidth: 134),
|
||||||
|
height: 36,
|
||||||
|
child: ConfirmDialogButton(
|
||||||
|
label: AppLocalizations.of(context).createARule,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
textColor: AppColor.primaryMain,
|
||||||
|
borderColor: AppColor.primaryMain,
|
||||||
|
onTapAction: onCreateRuleAction,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
PositionedDirectional(
|
||||||
|
top: 0,
|
||||||
|
end: 0,
|
||||||
|
child: TMailButtonWidget.fromIcon(
|
||||||
|
icon: imagePaths.icCloseDialog,
|
||||||
|
iconSize: 24,
|
||||||
|
iconColor: AppColor.m3Tertiary,
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
borderRadius: 24,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
onTapActionCallback: onCloseAction,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
|
import 'package:core/presentation/utils/theme_utils.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
|
import 'package:tmail_ui_user/features/composer/presentation/model/email_address_action_type.dart';
|
||||||
|
import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
|
||||||
|
|
||||||
|
typedef OnClickEmailAddressAction = void Function(EmailAddressActionType actionType);
|
||||||
|
|
||||||
|
class EmailAddressActionWidget extends StatelessWidget {
|
||||||
|
final ImagePaths imagePaths;
|
||||||
|
final EmailAddressActionType actionType;
|
||||||
|
final OnClickEmailAddressAction onClick;
|
||||||
|
|
||||||
|
const EmailAddressActionWidget({
|
||||||
|
super.key,
|
||||||
|
required this.imagePaths,
|
||||||
|
required this.actionType,
|
||||||
|
required this.onClick,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Material(
|
||||||
|
type: MaterialType.transparency,
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () => onClick(actionType),
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
height: 36,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
SvgPicture.asset(
|
||||||
|
actionType.getContextMenuIcon(imagePaths),
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
colorFilter: AppColor.steelGrayA540.asFilter(),
|
||||||
|
fit: BoxFit.fill,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 22),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
actionType.getContextMenuTitle(AppLocalizations.of(context)),
|
||||||
|
style: ThemeUtils.textStyleInter400.copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
height: 21.01 / 14,
|
||||||
|
letterSpacing: -0.15,
|
||||||
|
color: AppColor.gray424244.withOpacity(0.9),
|
||||||
|
),
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import 'package:core/utils/platform_info.dart';
|
|||||||
import 'package:core/utils/string_convert.dart';
|
import 'package:core/utils/string_convert.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:model/email/prefix_email_address.dart';
|
import 'package:model/email/prefix_email_address.dart';
|
||||||
import 'package:model/extensions/email_address_extension.dart';
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
@@ -77,6 +78,7 @@ class RecipientComposerWidget extends StatefulWidget {
|
|||||||
final bool isTestingForWeb;
|
final bool isTestingForWeb;
|
||||||
final int minInputLengthAutocomplete;
|
final int minInputLengthAutocomplete;
|
||||||
final String? composerId;
|
final String? composerId;
|
||||||
|
final VoidCallback? onClearFocusAction;
|
||||||
|
|
||||||
const RecipientComposerWidget({
|
const RecipientComposerWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -110,6 +112,7 @@ class RecipientComposerWidget extends StatefulWidget {
|
|||||||
this.onEnableAllRecipientsInputAction,
|
this.onEnableAllRecipientsInputAction,
|
||||||
this.focusNodeKeyboard,
|
this.focusNodeKeyboard,
|
||||||
this.onEditRecipientAction,
|
this.onEditRecipientAction,
|
||||||
|
this.onClearFocusAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -118,6 +121,8 @@ class RecipientComposerWidget extends StatefulWidget {
|
|||||||
|
|
||||||
class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
|
class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
|
||||||
|
|
||||||
|
final _responsiveUtils = Get.find<ResponsiveUtils>();
|
||||||
|
|
||||||
Timer? _gapBetweenTagChangedAndFindSuggestion;
|
Timer? _gapBetweenTagChangedAndFindSuggestion;
|
||||||
bool _lastTagFocused = false;
|
bool _lastTagFocused = false;
|
||||||
bool _isDragging = false;
|
bool _isDragging = false;
|
||||||
@@ -224,9 +229,11 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
|
|||||||
isCollapsed: _isCollapse,
|
isCollapsed: _isCollapse,
|
||||||
isLatestTagFocused: _lastTagFocused,
|
isLatestTagFocused: _lastTagFocused,
|
||||||
maxWidth: widget.maxWidth,
|
maxWidth: widget.maxWidth,
|
||||||
|
isMobile: _responsiveUtils.isMobile(context),
|
||||||
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
|
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
|
||||||
onShowFullAction: widget.onShowFullListEmailAddressAction,
|
onShowFullAction: widget.onShowFullListEmailAddressAction,
|
||||||
onEditRecipientAction: widget.onEditRecipientAction,
|
onEditRecipientAction: widget.onEditRecipientAction,
|
||||||
|
onClearFocusAction: widget.onClearFocusAction,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
|
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
|
||||||
@@ -317,9 +324,11 @@ class _RecipientComposerWidgetState extends State<RecipientComposerWidget> {
|
|||||||
isCollapsed: _isCollapse,
|
isCollapsed: _isCollapse,
|
||||||
isLatestTagFocused: _lastTagFocused,
|
isLatestTagFocused: _lastTagFocused,
|
||||||
maxWidth: widget.maxWidth,
|
maxWidth: widget.maxWidth,
|
||||||
|
isMobile: _responsiveUtils.isMobile(context),
|
||||||
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
|
onDeleteTagAction: (emailAddress) => _handleDeleteTagAction.call(emailAddress, stateSetter),
|
||||||
onShowFullAction: widget.onShowFullListEmailAddressAction,
|
onShowFullAction: widget.onShowFullListEmailAddressAction,
|
||||||
onEditRecipientAction: widget.onEditRecipientAction,
|
onEditRecipientAction: widget.onEditRecipientAction,
|
||||||
|
onClearFocusAction: widget.onClearFocusAction,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
|
onTagChanged: (value) => _handleOnTagChangeAction.call(value, stateSetter),
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
import 'package:core/presentation/extensions/color_extension.dart';
|
import 'package:core/presentation/extensions/color_extension.dart';
|
||||||
import 'package:core/presentation/resources/image_paths.dart';
|
import 'package:core/presentation/resources/image_paths.dart';
|
||||||
import 'package:core/presentation/views/text/rich_text_builder.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';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
@@ -50,7 +49,6 @@ class RecipientSuggestionItemWidget extends StatelessWidget {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: RecipientSuggestionItemWidgetStyle.labelPadding,
|
padding: RecipientSuggestionItemWidgetStyle.labelPadding,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
AvatarSuggestionItemWidget(emailAddress: emailAddress),
|
AvatarSuggestionItemWidget(emailAddress: emailAddress),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -58,18 +56,22 @@ class RecipientSuggestionItemWidget extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
RichTextWidget(
|
RichTextWidget(
|
||||||
textOrigin: emailAddress.asString(),
|
textOrigin: emailAddress.asString(),
|
||||||
wordSearched: suggestionValid ?? '',
|
wordSearched: suggestionValid ?? '',
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
if (emailAddress.displayName.isNotEmpty)
|
if (emailAddress.displayName.isNotEmpty)
|
||||||
RichTextBuilder(
|
RichTextWidget(
|
||||||
textOrigin: emailAddress.emailAddress,
|
textOrigin: emailAddress.emailAddress,
|
||||||
wordToStyle: suggestionValid ?? '',
|
wordSearched: suggestionValid ?? '',
|
||||||
styleOrigin: RecipientSuggestionItemWidgetStyle.labelTextStyle,
|
overflow: TextOverflow.ellipsis,
|
||||||
styleWord: RecipientSuggestionItemWidgetStyle.labelHighlightTextStyle,
|
maxLines: 1,
|
||||||
|
styleTextOrigin: RecipientSuggestionItemWidgetStyle.labelTextStyle,
|
||||||
|
styleWordSearched: RecipientSuggestionItemWidgetStyle.labelHighlightTextStyle,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -98,7 +100,6 @@ class RecipientSuggestionItemWidget extends StatelessWidget {
|
|||||||
child: Padding(
|
child: Padding(
|
||||||
padding: RecipientSuggestionItemWidgetStyle.labelPadding,
|
padding: RecipientSuggestionItemWidgetStyle.labelPadding,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
AvatarSuggestionItemWidget(emailAddress: emailAddress),
|
AvatarSuggestionItemWidget(emailAddress: emailAddress),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@@ -106,18 +107,22 @@ class RecipientSuggestionItemWidget extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
RichTextWidget(
|
RichTextWidget(
|
||||||
textOrigin: emailAddress.asString(),
|
textOrigin: emailAddress.asString(),
|
||||||
wordSearched: suggestionValid ?? '',
|
wordSearched: suggestionValid ?? '',
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
maxLines: 1,
|
||||||
),
|
),
|
||||||
if (emailAddress.displayName.isNotEmpty)
|
if (emailAddress.displayName.isNotEmpty)
|
||||||
RichTextBuilder(
|
RichTextWidget(
|
||||||
textOrigin: emailAddress.emailAddress,
|
textOrigin: emailAddress.emailAddress,
|
||||||
wordToStyle: suggestionValid ?? '',
|
wordSearched: suggestionValid ?? '',
|
||||||
styleOrigin: RecipientSuggestionItemWidgetStyle.labelTextStyle,
|
overflow: TextOverflow.ellipsis,
|
||||||
styleWord: RecipientSuggestionItemWidgetStyle.labelHighlightTextStyle,
|
maxLines: 1,
|
||||||
|
styleTextOrigin: RecipientSuggestionItemWidgetStyle.labelTextStyle,
|
||||||
|
styleWordSearched: RecipientSuggestionItemWidgetStyle.labelHighlightTextStyle,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ class RecipientTagItemWidget extends StatelessWidget {
|
|||||||
final OnEditRecipientAction? onEditRecipientAction;
|
final OnEditRecipientAction? onEditRecipientAction;
|
||||||
final bool isTestingForWeb;
|
final bool isTestingForWeb;
|
||||||
final String? composerId;
|
final String? composerId;
|
||||||
|
final bool isMobile;
|
||||||
|
final VoidCallback? onClearFocusAction;
|
||||||
|
|
||||||
const RecipientTagItemWidget({
|
const RecipientTagItemWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -49,28 +51,39 @@ class RecipientTagItemWidget extends StatelessWidget {
|
|||||||
this.isCollapsed = false,
|
this.isCollapsed = false,
|
||||||
this.isLatestTagFocused = false,
|
this.isLatestTagFocused = false,
|
||||||
this.isLatestEmail = false,
|
this.isLatestEmail = false,
|
||||||
|
this.isMobile = false,
|
||||||
this.onShowFullAction,
|
this.onShowFullAction,
|
||||||
this.onDeleteTagAction,
|
this.onDeleteTagAction,
|
||||||
this.onEditRecipientAction,
|
this.onEditRecipientAction,
|
||||||
this.maxWidth,
|
this.maxWidth,
|
||||||
this.composerId,
|
this.composerId,
|
||||||
|
this.onClearFocusAction,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final overlayWidth = isMobile ? 227.0 : 361.0;
|
||||||
Widget tagWidget = CardWithSmartInteractionOverlayView(
|
Widget tagWidget = CardWithSmartInteractionOverlayView(
|
||||||
|
overlayWidth: overlayWidth,
|
||||||
menuBuilder: (onClose) => EditRecipientsView(
|
menuBuilder: (onClose) => EditRecipientsView(
|
||||||
emailAddress: currentEmailAddress,
|
emailAddress: currentEmailAddress,
|
||||||
imagePaths: imagePaths,
|
imagePaths: imagePaths,
|
||||||
onCopyAction: () => _onEditRecipientAction(
|
isMobile: isMobile,
|
||||||
context,
|
width: overlayWidth,
|
||||||
EmailAddressActionType.copy,
|
onCopyAction: () {
|
||||||
),
|
if (isMobile) {
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
_onEditRecipientAction(
|
||||||
|
context,
|
||||||
|
EmailAddressActionType.copy,
|
||||||
|
);
|
||||||
|
},
|
||||||
onEditAction: () {
|
onEditAction: () {
|
||||||
onClose();
|
onClose();
|
||||||
_onEditRecipientAction(
|
_onEditRecipientAction(
|
||||||
context,
|
context,
|
||||||
EmailAddressActionType.modify,
|
EmailAddressActionType.edit,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onCreateRuleAction: () {
|
onCreateRuleAction: () {
|
||||||
@@ -82,6 +95,7 @@ class RecipientTagItemWidget extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
onCloseAction: onClose,
|
onCloseAction: onClose,
|
||||||
),
|
),
|
||||||
|
onClearFocusAction: onClearFocusAction,
|
||||||
child: Chip(
|
child: Chip(
|
||||||
labelPadding: EdgeInsetsDirectional.symmetric(
|
labelPadding: EdgeInsetsDirectional.symmetric(
|
||||||
horizontal: 4,
|
horizontal: 4,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2025-07-24T16:57:08.573149",
|
"@@last_modified": "2025-07-25T12:21:42.514040",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -4608,12 +4608,6 @@
|
|||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"modifyEmailAddress": "Modify email address",
|
|
||||||
"@modifyEmailAddress": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders_order": [],
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"editEmail": "Edit email",
|
"editEmail": "Edit email",
|
||||||
"@editEmail": {
|
"@editEmail": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
|||||||
@@ -4856,13 +4856,6 @@ class AppLocalizations {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get modifyEmailAddress {
|
|
||||||
return Intl.message(
|
|
||||||
'Modify email address',
|
|
||||||
name: 'modifyEmailAddress',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
String get editEmail {
|
String get editEmail {
|
||||||
return Intl.message(
|
return Intl.message(
|
||||||
'Edit email',
|
'Edit email',
|
||||||
|
|||||||
Reference in New Issue
Block a user