Skip to content

Commit 6b93036

Browse files
committed
TF-4066 Add Unread, Starred checkbox in advanced search form view
1 parent 246a1e7 commit 6b93036

File tree

5 files changed

+105
-10
lines changed

5 files changed

+105
-10
lines changed

core/lib/presentation/views/checkbox/labeled_checkbox.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class LabeledCheckbox extends StatelessWidget {
3030
children: <Widget>[
3131
buildCheckboxWidget,
3232
buildGapWidget,
33-
buildLabelWidget,
33+
Flexible(child: buildLabelWidget),
3434
],
3535
),
3636
);
@@ -53,5 +53,7 @@ class LabeledCheckbox extends StatelessWidget {
5353
Widget get buildLabelWidget => Text(
5454
label,
5555
style: textStyle ?? ThemeUtils.textStyleM3BodyMedium3,
56+
maxLines: 1,
57+
overflow: TextOverflow.ellipsis,
5658
);
5759
}

lib/features/mailbox_dashboard/presentation/controller/advanced_filter_controller.dart

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
44
import 'package:get/get.dart';
55
import 'package:jmap_dart_client/jmap/core/utc_date.dart';
66
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
7+
import 'package:jmap_dart_client/jmap/mail/email/keyword_identifier.dart';
78
import 'package:model/model.dart';
89
import 'package:super_tag_editor/tag_editor.dart';
910
import 'package:tmail_ui_user/features/base/base_controller.dart';
@@ -33,6 +34,8 @@ class AdvancedFilterController extends BaseController {
3334

3435
final receiveTimeType = EmailReceiveTimeType.allTime.obs;
3536
final hasAttachment = false.obs;
37+
final isStarred = false.obs;
38+
final isUnread = false.obs;
3639
final startDate = Rxn<DateTime>();
3740
final endDate = Rxn<DateTime>();
3841
final sortOrderType = SearchEmailFilter.defaultSortOrder.obs;
@@ -115,6 +118,7 @@ class AdvancedFilterController extends BaseController {
115118
Option<Set<String>>? toOption,
116119
Option<SearchQuery>? textOption,
117120
Option<String>? subjectOption,
121+
Option<Set<String>>? hasKeywordOption,
118122
Option<Set<String>>? notKeywordOption,
119123
Option<PresentationMailbox>? mailboxOption,
120124
Option<EmailReceiveTimeType>? emailReceiveTimeTypeOption,
@@ -131,6 +135,7 @@ class AdvancedFilterController extends BaseController {
131135
toOption: toOption,
132136
textOption: textOption,
133137
subjectOption: subjectOption,
138+
hasKeywordOption: hasKeywordOption,
134139
notKeywordOption: notKeywordOption,
135140
mailboxOption: mailboxOption,
136141
emailReceiveTimeTypeOption: emailReceiveTimeTypeOption,
@@ -176,6 +181,13 @@ class AdvancedFilterController extends BaseController {
176181

177182
final endDateOption = optionOf(endDate.value?.toUTCDate());
178183

184+
final unreadOption = Some(isUnread.value);
185+
186+
final hasKeywordOption = option(
187+
isStarred.isTrue,
188+
{KeyWordIdentifier.emailFlagged.value},
189+
);
190+
179191
_updateMemorySearchFilter(
180192
textOption: textOption,
181193
notKeywordOption: notKeywordsOption,
@@ -186,6 +198,8 @@ class AdvancedFilterController extends BaseController {
186198
subjectOption: subjectOption,
187199
emailReceiveTimeTypeOption: emailReceiveTimeTypeOption,
188200
hasAttachmentOption: hasAttachmentOption,
201+
unreadOption: unreadOption,
202+
hasKeywordOption: hasKeywordOption,
189203
startDateOption: startDateOption,
190204
endDateOption: endDateOption
191205
);
@@ -269,6 +283,11 @@ class AdvancedFilterController extends BaseController {
269283

270284
hasAttachment.value = _memorySearchFilter.hasAttachment;
271285

286+
isUnread.value = _memorySearchFilter.unread;
287+
288+
isStarred.value = _memorySearchFilter.hasKeyword
289+
.contains(KeyWordIdentifier.emailFlagged.value);
290+
272291
if (_memorySearchFilter.from.isEmpty) {
273292
listFromEmailAddress.clear();
274293
} else {
@@ -455,6 +474,8 @@ class AdvancedFilterController extends BaseController {
455474
endDate.value = null;
456475
receiveTimeType.value = EmailReceiveTimeType.allTime;
457476
hasAttachment.value = false;
477+
isUnread.value = false;
478+
isStarred.value = false;
458479
selectedFolderName.value = null;
459480
listFromEmailAddress.clear();
460481
listToEmailAddress.clear();
@@ -534,6 +555,26 @@ class AdvancedFilterController extends BaseController {
534555
_updateMemorySearchFilter(hasAttachmentOption: Some(hasAttachment.value));
535556
}
536557

558+
void onStarredCheckboxChanged(bool? isChecked) {
559+
isStarred.value = isChecked ?? false;
560+
final listHasKeywordFiltered = _memorySearchFilter.hasKeyword;
561+
if (isStarred.isTrue) {
562+
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
563+
} else {
564+
listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value);
565+
}
566+
_updateMemorySearchFilter(
567+
hasKeywordOption: Some(listHasKeywordFiltered),
568+
);
569+
}
570+
571+
void onUnreadCheckboxChanged(bool? isChecked) {
572+
isUnread.value = isChecked ?? false;
573+
_updateMemorySearchFilter(
574+
unreadOption: isStarred.isTrue ? const Some(true) : const None(),
575+
);
576+
}
577+
537578
void onTextChanged(FilterField filterField, String value) {
538579
switch (filterField) {
539580
case FilterField.subject:

lib/features/mailbox_dashboard/presentation/controller/input_field_focus_manager.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class InputFieldFocusManager {
1010
late FocusNode notKeywordFieldFocusNode;
1111
late FocusNode mailboxFieldFocusNode;
1212
late FocusNode attachmentCheckboxFocusNode;
13+
late FocusNode starredCheckboxFocusNode;
14+
late FocusNode unreadCheckboxFocusNode;
1315

1416
InputFieldFocusManager() {
1517
fromFieldFocusNode = FocusNode();
@@ -19,6 +21,8 @@ class InputFieldFocusManager {
1921
notKeywordFieldFocusNode = FocusNode();
2022
mailboxFieldFocusNode = FocusNode();
2123
attachmentCheckboxFocusNode = FocusNode();
24+
starredCheckboxFocusNode = FocusNode();
25+
unreadCheckboxFocusNode = FocusNode();
2226
}
2327

2428
factory InputFieldFocusManager.initial() {
@@ -33,5 +37,7 @@ class InputFieldFocusManager {
3337
notKeywordFieldFocusNode.dispose();
3438
mailboxFieldFocusNode.dispose();
3539
attachmentCheckboxFocusNode.dispose();
40+
starredCheckboxFocusNode.dispose();
41+
unreadCheckboxFocusNode.dispose();
3642
}
3743
}

lib/features/mailbox_dashboard/presentation/extensions/select_search_filter_action_extension.dart

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ import 'package:tmail_ui_user/features/mailbox_dashboard/presentation/controller
66
extension SelectSearchFilterActionExtension on MailboxDashBoardController {
77
void selectStarredSearchFilter() {
88
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
9-
if (!listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) {
10-
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
11-
}
9+
listHasKeywordFiltered.add(KeyWordIdentifier.emailFlagged.value);
1210
searchController.updateFilterEmail(
1311
hasKeywordOption: Some(listHasKeywordFiltered),
1412
);
@@ -22,9 +20,7 @@ extension SelectSearchFilterActionExtension on MailboxDashBoardController {
2220

2321
void deleteStarredSearchFilter() {
2422
final listHasKeywordFiltered = searchController.listHasKeywordFiltered;
25-
if (listHasKeywordFiltered.contains(KeyWordIdentifier.emailFlagged.value)) {
26-
listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value);
27-
}
23+
listHasKeywordFiltered.remove(KeyWordIdentifier.emailFlagged.value);
2824
searchController.updateFilterEmail(
2925
hasKeywordOption: Some(listHasKeywordFiltered),
3026
);

lib/features/mailbox_dashboard/presentation/widgets/advanced_search/advanced_search_filter_form_bottom_view.dart

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,25 @@ class AdvancedSearchFilterFormBottomView extends GetWidget<AdvancedFilterControl
2323
return Column(
2424
crossAxisAlignment: CrossAxisAlignment.start,
2525
children: [
26-
_buildCheckboxHasAttachment(
27-
context,
28-
focusManager.attachmentCheckboxFocusNode,
26+
Wrap(
27+
runSpacing: 12,
28+
spacing: 24,
29+
children: [
30+
_buildCheckboxHasAttachment(
31+
context,
32+
focusManager.attachmentCheckboxFocusNode,
33+
),
34+
_buildCheckboxUnread(
35+
context,
36+
focusManager.unreadCheckboxFocusNode,
37+
),
38+
_buildCheckboxStarred(
39+
context,
40+
focusManager.starredCheckboxFocusNode,
41+
),
42+
],
2943
),
44+
const SizedBox(height: 25),
3045
_buildListButton(context),
3146
],
3247
);
@@ -82,12 +97,47 @@ class AdvancedSearchFilterFormBottomView extends GetWidget<AdvancedFilterControl
8297
svgIconPath: controller.imagePaths.icCheckboxUnselected,
8398
selectedSvgIconPath: controller.imagePaths.icCheckboxSelected,
8499
focusNode: currentFocusNode,
100+
gap: 8.0,
85101
value: controller.hasAttachment.value,
86102
onChanged: controller.onHasAttachmentCheckboxChanged,
87103
),
88104
);
89105
}
90106

107+
Widget _buildCheckboxStarred(
108+
BuildContext context,
109+
FocusNode currentFocusNode,
110+
) {
111+
return Obx(
112+
() => CustomIconLabeledCheckbox(
113+
label: AppLocalizations.of(context).starred,
114+
svgIconPath: controller.imagePaths.icCheckboxUnselected,
115+
selectedSvgIconPath: controller.imagePaths.icCheckboxSelected,
116+
focusNode: currentFocusNode,
117+
gap: 8.0,
118+
value: controller.isStarred.value,
119+
onChanged: controller.onStarredCheckboxChanged,
120+
),
121+
);
122+
}
123+
124+
Widget _buildCheckboxUnread(
125+
BuildContext context,
126+
FocusNode currentFocusNode,
127+
) {
128+
return Obx(
129+
() => CustomIconLabeledCheckbox(
130+
label: AppLocalizations.of(context).unread,
131+
svgIconPath: controller.imagePaths.icCheckboxUnselected,
132+
selectedSvgIconPath: controller.imagePaths.icCheckboxSelected,
133+
focusNode: currentFocusNode,
134+
gap: 8.0,
135+
value: controller.isUnread.value,
136+
onChanged: controller.onUnreadCheckboxChanged,
137+
),
138+
);
139+
}
140+
91141
void _onClickCancelButton() {
92142
controller.clearSearchFilter();
93143
popBack();

0 commit comments

Comments
 (0)