Skip to content

Commit

Permalink
Merge branch 'develop' into YV-47-alt
Browse files Browse the repository at this point in the history
  • Loading branch information
stackchain authored Jan 20, 2025
2 parents a1b0c49 + fdc42e4 commit 710a649
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 19 deletions.
4 changes: 2 additions & 2 deletions apps/wallet-mobile/src/AppNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,6 @@ export const AppNavigator = () => {
onReady={onReady}
ref={navRef}
>
<NotificationUIHandler />

<ModalProvider>
<Stack.Navigator
screenOptions={{
Expand Down Expand Up @@ -229,6 +227,8 @@ export const AppNavigator = () => {
)}
</Stack.Navigator>
</ModalProvider>

<NotificationUIHandler />
</NavigationContainer>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {NotificationPopup} from './common/NotificationPopup'
import {NotificationStack} from './common/NotificationStack'

const displayLimit = 3
const displayTime = 20 * 1000

export const NotificationUIHandler = () => {
const enabled = useNotificationDisplaySettings()
Expand All @@ -29,6 +28,7 @@ export const NotificationUIHandler = () => {
event={event}
onCancel={() => removeEvent(event.id)}
onPress={() => removeEvent(event.id)}
onExpired={() => removeEvent(event.id)}
/>
))}
</NotificationStack>
Expand All @@ -38,14 +38,13 @@ export const NotificationUIHandler = () => {
const useCollectNewNotifications = ({enabled}: {enabled: boolean}) => {
const manager = useNotificationManager()
const walletManager = useWalletManager()
const selectedWalletId = walletManager.selected.wallet?.id
const selectedWalletId = walletManager.selected.wallet?.id ?? ''
const [events, setEvents] = React.useState<Notifications.Event[]>([])

React.useEffect(() => {
if (!enabled) return
const pushEvent = (event: Notifications.Event) => {
setEvents((e) => [...e, event])
setTimeout(() => setEvents((e) => e.filter((ev) => ev.id !== event.id)), displayTime)
}

const subscription = manager.newEvents$.subscribe((event) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const NotificationsDevScreen = () => {
const Screen = () => {
const manager = useNotificationManager()
const walletManager = useWalletManager()
const selectedWalletId = walletManager.selected.wallet?.id ?? 'walletId'
const selectedWalletId = walletManager.selected.wallet?.id ?? ''

const handleOnTriggerTransactionReceived = () => {
manager.events.push(
Expand All @@ -50,7 +50,7 @@ const Screen = () => {
<View style={{padding: 16, gap: 8}}>
<Text style={{fontSize: 24}}>Notifications Playground</Text>

<Button title="Trigger Transacrion Received Notification" onPress={handleOnTriggerTransactionReceived} />
<Button title="Trigger Transaction Received Notification" onPress={handleOnTriggerTransactionReceived} />

<Text style={{fontSize: 24}}>Settings</Text>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ type Props = {
event: Notifications.Event
onPress: () => void
onCancel: () => void
onExpired: () => void
}

export const NotificationPopup = ({event, onPress, onCancel}: Props) => {
export const NotificationPopup = ({event, onPress, onCancel, onExpired}: Props) => {
const navigation = useWalletNavigation()
const strings = useStrings()

if (event.trigger === Notifications.Trigger.TransactionReceived) {
return (
<SwipeOutWrapper onSwipeOut={onCancel}>
<SwipeOutWrapper onSwipeOut={onCancel} onExpired={onExpired}>
<NotificationItem
onPress={() => {
onPress()
Expand All @@ -37,7 +38,7 @@ export const NotificationPopup = ({event, onPress, onCancel}: Props) => {

if (event.trigger === Notifications.Trigger.RewardsUpdated) {
return (
<SwipeOutWrapper onSwipeOut={onCancel}>
<SwipeOutWrapper onSwipeOut={onCancel} onExpired={onExpired}>
<NotificationItem
onPress={() => {
onPress()
Expand Down Expand Up @@ -121,7 +122,7 @@ const useStyles = () => {
...atoms.gap_xs,
},
title: {
...atoms.body_2_md_regular,
...atoms.body_2_md_medium,
...atoms.font_semibold,
},
description: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const useStyles = () => {
left: 0,
right: 0,
...atoms.z_50,
...atoms.p_lg,
...atoms.px_lg,
},
flex: {
...atoms.gap_sm,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
import * as React from 'react'
import {Animated, Dimensions, PanResponder} from 'react-native'
import {Animated, Dimensions, Easing, PanResponder} from 'react-native'

type Props = {
children: React.ReactNode
onSwipeOut: () => void
onExpired: () => void
}

export const SwipeOutWrapper = ({children, onSwipeOut}: Props) => {
const {pan, panResponder} = usePanAnimation({onRelease: onSwipeOut})
const notificationDisplayTime = 20 * 1000 // 20 seconds
const fadeInTime = 200
const fadeOutPaddingTime = 100

export const SwipeOutWrapper = ({children, onSwipeOut, onExpired}: Props) => {
const {pan, panResponder, fadeIn, opacity, fadeOut, translateY} = usePanAnimation({onRelease: onSwipeOut})
const onExpiredRef = React.useRef(onExpired)
onExpiredRef.current = onExpired

React.useEffect(() => {
const expiredTimeout = setTimeout(() => onExpiredRef.current(), notificationDisplayTime)
const fadeOutTimeout = setTimeout(() => fadeOut(), notificationDisplayTime - fadeInTime - fadeOutPaddingTime)

return () => {
clearTimeout(expiredTimeout)
clearTimeout(fadeOutTimeout)
}
}, [fadeIn, fadeOut])

React.useLayoutEffect(() => {
fadeIn()
}, [fadeIn])

return (
<Animated.View
style={{
transform: [{translateX: pan.x}],
transform: [{translateX: pan.x}, {translateY}],
opacity,
}}
{...panResponder.panHandlers}
>
Expand All @@ -23,9 +45,45 @@ export const SwipeOutWrapper = ({children, onSwipeOut}: Props) => {

const usePanAnimation = ({onRelease}: {onRelease: () => void}) => {
const pan = React.useRef(new Animated.ValueXY()).current
const opacity = React.useRef(new Animated.Value(0)).current
const translateY = React.useRef(new Animated.Value(-50)).current
const screenWidth = Dimensions.get('window').width
const screenLimitInPercentAfterWhichShouldRelease = 0.3

const fadeIn = React.useCallback(() => {
Animated.parallel([
Animated.timing(opacity, {
toValue: 1,
duration: fadeInTime,
useNativeDriver: false,
easing: Easing.inOut(Easing.ease),
}),
Animated.timing(translateY, {
toValue: 0,
duration: fadeInTime,
useNativeDriver: false,
easing: Easing.inOut(Easing.ease),
}),
]).start()
}, [opacity, translateY])

const fadeOut = React.useCallback(() => {
Animated.parallel([
Animated.timing(opacity, {
toValue: 0,
duration: fadeInTime,
useNativeDriver: false,
easing: Easing.inOut(Easing.ease),
}),
Animated.timing(translateY, {
toValue: -50,
duration: fadeInTime,
useNativeDriver: false,
easing: Easing.inOut(Easing.ease),
}),
]).start()
}, [opacity, translateY])

const panResponder = React.useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
Expand All @@ -50,5 +108,5 @@ const usePanAnimation = ({onRelease}: {onRelease: () => void}) => {
}),
).current

return {pan, panResponder}
return {pan, panResponder, fadeIn, fadeOut, opacity, translateY}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import {useQuery, useQueryClient, UseQueryOptions} from 'react-query'
import {Notifications as NotificationTypes} from '@yoroi/types'
import {useNotificationManager} from './NotificationProvider'
import {useEffect} from 'react'
import * as React from 'react'

export const useReceivedNotificationEvents = (
options: UseQueryOptions<ReadonlyArray<NotificationTypes.Event>, Error> = {},
) => {
const queryClient = useQueryClient()
const manager = useNotificationManager()
useEffect(() => {
React.useEffect(() => {
const subscription = manager.unreadCounterByGroup$.subscribe(() =>
queryClient.invalidateQueries(['receivedNotificationEvents']),
)
Expand Down

0 comments on commit 710a649

Please sign in to comment.