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

Top bar for outstanding tab refuses to disappear when no transactions are found. #55329

Merged
merged 7 commits into from
Jan 29, 2025
Merged
Changes from all commits
Commits
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
76 changes: 43 additions & 33 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,25 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSearchHighlightAndScroll from '@hooks/useSearchHighlightAndScroll';
import useThemeStyles from '@hooks/useThemeStyles';
import {turnOffMobileSelectionMode, turnOnMobileSelectionMode} from '@libs/actions/MobileSelectionMode';
import * as SearchActions from '@libs/actions/Search';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import {createTransactionThread, search} from '@libs/actions/Search';
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
import Log from '@libs/Log';
import memoize from '@libs/memoize';
import isSearchTopmostCentralPane from '@libs/Navigation/isSearchTopmostCentralPane';
import type {PlatformStackNavigationProp} from '@libs/Navigation/PlatformStackNavigation/types';
import * as ReportUtils from '@libs/ReportUtils';
import * as SearchQueryUtils from '@libs/SearchQueryUtils';
import * as SearchUIUtils from '@libs/SearchUIUtils';
import * as TransactionUtils from '@libs/TransactionUtils';
import {generateReportID} from '@libs/ReportUtils';
import {buildSearchQueryString} from '@libs/SearchQueryUtils';
import {
getListItem,
getSections,
getSortedSections,
isReportActionListItemType,
isReportListItemType,
isSearchResultsEmpty as isSearchResultsEmptyUtils,
isTransactionListItemType,
shouldShowYear as shouldShowYearUtils,
} from '@libs/SearchUIUtils';
import {isOnHold} from '@libs/TransactionUtils';
import Navigation from '@navigation/Navigation';
import type {AuthScreensParamList} from '@navigation/types';
import EmptySearchView from '@pages/Search/EmptySearchView';
Expand Down Expand Up @@ -57,7 +66,7 @@ function mapTransactionItemToSelectedEntry(item: TransactionListItemType): [stri
isSelected: true,
canDelete: item.canDelete,
canHold: item.canHold,
isHeld: TransactionUtils.isOnHold(item),
isHeld: isOnHold(item),
canUnhold: item.canUnhold,
action: item.action,
reportID: item.reportID,
Expand All @@ -77,14 +86,14 @@ function mapToItemWithSelectionInfo(
canSelectMultiple: boolean,
shouldAnimateInHighlight: boolean,
) {
if (SearchUIUtils.isReportActionListItemType(item)) {
if (isReportActionListItemType(item)) {
return {
...item,
shouldAnimateInHighlight,
};
}

return SearchUIUtils.isTransactionListItemType(item)
return isTransactionListItemType(item)
? mapToTransactionItemWithSelectionInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight)
: {
...item,
Expand All @@ -107,7 +116,7 @@ function prepareTransactionsList(item: TransactionListItemType, selectedTransact
isSelected: true,
canDelete: item.canDelete,
canHold: item.canHold,
isHeld: TransactionUtils.isOnHold(item),
isHeld: isOnHold(item),
canUnhold: item.canUnhold,
action: item.action,
reportID: item.reportID,
Expand Down Expand Up @@ -176,12 +185,12 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
return;
}

SearchActions.search({queryJSON, offset});
search({queryJSON, offset});
}, [isOffline, offset, queryJSON]);

const getItemHeight = useCallback(
(item: TransactionListItemType | ReportListItemType | ReportActionListItemType) => {
if (SearchUIUtils.isTransactionListItemType(item) || SearchUIUtils.isReportActionListItemType(item)) {
if (isTransactionListItemType(item) || isReportActionListItemType(item)) {
return isLargeScreenWidth ? variables.optionRowHeight + listItemPadding : transactionItemMobileHeight + listItemPadding;
}

Expand Down Expand Up @@ -229,14 +238,14 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo

const shouldShowLoadingState = !isOffline && !isDataLoaded;
const shouldShowLoadingMoreItems = !shouldShowLoadingState && searchResults?.search?.isLoading && searchResults?.search?.offset > 0;
const isSearchResultsEmpty = !searchResults?.data || SearchUIUtils.isSearchResultsEmpty(searchResults);
const prevIsSearchResultEmpty = usePrevious(isSearchResultsEmpty);
const isSearchResultsEmpty = !searchResults?.data || isSearchResultsEmptyUtils(searchResults);
const isPrevSearchResultsEmpty = usePrevious(isSearchResultsEmpty);

const data = useMemo(() => {
if (searchResults === undefined) {
return [];
}
return SearchUIUtils.getSections(type, status, searchResults.data, searchResults.search);
return getSections(type, status, searchResults.data, searchResults.search);
}, [searchResults, status, type]);

useEffect(() => {
Expand All @@ -260,7 +269,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
newTransactionList[transaction.transactionID] = {
action: transaction.action,
canHold: transaction.canHold,
isHeld: TransactionUtils.isOnHold(transaction),
isHeld: isOnHold(transaction),
canUnhold: transaction.canUnhold,
isSelected: selectedTransactions[transaction.transactionID].isSelected,
canDelete: transaction.canDelete,
Expand All @@ -281,7 +290,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
newTransactionList[transaction.transactionID] = {
action: transaction.action,
canHold: transaction.canHold,
isHeld: TransactionUtils.isOnHold(transaction),
isHeld: isOnHold(transaction),
canUnhold: transaction.canUnhold,
isSelected: selectedTransactions[transaction.transactionID].isSelected,
canDelete: transaction.canDelete,
Expand All @@ -297,11 +306,11 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
}, [data, setSelectedTransactions]);

useEffect(() => {
if (!isSearchResultsEmpty || prevIsSearchResultEmpty) {
if (!isSearchResultsEmpty || isPrevSearchResultsEmpty) {
return;
}
turnOffMobileSelectionMode();
}, [isSearchResultsEmpty, prevIsSearchResultEmpty]);
}, [isSearchResultsEmpty, isPrevSearchResultsEmpty]);

useEffect(
() => () => {
Expand All @@ -328,8 +337,8 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
return <FullPageOfflineBlockingView>{null}</FullPageOfflineBlockingView>;
}

const ListItem = SearchUIUtils.getListItem(type, status);
const sortedData = SearchUIUtils.getSortedSections(type, status, data, sortBy, sortOrder);
const ListItem = getListItem(type, status);
const sortedData = getSortedSections(type, status, data, sortBy, sortOrder);
const isChat = type === CONST.SEARCH.DATA_TYPES.CHAT;
const sortedSelectedData = sortedData.map((item) => {
const baseKey = isChat
Expand All @@ -350,7 +359,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
return mapToItemWithSelectionInfo(item, selectedTransactions, canSelectMultiple, shouldAnimateInHighlight);
});

const shouldShowEmptyState = !isDataLoaded || data.length === 0;
const shouldShowEmptyState = isSearchResultsEmpty || !isDataLoaded;

if (shouldShowEmptyState) {
return (
Expand All @@ -364,10 +373,10 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
}

const toggleTransaction = (item: TransactionListItemType | ReportListItemType | ReportActionListItemType) => {
if (SearchUIUtils.isReportActionListItemType(item)) {
if (isReportActionListItemType(item)) {
return;
}
if (SearchUIUtils.isTransactionListItemType(item)) {
if (isTransactionListItemType(item)) {
if (!item.keyForList) {
return;
}
Expand Down Expand Up @@ -398,21 +407,21 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo

const openReport = (item: TransactionListItemType | ReportListItemType | ReportActionListItemType) => {
const isFromSelfDM = item.reportID === CONST.REPORT.UNREPORTED_REPORTID;
let reportID = SearchUIUtils.isTransactionListItemType(item) && (!item.isFromOneTransactionReport || isFromSelfDM) ? item.transactionThreadReportID : item.reportID;
let reportID = isTransactionListItemType(item) && (!item.isFromOneTransactionReport || isFromSelfDM) ? item.transactionThreadReportID : item.reportID;

if (!reportID) {
return;
}

// If we're trying to open a legacy transaction without a transaction thread, let's create the thread and navigate the user
if (SearchUIUtils.isTransactionListItemType(item) && reportID === '0' && item.moneyRequestReportActionID) {
reportID = ReportUtils.generateReportID();
SearchActions.createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID);
if (isTransactionListItemType(item) && reportID === '0' && item.moneyRequestReportActionID) {
reportID = generateReportID();
createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID);
}

const backTo = Navigation.getActiveRoute();

if (SearchUIUtils.isReportActionListItemType(item)) {
if (isReportActionListItemType(item)) {
const reportActionID = item.reportActionID;
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, reportActionID, backTo}));
return;
Expand Down Expand Up @@ -448,13 +457,14 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
};

const onSortPress = (column: SearchColumnType, order: SortOrder) => {
const newQuery = SearchQueryUtils.buildSearchQueryString({...queryJSON, sortBy: column, sortOrder: order});
const newQuery = buildSearchQueryString({...queryJSON, sortBy: column, sortOrder: order});
navigation.setParams({q: newQuery});
};

const shouldShowYear = SearchUIUtils.shouldShowYear(searchResults?.data);
const shouldShowSorting = !Array.isArray(status) && sortableSearchStatuses.includes(status);

const shouldShowYear = shouldShowYearUtils(searchResults?.data);

return (
<SelectionListWithModal<ReportListItemType | TransactionListItemType | ReportActionListItemType>
ref={handleSelectionListScroll(sortedSelectedData)}
Expand All @@ -477,7 +487,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
)
}
isSelected={(item) =>
status !== CONST.SEARCH.STATUS.EXPENSE.ALL && SearchUIUtils.isReportListItemType(item)
status !== CONST.SEARCH.STATUS.EXPENSE.ALL && isReportListItemType(item)
? item.transactions.some((transaction) => selectedTransactions[transaction.keyForList]?.isSelected)
: !!item.isSelected
}
Expand All @@ -501,7 +511,7 @@ function Search({queryJSON, onSearchListScroll, isSearchScreenFocused, contentCo
onSelectRow={openReport}
getItemHeight={getItemHeightMemoized}
shouldSingleExecuteRowSelect
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
shouldPreventDefaultFocusOnSelectRow={!canUseTouchScreen()}
shouldPreventDefault={false}
listHeaderWrapperStyle={[styles.ph8, styles.pt3]}
containerStyle={[styles.pv0, type === CONST.SEARCH.DATA_TYPES.CHAT && !isSmallScreenWidth && styles.pt3]}
Expand Down
Loading