diff --git a/packages/redux-devtools-inspector-monitor/src/ActionListHeader.tsx b/packages/redux-devtools-inspector-monitor/src/ActionListHeader.tsx index 961eaf36..70333c0c 100644 --- a/packages/redux-devtools-inspector-monitor/src/ActionListHeader.tsx +++ b/packages/redux-devtools-inspector-monitor/src/ActionListHeader.tsx @@ -9,6 +9,20 @@ const getActiveButtons = (hasSkippedActions: boolean): ('Sweep' | 'Commit')[] => (a): a is 'Sweep' | 'Commit' => !!a ); +const toggleButton = { + label: { + rtkq(val: boolean) { + return val ? 'Show rtk-query actions' : 'Hide rtk-query actions'; + }, + noop(val: boolean) { + return val ? 'Show noop actions' : 'Hide noop actions'; + }, + invertSearch(val: boolean) { + return val ? 'Disable inverse search' : 'Activate inverse search'; + }, + }, +}; + interface Props { styling: StylingFunction; onSearch: (value: string) => void; @@ -32,7 +46,8 @@ const ActionListHeader: FunctionComponent = ({ actionForm, onActionFormChange, }) => { - const { isNoopFilterActive, isRtkQueryFilterActive } = actionForm; + const { isNoopFilterActive, isRtkQueryFilterActive, isInvertSearchActive } = + actionForm; return ( <> @@ -44,9 +59,9 @@ const ActionListHeader: FunctionComponent = ({ />
+
{!hideMainButtons && ( @@ -115,6 +144,7 @@ ActionListHeader.propTypes = { searchValue: PropTypes.string.isRequired, isNoopFilterActive: PropTypes.bool.isRequired, isRtkQueryFilterActive: PropTypes.bool.isRequired, + isInvertSearchActive: PropTypes.bool.isRequired, }).isRequired, onActionFormChange: PropTypes.func.isRequired, }; diff --git a/packages/redux-devtools-inspector-monitor/src/redux.ts b/packages/redux-devtools-inspector-monitor/src/redux.ts index 7e3616fb..2553042d 100644 --- a/packages/redux-devtools-inspector-monitor/src/redux.ts +++ b/packages/redux-devtools-inspector-monitor/src/redux.ts @@ -8,9 +8,10 @@ const ACTION_FORM_VALUE_CHANGE = '@@redux-devtools-inspector-monitor/ACTION_FORM_VALUE_CHANGE'; export interface ActionForm { - searchValue: string; - isNoopFilterActive: boolean; - isRtkQueryFilterActive: boolean; + readonly searchValue: string; + readonly isNoopFilterActive: boolean; + readonly isRtkQueryFilterActive: boolean; + readonly isInvertSearchActive: boolean; } export interface UpdateMonitorStateAction { type: typeof UPDATE_MONITOR_STATE; @@ -57,6 +58,7 @@ export const DEFAULT_STATE: DevtoolsInspectorState = { searchValue: '', isNoopFilterActive: false, isRtkQueryFilterActive: false, + isInvertSearchActive: false, }, }; diff --git a/packages/redux-devtools-inspector-monitor/src/utils/filters.ts b/packages/redux-devtools-inspector-monitor/src/utils/filters.ts index 37c1ce80..ec3f8008 100644 --- a/packages/redux-devtools-inspector-monitor/src/utils/filters.ts +++ b/packages/redux-devtools-inspector-monitor/src/utils/filters.ts @@ -65,6 +65,24 @@ function filterOutRtkQueryActions( return typeof type !== 'string' || !rtkQueryRegex.test(type); }); } + +function invertSearchResults( + actionIds: number[], + filteredActionIds: number[] +): number[] { + if ( + actionIds.length === 0 || + actionIds.length === filteredActionIds.length || + filteredActionIds.length === 0 + ) { + return actionIds; + } + + const filteredSet = new Set(filteredActionIds); + + return actionIds.filter((actionId) => !filteredSet.has(actionId)); +} + export interface FilterActionsPayload> { readonly actionIds: number[]; readonly actions: Record>; @@ -94,6 +112,10 @@ function filterActions>({ output = filterOutRtkQueryActions(output, actions, rtkQueryRegex); } + if (actionForm.isInvertSearchActive) { + output = invertSearchResults(actionIds, output); + } + return output; }