Filter chats by Unread

This commit is contained in:
yash-signal 2024-11-13 13:33:41 -06:00 committed by GitHub
parent 45e9c07125
commit a56e7d0ade
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 883 additions and 438 deletions

View file

@ -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<LeftPaneSearchPropsType
private readonly searchConversation: undefined | ConversationType;
private readonly filterByUnread: boolean;
constructor({
contactResults,
conversationResults,
@ -89,6 +92,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
searchDisabled,
searchTerm,
startSearchCounter,
filterByUnread,
}: Readonly<LeftPaneSearchPropsType>) {
super();
@ -102,30 +106,33 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
this.searchDisabled = searchDisabled;
this.searchTerm = searchTerm;
this.startSearchCounter = startSearchCounter;
this.filterByUnread = filterByUnread;
this.onEnterKeyDown = this.onEnterKeyDown.bind(this);
}
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 (
<LeftPaneSearchInput
clearConversationSearch={clearConversationSearch}
clearSearch={clearSearch}
clearSearchQuery={clearSearchQuery}
endConversationSearch={endConversationSearch}
endSearch={endSearch}
disabled={this.searchDisabled}
@ -137,6 +144,9 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
showConversation={showConversation}
startSearchCounter={this.startSearchCounter}
updateSearchTerm={updateSearchTerm}
filterButtonEnabled={!this.searchConversation}
filterPressed={this.filterByUnread}
onFilterClick={updateFilterByUnread}
/>
);
}
@ -171,13 +181,29 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
/>
);
} 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 = (
<>
<div>
{i18n('icu:noSearchResults', {
searchTerm,
})}
</div>
{this.filterByUnread && (
<div
className="module-conversation-list__item--header module-left-pane__no-search-results__unread-header"
aria-label={i18n('icu:conversationsUnreadHeader')}
>
{i18n('icu:conversationsUnreadHeader')}
</div>
)}
<div>{noResultsMessage}</div>
{primarySendsSms && (
<div className="module-left-pane__no-search-results__sms-only">
{i18n('icu:noSearchResults--sms-only')}
@ -191,7 +217,11 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
<div
// We need this for Ctrl-T shortcut cycling through parts of app
tabIndex={-1}
className="module-left-pane__no-search-results"
className={
this.filterByUnread
? 'module-left-pane__no-search-results--withHeader'
: 'module-left-pane__no-search-results'
}
key={searchTerm}
>
{noResults}
@ -205,11 +235,18 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
return 1 + SEARCH_RESULTS_FAKE_ROW_COUNT;
}
return this.allResults().reduce(
let count = this.allResults().reduce(
(result: number, searchResults) =>
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<LeftPaneSearchPropsType
getRowCountForLoadedSearchResults(conversationResults);
const contactRowCount = getRowCountForLoadedSearchResults(contactResults);
const messageRowCount = getRowCountForLoadedSearchResults(messageResults);
const clearFilterButtonRowCount = this.filterByUnread ? 1 : 0;
if (rowIndex < conversationRowCount) {
let rowOffset = 0;
rowOffset += conversationRowCount;
if (rowIndex < rowOffset) {
if (rowIndex === 0) {
return {
type: RowType.Header,
getHeaderText: i18n => i18n('icu:conversationsHeader'),
getHeaderText: i18n =>
this.filterByUnread
? i18n('icu:conversationsUnreadHeader')
: i18n('icu:conversationsHeader'),
};
}
assertDev(
@ -257,7 +301,9 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
: undefined;
}
if (rowIndex < conversationRowCount + contactRowCount) {
rowOffset += contactRowCount;
if (rowIndex < rowOffset) {
const localIndex = rowIndex - conversationRowCount;
if (localIndex === 0) {
return {
@ -278,28 +324,40 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
: undefined;
}
if (rowIndex >= 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<LeftPaneSearchPropsType
}
shouldRecomputeRowHeights(old: Readonly<LeftPaneSearchPropsType>): 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<LeftPaneSearchPropsType
}
private onEnterKeyDown(
clearSearch: () => unknown,
clearSearchQuery: () => unknown,
showConversation: ShowConversationType
): void {
const conversation = this.getConversationAndMessageAtIndex(0);
@ -384,7 +443,7 @@ export class LeftPaneSearchHelper extends LeftPaneHelper<LeftPaneSearchPropsType
return;
}
showConversation(conversation);
clearSearch();
clearSearchQuery();
}
}