Skip to content

Commit

Permalink
feat: new home screen (#259)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan <[email protected]>
  • Loading branch information
janrtvld authored Jan 8, 2025
1 parent 4bed66a commit 58a5049
Show file tree
Hide file tree
Showing 38 changed files with 631 additions and 574 deletions.
36 changes: 36 additions & 0 deletions apps/easypid/assets/Blob.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { View } from 'react-native'
import Svg, { Path, G, type SvgProps, Defs, LinearGradient, Stop } from 'react-native-svg'

export function Blob({ color = 'black', ...props }: SvgProps) {
return (
<View style={{ width: '100%', aspectRatio: 393 / 471 }}>
<Svg width="100%" height="100%" viewBox="0 0 393 471" fill="none" {...props}>
<Path d="M0 0H393V451.5C251 475 143.5 477.506 0 451.5V0Z" fill="url(#paint0_linear_2268_545)" />
<G style={{ mixBlendMode: 'multiply', opacity: 0.65 }}>
<Path
d="M339.083 66.6639C331.109 153.347 240.586 158.69 196.079 212.134C162.606 252.33 161.812 300.955 135.753 342.996C75.479 440.234 -68.764 372.214 -105.311 285.451C-123.221 242.915 -116.624 198.794 -122.417 154.556C-130.644 91.7355 -184.073 -33.0719 -109.846 -71.7469C-57.4715 -99.0268 -8.93476 -35.334 34.1246 -15.6674C107.821 17.9942 196.501 -35.4184 272.601 -12.7329C306.399 -2.65453 342.605 28.2988 339.066 66.644L339.083 66.6639Z"
fill="#DFE7FA"
/>
</G>
<Path
opacity="0.4"
d="M121.77 314.308C112.062 343.686 86.1153 369.847 54.3033 372.691C29.0387 374.87 5.12616 361.79 -12.3284 344.487C-25.1756 331.79 -35.3742 317.128 -42.99 301.252C-43.1388 301.005 -43.0706 300.638 -42.7967 300.518C-42.5805 300.425 -42.3404 300.475 -42.1898 300.665L-34.0965 310.74C-28.6937 317.22 -22.6676 323.777 -16.6515 329.735C11.9817 358.048 49.1554 375.931 86.3997 351.398C100.573 341.824 112.244 328.562 120.889 313.84C121.024 313.603 121.325 313.513 121.577 313.663C121.814 313.798 121.891 314.085 121.784 314.323L121.77 314.308Z"
fill="white"
/>
<Defs>
<LinearGradient
id="paint0_linear_2268_545"
x1="196.5"
y1="0"
x2="196.5"
y2="470.077"
gradientUnits="userSpaceOnUse"
>
<Stop stopColor="#F1F4FD" />
<Stop offset="1" stopColor="#DFE7FA" />
</LinearGradient>
</Defs>
</Svg>
</View>
)
}
5 changes: 5 additions & 0 deletions apps/easypid/src/app/(app)/(home)/offline.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { FunkeOfflineQrScreen } from '@easypid/features/wallet/FunkeOfflineQrScreen'

export default function Screen() {
return <FunkeOfflineQrScreen />
}
5 changes: 2 additions & 3 deletions apps/easypid/src/app/(app)/(home)/scan.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { FunkeQrScannerScreen } from '@easypid/features/scan/FunkeQrScannerScreen'
import type { CredentialDataHandlerOptions } from '@package/app'
import { type CredentialDataHandlerOptions, QrScannerScreen } from '@package/app'

// When going form the scanner we want to replace (as we have the modal)
export const credentialDataHandlerOptions = {
routeMethod: 'replace',
} satisfies CredentialDataHandlerOptions

export default function Screen() {
return <FunkeQrScannerScreen credentialDataHandlerOptions={credentialDataHandlerOptions} />
return <QrScannerScreen credentialDataHandlerOptions={credentialDataHandlerOptions} />
}
6 changes: 6 additions & 0 deletions apps/easypid/src/app/(app)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ export default function AppLayout() {
}}
name="(home)/scan"
/>
<Stack.Screen
options={{
presentation: 'modal',
}}
name="(home)/offline"
/>
<Stack.Screen
name="notifications/openIdPresentation"
options={{
Expand Down
20 changes: 1 addition & 19 deletions apps/easypid/src/app/(app)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,5 @@
import { FunkeWalletScreen } from '@easypid/features/wallet/FunkeWalletScreen'
import { XStack } from '@package/ui'
import { Stack } from 'expo-router'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

export default function Screen() {
const { top } = useSafeAreaInsets()

return (
<>
<Stack.Screen
options={{
headerShown: true,
title: 'Home',
header: () => {
return <XStack h={top} bg="$background" />
},
}}
/>
<FunkeWalletScreen />
</>
)
return <FunkeWalletScreen />
}
23 changes: 10 additions & 13 deletions apps/easypid/src/app/onboarding/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useHasFinishedOnboarding, useOnboardingContext } from '@easypid/features/onboarding'
import { FlexPage, Heading, Paragraph, ProgressHeader, YStack } from '@package/ui'
import { useHaptics } from '@package/app'
import { AnimatedStack, FlexPage, Heading, Paragraph, ProgressHeader, YStack } from '@package/ui'
import type React from 'react'
import { useEffect, useRef } from 'react'
import { AccessibilityInfo, Alert } from 'react-native'
import { findNodeHandle } from 'react-native'
import Animated, { FadeIn, FadeInRight, FadeOut } from 'react-native-reanimated'

export default function OnboardingScreens() {
const { withHaptics } = useHaptics()
const [hasFinishedOnboarding] = useHasFinishedOnboarding()
const onboardingContext = useOnboardingContext()
const headerRef = useRef(null)
Expand All @@ -21,20 +23,20 @@ export default function OnboardingScreens() {
}
}, [onboardingContext.currentStep])

const onReset = () => {
const onReset = withHaptics(() => {
Alert.alert('Reset Onboarding', 'Are you sure you want to reset the onboarding process?', [
{
text: 'Cancel',
style: 'cancel',
},
{
text: 'Yes',
onPress: () => {
onPress: withHaptics(() => {
onboardingContext.reset()
},
}),
},
])
}
})

if (hasFinishedOnboarding) return null

Expand All @@ -43,10 +45,10 @@ export default function OnboardingScreens() {
page = onboardingContext.screen
} else {
page = (
<FlexPage gap="$2" jc="space-between">
<Animated.View entering={FadeIn.delay(300)}>
<FlexPage gap="$2" jc="space-between" bg="$background">
<AnimatedStack entering={FadeIn.delay(300)}>
<ProgressHeader enterAnimation progress={onboardingContext.progress} onBack={onReset} />
</Animated.View>
</AnimatedStack>

<Animated.View
key={onboardingContext.page.animationKey ?? onboardingContext.currentStep}
Expand All @@ -62,11 +64,6 @@ export default function OnboardingScreens() {
</Heading>
)}
{onboardingContext.page.subtitle && <Paragraph>{onboardingContext.page.subtitle}</Paragraph>}
{onboardingContext.page.caption && (
<Paragraph>
<Paragraph emphasis>Remember:</Paragraph> {onboardingContext.page.caption}
</Paragraph>
)}
</YStack>
{onboardingContext.screen}
</YStack>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export function FunkeActivityDetailScreen() {
'No information was provided on the purpose of the data request. Be cautious'
}
logo={activity.entity.logo}
overAskingResponse={{ validRequest: 'could_not_determine', reason: '' }}
/>
<Stack gap="$3">
<Stack gap="$2">
Expand Down
4 changes: 2 additions & 2 deletions apps/easypid/src/features/activity/FunkeActivityScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export function FunkeActivityScreen({ entityId }: { entityId?: string }) {
return (
<FlexPage gap="$0" paddingHorizontal="$0">
<YStack w="100%" top={0} borderBottomWidth="$0.5" borderColor={isScrolledByOffset ? '$grey-200' : '$background'}>
<YStack gap="$2" p="$4">
<Stack h="$1" />
<YStack p="$4" gap="$2">
<Stack h="$2" />
<Heading variant="h1">Activity</Heading>
</YStack>
</YStack>
Expand Down
4 changes: 2 additions & 2 deletions apps/easypid/src/features/menu/FunkeAboutScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export function FunkeAboutScreen() {
return (
<FlexPage gap="$0" paddingHorizontal="$0">
<YStack w="100%" top={0}>
<YStack gap="$4" p="$4">
<Stack h="$1" />
<YStack p="$4" gap="$2">
<Stack h="$2" />
<Heading variant="h1" fontWeight="$bold">
About the wallet
</Heading>
Expand Down
4 changes: 2 additions & 2 deletions apps/easypid/src/features/menu/FunkeFeedbackScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ export function FunkeFeedbackScreen() {
return (
<FlexPage gap="$0" paddingHorizontal="$0">
<YStack w="100%" top={0} borderBottomWidth="$0.5" borderColor={isScrolledByOffset ? '$grey-200' : '$background'}>
<YStack gap="$4" p="$4">
<Stack h="$1" />
<YStack p="$4" gap="$2">
<Stack h="$2" />
<Heading variant="h1" fontWeight="$bold">
Feedback
</Heading>
Expand Down
24 changes: 14 additions & 10 deletions apps/easypid/src/features/menu/FunkeMenuScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react'

import { useScrollViewPosition } from '@package/app/src/hooks'
import { useHaptics, useScrollViewPosition } from '@package/app/src/hooks'
import { Button, FlexPage, Heading, HeroIcons, ScrollView, Stack, XStack, YStack, useScaleAnimation } from '@package/ui'

import { usePidCredential } from '@easypid/hooks'
Expand Down Expand Up @@ -61,19 +61,16 @@ export function FunkeMenuScreen() {
icon: HeroIcons.IdentificationFilled,
title: 'Setup digital ID',
}}
onPress={onResetWallet}
idx={0}
/>
)

return (
<FlexPage gap="$0" paddingHorizontal="$0">
<YStack w="100%" top={0} borderBottomWidth="$0.5" borderColor={isScrolledByOffset ? '$grey-200' : '$background'}>
<YStack gap="$4" p="$4">
<Stack h="$1" />
<Heading variant="h1" fontWeight="$bold">
Menu
</Heading>
<YStack p="$4" gap="$2">
<Stack h="$2" />
<Heading variant="h1">Menu</Heading>
</YStack>
</YStack>
<ScrollView
Expand Down Expand Up @@ -112,6 +109,7 @@ export function FunkeMenuScreen() {

const MenuItem = ({ item, idx, onPress }: { item: (typeof menuItems)[number]; idx: number; onPress?: () => void }) => {
const { pressStyle, handlePressIn, handlePressOut } = useScaleAnimation()
const { withHaptics } = useHaptics()

const content = (
<XStack
Expand Down Expand Up @@ -148,7 +146,7 @@ const MenuItem = ({ item, idx, onPress }: { item: (typeof menuItems)[number]; id
<Stack
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onPress={() => Linking.openURL('mailto:[email protected]?subject=Feedback on the Funke EUDI Wallet')}
onPress={withHaptics(() => Linking.openURL('mailto:[email protected]?subject=Feedback on the Funke EUDI Wallet'))}
asChild
>
{content}
Expand All @@ -158,14 +156,20 @@ const MenuItem = ({ item, idx, onPress }: { item: (typeof menuItems)[number]; id

if (item.href === '/') {
return (
<Stack onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={onPress}>
<Stack onPressIn={handlePressIn} onPressOut={handlePressOut} onPress={withHaptics(() => onPress)}>
{content}
</Stack>
)
}

return (
<Link onPressIn={handlePressIn} onPressOut={handlePressOut} href={item.href} asChild>
<Link
onPress={withHaptics(() => undefined)}
onPressIn={handlePressIn}
onPressOut={handlePressOut}
href={item.href}
asChild
>
{content}
</Link>
)
Expand Down
4 changes: 2 additions & 2 deletions apps/easypid/src/features/menu/FunkeSettingsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export function FunkeSettingsScreen() {
return (
<FlexPage gap="$0" paddingHorizontal="$0">
<YStack w="100%" top={0} borderBottomWidth="$0.5" borderColor={isScrolledByOffset ? '$grey-200' : '$background'}>
<YStack gap="$4" p="$4">
<Stack h="$1" />
<YStack p="$4" gap="$2">
<Stack h="$2" />
<Heading variant="h1" fontWeight="$bold">
Settings
</Heading>
Expand Down
11 changes: 10 additions & 1 deletion apps/easypid/src/features/onboarding/onboardingContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
getCredentialForDisplay,
getCredentialForDisplayId,
} from '@package/agent'
import { useHaptics } from '@package/app'
import { secureWalletKey } from '@package/secure-store/secureUnlock'
import { useToastController } from '@package/ui'
import { capitalizeFirstLetter, getHostNameFromUrl, sleep } from '@package/utils'
Expand Down Expand Up @@ -142,6 +143,7 @@ export function OnboardingContextProvider({
}: PropsWithChildren<{
initialStep?: OnboardingStep['step']
}>) {
const { successHaptic, lightHaptic } = useHaptics()
const toast = useToastController()
const secureUnlock = useSecureUnlock()
const [currentStepName, setCurrentStepName] = useState<OnboardingStep['step']>(initialStep ?? 'welcome')
Expand All @@ -168,6 +170,12 @@ export function OnboardingContextProvider({
const currentStep = onboardingSteps.find((step) => step.step === currentStepName)
if (!currentStep) throw new Error(`Invalid step ${currentStepName}`)

useEffect(() => {
if (currentStepName && currentStepName !== 'welcome' && currentStepName !== 'pin-reenter') {
lightHaptic()
}
}, [lightHaptic, currentStepName])

const goToNextStep = useCallback(() => {
const currentStepIndex = onboardingSteps.findIndex((step) => step.step === currentStepName)
// goToNextStep excludes alternative flows
Expand Down Expand Up @@ -198,8 +206,9 @@ export function OnboardingContextProvider({
// Wait 500ms before navigating to home
setTimeout(() => {
router.replace('/')
successHaptic()
}, 500)
}, [router, setHasFinishedOnboarding, receivePidUseCase])
}, [router, setHasFinishedOnboarding, receivePidUseCase, successHaptic])

const onPinEnter = async (pin: string) => {
setWalletPin(pin)
Expand Down
3 changes: 2 additions & 1 deletion apps/easypid/src/features/onboarding/screens/id-card-pin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export const OnboardingIdCardPinEnter = forwardRef(({ goToNextStep }: Onboarding

return (
<YStack fg={1} jc="space-between" mb={shouldStickToBottom ? -16 : undefined}>
<ScrollView flex={1}>
{/* Overflow issue only present on smaller devices, so set to max height */}
<ScrollView flex={1} maxHeight={shouldStickToBottom ? 150 : undefined}>
<Stack jc="center">
<IdCard
backgroundImage={pidBackgroundImage}
Expand Down
7 changes: 6 additions & 1 deletion apps/easypid/src/features/pid/PidWalletPinSlide.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Heading, Paragraph, YStack } from '@package/ui'
import { PinDotsInput, type PinDotsInputRef, useWizard } from 'packages/app/src'
import { useRef, useState } from 'react'
import { useSafeAreaInsets } from 'react-native-safe-area-context'

interface PidWalletPinSlideProps {
title: string
Expand All @@ -13,6 +14,10 @@ export function PidWalletPinSlide({ title, subtitle, onEnterPin }: PidWalletPinS
const [isLoading, setIsLoading] = useState(false)
const ref = useRef<PinDotsInputRef>(null)

// Make the pin pad fixed to the bottom of the screen on smaller devices
const { bottom } = useSafeAreaInsets()
const shouldStickToBottom = bottom < 16

const onSubmitPin = async (pin: string) => {
if (isLoading) return
setIsLoading(true)
Expand All @@ -30,7 +35,7 @@ export function PidWalletPinSlide({ title, subtitle, onEnterPin }: PidWalletPinS
}

return (
<YStack fg={1} jc="space-between">
<YStack fg={1} jc="space-between" mb={shouldStickToBottom ? -16 : undefined}>
<YStack gap="$6">
<YStack gap="$3">
<Heading variant="h1">{title}</Heading>
Expand Down
20 changes: 13 additions & 7 deletions apps/easypid/src/features/proximity/mdocProximity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,19 @@ type ShareDeviceResponseOptions = {
submission: FormattedSubmission
}

const PERMISSIONS = [
'android.permission.ACCESS_FINE_LOCATION',
'android.permission.BLUETOOTH_CONNECT',
'android.permission.BLUETOOTH_SCAN',
'android.permission.BLUETOOTH_ADVERTISE',
'android.permission.ACCESS_COARSE_LOCATION',
] as const as Permission[]
// Determine if device is running Android 12 or higher
const isAndroid12OrHigher = Platform.OS === 'android' && Platform.Version >= 31

// Older devices require different permissions for BLE transfers
const PERMISSIONS = (
isAndroid12OrHigher
? [
'android.permission.BLUETOOTH_CONNECT',
'android.permission.BLUETOOTH_SCAN',
'android.permission.BLUETOOTH_ADVERTISE',
]
: ['android.permission.ACCESS_FINE_LOCATION', 'android.permission.ACCESS_COARSE_LOCATION']
) as Permission[]

export const requestMdocPermissions = async () => {
if (Platform.OS !== 'android') return
Expand Down
Loading

0 comments on commit 58a5049

Please sign in to comment.