TF-3952 Change style for item in list recipients

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-08-07 23:51:03 +07:00
committed by Dat H. Pham
parent 9d3923991a
commit a57985a5ed
8 changed files with 213 additions and 159 deletions
+5
View File
@@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M7.85718 13.2756L4.07654 9.49492C3.79759 9.21598 3.34533 9.21598 3.06639 9.49492C2.78744 9.77387 2.78744 10.2261 3.06639 10.5051L7.3521 14.7908C7.63105 15.0697 8.08331 15.0697 8.36225 14.7908L16.9337 6.21936C17.2126 5.94042 17.2126 5.48816 16.9337 5.20921C16.6547 4.93026 16.2025 4.93026 15.9235 5.20921L7.85718 13.2756Z"
fill="#007AFF" />
</svg>

After

Width:  |  Height:  |  Size: 472 B

@@ -271,6 +271,7 @@ extension AppColor on Color {
static const m3Primary = Color(0xFF0A84FF); static const m3Primary = Color(0xFF0A84FF);
static const m3Primary95 = Color(0xFFE3F1FF); static const m3Primary95 = Color(0xFFE3F1FF);
static const gray49454F = Color(0xFF49454F); static const gray49454F = Color(0xFF49454F);
static const lightGrayF9FAFB = Color(0xFFF9FAFB);
static const mapGradientColor = [ static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)], [Color(0xFF21D4FD), Color(0xFFB721FF)],
@@ -234,10 +234,9 @@ class ImagePaths {
String get icArrowBack => _getImagePath('ic_arrow_back.svg'); String get icArrowBack => _getImagePath('ic_arrow_back.svg');
String get icRadio => _getImagePath('ic_radio.svg'); String get icRadio => _getImagePath('ic_radio.svg');
String get icRadioSelected => _getImagePath('ic_radio_selected.svg'); String get icRadioSelected => _getImagePath('ic_radio_selected.svg');
String get icCheck => _getImagePath('ic_check.svg');
String get icFileDownload => _getImagePath('ic_file_download.svg'); String get icFileDownload => _getImagePath('ic_file_download.svg');
String get icTwakeWorkplace => _getIconPath('icon_twp.png'); String get icTwakeWorkplace => _getIconPath('icon_twp.png');
String get animLottieTmail => _getAnimationPath('lottie-tmail.json'); String get animLottieTmail => _getAnimationPath('lottie-tmail.json');
String get icExpandArrows => _getImagePath('ic_expand_arrows.svg'); String get icExpandArrows => _getImagePath('ic_expand_arrows.svg');
@@ -245,6 +245,15 @@ class ThemeUtils {
color: AppColor.m3Tertiary20, color: AppColor.m3Tertiary20,
); );
static TextStyle get textStyleM3TitleMedium => defaultTextStyleInterFont.copyWith(
fontFamily: ConstantsUI.fontApp,
fontWeight: FontWeight.w500,
letterSpacing: 0.15,
fontSize: 16,
height: 24 / 16,
color: AppColor.secondaryContrastText,
);
static TextStyle textStyleM3BodyMedium1 = defaultTextStyleInterFont.copyWith( static TextStyle textStyleM3BodyMedium1 = defaultTextStyleInterFont.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
letterSpacing: -0.15, letterSpacing: -0.15,
@@ -51,7 +51,11 @@ class ForwardView extends GetWidget<ForwardController> with AppLoaderMixin {
), ),
width: double.infinity, width: double.infinity,
padding: controller.responsiveUtils.isDesktop(context) padding: controller.responsiveUtils.isDesktop(context)
? const EdgeInsets.symmetric(vertical: 30, horizontal: 22) ? const EdgeInsetsDirectional.only(
start: 22,
end: 22,
top: 30,
)
: null, : null,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -62,7 +66,7 @@ class ForwardView extends GetWidget<ForwardController> with AppLoaderMixin {
textStyle: ThemeUtils.textStyleInter600().copyWith( textStyle: ThemeUtils.textStyleInter600().copyWith(
color: Colors.black.withValues(alpha: 0.9), color: Colors.black.withValues(alpha: 0.9),
), ),
padding: EdgeInsets.zero, padding: const EdgeInsets.only(bottom: 16),
) )
else else
const SettingExplanationWidget( const SettingExplanationWidget(
@@ -76,39 +80,42 @@ class ForwardView extends GetWidget<ForwardController> with AppLoaderMixin {
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
Expanded( Expanded(
child: Padding( child: SingleChildScrollView(
padding: isWebDesktop physics: const ClampingScrollPhysics(),
? EdgeInsets.zero child: Padding(
: const EdgeInsetsDirectional.symmetric(horizontal: 16), padding: isWebDesktop
child: Column( ? EdgeInsets.zero
crossAxisAlignment: CrossAxisAlignment.start, : const EdgeInsetsDirectional.symmetric(horizontal: 16),
children: [ child: Column(
Obx(() => KeepCopyInInboxWidget( crossAxisAlignment: CrossAxisAlignment.start,
imagePaths: controller.imagePaths, children: [
recipientForwards: controller.listRecipientForward, Obx(() => KeepCopyInInboxWidget(
localCopyState: controller.currentForwardLocalCopyState, imagePaths: controller.imagePaths,
onToggleLocalCopy: controller.handleEditLocalCopy, recipientForwards: controller.listRecipientForward,
)), localCopyState: controller.currentForwardLocalCopyState,
Obx( onToggleLocalCopy: controller.handleEditLocalCopy,
() => NumberOfRecipientWidget( )),
numberOfRecipient: Obx(
controller.listRecipientForward.length, () => NumberOfRecipientWidget(
numberOfRecipient:
controller.listRecipientForward.length,
),
), ),
), Obx(
Obx( () => controller.currentForward.value != null
() => controller.currentForward.value != null ? _buildAddRecipientsFormWidget(context)
? _buildAddRecipientsFormWidget(context) : const SizedBox.shrink(),
: const SizedBox.shrink(), ),
), _buildLoadingView(),
_buildLoadingView(), Obx(() {
Obx(() { if (controller.listRecipientForward.isNotEmpty) {
if (controller.listRecipientForward.isNotEmpty) { return const ListEmailForwardsWidget();
return const ListEmailForwardsWidget(); } else {
} else { return const SizedBox.shrink();
return const SizedBox.shrink(); }
} }),
}), ],
], ),
), ),
), ),
), ),
@@ -1,15 +1,15 @@
import 'dart:math';
import 'package:core/presentation/extensions/color_extension.dart'; import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/extensions/string_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/style_utils.dart'; import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart'; import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/button/icon_button_web.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart'; import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/image/avatar_builder.dart'; import 'package:core/presentation/views/image/avatar_builder.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.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:get/get.dart';
import 'package:model/extensions/email_address_extension.dart'; import 'package:model/extensions/email_address_extension.dart';
import 'package:model/mailbox/select_mode.dart'; import 'package:model/mailbox/select_mode.dart';
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart'; import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
@@ -20,19 +20,22 @@ typedef OnSelectRecipientCallbackAction = Function(RecipientForward recipientFor
typedef OnDeleteRecipientCallbackAction = Function(RecipientForward recipientForward); typedef OnDeleteRecipientCallbackAction = Function(RecipientForward recipientForward);
class EmailForwardItemWidget extends StatelessWidget { class EmailForwardItemWidget extends StatelessWidget {
final ImagePaths imagePaths;
final ResponsiveUtils responsiveUtils;
final RecipientForward recipientForward; final RecipientForward recipientForward;
final SelectMode selectionMode; final SelectMode selectionMode;
final String internalDomain; final String internalDomain;
final double maxWidth;
final OnSelectRecipientCallbackAction? onSelectRecipientCallback; final OnSelectRecipientCallbackAction? onSelectRecipientCallback;
final OnDeleteRecipientCallbackAction? onDeleteRecipientCallback; final OnDeleteRecipientCallbackAction? onDeleteRecipientCallback;
final ImagePaths _imagePaths = Get.find<ImagePaths>(); const EmailForwardItemWidget({
EmailForwardItemWidget({
Key? key, Key? key,
required this.imagePaths,
required this.responsiveUtils,
required this.recipientForward, required this.recipientForward,
required this.internalDomain, required this.internalDomain,
required this.maxWidth,
this.selectionMode = SelectMode.INACTIVE, this.selectionMode = SelectMode.INACTIVE,
this.onSelectRecipientCallback, this.onSelectRecipientCallback,
this.onDeleteRecipientCallback, this.onDeleteRecipientCallback,
@@ -40,108 +43,132 @@ class EmailForwardItemWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( final isScreenWithShortestSide = responsiveUtils
.isScreenWithShortestSide(context);
final isSameDomain = EmailUtils.isSameDomain(
emailAddress: recipientForward.emailAddress.emailAddress,
internalDomain: internalDomain,
);
final bodyWidget = Padding(
padding: const EdgeInsets.only(top: 4), padding: const EdgeInsets.only(top: 4),
child: Material( child: GestureDetector(
color: Colors.transparent, onLongPress: PlatformInfo.isMobile
child: InkWell( ? () => onSelectRecipientCallback?.call(recipientForward)
onLongPress: () { : null,
if (PlatformInfo.isMobile) { child: Container(
onSelectRecipientCallback?.call(recipientForward); padding: const EdgeInsets.symmetric(horizontal: 16),
} decoration: BoxDecoration(
}, color: _getBackgroundColor(),
customBorder: const RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(10)),
borderRadius: BorderRadius.all(Radius.circular(12))), ),
child: Container( width: isScreenWithShortestSide
padding: const EdgeInsets.only(left: 12, bottom: 12, top: 12), ? double.infinity
decoration: BoxDecoration( : min(maxWidth, 597),
color: _getBackgroundColor(), height: 72,
borderRadius: BorderRadius.all(Radius.circular( child: Row(
recipientForward.selectMode == SelectMode.ACTIVE ? 12 : 0)) children: [
), Expanded(
child: Row(children: [ child: Row(
_buildAvatarIcon(_imagePaths), crossAxisAlignment: CrossAxisAlignment.start,
const SizedBox(width: 12), children: [
Expanded(child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (EmailUtils.isSameDomain(
emailAddress: recipientForward.emailAddress.emailAddress,
internalDomain: internalDomain))
Text(
recipientForward.emailAddress.asString(),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black
)
)
else
Row(
children: [
Flexible(
child: Text(
recipientForward.emailAddress.asString(),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
maxLines: 1,
style: Theme.of(context).textTheme.labelSmall?.copyWith(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black
)
),
),
TMailButtonWidget.fromIcon(
icon: _imagePaths.icInfoCircleOutline,
iconColor: AppColor.colorQuotaError,
iconSize: 20,
backgroundColor: Colors.transparent,
padding: const EdgeInsets.all(3),
tooltipMessage: AppLocalizations.of(context).externalDomain,
)
],
),
if (recipientForward.emailAddress.displayName.isNotEmpty)
Padding( Padding(
padding: const EdgeInsets.only(top: 4), padding: const EdgeInsets.only(top: 3),
child: Text( child: _buildAvatarIcon(imagePaths),
recipientForward.emailAddress.email ?? '', ),
overflow: CommonTextStyle.defaultTextOverFlow, const SizedBox(width: 12),
softWrap: CommonTextStyle.defaultSoftWrap, Expanded(
maxLines: 1, child: Column(
style: ThemeUtils.defaultTextStyleInterFont.copyWith( mainAxisSize: MainAxisSize.min,
fontSize: 14, crossAxisAlignment: CrossAxisAlignment.start,
fontWeight: FontWeight.normal, children: [
color: AppColor.colorContentEmail Row(
) mainAxisSize: MainAxisSize.min,
children: [
Flexible(
child: Text(
recipientForward.emailAddress.asString(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: ThemeUtils.textStyleBodyBody2(
color: Colors.black,
),
),
),
TMailButtonWidget.fromIcon(
icon: isSameDomain
? imagePaths.icCheck
: imagePaths.icInfoCircleOutline,
iconColor: AppColor.primaryLinShare,
iconSize: 20,
margin: const EdgeInsetsDirectional.only(
start: 4,
),
backgroundColor: Colors.transparent,
padding: const EdgeInsets.all(2),
tooltipMessage: isSameDomain
? null
: AppLocalizations.of(context).externalDomain,
)
],
),
if (recipientForward.emailAddress.displayName.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 4),
child: Text(
recipientForward.emailAddress.email ?? '',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: ThemeUtils.textStyleBodyBody2(
color: AppColor.gray424244.withValues(
alpha: 0.64,
),
),
),
)
],
), ),
) )
], ],
)), ),
const SizedBox(width: 12), ),
if (selectionMode == SelectMode.INACTIVE) if (selectionMode == SelectMode.INACTIVE)
buildIconWeb( TMailButtonWidget.fromIcon(
iconSize: 30, icon: imagePaths.icDeleteComposer,
splashRadius: 20, iconSize: 20,
icon: SvgPicture.asset(_imagePaths.icDeleteRecipient), iconColor: AppColor.steelGrayA540,
onTap: () => onDeleteRecipientCallback?.call(recipientForward) backgroundColor: Colors.transparent,
) margin: EdgeInsetsDirectional.only(
]), start: 12,
end: isScreenWithShortestSide ? 0 : 12,
),
onTapActionCallback: () =>
onDeleteRecipientCallback?.call(recipientForward),
),
],
), ),
), ),
), ),
); );
if (isScreenWithShortestSide) {
return bodyWidget;
} else {
return Row(
children: [
bodyWidget,
const Spacer(),
],
);
}
} }
Color _getBackgroundColor() { Color _getBackgroundColor() {
if (recipientForward.selectMode == SelectMode.ACTIVE) { if (recipientForward.selectMode == SelectMode.ACTIVE) {
return AppColor.colorItemRecipientSelected; return AppColor.colorItemRecipientSelected;
} else { } else {
return Colors.transparent; return AppColor.lightGrayF9FAFB;
} }
} }
@@ -151,29 +178,28 @@ class EmailForwardItemWidget extends StatelessWidget {
customBorder: const CircleBorder(), customBorder: const CircleBorder(),
onTap: () => onSelectRecipientCallback?.call(recipientForward), onTap: () => onSelectRecipientCallback?.call(recipientForward),
child: Container( child: Container(
width: 40, width: 32,
height: 40, height: 32,
color: Colors.transparent, color: Colors.transparent,
alignment: Alignment.center, alignment: Alignment.center,
child: SvgPicture.asset( child: SvgPicture.asset(
imagePaths.icSelectedRecipient, imagePaths.icSelectedRecipient,
width: 40, width: 32,
height: 40, height: 32,
fit: BoxFit.fill, fit: BoxFit.fill,
), ),
), ),
); );
} else { } else {
return (AvatarBuilder() return (AvatarBuilder()
..text(recipientForward.emailAddress.asString().firstLetterToUpperCase) ..text(
..size(40) recipientForward.emailAddress.asString().firstLetterToUpperCase)
..addTextStyle(ThemeUtils.defaultTextStyleInterFont.copyWith( ..size(32)
fontWeight: FontWeight.w500, ..addTextStyle(ThemeUtils.textStyleM3TitleMedium)
fontSize: 16, ..avatarColor(recipientForward.emailAddress.avatarColors)
color: Colors.white)) ..addOnTapActionClick(
..avatarColor(recipientForward.emailAddress.avatarColors) () => onSelectRecipientCallback?.call(recipientForward)))
..addOnTapActionClick(() => onSelectRecipientCallback?.call(recipientForward)) .build();
).build();
} }
} }
} }
@@ -27,7 +27,7 @@ class KeepCopyInInboxWidget extends StatelessWidget {
} }
return Padding( return Padding(
padding: const EdgeInsets.only(top: 24), padding: const EdgeInsets.only(top: 8),
child: Row( child: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -26,22 +26,29 @@ class ListEmailForwardsWidget extends GetWidget<ForwardController> {
if (controller.listRecipientForward.isEmpty) { if (controller.listRecipientForward.isEmpty) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} else { } else {
return ListView.builder( return LayoutBuilder(
shrinkWrap: true, builder: (context, constraints) {
primary: false, return ListView.builder(
itemCount: controller.listRecipientForward.length, shrinkWrap: true,
padding: EdgeInsets.zero, primary: false,
itemBuilder: (context, index) { itemCount: controller.listRecipientForward.length,
return EmailForwardItemWidget( padding: const EdgeInsets.only(bottom: 30),
recipientForward: controller.listRecipientForward[index], itemBuilder: (context, index) {
internalDomain: controller.accountDashBoardController.sessionCurrent?.internalDomain ?? '', return EmailForwardItemWidget(
selectionMode: controller.selectionMode.value, imagePaths: controller.imagePaths,
onSelectRecipientCallback: controller.selectRecipientForward, responsiveUtils: controller.responsiveUtils,
onDeleteRecipientCallback: (recipientForward) { recipientForward: controller.listRecipientForward[index],
controller.deleteRecipients(context, recipientForward.emailAddress.emailAddress); internalDomain: controller.accountDashBoardController.sessionCurrent?.internalDomain ?? '',
}, selectionMode: controller.selectionMode.value,
maxWidth: constraints.maxWidth,
onSelectRecipientCallback: controller.selectRecipientForward,
onDeleteRecipientCallback: (recipientForward) {
controller.deleteRecipients(context, recipientForward.emailAddress.emailAddress);
},
);
}
); );
} },
); );
} }
}), }),