TF-3769 Enable toggle thread detail feature in setting

TF-3769 Thread Detail fallback to single email when get thread fails

TF-3769 Thread Detail fix font height thread

TF-3769 Thread Detail init with get status

TF-3769 Thread Detail fix font height email receiver and sender

TF-3769 Thread Detail refactor reset thread detail ui action UpdatedThreadDetailSettingAction

TF-3769 Thread Detail refresh settings on app lifecycle changed

TF-3769 Thread Detail fix font height email receiver and sender

TF-3769 Thread Detail fix scroll view exception of single email

TF-3769 Thread Detail refactor local setting

TF-3769 Thread Detail optimize get cache setting

TF-3769 Thread Detail fix font height email receiver

TF-3769 Thread Detail refactor local setting cache

TF-3769 Thread Detail fix font height email receiver and sender

TF-3769 Thread Detail use CacheExceptionThrower for ManageAccountDataSourceImpl

TF-3769 Thread Detail fix changing email in tablet view

TF-3769 Thread Detail refresh on setting changed

TF-3769 Thread Detail fix receiver alignments

TF-3769 Thread Detail fix receiver alignments

TF-3769 Thread Detail default setting enabled

TF-3769 Thread Detail fix font style email receiver and sender

TF-3769 Thread Detail fix toggle setting when responsive

TF-3769 Thread Detail adjust receive time position when single email

TF-3769 Thread Detail revert initializeThreadDetailEmails to void

TF-3769 Thread Detail fix CI on initializeThreadDetailEmails test

TF-3769 Thread Detail fix spacing email sender

TF-3769 Thread Detail update receiver color mobile

TF-3769 Thread Detail update collapsed preview letter spacing

TF-3769 Thread Detail update receiver color mobile

TF-3769 Thread Detail fix receive time position

TF-3769 Thread Detail add mark read button mobile collapsed email

TF-3769 Thread Detail fix font style email receiver and sender

TF-3769 Thread Detail update collapsed preview font weight

TF-3769 Thread Detail fix position email receiver and sender
This commit is contained in:
DatDang
2025-05-29 17:07:44 +07:00
committed by Dat H. Pham
parent c9ca3925cb
commit 1bc45e35f3
57 changed files with 830 additions and 165 deletions
@@ -103,7 +103,7 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
ConstrainedBox(
constraints: BoxConstraints(
maxWidth: _getMaxWidth(context),
maxHeight: 34,
maxHeight: _responsiveUtils.isMobile(context) ? 22 : 28,
),
child: ListView(
scrollDirection: Axis.horizontal,
@@ -239,10 +239,18 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
? emailAddress.asString()
: '${emailAddress.asString()},',
textStyle: ThemeUtils.textStyleHeadingHeadingSmall(
color: Colors.black,
color: _responsiveUtils.isMobile(context) ? AppColor.gray6D7885 : Colors.black,
fontWeight: FontWeight.w400,
).copyWith(height: 17),
padding: const EdgeInsetsDirectional.symmetric(vertical: 2, horizontal: 8),
).copyWith(
fontSize: _responsiveUtils.isMobile(context) ? 14 : 17,
height: 1,
letterSpacing: _responsiveUtils.isMobile(context) ? -0.14 : -0.17,
),
padding: EdgeInsetsDirectional.symmetric(
vertical: _responsiveUtils.isMobile(context) ? 2.5 : 3.5,
horizontal: 8,
),
margin: EdgeInsetsDirectional.only(top: _responsiveUtils.isMobile(context) ? 1.5 : 2),
backgroundColor: Colors.transparent,
onTapActionCallback: () => widget.openEmailAddressDetailAction?.call(context, emailAddress),
onLongPressActionCallback: () => AppUtils.copyEmailAddressToClipboard(context, emailAddress.emailAddress),
@@ -259,7 +267,10 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
PrefixRecipientWidget(prefixEmailAddress: prefixEmailAddress),
PrefixRecipientWidget(
prefixEmailAddress: prefixEmailAddress,
responsiveUtils: _responsiveUtils,
),
Expanded(
child: Wrap(
children: _buildRecipientsTag(listEmailAddress: listEmailAddress)
@@ -275,7 +286,10 @@ class _EmailReceiverWidgetState extends State<EmailReceiverWidget> {
required List<EmailAddress> listEmailAddress,
}) {
return [
PrefixRecipientWidget(prefixEmailAddress: prefixEmailAddress),
PrefixRecipientWidget(
prefixEmailAddress: prefixEmailAddress,
responsiveUtils: _responsiveUtils,
),
..._buildRecipientsTag(listEmailAddress: listEmailAddress)
];
}
@@ -25,45 +25,52 @@ class EmailSenderBuilder extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
scrollDirection: Axis.horizontal,
physics: const NeverScrollableScrollPhysics(),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
if (emailAddress.displayName.isNotEmpty)
MaterialTextButton(
label: emailAddress.displayName,
onTap: () => openEmailAddressDetailAction?.call(context, emailAddress),
onLongPress: () {
AppUtils.copyEmailAddressToClipboard(context, emailAddress.emailAddress);
},
borderRadius: 8,
padding: EdgeInsets.zero,
customStyle: ThemeUtils.textStyleHeadingH6(
color: Colors.black,
fontWeight: FontWeight.w500,
).copyWith(height: 20),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap
),
if (showSenderEmail)
MaterialTextButton(
label: '<${emailAddress.emailAddress}>',
onTap: () => openEmailAddressDetailAction?.call(context, emailAddress),
onLongPress: () {
AppUtils.copyEmailAddressToClipboard(context, emailAddress.emailAddress);
},
borderRadius: 8,
padding: EdgeInsets.zero,
customStyle: ThemeUtils.textStyleBodyBody1(
color: AppColor.steelGray400,
return Transform.translate(
offset: const Offset(-2, 0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
physics: const NeverScrollableScrollPhysics(),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
if (emailAddress.displayName.isNotEmpty)
MaterialTextButton(
label: emailAddress.displayName,
onTap: () => openEmailAddressDetailAction?.call(context, emailAddress),
onLongPress: () {
AppUtils.copyEmailAddressToClipboard(context, emailAddress.emailAddress);
},
borderRadius: 8,
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 4),
customStyle: ThemeUtils.textStyleHeadingH6(
color: Colors.black,
fontWeight: FontWeight.w500,
).copyWith(height: 1, letterSpacing: -0.2),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap
),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap
)
]
if (showSenderEmail)
MaterialTextButton(
label: '<${emailAddress.emailAddress}>',
onTap: () => openEmailAddressDetailAction?.call(context, emailAddress),
onLongPress: () {
AppUtils.copyEmailAddressToClipboard(context, emailAddress.emailAddress);
},
borderRadius: 8,
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 4),
customStyle: ThemeUtils.textStyleBodyBody1(
color: AppColor.gray6D7885,
).copyWith(
fontSize: 17,
height: 1,
letterSpacing: -0.17,
),
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap
)
]
),
),
);
}
@@ -2,6 +2,7 @@ import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/resources/image_paths.dart';
import 'package:core/presentation/utils/icon_utils.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:core/presentation/views/button/tmail_button_widget.dart';
import 'package:core/presentation/views/image/avatar_builder.dart';
import 'package:core/utils/platform_info.dart';
@@ -74,6 +75,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
EmailAvatarBuilder(
emailSelected: emailSelected,
onTapAvatarActionClick: onTapAvatarActionClick,
size: 56,
),
const SizedBox(width: 16),
Expanded(child: LayoutBuilder(builder: (context, constraints) {
@@ -82,7 +84,6 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 4),
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
@@ -92,13 +93,13 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
if (showUnreadVisualization &&
!emailSelected.hasRead &&
responsiveUtils.isMobile(context))
Padding(
padding: const EdgeInsetsDirectional.only(end: 8),
child: SvgPicture.asset(
imagePaths.icUnreadStatus,
width: 9,
height: 9,
fit: BoxFit.fill,
TMailButtonWidget.fromIcon(
icon: imagePaths.icUnreadStatus,
backgroundColor: Colors.transparent,
iconSize: 9,
onTapActionCallback: () => onEmailActionClick?.call(
emailSelected,
EmailActionType.markAsRead,
),
),
if (emailSelected.from?.isNotEmpty == true)
@@ -129,7 +130,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
color: AppColor.colorTextBody,
decoration: TextDecoration.underline,
),
padding: const EdgeInsetsDirectional.symmetric(vertical: 5, horizontal: 8),
padding: const EdgeInsetsDirectional.symmetric(vertical: 4, horizontal: 8),
backgroundColor: Colors.transparent,
onTapActionCallback: () => onEmailActionClick?.call(emailSelected, EmailActionType.unsubscribe),
),
@@ -154,7 +155,7 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
],
),
),
if (!isInsideThreadDetailView && !responsiveUtils.isMobile(context))
if (!isInsideThreadDetailView)
ReceivedTimeBuilder(
emailSelected: emailSelected,
padding: const EdgeInsetsDirectional.only(start: 16, top: 2),
@@ -187,11 +188,10 @@ class InformationSenderAndReceiverBuilder extends StatelessWidget {
),
],
),
const SizedBox(height: 4),
if (responsiveUtils.isMobile(context))
if (responsiveUtils.isMobile(context) && isInsideThreadDetailView)
ReceivedTimeBuilder(
emailSelected: emailSelected,
padding: const EdgeInsetsDirectional.only(top: 5),
padding: const EdgeInsetsDirectional.symmetric(vertical: 5),
),
if (emailSelected.countRecipients > 0 && showRecipients)
EmailReceiverWidget(
@@ -1,5 +1,6 @@
import 'package:core/presentation/extensions/color_extension.dart';
import 'package:core/presentation/utils/responsive_utils.dart';
import 'package:core/presentation/utils/theme_utils.dart';
import 'package:flutter/material.dart';
import 'package:model/email/prefix_email_address.dart';
@@ -7,14 +8,29 @@ import 'package:tmail_ui_user/features/composer/presentation/extensions/prefix_e
class PrefixRecipientWidget extends StatelessWidget {
final PrefixEmailAddress prefixEmailAddress;
final ResponsiveUtils responsiveUtils;
const PrefixRecipientWidget({super.key, required this.prefixEmailAddress});
const PrefixRecipientWidget({
super.key,
required this.prefixEmailAddress,
required this.responsiveUtils,
});
@override
Widget build(BuildContext context) {
return Text(
'${prefixEmailAddress.asName(context)}:',
style: ThemeUtils.textStyleBodyBody1(color: AppColor.steelGray400),
return Padding(
padding: EdgeInsets.symmetric(vertical: responsiveUtils.isMobile(context) ? 4 : 5.5),
child: Text(
'${prefixEmailAddress.asName(context)}:',
style: ThemeUtils.textStyleBodyBody1(
color: AppColor.steelGray400,
fontWeight: FontWeight.w400,
).copyWith(
fontSize: responsiveUtils.isMobile(context) ? 14 : 17,
height: 1,
letterSpacing: responsiveUtils.isMobile(context) ? -0.14 : -0.17
),
),
);
}
}
@@ -30,7 +30,10 @@ class ReceivedTimeBuilder extends StatelessWidget {
maxLines: 1,
overflow: CommonTextStyle.defaultTextOverFlow,
softWrap: CommonTextStyle.defaultSoftWrap,
style: ThemeUtils.textStyleBodyBody3(color: AppColor.steelGray400)
style: ThemeUtils.textStyleBodyBody3(color: AppColor.steelGray400).copyWith(
height: 1,
letterSpacing: -0.14
),
),
);
}