Skip to content
Draft
Show file tree
Hide file tree
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
901 changes: 228 additions & 673 deletions .github/actions/javascript/authorChecklist/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/awaitStagingDeploys/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/bumpVersion/index.js

Large diffs are not rendered by default.

903 changes: 229 additions & 674 deletions .github/actions/javascript/checkAndroidStatus/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/checkDeployBlockers/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/checkSVGCompression/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/failureNotifier/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/formatCodeCovComment/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/generateHelpPreviewComment/index.js

Large diffs are not rendered by default.

903 changes: 229 additions & 674 deletions .github/actions/javascript/getAndroidRolloutPercentage/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/getArtifactInfo/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/getDeployPullRequestList/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/getPreviousVersion/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/getPullRequestDetails/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/getPullRequestIncrementalChanges/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/isAuthorizedContributor/index.js

Large diffs are not rendered by default.

1,208 changes: 369 additions & 839 deletions .github/actions/javascript/isDeployChecklistLocked/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/markPullRequestsAsDeployed/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/postOrReplaceComment/index.js

Large diffs are not rendered by default.

1,208 changes: 369 additions & 839 deletions .github/actions/javascript/proposalPoliceComment/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/reopenIssueWithComment/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/reviewerChecklist/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/validateReassureOutput/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/verifySignedCommits/index.js

Large diffs are not rendered by default.

901 changes: 228 additions & 673 deletions .github/actions/javascript/verifyStagingBuildsSucceeded/index.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions __mocks__/react-native-onyx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import type {ConnectOptions, OnyxKey} from 'react-native-onyx';

// eslint-disable-next-line no-restricted-imports
import Onyx, {useOnyx} from 'react-native-onyx';
import Onyx, {useOnyx, useOnyxState} from 'react-native-onyx';

let connectCallbackDelay = 0;
function addDelayToConnectCallback(delay: number) {
Expand Down Expand Up @@ -41,4 +41,4 @@ const reactNativeOnyxMock: ReactNativeOnyxMock = {

export default reactNativeOnyxMock;

export {useOnyx};
export {useOnyx, useOnyxState};
2 changes: 0 additions & 2 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1438,7 +1438,6 @@ const ONYXKEYS = {
OUTSTANDING_REPORTS_BY_POLICY_ID: 'outstandingReportsByPolicyID',
VISIBLE_REPORT_ACTIONS: 'visibleReportActions',
NON_PERSONAL_AND_WORKSPACE_CARD_LIST: 'nonPersonalAndWorkspaceCardList',
PERSONAL_AND_WORKSPACE_CARD_LIST: 'personalAndWorkspaceCardList',
CARD_FEED_ERRORS: 'cardFeedErrors',
RAM_ONLY_SORTED_REPORT_ACTIONS: 'sortedReportActions',
LOGIN_TO_ACCOUNT_ID_MAP: 'loginToAccountIDMap',
Expand Down Expand Up @@ -2021,7 +2020,6 @@ type OnyxDerivedValuesMapping = {
[ONYXKEYS.DERIVED.OUTSTANDING_REPORTS_BY_POLICY_ID]: OnyxTypes.OutstandingReportsByPolicyIDDerivedValue;
[ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS]: OnyxTypes.VisibleReportActionsDerivedValue;
[ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST]: OnyxTypes.NonPersonalAndWorkspaceCardListDerivedValue;
[ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST]: OnyxTypes.PersonalAndWorkspaceCardListDerivedValue;
[ONYXKEYS.DERIVED.CARD_FEED_ERRORS]: OnyxTypes.CardFeedErrorsDerivedValue;
[ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: OnyxTypes.SortedReportActionsDerivedValue;
[ONYXKEYS.DERIVED.LOGIN_TO_ACCOUNT_ID_MAP]: OnyxTypes.LoginToAccountIDMapDerivedValue;
Expand Down
3 changes: 2 additions & 1 deletion src/components/Search/SearchAutocompleteList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePermissions from '@hooks/usePermissions';
import usePersonalAndWorkspaceCardList from '@hooks/usePersonalAndWorkspaceCardList';
import useReportAttributes from '@hooks/useReportAttributes';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useSortedReportActionsData from '@hooks/useSortedReportActionsData';
Expand Down Expand Up @@ -223,7 +224,7 @@ function SearchAutocompleteList({
const lastActions = sortedReportActionsData?.lastActions;
const personalDetails = usePersonalDetails();
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
const personalAndWorkspaceCards = usePersonalAndWorkspaceCardList();
const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
const allCards = personalAndWorkspaceCards ?? CONST.EMPTY_OBJECT;
Expand Down
3 changes: 2 additions & 1 deletion src/components/Search/SearchRouter/SearchRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import useKeyboardShortcut from '@hooks/useKeyboardShortcut';
import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePersonalAndWorkspaceCardList from '@hooks/usePersonalAndWorkspaceCardList';
import {useGetPersonalDetailsByLogin} from '@hooks/usePersonalDetailByLogin';
import useReportAttributes from '@hooks/useReportAttributes';
import useReportOrReportDraft from '@hooks/useReportOrReportDraft';
Expand Down Expand Up @@ -124,7 +125,7 @@ function SearchRouter({onRouterClose, shouldHideInputCaret, isSearchRouterDispla
const {currentSearchQueryJSON, currentSearchHash, currentSearchKey} = useSearchQueryContext();
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
const personalAndWorkspaceCards = usePersonalAndWorkspaceCardList();
const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
const getPersonalDetailsByLogin = useGetPersonalDetailsByLogin();
Expand Down
5 changes: 2 additions & 3 deletions src/components/Search/hooks/useFilterCardValue.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePersonalAndWorkspaceCardList from '@hooks/usePersonalAndWorkspaceCardList';

import {getCardDescription} from '@libs/CardUtils';

import ONYXKEYS from '@src/ONYXKEYS';
import {filterCardsHiddenFromSearch} from '@src/selectors/Card';

function useFilterCardValue(value: string[]): string {
const {translate} = useLocalize();
const [searchCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST, {selector: filterCardsHiddenFromSearch});
const searchCards = usePersonalAndWorkspaceCardList(filterCardsHiddenFromSearch);

const cardNames = Object.values(searchCards ?? {})
.filter((card) => value.includes(card.cardID.toString()))
Expand Down
3 changes: 2 additions & 1 deletion src/components/Search/hooks/useFilterFeedData.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import useFeedKeysWithAssignedCards from '@hooks/useFeedKeysWithAssignedCards';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePersonalAndWorkspaceCardList from '@hooks/usePersonalAndWorkspaceCardList';

import {getFeedOptions} from '@libs/SearchUIUtils';

Expand All @@ -9,7 +10,7 @@ import ONYXKEYS from '@src/ONYXKEYS';
function useFilterFeedData(value: string[] | undefined) {
const {translate, localeCompare} = useLocalize();
const [allFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
const personalAndWorkspaceCards = usePersonalAndWorkspaceCardList();
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const [domains] = useOnyx(ONYXKEYS.COLLECTION.DOMAIN);
const [expensifyCardSettings] = useOnyx(ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS);
Expand Down
3 changes: 2 additions & 1 deletion src/components/Search/hooks/useSearchSnapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useLocalize from '@hooks/useLocalize';
import useMultipleSnapshots from '@hooks/useMultipleSnapshots';
import useNetwork from '@hooks/useNetwork';
import useOnyx from '@hooks/useOnyx';
import usePersonalAndWorkspaceCardList from '@hooks/usePersonalAndWorkspaceCardList';
import {useAllPersonalDetails} from '@hooks/usePersonalDetails';
import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses';
import useReportAttributes from '@hooks/useReportAttributes';
Expand Down Expand Up @@ -139,7 +140,7 @@ function useSearchSnapshot({queryJSON, searchResults, transactions, reportAction
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
const [onyxPersonalDetailsList] = useAllPersonalDetails();
const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
const personalAndWorkspaceCards = usePersonalAndWorkspaceCardList();
const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
const [customCardNames] = useOnyx(ONYXKEYS.NVP_EXPENSIFY_COMPANY_CARDS_CUSTOM_NAMES);
const [conciergeReportID] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
Expand Down
7 changes: 5 additions & 2 deletions src/components/Table/TableBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ function TableBodyList({contentContainerStyle, emptyMessage, onLayout, style, ..
noResultsStateElement,
tableListMetadata,
isEmptyResult,
isDefaultViewEmpty,
scrollWidth,
tableWidth,
} = useTableContext<TableData>();
Expand Down Expand Up @@ -337,8 +338,10 @@ function TableBodyList({contentContainerStyle, emptyMessage, onLayout, style, ..
</View>
);

const emptyStateContent =
tableListMetadata.hasPageHeader && isEmptyResult ? (noResultsStateElement ?? EmptyResultComponent) : (emptyStateElement ?? renderListComponent(ListEmptyComponent));
// When the default view hides every row (e.g. all workspaces are archived), no search or filter is active,
// so show the empty state rather than "No results".
const shouldShowNoResultsState = tableListMetadata.hasPageHeader && isEmptyResult && !isDefaultViewEmpty;
const emptyStateContent = shouldShowNoResultsState ? (noResultsStateElement ?? EmptyResultComponent) : (emptyStateElement ?? renderListComponent(ListEmptyComponent));
const footerElement = renderListComponent(ListFooterComponent);
// Consumer footer flex growth is useful below normal rows, but inside the combined empty-state
// footer it can expand over the page header. Preserve the remaining style while disabling growth.
Expand Down
5 changes: 3 additions & 2 deletions src/components/Table/TableEmptyStates/TableNoResultsState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ type TableNoResultsStateProps = Omit<GenericEmptyStateComponentProps, 'headerMed
export default function TableNoResultsState(emptyStateProps: TableNoResultsStateProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isEmptyResult, tableListMetadata} = useTableContext();
const {isEmptyResult, isDefaultViewEmpty, tableListMetadata} = useTableContext();
const illustrations = useMemoizedLazyIllustrations(['EmptyShelves']);

if (!isEmptyResult) {
// The default view hiding every row is not a search/filter result, so the empty state handles it instead.
if (!isEmptyResult || isDefaultViewEmpty) {
return null;
}

Expand Down
3 changes: 2 additions & 1 deletion src/hooks/useAdvancedSearchFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {emailSelector} from '@selectors/Session';

import useLocalize from './useLocalize';
import useOnyx from './useOnyx';
import usePersonalAndWorkspaceCardList from './usePersonalAndWorkspaceCardList';
import useWorkspaceList from './useWorkspaceList';

/**
Expand Down Expand Up @@ -312,7 +313,7 @@ function shouldDisplayCardFilterSelector(cardList: OnyxEntry<CardList>) {
}

function useAdvancedSearchFilters(type: SearchDataTypes | undefined) {
const [shouldDisplayCardFilter] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST, {selector: shouldDisplayCardFilterSelector});
const shouldDisplayCardFilter = usePersonalAndWorkspaceCardList(shouldDisplayCardFilterSelector);
const [policies = getEmptyObject<NonNullable<OnyxCollection<Policy>>>()] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: advancedSearchPoliciesSelector});
const [policyDerived] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: policyDerivedSelector});
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);
Expand Down
42 changes: 42 additions & 0 deletions src/hooks/usePersonalAndWorkspaceCardList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import ONYXKEYS from '@src/ONYXKEYS';
import type {CardList, WorkspaceCardsList} from '@src/types/onyx';

import type {OnyxCollection} from 'react-native-onyx';

import {personalAndWorkspaceCardListSelector} from '@selectors/Card';
import {useOnyxState} from 'react-native-onyx';

type CardListSelector<TReturn> = (cardList: CardList) => TReturn;

const dependencies = [ONYXKEYS.CARD_LIST, ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST];

// useOnyxState runs the selector on every write to either key, so each selector's output is kept per merged list
const selectedValues = new WeakMap<CardListSelector<unknown>, {cardList: CardList; value: unknown}>();

function select<TReturn>(selector: CardListSelector<TReturn>, cardList: CardList): TReturn {
const cached = selectedValues.get(selector);
if (cached?.cardList === cardList) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
return cached.value as TReturn;
}
const value = selector(cardList);
selectedValues.set(selector, {cardList, value});
return value;
}

function usePersonalAndWorkspaceCardList(): CardList;
function usePersonalAndWorkspaceCardList<TReturn>(selector: CardListSelector<TReturn>): TReturn;
function usePersonalAndWorkspaceCardList<TReturn>(selector?: CardListSelector<TReturn>) {
return useOnyxState(
(state) => {
// useOnyxState's state view types a collection key as one member, but at runtime it returns the whole collection
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
const workspaceCardFeeds = state[ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST] as OnyxCollection<WorkspaceCardsList>;
const cardList = personalAndWorkspaceCardListSelector(state[ONYXKEYS.CARD_LIST], workspaceCardFeeds);
return selector ? select(selector, cardList) : cardList;
},
{dependencies},
);
}

export default usePersonalAndWorkspaceCardList;
3 changes: 2 additions & 1 deletion src/hooks/useSearchSections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useFilterPendingDeleteReports from './useFilterPendingDeleteReports';
import useLocalize from './useLocalize';
import useOnyx from './useOnyx';
import usePersonalAndWorkspaceCardList from './usePersonalAndWorkspaceCardList';
import useReportAttributes from './useReportAttributes';

type UseSearchSectionsResult = {
Expand All @@ -28,7 +29,7 @@ function useSearchSections(): UseSearchSectionsResult {
const {convertToDisplayString} = useCurrencyListActions();

const [cardFeeds] = useOnyx(ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER);
const [personalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST);
const personalAndWorkspaceCards = usePersonalAndWorkspaceCardList();
const [nonPersonalAndWorkspaceCards] = useOnyx(ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST);
const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST);

Expand Down
2 changes: 0 additions & 2 deletions src/libs/actions/OnyxDerived/ONYX_DERIVED_VALUES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import loginToAccountIDMapConfig from './configs/loginToAccountIDMap';
import nonPersonalAndWorkspaceCardListConfig from './configs/nonPersonalAndWorkspaceCardList';
import oneOnOneChatReportIDsConfig from './configs/oneOnOneChatReportIDs';
import outstandingReportsByPolicyIDConfig from './configs/outstandingReportsByPolicyID';
import personalAndWorkspaceCardListConfig from './configs/personalAndWorkspaceCardList';
import reportAttributesConfig from './configs/reportAttributes';
import reportTransactionsAndViolationsConfig from './configs/reportTransactionsAndViolations';
import sortedReportActionsConfig from './configs/sortedReportActions';
Expand All @@ -27,7 +26,6 @@ const ONYX_DERIVED_VALUES = {
[ONYXKEYS.DERIVED.OUTSTANDING_REPORTS_BY_POLICY_ID]: outstandingReportsByPolicyIDConfig,
[ONYXKEYS.DERIVED.VISIBLE_REPORT_ACTIONS]: visibleReportActionsConfig,
[ONYXKEYS.DERIVED.NON_PERSONAL_AND_WORKSPACE_CARD_LIST]: nonPersonalAndWorkspaceCardListConfig,
[ONYXKEYS.DERIVED.PERSONAL_AND_WORKSPACE_CARD_LIST]: personalAndWorkspaceCardListConfig,
[ONYXKEYS.DERIVED.CARD_FEED_ERRORS]: cardFeedErrorsConfig,
[ONYXKEYS.DERIVED.RAM_ONLY_SORTED_REPORT_ACTIONS]: sortedReportActionsConfig,
[ONYXKEYS.DERIVED.LOGIN_TO_ACCOUNT_ID_MAP]: loginToAccountIDMapConfig,
Expand Down

This file was deleted.

42 changes: 41 additions & 1 deletion src/selectors/Card.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import {getExpensifyCardFeedsForDisplay} from '@libs/CardFeedUtils';
import {hasActiveExpensifyCard, hasAssignedCardMatching, isActiveCard, isCard, isCardHiddenFromSearch, isCSVFeedOrExpensifyCard, isExpensifyCard, isPersonalCard} from '@libs/CardUtils';
import {
hasActiveExpensifyCard,
hasAssignedCardMatching,
isActiveCard,
isCard,
isCardHiddenFromSearch,
isCSVFeedOrExpensifyCard,
isExpensifyCard,
isPersonalCard,
mergeCardListWithWorkspaceFeeds,
} from '@libs/CardUtils';
import {filterObject} from '@libs/ObjectUtils';

import CONST from '@src/CONST';
Expand All @@ -8,6 +18,8 @@ import type {CardFeeds, CardList, NonPersonalAndWorkspaceCardListDerivedValue, W

import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';

import {deepEqual} from 'fast-equals';

/**
* Builds a lightweight map of "${domainID}_${feedName}" keys that have card entries.
* A feed counts as having cards when:
Expand Down Expand Up @@ -87,6 +99,33 @@ const defaultExpensifyCardSelector = (allCards: OnyxEntry<NonPersonalAndWorkspac
return expensifyCardFeedsForDisplaySelector(allCards).at(0);
};

/**
* Merges the user's card list with every workspace card feed. The last pair of inputs and its result are kept, so
* every mounted consumer shares one merge per write. A merge equal to the last one returns the last object, so a
* write that leaves the merged list unchanged doesn't make consumers re-run their selectors.
*/
const createCardListWithWorkspaceFeedsSelector = (shouldFilterOutPersonalCards: boolean) => {
let lastCardList: OnyxEntry<CardList>;
let lastWorkspaceCardFeeds: OnyxCollection<WorkspaceCardsList>;
let lastResult: CardList | undefined;

return (cardList: OnyxEntry<CardList>, workspaceCardFeeds: OnyxCollection<WorkspaceCardsList>): CardList => {
if (lastResult && cardList === lastCardList && workspaceCardFeeds === lastWorkspaceCardFeeds) {
return lastResult;
}
lastCardList = cardList;
lastWorkspaceCardFeeds = workspaceCardFeeds;
const result = mergeCardListWithWorkspaceFeeds(workspaceCardFeeds ?? CONST.EMPTY_OBJECT, cardList, shouldFilterOutPersonalCards);
if (!lastResult || !deepEqual(result, lastResult)) {
lastResult = result;
}
return lastResult;
};
};

/** The user's cards, personal ones included, plus every workspace feed card. */
const personalAndWorkspaceCardListSelector = createCardListWithWorkspaceFeedsSelector(false);

/**
* Returns a selector that picks a single card from the card list by card ID.
*/
Expand Down Expand Up @@ -135,4 +174,5 @@ export {
companyCardCustomNamesSelector,
hasIssuedExpensifyCardSelector,
hasActiveExpensifyCardSelector,
personalAndWorkspaceCardListSelector,
};
6 changes: 0 additions & 6 deletions src/types/onyx/DerivedValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ type SortedReportActionsDerivedValue = {
transactionThreadIDs: Record<string, string | undefined>;
};

/**
* The derived value for merged personal and workspace card feeds.
*/
type PersonalAndWorkspaceCardListDerivedValue = CardList;

/**
* The derived value mapping each user's login (lowercased) to their accountID.
*
Expand Down Expand Up @@ -253,7 +248,6 @@ export type {
VisibleReportActionsDerivedValue,
SortedReportActionsDerivedValue,
NonPersonalAndWorkspaceCardListDerivedValue,
PersonalAndWorkspaceCardListDerivedValue,
CardFeedErrorsDerivedValue,
LoginToAccountIDMapDerivedValue,
GuideAccountIDsDerivedValue,
Expand Down
2 changes: 0 additions & 2 deletions src/types/onyx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ import type {
NonPersonalAndWorkspaceCardListDerivedValue,
OneOnOneChatReportIDsDerivedValue,
OutstandingReportsByPolicyIDDerivedValue,
PersonalAndWorkspaceCardListDerivedValue,
ReportAttributesDerivedValue,
ReportTransactionsAndViolationsDerivedValue,
SortedReportActionsDerivedValue,
Expand Down Expand Up @@ -499,7 +498,6 @@ export type {
VisibleReportActionsDerivedValue,
SortedReportActionsDerivedValue,
NonPersonalAndWorkspaceCardListDerivedValue,
PersonalAndWorkspaceCardListDerivedValue,
CardFeedErrorsDerivedValue,
LoginToAccountIDMapDerivedValue,
GuideAccountIDsDerivedValue,
Expand Down
Loading