Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search improvement sprint 28 #3197

Merged
merged 30 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
beea96b
TF-3002 [WEB] Apply new design for SearchFilterButton
dab246 Sep 16, 2024
ba23141
TF-3002 [WEB] Add `To/Folder` search filters
dab246 Sep 12, 2024
d920a18
TF-3002 [WEB] Add delete button in search filters
dab246 Sep 12, 2024
c11bbe9
TF-3002 [WEB] Add `Advanced Search` & `Clear filter` button in search…
dab246 Sep 13, 2024
3afae3e
TF-3002 [WEB] Add `Starred` search filters in suggestion search view
dab246 Sep 13, 2024
0411947
TF-3002 [WEB] Update unselected icon color for filter message button
dab246 Sep 13, 2024
fcb7661
TF-3002 [WEB] Hide `Select all message this page` when current list e…
dab246 Sep 13, 2024
ef270ad
TF-3002 [WEB] Add left padding for `All mailbox` in destination picke…
dab246 Sep 13, 2024
06aa3e3
TF-3002 [WEB] Remove `BuildContext` in dashboard action
dab246 Sep 16, 2024
0408a5a
TF-3002 [WEB] Allow select `All folder` from destination picker when …
dab246 Oct 1, 2024
151fe26
TF-3002 [MOBILE] Combine `SimpleSearchFilter` & `SearchEmailFilter`
dab246 Sep 13, 2024
45dee0d
TF-3002 [MOBILE] Apply new design for SearchFilterButton
dab246 Sep 13, 2024
501e59b
TF-3002 [MOBILE] Add delete button in search filters
dab246 Sep 13, 2024
e77f12a
TF-3002 [MOBILE] Handle select & delete `Starred` search filters in s…
dab246 Sep 13, 2024
b7f58fe
TF-3002 [MOBILE] Add `Clear filter` button in search filters
dab246 Sep 13, 2024
a03c92e
TF-3002 [MOBILE] Search filter only apply this contact in `From` when…
dab246 Oct 3, 2024
ce8e340
TF-3002 [MOBILE] Allow search when empty string query in search input
dab246 Oct 3, 2024
e790240
TF-3002 [MOBILE] Fix `no result` screen still show during search is i…
dab246 Oct 3, 2024
3f80d69
TF-3002 Write test to ensure search filter send to interactor is exac…
dab246 Oct 3, 2024
59a0551
TF-3006 [WEB] Handle mail address in quick search bar
dab246 Sep 17, 2024
2bb8070
TF-3006 [MOBILE] Handle mail address in quick search bar
dab246 Sep 17, 2024
e37b917
TF-3006 Add ADR for logic SortOrder in search
dab246 Oct 7, 2024
db56dda
TF-3192 Update highlight style as design
dab246 Oct 7, 2024
b510278
TF-3007 [SEARCH] Support drag and drop between From & To field (#3154)
dab246 Oct 8, 2024
49fae17
TF-3005 Apply new design app bar contact view
dab246 Sep 17, 2024
e53b49f
TF-3005 Apply new design search input contact view
dab246 Sep 17, 2024
3c66b25
TF-3005 Apply new design search result list contact view
dab246 Oct 8, 2024
f54c612
TF-3004 Fix open close advanced search looses data
dab246 Oct 9, 2024
2e0026b
TF-3025 Avoid search results being reloaded when performing certain a…
dab246 Oct 1, 2024
c549397
TF-3025 Correctly update the action for the selection list when perfo…
dab246 Oct 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions assets/images/ic_delete_selection.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 10 additions & 1 deletion core/lib/presentation/extensions/color_extension.dart
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ extension AppColor on Color {
static const buttonActionToastWithActionColor = Color(0xFF7ADCF8);
static const backgroundCountAttachment = Color(0x681C1C1C);
static const bgStatusResultSearch = Color(0xFFF5F5F7);
static const bgWordSearch = Color(0x3D007AFF);
static const colorNameEmail = Color(0xFF000000);
static const colorContentEmail = Color(0xFF6D7885);
static const colorTextButton = Color(0xFF007AFF);
Expand Down Expand Up @@ -225,6 +224,16 @@ extension AppColor on Color {
static const loginViewShadowColor = Color(0x3DBCBCBC);
static const colorEmailTileCheckboxUnhover = Color(0xFFAEB7C2);
static const colorEmailTileHoverWeb = Color(0xFFDFEEFF);
static const colorSearchFilterButton = Color(0xFFECEEF1);
static const colorSearchFilterTitle = Color(0xFF686E76);
static const colorSearchFilterIcon = Color(0xFF686E76);
static const colorSuggestionSearchFilterButton = Color(0xFFEBEDF0);
static const colorFilterMessageButton = Color(0xFFEBEDF0);
static const colorFilterMessageIcon = Color(0xFF686E76);
static const colorFilterMessageTitle = Color(0xFF686E76);
static const colorStarredSearchFilterIcon = Color(0xFFFFCC00);
static const colorMobileSearchFilterButton = Color(0xFFEBEDF0);
static const colorContactViewClearFilterButton = Color(0x001C3D0D);

static const mapGradientColor = [
[Color(0xFF21D4FD), Color(0xFFB721FF)],
Expand Down
1 change: 1 addition & 0 deletions core/lib/presentation/resources/image_paths.dart
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ class ImagePaths {
String get icCheckboxSelected => _getImagePath('ic_checkbox_selected.svg');
String get icGoodSignature => _getImagePath('ic_good_signature.svg');
String get icBadSignature => _getImagePath('ic_bad_signature.svg');
String get icDeleteSelection => _getImagePath('ic_delete_selection.svg');

String _getImagePath(String imageName) {
return AssetsPaths.images + imageName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ typedef ItemBuilder<T> = Widget Function(BuildContext context, T itemData);
typedef SuggestionSelectionCallback<T> = void Function(T suggestion);
typedef RecentSelectionCallback<R> = void Function(R recent);
typedef ErrorBuilder = Widget Function(BuildContext context, Object? error);
typedef ButtonActionBuilder = Widget Function(BuildContext context, dynamic action);
typedef ButtonActionBuilder = Widget Function(
BuildContext context,
dynamic action,
SuggestionsListState suggestionsListState);
typedef ButtonActionCallback = void Function(dynamic action);

typedef AnimationTransitionBuilder = Widget Function(
Expand Down Expand Up @@ -315,8 +318,8 @@ class TypeAheadFieldQuickSearch<T, P, R> extends StatefulWidget {

final QuickSearchSuggestionsBoxDecoration suggestionsBoxDecoration;

/// Used to control the `_SuggestionsBox`. Allows manual control to
/// open, close, toggle, or resize the `_SuggestionsBox`.
/// Used to control the `SuggestionsBox`. Allows manual control to
/// open, close, toggle, or resize the `SuggestionsBox`.
final QuickSearchSuggestionsBoxController? suggestionsBoxController;

/// The duration to wait after the user stops typing before calling
Expand Down Expand Up @@ -590,7 +593,7 @@ class _TypeAheadFieldQuickSearchState<T, P, R> extends State<TypeAheadFieldQuick
with WidgetsBindingObserver {
FocusNode? _focusNode;
TextEditingController? _textEditingController;
_SuggestionsBox? _suggestionsBox;
SuggestionsBox? _suggestionsBox;
late TextDirection _textDirection;

TextEditingController? get _effectiveController =>
Expand Down Expand Up @@ -648,7 +651,7 @@ class _TypeAheadFieldQuickSearchState<T, P, R> extends State<TypeAheadFieldQuick
_focusNode = FocusNode();
}

_suggestionsBox = _SuggestionsBox(
_suggestionsBox = SuggestionsBox(
context,
widget.direction,
widget.autoFlipDirection,
Expand Down Expand Up @@ -721,7 +724,7 @@ class _TypeAheadFieldQuickSearchState<T, P, R> extends State<TypeAheadFieldQuick

void _initOverlayEntry() {
_suggestionsBox!._overlayEntry = OverlayEntry(builder: (context) {
final suggestionsList = _SuggestionsList<T, P, R>(
final suggestionsList = SuggestionsList<T, P, R>(
suggestionsBox: _suggestionsBox,
decoration: widget.suggestionsBoxDecoration,
debounceDuration: widget.debounceDuration,
Expand Down Expand Up @@ -905,8 +908,8 @@ class _TypeAheadFieldQuickSearchState<T, P, R> extends State<TypeAheadFieldQuick
}
}

class _SuggestionsList<T, P, R> extends StatefulWidget {
final _SuggestionsBox? suggestionsBox;
class SuggestionsList<T, P, R> extends StatefulWidget {
final SuggestionsBox? suggestionsBox;
final TextEditingController? controller;
final bool getImmediateSuggestions;
final SuggestionSelectionCallback<T>? onSuggestionSelected;
Expand Down Expand Up @@ -942,7 +945,8 @@ class _SuggestionsList<T, P, R> extends StatefulWidget {
final SuggestionsCallback<P>? contactSuggestionCallback;
final SuggestionSelectionCallback<P>? onContactSuggestionSelected;

const _SuggestionsList({
const SuggestionsList({
super.key,
required this.suggestionsBox,
this.controller,
this.getImmediateSuggestions = false,
Expand Down Expand Up @@ -981,10 +985,10 @@ class _SuggestionsList<T, P, R> extends StatefulWidget {
});

@override
_SuggestionsListState<T, P, R> createState() => _SuggestionsListState<T, P, R>();
SuggestionsListState<T, P, R> createState() => SuggestionsListState<T, P, R>();
}

class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
class SuggestionsListState<T, P, R> extends State<SuggestionsList<T, P, R>>
with SingleTickerProviderStateMixin {
Iterable<T>? _suggestions;
Iterable<R>? _recentItems;
Expand All @@ -998,7 +1002,7 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
late final ScrollController _scrollController =
widget.scrollController ?? ScrollController();

_SuggestionsListState() {
SuggestionsListState() {
_controllerListener = () async {
// If we came here because of a change in selected text, not because of
// actual change in text
Expand All @@ -1015,7 +1019,7 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
recentItems = await widget.fetchRecentActionCallback!(widget.controller!.text);
}
} catch (e) {
logError('_SuggestionsListState::_SuggestionsListState(): $e');
logError('SuggestionsListState::SuggestionsListState(): $e');
}

setState(() {
Expand Down Expand Up @@ -1046,7 +1050,7 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
}

@override
void didUpdateWidget(_SuggestionsList<T, P, R> oldWidget) {
void didUpdateWidget(SuggestionsList<T, P, R> oldWidget) {
super.didUpdateWidget(oldWidget);
widget.controller!.addListener(_controllerListener);
_getSuggestions();
Expand Down Expand Up @@ -1215,7 +1219,7 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
if (listActionWidget != null) listActionWidget,
if (loadingWidget != null) loadingWidget,
if (widget.buttonShowAllResult != null && widget.controller?.text.isNotEmpty == true)
widget.buttonShowAllResult!(context, widget.controller?.text),
widget.buttonShowAllResult!(context, widget.controller?.text, this),
if (listItemContactWidget.isNotEmpty)
... listItemContactWidget,
if (listItemContactWidget.isNotEmpty && listItemSuggestionWidget.isNotEmpty)
Expand Down Expand Up @@ -1253,7 +1257,7 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
if (listActionWidget != null) listActionWidget,
if (loadingWidget != null) loadingWidget,
if (widget.buttonShowAllResult != null && widget.controller?.text.isNotEmpty == true)
widget.buttonShowAllResult!(context, widget.controller?.text),
widget.buttonShowAllResult!(context, widget.controller?.text, this),
if (_recentItems?.isNotEmpty == true && widget.itemRecentBuilder != null && widget.titleHeaderRecent != null)
widget.titleHeaderRecent!,
if (listItemRecent.isNotEmpty)
Expand Down Expand Up @@ -1286,19 +1290,22 @@ class _SuggestionsListState<T, P, R> extends State<_SuggestionsList<T, P, R>>
if (widget.buttonActionCallback != null) {
return Padding(
padding: const EdgeInsetsDirectional.only(end: 8, bottom: 8),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(10)),
onTap: () {
widget.buttonActionCallback?.call(action);
invalidateSuggestions();
},
child: widget.actionButtonBuilder!(context, action),
child: Material(
type: MaterialType.transparency,
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(10)),
onTap: () {
widget.buttonActionCallback?.call(action);
invalidateSuggestions();
},
child: widget.actionButtonBuilder!(context, action, this),
),
),
);
} else {
return Padding(
padding: const EdgeInsetsDirectional.only(end: 8, bottom: 8),
child: widget.actionButtonBuilder!(context, action)
child: widget.actionButtonBuilder!(context, action, this)
);
}
})
Expand Down Expand Up @@ -1729,7 +1736,7 @@ class QuickSearchTextFieldConfiguration {
}
}

class _SuggestionsBox {
class SuggestionsBox {
static const int waitMetricsTimeoutMillis = 1000;
static const double minOverlaySpace = 64.0;

Expand All @@ -1748,7 +1755,7 @@ class _SuggestionsBox {
double textBoxHeight = 100.0;
late double directionUpOffset;

_SuggestionsBox(
SuggestionsBox(
this.context,
this.direction,
this.autoFlipDirection,
Expand Down Expand Up @@ -1947,7 +1954,7 @@ class _SuggestionsBox {
/// Supply an instance of this class to the [TypeAhead.suggestionsBoxController]
/// property to manually control the suggestions box
class QuickSearchSuggestionsBoxController {
_SuggestionsBox? _suggestionsBox;
SuggestionsBox? _suggestionsBox;
FocusNode? _effectiveFocusNode;

/// Opens the suggestions box
Expand Down
Loading
Loading