-
Notifications
You must be signed in to change notification settings - Fork 508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(Mobile): add notifications opt-In screen #4837
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
94c8099
chore: adds new images for notification onboarding optIn
Jonathansoufer 524acd0
refactor: enables notifications method on hook
Jonathansoufer 7d2c598
refactor: adds Notification item & adpat for new 2 button pattern
Jonathansoufer b19c9f6
refactor: adds new variant to button
Jonathansoufer a03c88d
refactor: adds logic to handle themed driven images & buttons
Jonathansoufer 0f00dc4
chore: adds jest mocks and fix tests
Jonathansoufer 9f8c41b
chore: adds navigation and onboarding awareness to Service
Jonathansoufer 18eb08a
refactor: rollbacks Onboarding changes in favour of OptIn screens
Jonathansoufer 65456b5
feat: adds reusable floating view
Jonathansoufer 5699283
feat: adds reusable OptIn component
Jonathansoufer 7b54196
refactor: rollback tests changes on onboarding flow
Jonathansoufer 8e861bb
chore: adds auxiliary constants
Jonathansoufer 340dccf
chore: moves mock to central place
Jonathansoufer 849b093
feat: adds optIn on navigation stack
Jonathansoufer 8bcd072
chore: adds a (temp) icon for enable notification OptIn
Jonathansoufer 248be14
refactor: adds new UX on how Notifications will be propmt to be enabled
Jonathansoufer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React from 'react' | ||
import { useColorScheme } from 'react-native' | ||
import { OptIn } from '@/src/components/OptIn' | ||
import useNotifications from '@/src/hooks/useNotifications' | ||
import { router, useFocusEffect } from 'expo-router' | ||
|
||
function NotificationsOptIn() { | ||
const { enableNotifications, isAppNotificationEnabled } = useNotifications() | ||
const colorScheme = useColorScheme() | ||
|
||
useFocusEffect(() => { | ||
if (isAppNotificationEnabled) { | ||
router.replace('/(tabs)') | ||
} | ||
}) | ||
|
||
const image = | ||
colorScheme === 'dark' | ||
? require('@/assets/images/notifications-dark.png') | ||
: require('@/assets/images/notifications-light.png') | ||
|
||
return ( | ||
<OptIn | ||
testID="notifications-opt-in" | ||
title="Stay in the loop with account activity" | ||
description="Get notified when you receive assets, and when transactions require your action." | ||
image={image} | ||
isVisible | ||
ctaButton={{ | ||
onPress: enableNotifications, | ||
label: 'Enable notifications', | ||
}} | ||
secondaryButton={{ | ||
onPress: () => router.back(), | ||
label: 'Maybe later', | ||
}} | ||
/> | ||
) | ||
} | ||
|
||
export default NotificationsOptIn |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
apps/mobile/src/components/FloatingContainer/FloatingContainer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import { Layout } from '@/src/store/constants' | ||
import React, { FC, useMemo } from 'react' | ||
import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||
|
||
import { KeyboardAvoidingView, KeyboardAvoidingViewProps, Platform, StyleSheet, View } from 'react-native' | ||
|
||
interface FloatingContainerProps { | ||
children: React.ReactNode | ||
noOffset?: boolean | ||
sticky?: boolean | ||
keyboardAvoidEnabled?: boolean | ||
onLayout?: KeyboardAvoidingViewProps['onLayout'] | ||
testID?: string | ||
} | ||
|
||
export const FloatingContainer: FC<FloatingContainerProps> = ({ | ||
children, | ||
noOffset, | ||
sticky, | ||
keyboardAvoidEnabled, | ||
onLayout, | ||
testID, | ||
}: FloatingContainerProps) => { | ||
const bottomInset = useSafeAreaInsets().bottom | ||
const deviceBottom = Layout.isSmallDevice ? 10 : 20 | ||
|
||
const bottomPadding = useMemo(() => { | ||
return Math.max(bottomInset, deviceBottom) | ||
}, [bottomInset]) | ||
|
||
const keyboardVerticalOffset = useMemo(() => { | ||
return noOffset ? 0 : Platform.select({ ios: 40, default: 0 }) | ||
}, [noOffset]) | ||
|
||
return ( | ||
<KeyboardAvoidingView | ||
testID={testID} | ||
behavior={sticky ? 'height' : 'position'} | ||
keyboardVerticalOffset={keyboardVerticalOffset} | ||
enabled={keyboardAvoidEnabled} | ||
style={[styles.floatingContainer, { paddingBottom: bottomPadding }]} | ||
onLayout={onLayout} | ||
> | ||
<View style={styles.childContainer}>{children}</View> | ||
</KeyboardAvoidingView> | ||
) | ||
} | ||
|
||
const styles = StyleSheet.create({ | ||
floatingContainer: { | ||
position: 'fixed', | ||
bottom: -40, | ||
width: '100%', | ||
zIndex: 1, | ||
}, | ||
childContainer: { | ||
flexDirection: 'column', | ||
justifyContent: 'space-between', | ||
flexGrow: 1, | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import { FloatingContainer } from './FloatingContainer' | ||
export { FloatingContainer } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React from 'react' | ||
import { ImageSourcePropType, StyleSheet } from 'react-native' | ||
import { View, Image, Text } from 'tamagui' | ||
import { SafeButton } from '@/src/components/SafeButton' | ||
import { WINDOW_HEIGHT } from '@/src/store/constants' | ||
import { FloatingContainer } from '../FloatingContainer' | ||
|
||
interface OptInProps { | ||
title: string | ||
ctaButton: { | ||
onPress: () => void | ||
label: string | ||
} | ||
kicker?: string | ||
description?: string | ||
image?: ImageSourcePropType | ||
secondaryButton?: { | ||
onPress: () => void | ||
label: string | ||
} | ||
testID?: string | ||
isVisible?: boolean | ||
} | ||
|
||
export const OptIn: React.FC<OptInProps> = React.memo( | ||
({ testID, kicker, title, description, image, ctaButton, secondaryButton, isVisible }: OptInProps) => { | ||
if (!isVisible) { | ||
return | ||
} | ||
|
||
return ( | ||
<View | ||
testID={testID} | ||
style={styles.wrapper} | ||
padding="$4" | ||
gap="$8" | ||
alignItems="center" | ||
justifyContent="flex-start" | ||
> | ||
{kicker && ( | ||
<Text textAlign="center" fontWeight={700} fontSize="$4" lineHeight="$6"> | ||
{kicker} | ||
</Text> | ||
)} | ||
<Text textAlign="center" fontWeight={600} fontSize="$8" lineHeight="$8"> | ||
{title} | ||
</Text> | ||
{description && ( | ||
<Text textAlign="center" fontWeight={400} fontSize="$4"> | ||
{description} | ||
</Text> | ||
)} | ||
{image && <Image style={styles.image} source={image} />} | ||
|
||
<FloatingContainer sticky testID="notifications-opt-in-cta-buttons"> | ||
<SafeButton onPress={ctaButton.onPress} label={ctaButton.label} /> | ||
{secondaryButton && ( | ||
<SafeButton variant="secondary" onPress={secondaryButton.onPress} label={secondaryButton.label} /> | ||
)} | ||
</FloatingContainer> | ||
</View> | ||
) | ||
}, | ||
) | ||
|
||
const styles = StyleSheet.create({ | ||
wrapper: { | ||
flex: 1, | ||
}, | ||
image: { | ||
width: '100%', | ||
height: Math.abs(WINDOW_HEIGHT * 0.42), | ||
}, | ||
}) | ||
|
||
OptIn.displayName = 'OptIn' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import { OptIn } from './OptIn' | ||
export { OptIn } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 1 addition & 13 deletions
14
apps/mobile/src/features/Onboarding/Onboarding.container.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,7 @@ | ||
import React from 'react' | ||
import { OnboardingCarousel } from './components/OnboardingCarousel' | ||
import { items } from './components/OnboardingCarousel/items' | ||
import { useRouter } from 'expo-router' | ||
import { SafeButton } from '@/src/components/SafeButton' | ||
|
||
export function Onboarding() { | ||
const router = useRouter() | ||
|
||
const onGetStartedPress = () => { | ||
router.navigate('/(tabs)') | ||
} | ||
|
||
return ( | ||
<OnboardingCarousel items={items}> | ||
<SafeButton onPress={onGetStartedPress} label="Get started" /> | ||
</OnboardingCarousel> | ||
) | ||
return <OnboardingCarousel items={items} /> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is weird. The AssetsContainer should not care about notifications.
Get some inspiration from here:
https://docs.expo.dev/router/reference/authentication/
https://reactnavigation.org/docs/auth-flow
I think that the _layout.tsx should be the place where we decide what first screen we show to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I completely get your point here, but we don't wanna spam our users before the Onboarding, and if we use _layout, this takes place before anything. The other alternative would be calling it at HomeScreen, wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the user clicks on "get started/continue" in the onboarding flow we should set a flag "onboarding_done": true. Next time the user starts we should not show the onboarding screens. So we will be deciding in the _layout.tsx which screen to show anyway.