Skip to content

Commit

Permalink
feat: OpenID4VP common OCA UI (#1392)
Browse files Browse the repository at this point in the history
Signed-off-by: Mostafa Gamal <[email protected]>
Signed-off-by: Mostafa Gamal <[email protected]>
Co-authored-by: Bryce McMath <[email protected]>
  • Loading branch information
MosCD3 and bryce-mcmath authored Feb 13, 2025
1 parent 99f7e09 commit 1c620cb
Show file tree
Hide file tree
Showing 18 changed files with 333 additions and 154 deletions.
9 changes: 6 additions & 3 deletions packages/legacy/core/App/components/misc/ConnectionImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { useConnectionImageUrl } from '../../utils/helpers'

interface ConnectionImageProps {
connectionId?: string
imageUri?: string
marginTop?: number
}

const ConnectionImage: React.FC<ConnectionImageProps> = ({ connectionId }) => {
const ConnectionImage: React.FC<ConnectionImageProps> = ({ connectionId, imageUri, marginTop }) => {
const { ColorPallet } = useTheme()
const styles = StyleSheet.create({
connectionImageContainer: {
Expand All @@ -19,7 +21,7 @@ const ConnectionImage: React.FC<ConnectionImageProps> = ({ connectionId }) => {
alignItems: 'center',
justifyContent: 'center',
borderRadius: 45,
marginTop: 15,
marginTop: marginTop ?? 15,
borderColor: ColorPallet.grayscale.lightGrey,
borderWidth: 3,
alignSelf: 'center',
Expand All @@ -30,7 +32,8 @@ const ConnectionImage: React.FC<ConnectionImageProps> = ({ connectionId }) => {
},
})

const connectionImage = useConnectionImageUrl(connectionId ?? '')
const anonCredsImageUri = useConnectionImageUrl(connectionId ?? '')
const connectionImage = imageUri ? imageUri : anonCredsImageUri

return connectionImage ? (
<View style={styles.connectionImageContainer}>
Expand Down
40 changes: 27 additions & 13 deletions packages/legacy/core/App/components/misc/CredentialCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import CredentialCard10 from './CredentialCard10'
import CredentialCard11, { CredentialErrors } from './CredentialCard11'
import { GenericCredentialExchangeRecord } from '../../types/credentials'
import { BrandingOverlay } from '@hyperledger/aries-oca'
import { useOpenIDCredentials } from '../../modules/openid/context/OpenIDCredentialRecordProvider'
import { getCredentialForDisplay } from '../../modules/openid/display'
import { buildOverlayFromW3cCredential } from '../../utils/oca'
import { useTranslation } from 'react-i18next'
import { getAttributeField } from '../../modules/openid/utils/utils'

interface CredentialCardProps {
credential?: GenericCredentialExchangeRecord
Expand All @@ -27,6 +27,7 @@ interface CredentialCardProps {
hasAltCredentials?: boolean
credentialErrors?: CredentialErrors[]
handleAltCredChange?: () => void
brandingOverlay?: CredentialOverlay<BrandingOverlay>
}

const CredentialCard: React.FC<CredentialCardProps> = ({
Expand All @@ -41,30 +42,38 @@ const CredentialCard: React.FC<CredentialCardProps> = ({
style = {},
onPress = undefined,
credentialErrors,
brandingOverlay,
}) => {
// add ability to reference credential by ID, allows us to get past react hook restrictions
const [bundleResolver] = useServices([TOKENS.UTIL_OCA_RESOLVER])
const { ColorPallet } = useTheme()
const [overlay, setOverlay] = useState<CredentialOverlay<BrandingOverlay>>({})
const { i18n } = useTranslation()
const { resolveBundleForCredential } = useOpenIDCredentials()
const [extraOverlayAttribute, setExtraOverlayAttribute] = useState<string | number | null | undefined>()

useEffect(() => {
const resolveOverlay = async (w3cCred: W3cCredentialRecord) => {
const credentialDisplay = getCredentialForDisplay(w3cCred)

const resolvedOverlay = await buildOverlayFromW3cCredential({
credentialDisplay,
language: i18n.language,
resolver: bundleResolver,
})
if (brandingOverlay) {
setOverlay(brandingOverlay as unknown as CredentialOverlay<BrandingOverlay>)
return
}

setOverlay(resolvedOverlay)
const resolveOverlay = async (w3cCred: W3cCredentialRecord) => {
const brandingOverlay = await resolveBundleForCredential(w3cCred)
setOverlay(brandingOverlay)
}

if (credential instanceof W3cCredentialRecord) {
resolveOverlay(credential)
const credentialDisplay = getCredentialForDisplay(credential)
if (credentialDisplay.display.primary_overlay_attribute) {
const attributeValue = getAttributeField(
credentialDisplay,
credentialDisplay.display.primary_overlay_attribute
)?.value
setExtraOverlayAttribute(attributeValue)
}
}
}, [credential, bundleResolver, i18n.language])
}, [credential, brandingOverlay, resolveBundleForCredential])

const getCredOverlayType = (type: BrandingOverlayType) => {
const isBranding10 = bundleResolver.getBrandingOverlayType() === BrandingOverlayType.Branding10
Expand Down Expand Up @@ -126,6 +135,11 @@ const CredentialCard: React.FC<CredentialCardProps> = ({
onPress={onPress}
brandingOverlay={overlay}
credentialErrors={credentialErrors ?? []}
proof={proof}
elevated={proof}
displayItems={displayItems}
hideSlice={true}
extraOverlayParameter={extraOverlayAttribute}
brandingOverlayType={bundleResolver.getBrandingOverlayType()}
/>
)
Expand Down
41 changes: 34 additions & 7 deletions packages/legacy/core/App/components/misc/CredentialCard11.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import CredentialActionFooter from './CredentialCard11ActionFooter'
import CredentialCard11Logo from './CredentialCard11Logo'
import useCredentialCardStyles from '../../hooks/credential-card-styles'
import CredentialIssuerBody from './CredentialCard11Issuer'
import { ColorValue } from 'react-native'

export enum CredentialErrors {
Revoked, // Credential has been revoked
Expand All @@ -54,6 +55,8 @@ interface CredentialCard11Props {
hasAltCredentials?: boolean
handleAltCredChange?: () => void
brandingOverlay?: CredentialOverlay<BrandingOverlay>
hideSlice?: boolean
extraOverlayParameter?: string | number | null | undefined
brandingOverlayType?: BrandingOverlayType
}

Expand Down Expand Up @@ -100,6 +103,8 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
credentialErrors = [],
handleAltCredChange,
brandingOverlay,
hideSlice = false,
extraOverlayParameter,
brandingOverlayType = BrandingOverlayType.Branding10,
}) => {
const [dimensions, setDimensions] = useState({ cardWidth: 0, cardHeight: 0 })
Expand Down Expand Up @@ -420,6 +425,11 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
</Text>
</View>
</View>
{extraOverlayParameter && (
<View style={{ flex: 1, justifyContent: 'flex-end' }}>
<Text style={TextTheme.caption}>{extraOverlayParameter}</Text>
</View>
)}

{/* Render Error text at the top of the credential card */}
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
Expand Down Expand Up @@ -466,23 +476,28 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
)
}

function getSliceBackgroundColor(): ColorValue | undefined {
if (hideSlice) return 'transparent'
return brandingOverlayType === BrandingOverlayType.Branding10
? backgroundColorIfRevoked(styles.secondaryBodyContainer.backgroundColor)
: overlay.brandingOverlay?.secondaryBackgroundColor
}

const CredentialCardSecondaryBody: React.FC = () => {
return (
<View
testID={testIdWithKey('CredentialCardSecondaryBody')}
style={[
styles.secondaryBodyContainer,
{
backgroundColor:
brandingOverlayType === BrandingOverlayType.Branding10
? backgroundColorIfRevoked(styles.secondaryBodyContainer.backgroundColor)
: overlay.brandingOverlay?.secondaryBackgroundColor,
backgroundColor: getSliceBackgroundColor() ?? ColorPallet.brand.secondaryBackground,
overflow: 'hidden',
},
]}
>
{overlay.brandingOverlay?.backgroundImageSlice &&
(!displayItems || brandingOverlayType === BrandingOverlayType.Branding11) ? (
(!displayItems || brandingOverlayType === BrandingOverlayType.Branding11) &&
!hideSlice ? (
<ImageBackground
source={toImageSource(overlay.brandingOverlay?.backgroundImageSlice)}
style={{ flexGrow: 1 }}
Expand All @@ -492,7 +507,8 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
}}
/>
) : (
!(Boolean(credentialErrors.length) || proof || getSecondaryBackgroundColor(overlay, proof)) && (
!(Boolean(credentialErrors.length) || proof || getSecondaryBackgroundColor(overlay, proof)) &&
!hideSlice && (
<View
style={[
{
Expand Down Expand Up @@ -542,7 +558,7 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
}

const CredentialCard: React.FC<{ status?: 'error' | 'warning' }> = ({ status }) => {
return (
const MainCredentialBody = () => (
<View
style={styles.cardContainer}
accessible={true}
Expand Down Expand Up @@ -571,6 +587,17 @@ const CredentialCard11: React.FC<CredentialCard11Props> = ({
<CredentialCardStatus status={status} />
</View>
)
return (
<>
{overlay.brandingOverlay?.backgroundImage && hideSlice ? (
<ImageBackground source={toImageSource(overlay.brandingOverlay?.backgroundImage)}>
<MainCredentialBody />
</ImageBackground>
) : (
<MainCredentialBody />
)}
</>
)
}

const getCredentialStatus = (): 'error' | 'warning' | undefined => {
Expand Down
1 change: 1 addition & 0 deletions packages/legacy/core/App/components/record/Record.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const Record: React.FC<RecordProps> = ({ header, footer, fields, hideFieldValues
<FlatList
data={fields}
keyExtractor={({ name }, index) => name || index.toString()}
showsVerticalScrollIndicator={false}
renderItem={({ item: attr, index }) =>
field ? (
field(attr, index, fields)
Expand Down
Loading

0 comments on commit 1c620cb

Please sign in to comment.