Skip to content

Commit

Permalink
feat:implement hide lists for credentials and contacts (#1088)
Browse files Browse the repository at this point in the history
Signed-off-by: Bryce McMath <[email protected]>
  • Loading branch information
bryce-mcmath authored Feb 14, 2024
1 parent 99f62c9 commit fd89d3c
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 4 deletions.
2 changes: 2 additions & 0 deletions packages/legacy/core/App/contexts/configuration.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export interface ConfigurationContext {
globalScreenOptions?: StackNavigationOptions
showDetailsInfo?: boolean
getCredentialHelpDictionary?: GetCredentialHelpEntry[]
contactHideList?: string[]
credentialHideList?: string[]
}

export const ConfigurationContext = createContext<ConfigurationContext>(null as unknown as ConfigurationContext)
Expand Down
11 changes: 9 additions & 2 deletions packages/legacy/core/App/screens/ListContacts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -32,10 +33,16 @@ const ListContacts: React.FC<ListContactsProps> = ({ 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 = () => {
Expand Down
16 changes: 14 additions & 2 deletions packages/legacy/core/App/screens/ListCredentials.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<StackNavigationProp<CredentialStackParams>>()
const { ColorPallet } = useTheme()
const [store, dispatch] = useStore()
const { start, stop } = useTour()
const screenIsFocused = useIsFocused()

Expand Down
53 changes: 53 additions & 0 deletions packages/legacy/core/__tests__/screens/ListContacts.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -83,4 +84,56 @@ describe('ListContacts Component', () => {
})
})
})

test('Hide list filters out specific contacts', async () => {
const navigation = useNavigation()
const tree = render(
<StoreProvider
initialState={{
...defaultState,
preferences: {
...defaultState.preferences,
developerModeEnabled: false,
},
}}
>
<ConfigurationContext.Provider value={{ ...configurationContext, contactHideList: ['Faber'] }}>
<ListContacts navigation={navigation as any} />
</ConfigurationContext.Provider>
</StoreProvider>
)
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(
<StoreProvider
initialState={{
...defaultState,
preferences: {
...defaultState.preferences,
developerModeEnabled: true,
},
}}
>
<ConfigurationContext.Provider value={{ ...configurationContext, contactHideList: ['Faber'] }}>
<ListContacts navigation={navigation as any} />
</ConfigurationContext.Provider>
</StoreProvider>
)
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)
})
})
54 changes: 54 additions & 0 deletions packages/legacy/core/__tests__/screens/ListCredentials.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand All @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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(
<StoreProvider
initialState={{
...defaultState,
preferences: {
...defaultState.preferences,
developerModeEnabled: false,
},
}}
>
<ConfigurationContext.Provider
value={{ ...configurationContext, credentialHideList: [credentialDefinitionId] }}
>
<ListCredentials />
</ConfigurationContext.Provider>
</StoreProvider>
)
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(
<StoreProvider
initialState={{
...defaultState,
preferences: {
...defaultState.preferences,
developerModeEnabled: true,
},
}}
>
<ConfigurationContext.Provider
value={{ ...configurationContext, credentialHideList: [credentialDefinitionId] }}
>
<ListCredentials />
</ConfigurationContext.Provider>
</StoreProvider>
)
await act(async () => {
const credentialCards = tree.UNSAFE_getAllByType(CredentialCard)

expect(credentialCards.length).toBe(3)
})
})
})

0 comments on commit fd89d3c

Please sign in to comment.