Skip to content

Commit

Permalink
feat: add mdoc presentation (#199)
Browse files Browse the repository at this point in the history
Signed-off-by: Timo Glastra <[email protected]>
  • Loading branch information
TimoGlastra authored and Berend Sliedrecht committed Nov 6, 2024
1 parent 21c144a commit 359d058
Show file tree
Hide file tree
Showing 19 changed files with 1,242 additions and 971 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { FunkeRequestedAttributesDetailScreen } from '@easypid/features/share/FunkeRequestedAttributesDetailScreen'
import type { CredentialForDisplayId } from '@package/agent'
import { useLocalSearchParams } from 'expo-router'

export default function Screen() {
const { disclosedPayload, disclosedAttributeLength, id } = useLocalSearchParams<{
disclosedPayload: string
disclosedAttributeLength: string
id: string
id: CredentialForDisplayId
}>()

return (
Expand Down
16 changes: 8 additions & 8 deletions apps/easypid/src/features/activity/FunkeActivityDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function FunkeActivityDetailScreen() {
const { params } = useParams()
const router = useRouter()
const { bottom } = useSafeAreaInsets()
const { credential: pidCredential } = usePidCredential()
const { pidCredentialForDisplay } = usePidCredential()

const { activities } = useActivities()
const { credentials } = useCredentialsWithCustomDisplay()
Expand Down Expand Up @@ -96,13 +96,13 @@ export function FunkeActivityDetailScreen() {
if (isPidCredential(credential.metadata.type)) {
return (
<CardWithAttributes
key={pidCredential?.id}
id={pidCredential?.id as string}
name={pidCredential?.display.name as string}
issuerImage={pidCredential?.display.issuer.logo}
backgroundImage={pidCredential?.display.backgroundImage}
backgroundColor={pidCredential?.display.backgroundColor}
textColor={pidCredential?.display.textColor}
key={pidCredentialForDisplay?.id}
id={pidCredentialForDisplay?.id as string}
name={pidCredentialForDisplay?.display.name as string}
issuerImage={pidCredentialForDisplay?.display.issuer.logo}
backgroundImage={pidCredentialForDisplay?.display.backgroundImage}
backgroundColor={pidCredentialForDisplay?.display.backgroundColor}
textColor={pidCredentialForDisplay?.display.textColor}
disclosedAttributes={getPidDisclosedAttributeNames(
activityCredential?.disclosedPayload ?? {},
credential?.claimFormat as ClaimFormat.SdJwtVc | ClaimFormat.MsoMdoc
Expand Down
6 changes: 3 additions & 3 deletions apps/easypid/src/features/menu/FunkeMenuScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ const menuItems = [
export function FunkeMenuScreen() {
const { handleScroll, isScrolledByOffset, scrollEventThrottle } = useScrollViewPosition()
const onResetWallet = useWalletReset()
const { credential } = usePidCredential()
const { pidCredentialForDisplay } = usePidCredential()

const idItem = credential ? (
const idItem = pidCredentialForDisplay ? (
<MenuItem
key="id"
item={{
href: `credentials/${credential.id}`,
href: `credentials/${pidCredentialForDisplay.id}`,
icon: HeroIcons.IdentificationFilled,
title: 'Your digital ID',
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
import { useSeedCredentialPidData } from '@easypid/storage'
import { getOpenIdFedIssuerMetadata } from '@easypid/utils/issuer'
import { usePushToWallet } from '@package/app/src/hooks/usePushToWallet'
import { usePidCredential } from '../../hooks'
import { isPidCredential } from '../../hooks'
import { addSharedActivity, useActivities } from '../activity/activityRecord'
import { FunkePresentationNotificationScreen } from './FunkePresentationNotificationScreen'

Expand All @@ -40,7 +40,6 @@ export function FunkeOpenIdPresentationNotificationScreen() {
const pushToWallet = usePushToWallet()
const { agent } = useAppAgent()
const { seedCredential } = useSeedCredentialPidData()
const { credential: pidCredential } = usePidCredential()
const { activities } = useActivities()

const [credentialsForRequest, setCredentialsForRequest] =
Expand Down Expand Up @@ -102,10 +101,10 @@ export function FunkeOpenIdPresentationNotificationScreen() {
const usePin = useMemo(() => {
const isPidInSubmission =
submission?.entries.some((entry) =>
entry.credentials.some((credential) => credential.id === pidCredential?.id)
entry.credentials.some((credential) => isPidCredential(credential.metadata?.type))
) ?? false
return isPidInSubmission && !!seedCredential
}, [submission, pidCredential, seedCredential])
}, [submission, seedCredential])

useEffect(() => {
if (credentialsForRequest) return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ import React, { useEffect, useRef, useState } from 'react'
import { CredentialAttributes, TextBackButton } from '@package/app/src/components'
import { useHaptics, useHasInternetConnection, useScrollViewPosition } from '@package/app/src/hooks'

import { useCredentialsWithCustomDisplay } from '@easypid/hooks/useCredentialsWithCustomDisplay'
import { useCredentialsWithCustomDisplayById } from '@easypid/hooks/useCredentialsWithCustomDisplay'
import type { CredentialForDisplayId } from '@package/agent'
import { useNavigation } from 'expo-router'
import { FadeInUp, FadeOutUp } from 'react-native-reanimated'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

interface FunkeRequestedAttributesDetailScreenProps {
id: string
id: CredentialForDisplayId
disclosedPayload: Record<string, unknown>
disclosedAttributeLength: number
}
Expand All @@ -41,14 +42,12 @@ export function FunkeRequestedAttributesDetailScreen({
const toast = useToastController()
const { handleScroll, isScrolledByOffset, scrollEventThrottle } = useScrollViewPosition()
const { bottom } = useSafeAreaInsets()
const { isLoading, credentials } = useCredentialsWithCustomDisplay()
const { credential: activeCredential, isLoading } = useCredentialsWithCustomDisplayById(id)
const router = useRouter()
const [scrollViewHeight, setScrollViewHeight] = useState(0)
const { withHaptics } = useHaptics()
const navigation = useNavigation()

const activeCredential = credentials.find((cred) => cred.id.includes(id))

const [isSheetOpen, setIsSheetOpen] = useState(false)
const scrollViewRef = useRef<ScrollViewRefType>(null)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type RequestedAttributesSectionProps = {
}

export function RequestedAttributesSection({ submission }: RequestedAttributesSectionProps) {
const { credential: pidCredential } = usePidCredential()
const { pidCredentialForDisplay } = usePidCredential()

return (
<YStack gap="$4">
Expand All @@ -32,13 +32,13 @@ export function RequestedAttributesSection({ submission }: RequestedAttributesSe
if (isPidCredential(credential.metadata?.type)) {
return (
<CardWithAttributes
key={pidCredential?.id}
id={pidCredential?.id as string}
name={pidCredential?.display.name as string}
issuerImage={pidCredential?.display.issuer.logo}
backgroundImage={pidCredential?.display.backgroundImage}
backgroundColor={pidCredential?.display.backgroundColor}
textColor={pidCredential?.display.textColor}
key={pidCredentialForDisplay?.id}
id={pidCredentialForDisplay?.id as string}
name={pidCredentialForDisplay?.display.name as string}
issuerImage={pidCredentialForDisplay?.display.issuer.logo}
backgroundImage={pidCredentialForDisplay?.display.backgroundImage}
backgroundColor={pidCredentialForDisplay?.display.backgroundColor}
textColor={pidCredentialForDisplay?.display.textColor}
disclosedAttributes={getPidDisclosedAttributeNames(
credential?.disclosedPayload ?? {},
credential?.claimFormat as ClaimFormat.SdJwtVc | ClaimFormat.MsoMdoc
Expand Down
15 changes: 6 additions & 9 deletions apps/easypid/src/features/wallet/FunkeCredentialDetailScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ import React, { useState } from 'react'
import { useHeaderRightAction, useScrollViewPosition } from '@package/app/src/hooks'
import { DeleteCredentialSheet, TextBackButton } from 'packages/app'

import { useCredentialsWithCustomDisplay } from '@easypid/hooks/useCredentialsWithCustomDisplay'
import { useCredentialsWithCustomDisplayById } from '@easypid/hooks/useCredentialsWithCustomDisplay'
import type { CredentialForDisplayId } from '@package/agent'
import { useRouter } from 'expo-router'
import { useHaptics } from 'packages/app'
import { CardInfoLifecycle, FunkeCredentialCard } from 'packages/app/src/components'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { createParam } from 'solito'
import { usePidCredential } from '../../hooks'
import { isPidCredential } from '../../hooks'

const { useParams } = createParam<{ id: string }>()
const { useParams } = createParam<{ id: CredentialForDisplayId }>()

export function FunkeCredentialDetailScreen() {
const toast = useToastController()
Expand All @@ -33,17 +34,13 @@ export function FunkeCredentialDetailScreen() {
const { bottom } = useSafeAreaInsets()
const { withHaptics } = useHaptics()

const { credentials } = useCredentialsWithCustomDisplay()
const { credential: pidCredential } = usePidCredential()
const isPidCredential = pidCredential?.id.includes(params.id)
const credential = isPidCredential ? pidCredential : credentials.find((cred) => cred.id.includes(params.id))

const { credential } = useCredentialsWithCustomDisplayById(params.id)
const [isSheetOpen, setIsSheetOpen] = useState(false)

useHeaderRightAction({
icon: <HeroIcons.Trash />,
onPress: withHaptics(() => setIsSheetOpen(true)),
renderCondition: !isPidCredential,
renderCondition: !isPidCredential(credential?.metadata.type),
})

if (!credential) {
Expand Down
58 changes: 43 additions & 15 deletions apps/easypid/src/hooks/useCredentialsWithCustomDisplay.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,53 @@
import { type CredentialForDisplay, useCredentialsForDisplay } from 'packages/agent/src'
import { type CredentialForDisplay, type CredentialForDisplayId, useCredentialsForDisplay } from '@package/agent'
import { useMemo } from 'react'
import { type PidSdJwtVcAttributes, usePidCredential } from './usePidCredential'

type CustomCredentialForDisplay = CredentialForDisplay & {
attributesForDisplay: PidSdJwtVcAttributes
metadataForDisplay: Record<string, unknown>
attributesForDisplay?: PidSdJwtVcAttributes
metadataForDisplay?: Record<string, unknown>
}

export const useCredentialsWithCustomDisplay = () => {
const credentials = useCredentialsForDisplay()
const pidCredential = usePidCredential()
export const useCredentialsWithCustomDisplayById = (id: CredentialForDisplayId) => {
const { credentials, isLoading } = useCredentialsWithCustomDisplay(true)

// replace PID credential with custom one
const index = credentials.credentials.findIndex(
(credential) => credential.metadata.type === pidCredential.credential?.type
)
if (index !== -1 && pidCredential.credential) {
credentials.credentials[index] = pidCredential.credential as CredentialForDisplay
return {
// NOTE: we support both the prefixed id and non-prefixed. We should fix the input id
// but for now this is the easiest approach
credential: useMemo(() => credentials.find((c) => c.id === id || c.id.endsWith(id)), [id, credentials]),
isLoading,
}
}

export const useCredentialsWithCustomDisplay = (includeHiddenCredentials = false) => {
const { credentials, isLoading: isLoadingCredentialsForDisplay } = useCredentialsForDisplay()
const {
pidCredentialForDisplay: pidCredential,
credentialIds: pidCredentialIds,
credentials: pidCredentials,
isLoading: isLoadingPidCredential,
} = usePidCredential()

const filteredCredentials = useMemo(() => {
const pidIndex = credentials.findIndex((c) => c.id === pidCredential?.id)
const withoutPids = credentials
.filter((c) => !pidCredentialIds?.includes(c.id))
.map((c) => ({ ...c, isPid: false }))

// No pids, just return
if (pidIndex === -1 || !pidCredential) return withoutPids

// Insert only one of the pids
return [
...withoutPids.slice(0, pidIndex),
...(includeHiddenCredentials
? pidCredentials.map((p) => ({ ...p, isPid: true }))
: [{ ...pidCredential, isPid: true }]),
...withoutPids.slice(pidIndex),
]
}, [credentials, pidCredential, pidCredentials, pidCredentialIds, includeHiddenCredentials])

return credentials as {
credentials: CustomCredentialForDisplay[]
isLoading: boolean
return {
credentials: filteredCredentials as CustomCredentialForDisplay[],
isLoading: isLoadingCredentialsForDisplay || isLoadingPidCredential,
}
}
Loading

0 comments on commit 359d058

Please sign in to comment.