diff --git a/packages/legacy/core/App/contexts/configuration.tsx b/packages/legacy/core/App/contexts/configuration.tsx index e74a4f83b5..4479dcafc2 100644 --- a/packages/legacy/core/App/contexts/configuration.tsx +++ b/packages/legacy/core/App/contexts/configuration.tsx @@ -59,6 +59,8 @@ export interface ConfigurationContext { globalScreenOptions?: StackNavigationOptions showDetailsInfo?: boolean getCredentialHelpDictionary?: GetCredentialHelpEntry[] + contactHideList?: string[] + credentialHideList?: string[] } export const ConfigurationContext = createContext(null as unknown as ConfigurationContext) diff --git a/packages/legacy/core/App/screens/ListContacts.tsx b/packages/legacy/core/App/screens/ListContacts.tsx index d70d3ad604..77c79a4c89 100644 --- a/packages/legacy/core/App/screens/ListContacts.tsx +++ b/packages/legacy/core/App/screens/ListContacts.tsx @@ -8,6 +8,7 @@ import { FlatList, StyleSheet, View } from 'react-native' import HeaderButton, { ButtonLocation } from '../components/buttons/HeaderButton' import ContactListItem from '../components/listItems/ContactListItem' import EmptyListContacts from '../components/misc/EmptyListContacts' +import { useConfiguration } from '../contexts/configuration' import { useStore } from '../contexts/store' import { useTheme } from '../contexts/theme' import { ContactStackParams, Screens, Stacks } from '../types/navigators' @@ -32,10 +33,16 @@ const ListContacts: React.FC = ({ navigation }) => { }) const { records } = useConnections() const [store] = useStore() - // Filter out mediator agents + const { contactHideList } = useConfiguration() + // Filter out mediator agents and hidden contacts when not in dev mode let connections: ConnectionRecord[] = records if (!store.preferences.developerModeEnabled) { - connections = records.filter((r) => !r.connectionTypes.includes(ConnectionType.Mediator)) + connections = records.filter((r) => { + return ( + !r.connectionTypes.includes(ConnectionType.Mediator) && + !contactHideList?.includes((r.theirLabel || r.alias) ?? '') + ) + }) } const onPressAddContact = () => { diff --git a/packages/legacy/core/App/screens/ListCredentials.tsx b/packages/legacy/core/App/screens/ListCredentials.tsx index 32f77fb369..423a4aba8e 100644 --- a/packages/legacy/core/App/screens/ListCredentials.tsx +++ b/packages/legacy/core/App/screens/ListCredentials.tsx @@ -1,3 +1,4 @@ +import { AnonCredsCredentialMetadataKey } from '@aries-framework/anoncreds/build/utils/metadata' import { CredentialState } from '@aries-framework/core' import { useCredentialByState } from '@aries-framework/react-hooks' import { useNavigation } from '@react-navigation/core' @@ -18,18 +19,29 @@ import { TourID } from '../types/tour' const ListCredentials: React.FC = () => { const { t } = useTranslation() + const [store, dispatch] = useStore() const { credentialListOptions: CredentialListOptions, credentialEmptyList: CredentialEmptyList, enableTours: enableToursConfig, + credentialHideList, } = useConfiguration() - const credentials = [ + + let credentials = [ ...useCredentialByState(CredentialState.CredentialReceived), ...useCredentialByState(CredentialState.Done), ] + + // Filter out hidden credentials when not in dev mode + if (!store.preferences.developerModeEnabled) { + credentials = credentials.filter((r) => { + const credDefId = r.metadata.get(AnonCredsCredentialMetadataKey)?.credentialDefinitionId + return !credentialHideList?.includes(credDefId) + }) + } + const navigation = useNavigation>() const { ColorPallet } = useTheme() - const [store, dispatch] = useStore() const { start, stop } = useTour() const screenIsFocused = useIsFocused() diff --git a/packages/legacy/core/__tests__/screens/ListContacts.test.tsx b/packages/legacy/core/__tests__/screens/ListContacts.test.tsx index 1b9fab9007..0086bc70e6 100644 --- a/packages/legacy/core/__tests__/screens/ListContacts.test.tsx +++ b/packages/legacy/core/__tests__/screens/ListContacts.test.tsx @@ -5,6 +5,7 @@ import { act, fireEvent, render } from '@testing-library/react-native' import React from 'react' import { ConfigurationContext } from '../../App/contexts/configuration' +import { StoreProvider, defaultState } from '../../App/contexts/store' import ListContacts from '../../App/screens/ListContacts' import configurationContext from '../contexts/configuration' @@ -83,4 +84,56 @@ describe('ListContacts Component', () => { }) }) }) + + test('Hide list filters out specific contacts', async () => { + const navigation = useNavigation() + const tree = render( + + + + + + ) + await act(async () => {}) + + const faberContact = await tree.queryByText('Faber', { exact: false }) + const bobContact = await tree.queryByText('Bob', { exact: false }) + + expect(faberContact).toBe(null) + expect(bobContact).not.toBe(null) + }) + + test('Hide list does not filter out specific contacts when developer mode is enabled', async () => { + const navigation = useNavigation() + const tree = render( + + + + + + ) + await act(async () => {}) + + const faberContact = await tree.queryByText('Faber', { exact: false }) + const bobContact = await tree.queryByText('Bob', { exact: false }) + + expect(faberContact).not.toBe(null) + expect(bobContact).not.toBe(null) + }) }) diff --git a/packages/legacy/core/__tests__/screens/ListCredentials.test.tsx b/packages/legacy/core/__tests__/screens/ListCredentials.test.tsx index f9eb8ea7c5..584ab64681 100644 --- a/packages/legacy/core/__tests__/screens/ListCredentials.test.tsx +++ b/packages/legacy/core/__tests__/screens/ListCredentials.test.tsx @@ -9,6 +9,7 @@ import { ReactTestInstance } from 'react-test-renderer' import CredentialCard from '../../App/components/misc/CredentialCard' import { ConfigurationContext } from '../../App/contexts/configuration' +import { StoreProvider, defaultState } from '../../App/contexts/store' import ListCredentials from '../../App/screens/ListCredentials' import configurationContext from '../contexts/configuration' @@ -26,6 +27,8 @@ jest.mock('@react-navigation/native', () => { // eslint-disable-next-line @typescript-eslint/no-empty-function jest.mock('react-native-localize', () => {}) +const credentialDefinitionId = 'xxxxxxxxxxxxxxxxxx:3:CL:11111:default' + describe('displays a credentials list screen', () => { const testOpenVPCredentialRecord = new CredentialExchangeRecord({ threadId: '1', @@ -35,6 +38,7 @@ describe('displays a credentials list screen', () => { }) testOpenVPCredentialRecord.metadata.set(AnonCredsCredentialMetadataKey, { schemaId: 'Ui6HA36FvN83cEtmYYHxrn:2:unverified_person:0.1.0', + credentialDefinitionId, }) testOpenVPCredentialRecord.credentials.push({ credentialRecordType: 'anoncreds', @@ -126,4 +130,54 @@ describe('displays a credentials list screen', () => { expect(new Date(createdAtDates[2])).toEqual(new Date('2020-01-01T00:00:00')) }) }) + + test('Hide list filters out specific credentials', async () => { + const tree = render( + + + + + + ) + await act(async () => { + const credentialCards = tree.UNSAFE_getAllByType(CredentialCard) + + expect(credentialCards.length).toBe(2) + }) + }) + + test('Hide list does not filter out specific credentials when developer mode is enabled', async () => { + const tree = render( + + + + + + ) + await act(async () => { + const credentialCards = tree.UNSAFE_getAllByType(CredentialCard) + + expect(credentialCards.length).toBe(3) + }) + }) })