,
}}
@@ -723,6 +749,32 @@ export function CallsList({
);
}
+ if (item === 'FilterHeader') {
+ return (
+
+ {i18n('icu:CallsList__FilteredByMissedHeader')}
+
+ );
+ }
+
+ if (item === 'ClearFilterButton') {
+ return (
+
+
+
+ );
+ }
+
const conversation = getConversationForItem(item);
const activeCallConversationId = activeCall?.conversationId;
@@ -918,6 +970,8 @@ export function CallsList({
getIsAnybodyInCall,
getIsCallActive,
getIsInCall,
+ hasMissedCallFilter,
+ hasSearchStateQuery,
selectedCallHistoryGroup,
onChangeCallsTabSelectedView,
onCreateCallLink,
@@ -927,6 +981,7 @@ export function CallsList({
toggleConfirmLeaveCallModal,
togglePip,
i18n,
+ isEmpty,
]
);
@@ -957,20 +1012,14 @@ export function CallsList({
subtitle={i18n('icu:CallsList__EmptyState--noQuery__subtitle')}
/>
)}
- {isEmpty &&
- statusInput === CallHistoryFilterStatus.Missed &&
- !hasSearchStateQuery && (
-
- )}
+
)}
-
+ >
);
}
diff --git a/ts/components/StoriesSettingsModal.tsx b/ts/components/StoriesSettingsModal.tsx
index e46e70f27..20dfcd326 100644
--- a/ts/components/StoriesSettingsModal.tsx
+++ b/ts/components/StoriesSettingsModal.tsx
@@ -1217,6 +1217,7 @@ export function EditDistributionListModal({
i18n={i18n}
lookupConversationWithoutServiceId={asyncShouldNeverBeCalled}
onClickArchiveButton={shouldNeverBeCalled}
+ onClickClearFilterButton={shouldNeverBeCalled}
onClickContactCheckbox={(conversationId: string) => {
toggleSelectedConversation(conversationId);
}}
diff --git a/ts/components/leftPane/LeftPaneArchiveHelper.tsx b/ts/components/leftPane/LeftPaneArchiveHelper.tsx
index 2f4783c37..32e5e06b7 100644
--- a/ts/components/leftPane/LeftPaneArchiveHelper.tsx
+++ b/ts/components/leftPane/LeftPaneArchiveHelper.tsx
@@ -85,7 +85,7 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper unknown;
- clearSearch: () => unknown;
+ clearSearchQuery: () => unknown;
endConversationSearch: () => unknown;
endSearch: () => unknown;
i18n: LocalizerType;
@@ -107,7 +107,7 @@ export class LeftPaneArchiveHelper extends LeftPaneHelper {
getSearchInput(
_: Readonly<{
clearConversationSearch: () => unknown;
- clearSearch: () => unknown;
+ clearSearchQuery: () => unknown;
endConversationSearch: () => unknown;
endSearch: () => unknown;
i18n: LocalizerType;
@@ -50,6 +50,7 @@ export abstract class LeftPaneHelper {
updateSearchTerm: (searchTerm: string) => unknown;
showConversation: ShowConversationType;
showInbox: () => void;
+ updateFilterByUnread: (filterByUnread: boolean) => void;
}> &
LookupConversationWithoutServiceIdActionsType
): null | ReactChild {
@@ -78,7 +79,7 @@ export abstract class LeftPaneHelper {
_: Readonly<{
clearConversationSearch: () => unknown;
clearGroupCreationError: () => void;
- clearSearch: () => unknown;
+ clearSearchQuery: () => unknown;
closeMaximumGroupSizeModal: () => unknown;
closeRecommendedGroupSizeModal: () => unknown;
composeDeleteAvatarFromDisk: DeleteAvatarFromDiskActionType;
diff --git a/ts/components/leftPane/LeftPaneInboxHelper.tsx b/ts/components/leftPane/LeftPaneInboxHelper.tsx
index 90d182366..60f923042 100644
--- a/ts/components/leftPane/LeftPaneInboxHelper.tsx
+++ b/ts/components/leftPane/LeftPaneInboxHelper.tsx
@@ -30,6 +30,7 @@ export type LeftPaneInboxPropsType = {
searchDisabled: boolean;
searchTerm: string;
searchConversation: undefined | ConversationType;
+ filterByUnread: boolean;
};
export class LeftPaneInboxHelper extends LeftPaneHelper {
@@ -51,6 +52,8 @@ export class LeftPaneInboxHelper extends LeftPaneHelper
private readonly searchConversation: undefined | ConversationType;
+ private readonly filterByUnread: boolean;
+
constructor({
conversations,
archivedConversations,
@@ -61,6 +64,7 @@ export class LeftPaneInboxHelper extends LeftPaneHelper
searchDisabled,
searchTerm,
searchConversation,
+ filterByUnread,
}: Readonly) {
super();
@@ -73,6 +77,7 @@ export class LeftPaneInboxHelper extends LeftPaneHelper
this.searchDisabled = searchDisabled;
this.searchTerm = searchTerm;
this.searchConversation = searchConversation;
+ this.filterByUnread = filterByUnread;
}
getRowCount(): number {
@@ -88,25 +93,27 @@ export class LeftPaneInboxHelper extends LeftPaneHelper
override getSearchInput({
clearConversationSearch,
- clearSearch,
+ clearSearchQuery,
endConversationSearch,
endSearch,
i18n,
showConversation,
updateSearchTerm,
+ updateFilterByUnread,
}: Readonly<{
clearConversationSearch: () => unknown;
- clearSearch: () => unknown;
+ clearSearchQuery: () => unknown;
endConversationSearch: () => unknown;
endSearch: () => unknown;
i18n: LocalizerType;
showConversation: ShowConversationType;
updateSearchTerm: (searchTerm: string) => unknown;
+ updateFilterByUnread: (filterByUnread: boolean) => void;
}>): ReactChild {
return (
showConversation={showConversation}
startSearchCounter={this.startSearchCounter}
updateSearchTerm={updateSearchTerm}
+ onFilterClick={updateFilterByUnread}
+ filterButtonEnabled={!this.searchConversation}
+ filterPressed={this.filterByUnread}
/>
);
}
diff --git a/ts/components/leftPane/LeftPaneSearchHelper.tsx b/ts/components/leftPane/LeftPaneSearchHelper.tsx
index f30077019..b4fd1f85b 100644
--- a/ts/components/leftPane/LeftPaneSearchHelper.tsx
+++ b/ts/components/leftPane/LeftPaneSearchHelper.tsx
@@ -43,6 +43,7 @@ export type LeftPaneSearchPropsType = {
searchConversationName?: string;
primarySendsSms: boolean;
searchTerm: string;
+ filterByUnread: boolean;
startSearchCounter: number;
isSearchingGlobally: boolean;
searchDisabled: boolean;
@@ -78,6 +79,8 @@ export class LeftPaneSearchHelper extends LeftPaneHelper) {
super();
@@ -102,30 +106,33 @@ export class LeftPaneSearchHelper extends LeftPaneHelper unknown;
- clearSearch: () => unknown;
+ clearSearchQuery: () => unknown;
endConversationSearch: () => unknown;
endSearch: () => unknown;
i18n: LocalizerType;
showConversation: ShowConversationType;
updateSearchTerm: (searchTerm: string) => unknown;
+ updateFilterByUnread: (filterByUnread: boolean) => void;
}>): ReactChild {
return (
);
}
@@ -171,13 +181,29 @@ export class LeftPaneSearchHelper extends LeftPaneHelper
);
} else {
+ let noResultsMessage: string;
+ if (this.filterByUnread && this.searchTerm.length > 0) {
+ noResultsMessage = i18n('icu:noSearchResultsWithUnreadFilter', {
+ searchTerm,
+ });
+ } else if (this.filterByUnread) {
+ noResultsMessage = i18n('icu:noSearchResultsOnlyUnreadFilter');
+ } else {
+ noResultsMessage = i18n('icu:noSearchResults', {
+ searchTerm,
+ });
+ }
noResults = (
<>
-
- {i18n('icu:noSearchResults', {
- searchTerm,
- })}
-
+ {this.filterByUnread && (
+
+ {i18n('icu:conversationsUnreadHeader')}
+
+ )}
+ {noResultsMessage}
{primarySendsSms && (
{i18n('icu:noSearchResults--sms-only')}
@@ -191,7 +217,11 @@ export class LeftPaneSearchHelper extends LeftPaneHelper
{noResults}
@@ -205,11 +235,18 @@ export class LeftPaneSearchHelper extends LeftPaneHelper
result + getRowCountForLoadedSearchResults(searchResults),
0
);
+
+ // The clear unread filter button adds an extra row
+ if (this.filterByUnread) {
+ count += 1;
+ }
+
+ return count;
}
// This is currently unimplemented. See DESKTOP-1170.
@@ -236,12 +273,19 @@ export class LeftPaneSearchHelper extends LeftPaneHelper i18n('icu:conversationsHeader'),
+ getHeaderText: i18n =>
+ this.filterByUnread
+ ? i18n('icu:conversationsUnreadHeader')
+ : i18n('icu:conversationsHeader'),
};
}
assertDev(
@@ -257,7 +301,9 @@ export class LeftPaneSearchHelper extends LeftPaneHelper= conversationRowCount + contactRowCount + messageRowCount) {
- return undefined;
+ rowOffset += messageRowCount;
+ if (rowIndex < rowOffset) {
+ const localIndex = rowIndex - conversationRowCount - contactRowCount;
+ if (localIndex === 0) {
+ return {
+ type: RowType.Header,
+ getHeaderText: i18n => i18n('icu:messagesHeader'),
+ };
+ }
+ assertDev(
+ !messageResults.isLoading,
+ "We shouldn't get here with message results still loading"
+ );
+ const message = messageResults.results[localIndex - 1];
+ return message
+ ? {
+ type: RowType.MessageSearchResult,
+ messageId: message.id,
+ }
+ : undefined;
}
- const localIndex = rowIndex - conversationRowCount - contactRowCount;
- if (localIndex === 0) {
+ rowOffset += clearFilterButtonRowCount;
+ if (rowIndex < rowOffset) {
return {
- type: RowType.Header,
- getHeaderText: i18n => i18n('icu:messagesHeader'),
+ type: RowType.ClearFilterButton,
+ isOnNoResultsPage: this.allResults().every(
+ searchResult =>
+ searchResult.isLoading || searchResult.results.length === 0
+ ),
};
}
- assertDev(
- !messageResults.isLoading,
- "We shouldn't get here with message results still loading"
- );
- const message = messageResults.results[localIndex - 1];
- return message
- ? {
- type: RowType.MessageSearchResult,
- messageId: message.id,
- }
- : undefined;
+
+ return undefined;
}
override isScrollable(): boolean {
@@ -307,7 +365,8 @@ export class LeftPaneSearchHelper extends LeftPaneHelper): boolean {
- const oldIsLoading = new LeftPaneSearchHelper(old).isLoading();
+ const oldSearchPaneHelper = new LeftPaneSearchHelper(old);
+ const oldIsLoading = oldSearchPaneHelper.isLoading();
const newIsLoading = this.isLoading();
if (oldIsLoading && newIsLoading) {
return false;
@@ -376,7 +435,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper unknown,
+ clearSearchQuery: () => unknown,
showConversation: ShowConversationType
): void {
const conversation = this.getConversationAndMessageAtIndex(0);
@@ -384,7 +443,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper
): ThunkAction {
- return dispatch => {
+ return (dispatch, getState) => {
for (const conversation of data) {
calling.groupMembersChanged(conversation.id);
}
+
+ const { conversationLookup } = getState().conversations;
+
+ const someConversationsHaveNewMessages = data.some(conversation => {
+ return (
+ conversationLookup[conversation.id]?.lastMessageReceivedAt !==
+ conversation.lastMessageReceivedAt
+ );
+ });
+
dispatch({
type: 'CONVERSATIONS_UPDATED',
payload: {
data,
},
});
+
+ if (someConversationsHaveNewMessages) {
+ dispatch(searchActions.refreshSearch());
+ }
};
}
+
function conversationRemoved(id: string): ConversationRemovedActionType {
return {
type: 'CONVERSATION_REMOVED',
diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts
index 6e6e7c1c7..f96c734d0 100644
--- a/ts/state/ducks/search.ts
+++ b/ts/state/ducks/search.ts
@@ -24,7 +24,12 @@ import type {
ShowArchivedConversationsActionType,
MessageType,
} from './conversations';
-import { getQuery, getSearchConversation } from '../selectors/search';
+import {
+ getFilterByUnread,
+ getIsActivelySearching,
+ getQuery,
+ getSearchConversation,
+} from '../selectors/search';
import { getAllConversations } from '../selectors/conversations';
import {
getIntl,
@@ -62,6 +67,7 @@ export type SearchStateType = ReadonlyDeep<{
contactIds: Array;
conversationIds: Array;
query: string;
+ filterByUnread: boolean;
messageIds: Array;
// We do store message data to pass through the selector
messageLookup: MessageSearchResultLookupType;
@@ -98,8 +104,8 @@ type StartSearchActionType = ReadonlyDeep<{
type: 'SEARCH_START';
payload: null;
}>;
-type ClearSearchActionType = ReadonlyDeep<{
- type: 'SEARCH_CLEAR';
+type ClearSearchQueryActionType = ReadonlyDeep<{
+ type: 'SEARCH_QUERY_CLEAR';
payload: null;
}>;
type ClearConversationSearchActionType = ReadonlyDeep<{
@@ -119,12 +125,22 @@ type SearchInConversationActionType = ReadonlyDeep<{
payload: { searchConversationId: string };
}>;
+type UpdateFilterByUnreadActionType = ReadonlyDeep<{
+ type: 'FILTER_BY_UNREAD_UPDATE';
+ payload: { enabled: boolean };
+}>;
+
+type RefreshSearchActionType = ReadonlyDeep<{
+ type: 'SEARCH_REFRESH';
+ payload: null;
+}>;
+
export type SearchActionType = ReadonlyDeep<
| SearchMessagesResultsFulfilledActionType
| SearchDiscussionsResultsFulfilledActionType
| UpdateSearchTermActionType
| StartSearchActionType
- | ClearSearchActionType
+ | ClearSearchQueryActionType
| ClearConversationSearchActionType
| EndSearchActionType
| EndConversationSearchActionType
@@ -134,18 +150,22 @@ export type SearchActionType = ReadonlyDeep<
| TargetedConversationChangedActionType
| ShowArchivedConversationsActionType
| ConversationUnloadedActionType
+ | UpdateFilterByUnreadActionType
+ | RefreshSearchActionType
>;
// Action Creators
export const actions = {
startSearch,
- clearSearch,
+ clearSearchQuery,
clearConversationSearch,
endSearch,
endConversationSearch,
searchInConversation,
updateSearchTerm,
+ updateFilterByUnread,
+ refreshSearch,
};
export const useSearchActions = (): BoundActionCreatorsMapObject<
@@ -158,10 +178,22 @@ function startSearch(): StartSearchActionType {
payload: null,
};
}
-function clearSearch(): ClearSearchActionType {
- return {
- type: 'SEARCH_CLEAR',
- payload: null,
+function clearSearchQuery(): ThunkAction<
+ void,
+ RootStateType,
+ unknown,
+ ClearSearchQueryActionType
+> {
+ return async (dispatch, getState) => {
+ dispatch({
+ type: 'SEARCH_QUERY_CLEAR',
+ payload: null,
+ });
+
+ doSearch({
+ dispatch,
+ state: getState(),
+ });
};
}
function clearConversationSearch(): ClearConversationSearchActionType {
@@ -191,6 +223,49 @@ function searchInConversation(
};
}
+function refreshSearch(): ThunkAction<
+ void,
+ RootStateType,
+ unknown,
+ RefreshSearchActionType
+> {
+ return (dispatch, getState) => {
+ const state = getState();
+
+ if (!getIsActivelySearching(state)) {
+ return;
+ }
+
+ dispatch({
+ type: 'SEARCH_REFRESH',
+ payload: null,
+ });
+
+ doSearch({
+ dispatch,
+ state,
+ });
+ };
+}
+
+function updateFilterByUnread(
+ filterByUnread: boolean
+): ThunkAction {
+ return (dispatch, getState) => {
+ dispatch({
+ type: 'FILTER_BY_UNREAD_UPDATE',
+ payload: {
+ enabled: filterByUnread,
+ },
+ });
+
+ doSearch({
+ dispatch,
+ state: getState(),
+ });
+ };
+}
+
function updateSearchTerm(
query: string
): ThunkAction {
@@ -200,23 +275,9 @@ function updateSearchTerm(
payload: { query },
});
- const state = getState();
- const ourConversationId = getUserConversationId(state);
- strictAssert(
- ourConversationId,
- 'updateSearchTerm our conversation is missing'
- );
-
- const i18n = getIntl(state);
-
doSearch({
dispatch,
- allConversations: getAllConversations(state),
- regionCode: getRegionCode(state),
- noteToSelf: i18n('icu:noteToSelf').toLowerCase(),
- ourConversationId,
- query: getQuery(state),
- searchConversationId: getSearchConversation(state)?.id,
+ state: getState(),
});
};
}
@@ -224,12 +285,7 @@ function updateSearchTerm(
const doSearch = debounce(
({
dispatch,
- allConversations,
- regionCode,
- noteToSelf,
- ourConversationId,
- query,
- searchConversationId,
+ state,
}: Readonly<{
dispatch: ThunkDispatch<
RootStateType,
@@ -237,21 +293,37 @@ const doSearch = debounce(
| SearchMessagesResultsFulfilledActionType
| SearchDiscussionsResultsFulfilledActionType
>;
- allConversations: ReadonlyArray;
- noteToSelf: string;
- regionCode: string | undefined;
- ourConversationId: string;
- query: string;
- searchConversationId: undefined | string;
+ state: RootStateType;
}>) => {
- if (!query) {
+ if (!getIsActivelySearching(state)) {
return;
}
+ const query = getQuery(state);
+ const filterByUnread = getFilterByUnread(state);
+ const i18n = getIntl(state);
+ const allConversations = getAllConversations(state);
+ const regionCode = getRegionCode(state);
+ const noteToSelf = i18n('icu:noteToSelf').toLowerCase();
+ const ourConversationId = getUserConversationId(state);
+ const searchConversationId = getSearchConversation(state)?.id;
+
+ strictAssert(ourConversationId, 'doSearch our conversation is missing');
+
// Limit the number of contacts to something reasonable
const MAX_MATCHING_CONTACTS = 100;
void (async () => {
+ if (filterByUnread) {
+ dispatch({
+ type: 'SEARCH_MESSAGES_RESULTS_FULFILLED',
+ payload: {
+ messages: [],
+ query,
+ },
+ });
+ return;
+ }
const segmenter = new Intl.Segmenter([], { granularity: 'word' });
const queryWords = [...segmenter.segment(query)]
.filter(word => word.isWordLike)
@@ -284,6 +356,7 @@ const doSearch = debounce(
void (async () => {
const { conversationIds, contactIds } =
await queryConversationsAndContacts(query, {
+ filterByUnread,
ourConversationId,
noteToSelf,
regionCode,
@@ -314,7 +387,7 @@ async function queryMessages({
contactServiceIdsMatchingQuery?: Array;
}): Promise> {
try {
- if (query.length === 0) {
+ if (query.trim().length === 0) {
return [];
}
@@ -338,6 +411,7 @@ async function queryMessages({
async function queryConversationsAndContacts(
query: string,
options: {
+ filterByUnread: boolean;
ourConversationId: string;
noteToSelf: string;
regionCode: string | undefined;
@@ -347,8 +421,13 @@ async function queryConversationsAndContacts(
contactIds: Array;
conversationIds: Array;
}> {
- const { ourConversationId, noteToSelf, regionCode, allConversations } =
- options;
+ const {
+ filterByUnread,
+ ourConversationId,
+ noteToSelf,
+ regionCode,
+ allConversations,
+ } = options;
const normalizedQuery = removeDiacritics(query);
@@ -382,7 +461,8 @@ async function queryConversationsAndContacts(
const searchResults: Array = filterAndSortConversations(
visibleConversations,
normalizedQuery,
- regionCode
+ regionCode,
+ filterByUnread
);
// Split into two groups - active conversations and items just from address book
@@ -408,6 +488,11 @@ async function queryConversationsAndContacts(
contactIds.unshift(ourConversationId);
}
+ // Don't show contacts in the left pane if we're filtering by unread
+ if (filterByUnread) {
+ contactIds = [];
+ }
+
return { conversationIds, contactIds };
}
@@ -417,6 +502,7 @@ export function getEmptyState(): SearchStateType {
return {
startSearchCounter: 0,
query: '',
+ filterByUnread: false,
messageIds: [],
messageLookup: {},
conversationIds: [],
@@ -426,10 +512,51 @@ export function getEmptyState(): SearchStateType {
};
}
+function handleSearchUpdate(
+ state: SearchStateType,
+ params: { query?: string; filterByUnread?: boolean }
+): SearchStateType {
+ const { query, filterByUnread } = params;
+
+ // Determine the new state values, falling back to existing state if not provided
+ const newQuery = query ?? state.query;
+ const newFilterByUnread = filterByUnread ?? state.filterByUnread;
+
+ const isValidSearch = newQuery.length > 0 || newFilterByUnread;
+ const isWithinConversation = Boolean(state.searchConversationId);
+
+ if (isValidSearch) {
+ return {
+ ...state,
+ query: newQuery,
+ filterByUnread: newFilterByUnread,
+ messagesLoading: true,
+ messageIds: [],
+ messageLookup: {},
+ discussionsLoading: !isWithinConversation,
+ contactIds: [],
+ conversationIds: [],
+ };
+ }
+
+ return {
+ ...getEmptyState(),
+ startSearchCounter: state.startSearchCounter,
+ searchConversationId: state.searchConversationId,
+ globalSearch: state.globalSearch,
+ };
+}
+
export function reducer(
state: Readonly = getEmptyState(),
action: Readonly
): SearchStateType {
+ if (action.type === 'FILTER_BY_UNREAD_UPDATE') {
+ return handleSearchUpdate(state, {
+ filterByUnread: action.payload.enabled,
+ });
+ }
+
if (action.type === 'SHOW_ARCHIVED_CONVERSATIONS') {
log.info('search: show archived conversations, clearing message lookup');
return getEmptyState();
@@ -444,15 +571,8 @@ export function reducer(
};
}
- if (action.type === 'SEARCH_CLEAR') {
- log.info('search: cleared, clearing message lookup');
-
- return {
- ...getEmptyState(),
- startSearchCounter: state.startSearchCounter,
- searchConversationId: state.searchConversationId,
- globalSearch: state.globalSearch,
- };
+ if (action.type === 'SEARCH_QUERY_CLEAR') {
+ return handleSearchUpdate(state, { query: '' });
}
if (action.type === 'SEARCH_END') {
@@ -463,26 +583,7 @@ export function reducer(
}
if (action.type === 'SEARCH_UPDATE') {
- const { payload } = action;
- const { query } = payload;
-
- const hasQuery = Boolean(query);
- const isWithinConversation = Boolean(state.searchConversationId);
-
- return {
- ...state,
- query,
- messagesLoading: hasQuery,
- ...(hasQuery
- ? {
- messageIds: [],
- messageLookup: {},
- discussionsLoading: !isWithinConversation,
- contactIds: [],
- conversationIds: [],
- }
- : {}),
- };
+ return handleSearchUpdate(state, { query: action.payload.query });
}
if (action.type === 'SEARCH_IN_CONVERSATION') {
diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts
index 03367eeae..f0e674d9c 100644
--- a/ts/state/selectors/conversations.ts
+++ b/ts/state/selectors/conversations.ts
@@ -774,7 +774,9 @@ export const getFilteredCandidateContactsForNewGroup = createSelector(
getCandidateContactsForNewGroup,
getNormalizedComposerConversationSearchTerm,
getRegionCode,
- filterAndSortConversations
+ (contacts, searchTerm, regionCode): Array => {
+ return filterAndSortConversations(contacts, searchTerm, regionCode);
+ }
);
const getGroupCreationComposerState = createSelector(
diff --git a/ts/state/selectors/search.ts b/ts/state/selectors/search.ts
index 09c50353f..5ed07a074 100644
--- a/ts/state/selectors/search.ts
+++ b/ts/state/selectors/search.ts
@@ -34,6 +34,11 @@ import { getOwn } from '../../util/getOwn';
export const getSearch = (state: StateType): SearchStateType => state.search;
+export const getFilterByUnread = createSelector(
+ getSearch,
+ (state: SearchStateType): boolean => state.filterByUnread
+);
+
export const getQuery = createSelector(
getSearch,
(state: SearchStateType): string => state.query
@@ -96,6 +101,12 @@ export const getHasSearchQuery = createSelector(
(query: string): boolean => query.trim().length > 0
);
+export const getIsActivelySearching = createSelector(
+ [getFilterByUnread, getHasSearchQuery],
+ (filterByUnread: boolean, hasSearchQuery: boolean): boolean =>
+ filterByUnread || hasSearchQuery
+);
+
export const getMessageSearchResultLookup = createSelector(
getSearch,
(state: SearchStateType) => state.messageLookup
@@ -114,6 +125,7 @@ export const getSearchResults = createSelector(
| 'messageResults'
| 'searchConversationName'
| 'searchTerm'
+ | 'filterByUnread'
> => {
const {
contactIds,
@@ -145,6 +157,7 @@ export const getSearchResults = createSelector(
},
searchConversationName,
searchTerm: state.query,
+ filterByUnread: state.filterByUnread,
};
}
);
diff --git a/ts/state/smart/LeftPane.tsx b/ts/state/smart/LeftPane.tsx
index fa6d7a692..0dc9374db 100644
--- a/ts/state/smart/LeftPane.tsx
+++ b/ts/state/smart/LeftPane.tsx
@@ -69,7 +69,9 @@ import {
hasNetworkDialog as getHasNetworkDialog,
} from '../selectors/network';
import {
+ getFilterByUnread,
getHasSearchQuery,
+ getIsActivelySearching,
getIsSearching,
getIsSearchingGlobally,
getQuery,
@@ -172,7 +174,7 @@ const getModeSpecificProps = (
...(searchConversation && searchTerm ? getSearchResults(state) : {}),
};
}
- if (getHasSearchQuery(state)) {
+ if (getIsActivelySearching(state)) {
const primarySendsSms = Boolean(
get(state.items, ['primarySendsSms'], false)
);
@@ -195,6 +197,7 @@ const getModeSpecificProps = (
searchDisabled: state.network.challengeStatus !== 'idle',
searchTerm: getQuery(state),
startSearchCounter: getStartSearchCounter(state),
+ filterByUnread: getFilterByUnread(state),
...getLeftPaneLists(state),
};
case ComposerStep.StartDirectConversation:
@@ -329,12 +332,13 @@ export const SmartLeftPane = memo(function SmartLeftPane({
} = useConversationsActions();
const {
clearConversationSearch,
- clearSearch,
+ clearSearchQuery,
endConversationSearch,
endSearch,
searchInConversation,
startSearch,
updateSearchTerm,
+ updateFilterByUnread,
} = useSearchActions();
const {
onOutgoingAudioCallInConversation,
@@ -376,7 +380,7 @@ export const SmartLeftPane = memo(function SmartLeftPane({
challengeStatus={challengeStatus}
clearConversationSearch={clearConversationSearch}
clearGroupCreationError={clearGroupCreationError}
- clearSearch={clearSearch}
+ clearSearchQuery={clearSearchQuery}
closeMaximumGroupSizeModal={closeMaximumGroupSizeModal}
closeRecommendedGroupSizeModal={closeRecommendedGroupSizeModal}
composeDeleteAvatarFromDisk={composeDeleteAvatarFromDisk}
@@ -448,6 +452,7 @@ export const SmartLeftPane = memo(function SmartLeftPane({
updateSearchTerm={updateSearchTerm}
usernameCorrupted={usernameCorrupted}
usernameLinkCorrupted={usernameLinkCorrupted}
+ updateFilterByUnread={updateFilterByUnread}
/>
);
});
diff --git a/ts/test-both/state/selectors/search_test.ts b/ts/test-both/state/selectors/search_test.ts
index f95eccb34..e13646b51 100644
--- a/ts/test-both/state/selectors/search_test.ts
+++ b/ts/test-both/state/selectors/search_test.ts
@@ -395,6 +395,7 @@ describe('both/state/selectors/search', () => {
messageResults: { isLoading: true },
searchConversationName: undefined,
searchTerm: 'foo bar',
+ filterByUnread: false,
});
});
@@ -450,6 +451,7 @@ describe('both/state/selectors/search', () => {
},
searchConversationName: undefined,
searchTerm: 'foo bar',
+ filterByUnread: false,
});
});
});
diff --git a/ts/test-node/components/leftPane/LeftPaneInboxHelper_test.tsx b/ts/test-node/components/leftPane/LeftPaneInboxHelper_test.tsx
index d50ce5cf4..8e98048b2 100644
--- a/ts/test-node/components/leftPane/LeftPaneInboxHelper_test.tsx
+++ b/ts/test-node/components/leftPane/LeftPaneInboxHelper_test.tsx
@@ -14,6 +14,7 @@ describe('LeftPaneInboxHelper', () => {
const defaultProps: LeftPaneInboxPropsType = {
archivedConversations: [],
conversations: [],
+ filterByUnread: false,
isSearchingGlobally: false,
isAboutToSearch: false,
pinnedConversations: [],
diff --git a/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts b/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts
index 62cd330c1..792ffc361 100644
--- a/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts
+++ b/ts/test-node/components/leftPane/LeftPaneSearchHelper_test.ts
@@ -9,6 +9,18 @@ import { getDefaultConversation } from '../../../test-both/helpers/getDefaultCon
import { LeftPaneSearchHelper } from '../../../components/leftPane/LeftPaneSearchHelper';
+const baseSearchHelperArgs = {
+ conversationResults: { isLoading: false, results: [] },
+ contactResults: { isLoading: false, results: [] },
+ filterByUnread: false,
+ messageResults: { isLoading: false, results: [] },
+ isSearchingGlobally: true,
+ searchTerm: 'foo',
+ primarySendsSms: false,
+ searchConversation: undefined,
+ searchDisabled: false,
+ startSearchCounter: 0,
+};
describe('LeftPaneSearchHelper', () => {
const fakeMessage = () => ({
id: uuid(),
@@ -18,17 +30,7 @@ describe('LeftPaneSearchHelper', () => {
describe('getBackAction', () => {
it('returns undefined; going back is handled elsewhere in the app', () => {
- const helper = new LeftPaneSearchHelper({
- conversationResults: { isLoading: false, results: [] },
- contactResults: { isLoading: false, results: [] },
- messageResults: { isLoading: false, results: [] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
- });
+ const helper = new LeftPaneSearchHelper(baseSearchHelperArgs);
assert.isUndefined(
helper.getBackAction({
@@ -44,46 +46,31 @@ describe('LeftPaneSearchHelper', () => {
it('returns 100 if any results are loading', () => {
assert.strictEqual(
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}).getRowCount(),
100
);
assert.strictEqual(
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}).getRowCount(),
100
);
assert.strictEqual(
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}).getRowCount(),
100
);
@@ -100,6 +87,7 @@ describe('LeftPaneSearchHelper', () => {
searchConversation: undefined,
searchDisabled: false,
startSearchCounter: 0,
+ filterByUnread: false,
});
assert.strictEqual(helper.getRowCount(), 0);
@@ -107,18 +95,13 @@ describe('LeftPaneSearchHelper', () => {
it('returns 1 + the number of results, dropping empty sections', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.strictEqual(helper.getRowCount(), 5);
@@ -129,40 +112,25 @@ describe('LeftPaneSearchHelper', () => {
it('returns a "loading search results" row if any results are loading', () => {
const helpers = [
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
];
@@ -188,18 +156,13 @@ describe('LeftPaneSearchHelper', () => {
const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: conversations,
},
contactResults: { isLoading: false, results: contacts },
messageResults: { isLoading: false, results: messages },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.deepEqual(
@@ -235,18 +198,9 @@ describe('LeftPaneSearchHelper', () => {
const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({
- conversationResults: {
- isLoading: false,
- results: [],
- },
+ ...baseSearchHelperArgs,
contactResults: { isLoading: false, results: contacts },
messageResults: { isLoading: false, results: messages },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.deepEqual(_testHeaderText(helper.getRow(0)), 'icu:contactsHeader');
@@ -273,18 +227,12 @@ describe('LeftPaneSearchHelper', () => {
const messages = [fakeMessage(), fakeMessage()];
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: conversations,
},
- contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: messages },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.deepEqual(
@@ -316,18 +264,12 @@ describe('LeftPaneSearchHelper', () => {
const contacts = [getDefaultConversation()];
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: conversations,
},
contactResults: { isLoading: false, results: contacts },
- messageResults: { isLoading: false, results: [] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.deepEqual(
@@ -354,40 +296,25 @@ describe('LeftPaneSearchHelper', () => {
it('returns false if any results are loading', () => {
const helpers = [
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
}),
];
@@ -398,21 +325,15 @@ describe('LeftPaneSearchHelper', () => {
it('returns true if all results have loaded', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
messageResults: {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isTrue(helper.isScrollable());
});
@@ -421,25 +342,20 @@ describe('LeftPaneSearchHelper', () => {
describe('shouldRecomputeRowHeights', () => {
it("returns false if the number of results doesn't change", () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
messageResults: {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isFalse(
helper.shouldRecomputeRowHeights({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
@@ -449,108 +365,68 @@ describe('LeftPaneSearchHelper', () => {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'bar',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
})
);
});
it('returns false when a section completes loading, but not all sections are done (because the pane is still loading overall)', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isFalse(
helper.shouldRecomputeRowHeights({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation()],
},
contactResults: { isLoading: true },
messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'bar',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
})
);
});
it('returns true when all sections finish loading', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isTrue(
helper.shouldRecomputeRowHeights({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
contactResults: { isLoading: false, results: [] },
messageResults: { isLoading: false, results: [fakeMessage()] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
})
);
});
it('returns true if the number of results in a section changes', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
- messageResults: { isLoading: false, results: [] },
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isTrue(
helper.shouldRecomputeRowHeights({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation()],
},
- contactResults: { isLoading: true },
- messageResults: { isLoading: true },
- isSearchingGlobally: true,
- searchTerm: 'bar',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
})
);
});
@@ -560,21 +436,15 @@ describe('LeftPaneSearchHelper', () => {
it('returns correct conversation at given index', () => {
const expected = getDefaultConversation();
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [expected, getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
messageResults: {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.strictEqual(
helper.getConversationAndMessageAtIndex(0)?.conversationId,
@@ -585,6 +455,7 @@ describe('LeftPaneSearchHelper', () => {
it('returns correct contact at given index', () => {
const expected = getDefaultConversation();
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
@@ -597,12 +468,6 @@ describe('LeftPaneSearchHelper', () => {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.strictEqual(
helper.getConversationAndMessageAtIndex(2)?.conversationId,
@@ -613,21 +478,15 @@ describe('LeftPaneSearchHelper', () => {
it('returns correct message at given index', () => {
const expected = fakeMessage();
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
messageResults: {
isLoading: false,
results: [fakeMessage(), fakeMessage(), expected],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.strictEqual(
helper.getConversationAndMessageAtIndex(4)?.messageId,
@@ -638,18 +497,13 @@ describe('LeftPaneSearchHelper', () => {
it('returns correct message at given index skipping not loaded results', () => {
const expected = fakeMessage();
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: { isLoading: true },
contactResults: { isLoading: true },
messageResults: {
isLoading: false,
results: [fakeMessage(), expected, fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.strictEqual(
helper.getConversationAndMessageAtIndex(1)?.messageId,
@@ -659,21 +513,15 @@ describe('LeftPaneSearchHelper', () => {
it('returns undefined if search candidate with given index does not exist', () => {
const helper = new LeftPaneSearchHelper({
+ ...baseSearchHelperArgs,
conversationResults: {
isLoading: false,
results: [getDefaultConversation(), getDefaultConversation()],
},
- contactResults: { isLoading: false, results: [] },
messageResults: {
isLoading: false,
results: [fakeMessage(), fakeMessage(), fakeMessage()],
},
- isSearchingGlobally: true,
- searchTerm: 'foo',
- primarySendsSms: false,
- searchConversation: undefined,
- searchDisabled: false,
- startSearchCounter: 0,
});
assert.isUndefined(
helper.getConversationAndMessageAtIndex(100)?.messageId
diff --git a/ts/util/filterAndSortConversations.ts b/ts/util/filterAndSortConversations.ts
index d85abd7c8..fe69dcdfd 100644
--- a/ts/util/filterAndSortConversations.ts
+++ b/ts/util/filterAndSortConversations.ts
@@ -64,6 +64,17 @@ type CommandRunnerType = (
const COMMANDS = new Map();
+function filterConversationsByUnread(
+ conversations: ReadonlyArray,
+ includeMuted: boolean
+): Array {
+ return conversations.filter(conversation => {
+ return hasUnread(
+ countConversationUnreadStats(conversation, { includeMuted })
+ );
+ });
+}
+
COMMANDS.set('serviceIdEndsWith', (conversations, query) => {
return conversations.filter(convo => convo.serviceId?.endsWith(query));
});
@@ -95,11 +106,7 @@ COMMANDS.set('unread', (conversations, query) => {
/^(?:m|muted)$/i.test(query) ||
window.storage.get('badge-count-muted-conversations') ||
false;
- return conversations.filter(conversation => {
- return hasUnread(
- countConversationUnreadStats(conversation, { includeMuted })
- );
- });
+ return filterConversationsByUnread(conversations, includeMuted);
});
// See https://fusejs.io/examples.html#extended-search for
@@ -157,14 +164,24 @@ function sortAlphabetically(a: ConversationType, b: ConversationType) {
export function filterAndSortConversations(
conversations: ReadonlyArray,
searchTerm: string,
- regionCode: string | undefined
+ regionCode: string | undefined,
+ filterByUnread: boolean = false
): Array {
+ const filteredConversations = filterByUnread
+ ? filterConversationsByUnread(conversations, true)
+ : conversations;
+
if (searchTerm.length) {
const now = Date.now();
+ const withoutUnknownAndFiltered = filteredConversations.filter(
+ item => item.titleNoDefault
+ );
- const withoutUnknown = conversations.filter(item => item.titleNoDefault);
-
- return searchConversations(withoutUnknown, searchTerm, regionCode)
+ return searchConversations(
+ withoutUnknownAndFiltered,
+ searchTerm,
+ regionCode
+ )
.slice()
.sort((a, b) => {
const { activeAt: aActiveAt = 0, left: aLeft = false } = a.item;
@@ -190,7 +207,7 @@ export function filterAndSortConversations(
.map(result => result.item);
}
- return conversations.concat().sort((a, b) => {
+ return filteredConversations.concat().sort((a, b) => {
const aScore = a.activeAt ?? 0;
const bScore = b.activeAt ?? 0;
const score = bScore - aScore;