Skip to content

Commit a55516c

Browse files
committed
chore(wallet-mobile): add exmple of banner managed by banners package
1 parent 91be713 commit a55516c

File tree

8 files changed

+179
-10
lines changed

8 files changed

+179
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import * as React from 'react'
2+
import {Animated, ViewStyle} from 'react-native'
3+
4+
type Props = {
5+
isVisible: boolean
6+
children: React.ReactNode
7+
duration?: number
8+
style?: ViewStyle
9+
}
10+
11+
export const DismissibleBanner = ({isVisible, children, style, duration = 300}: Props) => {
12+
const fadeAnim = React.useRef(new Animated.Value(0)).current
13+
const [shouldRender, setShouldRender] = React.useState(isVisible)
14+
15+
React.useEffect(() => {
16+
if (isVisible) {
17+
fadeAnim.setValue(0)
18+
setShouldRender(true)
19+
Animated.timing(fadeAnim, {
20+
toValue: 1,
21+
duration,
22+
useNativeDriver: true,
23+
}).start()
24+
} else {
25+
fadeAnim.setValue(1)
26+
Animated.timing(fadeAnim, {
27+
toValue: 0,
28+
duration,
29+
useNativeDriver: true,
30+
}).start(() => setShouldRender(false))
31+
}
32+
}, [isVisible, fadeAnim, duration])
33+
34+
if (!shouldRender) return null
35+
36+
return <Animated.View style={{...style, opacity: fadeAnim}}>{children}</Animated.View>
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {time} from '../../../kernel/constants'
2+
import {shouldShowDRepConsiderDelegating} from './should-show-drep-consider-delegating'
3+
4+
describe('shouldShowDRepConsiderDelegating', () => {
5+
const moreThanOneMonthAgo = Date.now() - time.oneMonth - time.oneSecond
6+
const lessThanOneSecondAgo = Date.now() - time.oneSecond
7+
8+
it.each`
9+
isStaking | currentDRepIdHex | yoroiDRepIdHex | dismissedAt | expected
10+
${true} | ${'DE'} | ${'AD'} | ${moreThanOneMonthAgo} | ${true}
11+
${false} | ${'DE'} | ${'AD'} | ${moreThanOneMonthAgo} | ${false}
12+
${true} | ${'DE'} | ${'AD'} | ${lessThanOneSecondAgo} | ${false}
13+
${true} | ${'AD'} | ${'AD'} | ${moreThanOneMonthAgo} | ${false}
14+
`(
15+
'returns $expected when isStaking is $isStaking, currentDRepId is $currentDRepId, yoroiDRep is $yoroiDRepId, and dismissedAt is $dismissedAt',
16+
({isStaking, currentDRepIdHex, yoroiDRepIdHex, dismissedAt, expected}) => {
17+
const result = shouldShowDRepConsiderDelegating({
18+
isStaking,
19+
currentDRepIdHex,
20+
yoroiDRepIdHex,
21+
dismissedAt,
22+
})
23+
expect(result).toBe(expected)
24+
},
25+
)
26+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import {time} from '../../../kernel/constants'
2+
3+
export const shouldShowDRepConsiderDelegating = ({
4+
isStaking,
5+
currentDRepIdHex,
6+
yoroiDRepIdHex,
7+
dismissedAt,
8+
}: Readonly<{
9+
isStaking: boolean
10+
currentDRepIdHex: string
11+
yoroiDRepIdHex: string
12+
dismissedAt: number
13+
}>) => {
14+
const isYoroiDRep = currentDRepIdHex === yoroiDRepIdHex
15+
const hasBeenThirtyDays = dismissedAt + time.oneMonth < Date.now()
16+
return !isYoroiDRep && hasBeenThirtyDays && isStaking
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export enum BannerId {
2+
DRepConsiderDelegating = 'drep-consider-delegating',
3+
}
4+
5+
export type BannerStorageKey = `${BannerId}`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import {useBanner, useBanners} from '@yoroi/banners'
2+
import {useTheme} from '@yoroi/theme'
3+
import * as React from 'react'
4+
import {Button, Text, View} from 'react-native'
5+
6+
import {yoroiDRepIdHex} from '../../../kernel/constants'
7+
import {DismissibleBanner} from '../common/DismissableBanner'
8+
import {shouldShowDRepConsiderDelegating} from '../common/should-show-drep-consider-delegating'
9+
import {BannerId, BannerStorageKey} from '../common/types'
10+
11+
type Props = {
12+
isStaking: boolean
13+
currentDRepIdHex: string
14+
}
15+
16+
export const ShowBannerDRepConsiderDelegating = ({isStaking, currentDRepIdHex}: Props) => {
17+
const {
18+
color: {gray_200},
19+
atoms: {p_lg},
20+
} = useTheme()
21+
const {manager} = useBanners<BannerStorageKey>()
22+
const {dismiss, dismissedAt} = useBanner({id: BannerId.DRepConsiderDelegating, manager})
23+
24+
const shouldShow = shouldShowDRepConsiderDelegating({
25+
yoroiDRepIdHex,
26+
currentDRepIdHex,
27+
isStaking,
28+
dismissedAt,
29+
})
30+
31+
return (
32+
<DismissibleBanner isVisible={shouldShow} style={{backgroundColor: gray_200, ...p_lg, borderRadius: 4}}>
33+
<View>
34+
<Text>Consider delegating to DREP</Text>
35+
36+
<Button onPress={() => dismiss()} title="Dismiss" />
37+
</View>
38+
</DismissibleBanner>
39+
)
40+
}
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,52 @@
1+
import {bannersManagerMaker, BannersProvider} from '@yoroi/banners'
2+
import {observableStorageMaker} from '@yoroi/common'
3+
import {useTheme} from '@yoroi/theme'
14
import * as React from 'react'
2-
import {View} from 'react-native'
5+
import {SafeAreaView} from 'react-native-safe-area-context'
6+
7+
import {Button} from '../../components/Button/Button'
8+
import {Spacer} from '../../components/Spacer/Spacer'
9+
import {logger} from '../../kernel/logger/logger'
10+
import {BannerId, BannerStorageKey} from '../Banners/common/types'
11+
import {ShowBannerDRepConsiderDelegating} from '../Banners/useCases/ShowBannerDRepConsiderDelegating'
12+
import {useSelectedWallet} from '../WalletManager/common/hooks/useSelectedWallet'
13+
14+
// --------------------------------------------------------------------------------------------------
15+
// PINEED: this component can be replaced at anytime by anyone
316

4-
// Please, clean component after use
517
export const Playground = () => {
6-
return <View></View>
7-
}
18+
const {
19+
atoms: {pl_lg, pr_lg},
20+
} = useTheme()
21+
const {wallet} = useSelectedWallet()
22+
const walletStorage = wallet.networkManager.rootStorage.join(`${wallet.id}/`)
23+
const bannersStorage = observableStorageMaker<false, BannerStorageKey>(walletStorage.join('banners/'))
24+
const bannersManager = bannersManagerMaker<BannerStorageKey>({
25+
storage: bannersStorage,
26+
})
27+
const [refresh, setRefresh] = React.useState(0)
28+
29+
bannersStorage.onChange([BannerId.DRepConsiderDelegating], () => {
30+
logger.debug(`BannersStorageKey ${BannerId.DRepConsiderDelegating}:`, {
31+
dismissedAt: bannersManager.dismissedAt(BannerId.DRepConsiderDelegating),
32+
})
33+
})
834

9-
// const styles = StyleSheet.create({})
35+
return (
36+
<SafeAreaView edges={['top', 'left', 'right']} style={[pl_lg, pr_lg]}>
37+
<Button
38+
title="Reset"
39+
onPress={() => {
40+
bannersStorage.setItem(BannerId.DRepConsiderDelegating, '0')
41+
setRefresh(() => refresh + 1)
42+
}}
43+
/>
44+
45+
<Spacer height={20} />
46+
47+
<BannersProvider manager={bannersManager} key={refresh}>
48+
<ShowBannerDRepConsiderDelegating isStaking={true} currentDRepIdHex="123" />
49+
</BannersProvider>
50+
</SafeAreaView>
51+
)
52+
}

apps/wallet-mobile/translations/messages/src/legacy/Dashboard/Dashboard.json

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
"defaultMessage": "!!!Go to Staking Center",
55
"file": "src/legacy/Dashboard/Dashboard.tsx",
66
"start": {
7-
"line": 241,
7+
"line": 237,
88
"column": 23,
9-
"index": 7828
9+
"index": 7685
1010
},
1111
"end": {
12-
"line": 244,
12+
"line": 240,
1313
"column": 3,
14-
"index": 7961
14+
"index": 7818
1515
}
1616
}
1717
]

packages/banners/src/banners-manager.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import {freeze} from 'immer'
55
export const bannersManagerMaker = <K extends string = string>({
66
storage,
77
}: Readonly<Banners.Config<K>>): Readonly<Banners.Manager<K>> => {
8-
const dismiss = (id: K) =>
8+
const dismiss = (id: K) => {
99
storage.setItem(id, new Date().getTime().toString())
10+
}
1011

1112
const dismissedAt = (id: K) => {
1213
return toNumber(storage.getItem(id))

0 commit comments

Comments
 (0)