TF-2907 Hide widget when corresponding event attribute is null

This commit is contained in:
dab246
2024-06-09 00:25:44 +07:00
committed by Dat H. Pham
parent 3aabee59da
commit 3d2ef50a00
7 changed files with 157 additions and 127 deletions
@@ -362,7 +362,10 @@ class EmailView extends GetWidget<SingleEmailController> {
presentationEmail: controller.currentEmail,
onMailtoAttendeesAction: controller.handleMailToAttendees,
)),
if (calendarEvent.getTitleEventAction(context, emailAddressSender ?? []).isNotEmpty)
if (_validateDisplayEventActionBanner(
context: context,
event: calendarEvent,
emailAddressSender: emailAddressSender ?? []))
CalendarEventActionBannerWidget(
calendarEvent: calendarEvent,
listEmailAddressSender: emailAddressSender ?? []
@@ -472,6 +475,20 @@ class EmailView extends GetWidget<SingleEmailController> {
);
}
bool _validateDisplayEventActionBanner({
required BuildContext context,
required CalendarEvent event,
required List<String> emailAddressSender
}) {
final usernameEvent = event.getUserNameEventAction(
context: context,
imagePaths: controller.imagePaths,
listEmailAddressSender: emailAddressSender);
final titleEvent = event.getTitleEventAction(context, emailAddressSender);
return usernameEvent.isNotEmpty && titleEvent.isNotEmpty;
}
void _handleMoreEmailAction({
required BuildContext context,
required PresentationEmail presentationEmail,
@@ -110,7 +110,7 @@ extension CalendarEventExtension on CalendarEvent {
case EventMethod.refresh:
case EventMethod.cancel:
case EventMethod.declineCounter:
return getOrganizerNameEvent(context);
return organizerName;
case EventMethod.reply:
case EventMethod.counter:
return getAttendeeNameEvent(context, listEmailAddressSender);
@@ -119,8 +119,6 @@ extension CalendarEventExtension on CalendarEvent {
}
}
String getOrganizerNameEvent(BuildContext context) => organizer?.name ?? AppLocalizations.of(context).you;
String get organizerName => organizer?.name ?? organizer?.mailto?.value ?? '';
String getAttendeeNameEvent(BuildContext context, List<String> listEmailAddressSender) {
@@ -11,9 +11,12 @@ extension ListAttendeeExtension on List<CalendarAttendee> {
.join(', ');
}
List<CalendarAttendee> withoutOrganizer(CalendarOrganizer organizer) {
return where((attendee) => attendee.mailto?.mailAddress != organizer.mailto)
.whereNotNull()
.toList();
List<CalendarAttendee> withoutOrganizer(CalendarOrganizer? organizer) {
if (organizer == null) {
return this;
}
return where((attendee) => attendee.mailto?.mailAddress != organizer.mailto)
.whereNotNull()
.toList();
}
}
@@ -72,12 +72,13 @@ class CalendarEventDetailWidget extends StatelessWidget {
children: [
if (calendarEvent.title?.isNotEmpty == true)
EventTitleWidget(title: calendarEvent.title!),
Padding(
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
child: EventBodyContentWidget(
content: eventDesc,
isDraggableAppActive: isDraggableAppActive,
onMailtoDelegateAction: onMailtoDelegateAction)),
if (eventDesc.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
child: EventBodyContentWidget(
content: eventDesc,
isDraggableAppActive: isDraggableAppActive,
onMailtoDelegateAction: onMailtoDelegateAction)),
_buildEventTimeWidget(),
if (calendarEvent.videoConferences.isNotEmpty)
Padding(
@@ -93,12 +94,12 @@ class CalendarEventDetailWidget extends StatelessWidget {
onOpenNewTabAction: onOpenNewTabAction,
),
),
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
if (calendarEvent.participants?.isNotEmpty == true || calendarEvent.organizer != null)
Padding(
padding: const EdgeInsets.only(top: CalendarEventDetailWidgetStyles.fieldTopPadding),
child: EventAttendeeDetailWidget(
attendees: calendarEvent.participants!,
organizer: calendarEvent.organizer!,
attendees: calendarEvent.participants ?? [],
organizer: calendarEvent.organizer,
),
),
if (calendarEvent.isDisplayedEventReplyAction)
@@ -79,27 +79,30 @@ class CalendarEventInformationWidget extends StatelessWidget {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
style: const TextStyle(
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w500,
color: CalendarEventInformationWidgetStyles.invitationMessageColor
),
children: [
if (calendarEvent.organizerName.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: CalendarEventInformationWidgetStyles.space),
child: Text.rich(
TextSpan(
text: calendarEvent.organizerName,
style: const TextStyle(
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w700
fontWeight: FontWeight.w500,
color: CalendarEventInformationWidgetStyles.invitationMessageColor
),
),
TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation)
]
)
),
const SizedBox(height: CalendarEventInformationWidgetStyles.space),
children: [
TextSpan(
text: calendarEvent.organizerName,
style: const TextStyle(
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w700
),
),
TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation)
]
)
),
),
if (calendarEvent.title?.isNotEmpty == true)
EventTitleWidget(title: calendarEvent.title!),
_buildEventTimeInformationWidget(),
@@ -112,12 +115,12 @@ class CalendarEventInformationWidget extends StatelessWidget {
onOpenNewTabAction: onOpenNewTabAction,
),
),
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
if (calendarEvent.participants?.isNotEmpty == true || calendarEvent.organizer != null)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
child: EventAttendeeInformationWidget(
attendees: calendarEvent.participants!,
organizer: calendarEvent.organizer!,
attendees: calendarEvent.participants ?? [],
organizer: calendarEvent.organizer,
),
),
if (calendarEvent.isDisplayedEventReplyAction)
@@ -136,81 +139,82 @@ class CalendarEventInformationWidget extends StatelessWidget {
)
],
)
: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CalendarDateIconWidget(calendarEvent: calendarEvent),
Expanded(child: Container(
clipBehavior: Clip.antiAlias,
decoration: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius),
bottomRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius)
)
),
color: Colors.white
),
padding: const EdgeInsets.all(CalendarEventInformationWidgetStyles.calendarInformationMargin),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text.rich(
TextSpan(
style: const TextStyle(
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w500,
color: CalendarEventInformationWidgetStyles.invitationMessageColor
),
children: [
TextSpan(
text: calendarEvent.organizerName,
style: const TextStyle(
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w700
),
),
TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation)
]
: IntrinsicHeight(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CalendarDateIconWidget(calendarEvent: calendarEvent),
Expanded(child: Container(
clipBehavior: Clip.antiAlias,
decoration: const ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius),
bottomRight: Radius.circular(CalendarEventInformationWidgetStyles.borderRadius)
)
),
const SizedBox(height: CalendarEventInformationWidgetStyles.space),
if (calendarEvent.title?.isNotEmpty == true)
EventTitleWidget(title: calendarEvent.title!),
_buildEventTimeInformationWidget(),
if (calendarEvent.location?.isNotEmpty == true)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
child: EventLocationInformationWidget(
locationEvent: calendarEvent.location!,
onOpenComposerAction: onOpenComposerAction,
onOpenNewTabAction: onOpenNewTabAction,
color: Colors.white
),
padding: const EdgeInsets.all(CalendarEventInformationWidgetStyles.calendarInformationMargin),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (calendarEvent.organizerName.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: CalendarEventInformationWidgetStyles.space),
child: Text.rich(
TextSpan(
style: const TextStyle(
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w500,
color: CalendarEventInformationWidgetStyles.invitationMessageColor
),
children: [
TextSpan(
text: calendarEvent.organizerName,
style: const TextStyle(
color: CalendarEventInformationWidgetStyles.invitationMessageColor,
fontSize: CalendarEventInformationWidgetStyles.invitationMessageTextSize,
fontWeight: FontWeight.w700
),
),
TextSpan(text: AppLocalizations.of(context).invitationMessageCalendarInformation)
]
)
),
),
),
if (calendarEvent.participants?.isNotEmpty == true && calendarEvent.organizer != null)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
child: EventAttendeeInformationWidget(
attendees: calendarEvent.participants!,
organizer: calendarEvent.organizer!,
if (calendarEvent.title?.isNotEmpty == true)
EventTitleWidget(title: calendarEvent.title!),
_buildEventTimeInformationWidget(),
if (calendarEvent.location?.isNotEmpty == true)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
child: EventLocationInformationWidget(
locationEvent: calendarEvent.location!,
onOpenComposerAction: onOpenComposerAction,
onOpenNewTabAction: onOpenNewTabAction,
),
),
),
if (calendarEvent.isDisplayedEventReplyAction)
CalendarEventActionButtonWidget(
margin: EdgeInsetsDirectional.zero,
onCalendarEventReplyActionClick: onCalendarEventReplyActionClick,
calendarEventReplying: calendarEventReplying,
presentationEmail: presentationEmail,
onMailToAttendeesAction: () => onMailtoAttendeesAction?.call(
calendarEvent.organizer,
calendarEvent.participants,
if (calendarEvent.participants?.isNotEmpty == true || calendarEvent.organizer != null)
Padding(
padding: const EdgeInsets.only(top: CalendarEventInformationWidgetStyles.fieldTopPadding),
child: EventAttendeeInformationWidget(
attendees: calendarEvent.participants ?? [],
organizer: calendarEvent.organizer,
),
),
),
],
),
))
],
if (calendarEvent.isDisplayedEventReplyAction)
CalendarEventActionButtonWidget(
margin: EdgeInsetsDirectional.zero,
onCalendarEventReplyActionClick: onCalendarEventReplyActionClick,
calendarEventReplying: calendarEventReplying,
presentationEmail: presentationEmail,
),
],
),
))
],
),
),
);
}
@@ -15,7 +15,7 @@ class EventAttendeeDetailWidget extends StatefulWidget {
static const int maxAttendeeDisplayed = 6;
final List<CalendarAttendee> attendees;
final CalendarOrganizer organizer;
final CalendarOrganizer? organizer;
const EventAttendeeDetailWidget({
super.key,
@@ -59,10 +59,12 @@ class _EventAttendeeDetailWidgetState extends State<EventAttendeeDetailWidget> {
Expanded(child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
OrganizerWidget(organizer: widget.organizer),
..._attendeesDisplayed
.map((attendee) => AttendeeWidget(attendee: attendee, listAttendees: _attendeesDisplayed))
.toList(),
if (widget.organizer != null)
OrganizerWidget(organizer: widget.organizer!),
if (_attendeesDisplayed.isNotEmpty)
..._attendeesDisplayed
.map((attendee) => AttendeeWidget(attendee: attendee, listAttendees: _attendeesDisplayed))
.toList(),
if (!_isShowAllAttendee)
Padding(
padding: const EdgeInsets.only(top: EventAttendeeDetailWidgetStyles.fieldTopPadding),
@@ -11,9 +11,11 @@ import 'package:tmail_ui_user/main/localizations/app_localizations.dart';
class EventAttendeeInformationWidget extends StatelessWidget {
final List<CalendarAttendee> attendees;
final CalendarOrganizer organizer;
final CalendarOrganizer? organizer;
const EventAttendeeInformationWidget({
final _responsiveUtils = Get.find<ResponsiveUtils>();
EventAttendeeInformationWidget({
super.key,
required this.attendees,
required this.organizer
@@ -21,7 +23,6 @@ class EventAttendeeInformationWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
final responsiveUtils = Get.find<ResponsiveUtils>();
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -44,22 +45,26 @@ class EventAttendeeInformationWidget extends StatelessWidget {
color: EventAttendeeInformationWidgetStyles.valueColor
),
children: [
TextSpan(
text: '${organizer.mailto?.value} (${AppLocalizations.of(context).organizer})',
style: const TextStyle(
color: EventAttendeeInformationWidgetStyles.valueOrganizerColor,
fontSize: EventAttendeeInformationWidgetStyles.textSize,
fontWeight: FontWeight.w500
),
),
const TextSpan(text: ', '),
TextSpan(text: attendees.withoutOrganizer(organizer).mailtoAsString)
if (organizer != null)
...[
TextSpan(
text: '${organizer!.mailto?.value} (${AppLocalizations.of(context).organizer})',
style: const TextStyle(
color: EventAttendeeInformationWidgetStyles.valueOrganizerColor,
fontSize: EventAttendeeInformationWidgetStyles.textSize,
fontWeight: FontWeight.w500
),
),
const TextSpan(text: ', '),
],
if (attendees.isNotEmpty)
TextSpan(text: attendees.withoutOrganizer(organizer).mailtoAsString)
]
),
overflow: responsiveUtils.isPortraitMobile(context)
overflow: _responsiveUtils.isPortraitMobile(context)
? TextOverflow.clip
: TextOverflow.ellipsis,
maxLines: responsiveUtils.isPortraitMobile(context) ? null : 2,
maxLines: _responsiveUtils.isPortraitMobile(context) ? null : 2,
))
],
);