Skip to content

Commit

Permalink
chore(wallet-mobile): wiring up
Browse files Browse the repository at this point in the history
  • Loading branch information
stackchain committed May 3, 2024
1 parent 36bec08 commit f9ca4fd
Show file tree
Hide file tree
Showing 7 changed files with 215 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {FlashList, FlashListProps} from '@shopify/flash-list'
import {Balance, Portfolio} from '@yoroi/types'
import {Balance} from '@yoroi/types'
import React from 'react'
import {Dimensions, StyleSheet, TouchableOpacity, TouchableOpacityProps, View} from 'react-native'
import SkeletonPlaceholder from 'react-native-skeleton-placeholder'
Expand All @@ -21,7 +21,7 @@ export const SkeletonGallery = ({amount}: {amount: number}) => {
}

type Props = {
amounts: Portfolio.Token.Amount[]
nfts: Balance.TokenInfo[]
onSelect: (id: string) => void
onRefresh: () => void
isRefreshing: boolean
Expand All @@ -31,7 +31,7 @@ type Props = {
readOnly?: boolean
}
export const NftImageGallery = ({
amounts = [],
nfts = [],
onSelect,
onRefresh,
isRefreshing,
Expand All @@ -42,24 +42,19 @@ export const NftImageGallery = ({
}: Props) => {
return (
<GalleryList
data={amounts}
data={nfts}
onRefresh={onRefresh}
refreshing={isRefreshing}
bounces={bounces}
ListEmptyComponent={ListEmptyComponent}
withVerticalPadding={withVerticalPadding}
renderItem={(amount) =>
!('id' in amount.info) ? (
renderItem={(nft) =>
!('id' in nft) ? (
<EmptyImage />
) : features.moderatingNftsEnabled ? (
<ModeratedImage onPress={() => onSelect(amount.info.id)} nft={nft} key={amount.info.id} disabled={readOnly} />
<ModeratedImage onPress={() => onSelect(nft.id)} nft={nft} key={nft.id} disabled={readOnly} />
) : (
<UnModeratedImage
onPress={() => onSelect(amount.info.id)}
nft={nft}
key={amount.info.id}
disabled={readOnly}
/>
<UnModeratedImage onPress={() => onSelect(nft.id)} nft={nft} key={nft.id} disabled={readOnly} />
)
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import {FlashList, FlashListProps} from '@shopify/flash-list'
import {Balance, Portfolio} from '@yoroi/types'
import React from 'react'
import {StyleSheet, Text, TouchableOpacity, useWindowDimensions, View} from 'react-native'

import {Spacer} from '../../../../components/Spacer/Spacer'
import {MediaPreview} from './MediaPreview'

type Props = {
amounts: ReadonlyArray<Portfolio.Token.Amount>
onSelect: (amount: Portfolio.Token.Amount) => void
onRefresh: () => void
isRefreshing: boolean
bounces?: FlashListProps<Balance.TokenInfo>['bounces']
ListEmptyComponent?: FlashListProps<Balance.TokenInfo>['ListEmptyComponent']
withVerticalPadding?: boolean
readOnly?: boolean
}
export const MediaGallery = ({
amounts = [],
onSelect,
onRefresh,
isRefreshing,
readOnly,
bounces = false,
ListEmptyComponent = undefined,
withVerticalPadding = undefined,
}: Props) => {
const dimensions = useWindowDimensions()
const minSize = Math.min(dimensions.width, dimensions.height)
const imageSize = (minSize - horizontalPadding * 2) / numberOfColumns - imageHorizontalPadding

return (
<GalleryList
imageSize={imageSize}
data={amounts}
onRefresh={onRefresh}
refreshing={isRefreshing}
bounces={bounces}
ListEmptyComponent={ListEmptyComponent}
withVerticalPadding={withVerticalPadding}
renderMedia={(amount) => (
<TouchableOpacity onPress={() => onSelect(amount)} disabled={readOnly} key={amount.info.id}>
<Media info={amount.info} imageSize={imageSize} />
</TouchableOpacity>
)}
/>
)
}

function Media({info, imageSize}: {info: Portfolio.Token.Info; imageSize: number}) {
return (
<View>
<View style={styles.imageWrapper}>
<MediaPreview info={info} width={imageSize} height={imageSize} style={styles.image} />
</View>

<Spacer height={imagePadding} />

<Text style={[styles.text, {width: imageSize}]}>{info.name}</Text>
</View>
)
}

const textHeight = 20
const imagePadding = 8
const rowSpacing = 14
const numberOfColumns = 2
const horizontalPadding = 16
const verticalPadding = 16
const gapBetweenColumns = horizontalPadding
const imageHorizontalPadding = gapBetweenColumns / numberOfColumns

function GalleryList({
imageSize,
renderMedia,
withVerticalPadding = false,
...rest
}: Partial<FlashListProps<Portfolio.Token.Amount>> & {
renderMedia: (item: Portfolio.Token.Amount) => React.ReactElement
withVerticalPadding?: boolean
imageSize: number
}) {
return (
<FlashList
{...rest}
numColumns={2}
renderItem={({item, index}) => (
<View
style={[index % 2 === 0 ? {paddingRight: imageHorizontalPadding} : {paddingLeft: imageHorizontalPadding}]}
>
<View>{renderMedia(item)}</View>

<Spacer height={rowSpacing} />
</View>
)}
contentContainerStyle={{
paddingHorizontal: horizontalPadding,
paddingVertical: withVerticalPadding ? verticalPadding : undefined,
}}
keyExtractor={(_, index) => index.toString()}
horizontal={false}
estimatedItemSize={imageSize + imagePadding + textHeight + rowSpacing}
/>
)
}

const styles = StyleSheet.create({
imageWrapper: {
position: 'relative',
overflow: 'hidden',
borderRadius: 8,
},
image: {
borderRadius: 8,
overlayColor: '#FFFFFF',
},
text: {
fontSize: 14,
lineHeight: textHeight,
},
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {Portfolio} from '@yoroi/types'
import {Image} from 'expo-image'
import React from 'react'
import {ImageStyle, View} from 'react-native'
import SkeletonPlaceholder from 'react-native-skeleton-placeholder'

import placeholder from '../../../../assets/img/nft-placeholder.png'
import {useSelectedWallet} from '../../../WalletManager/Context'

type MediaPreviewProps = {
info: Portfolio.Token.Info
showPlaceholder?: boolean
style?: ImageStyle
height: number
width: number
contentFit?: 'cover' | 'contain'
blurRadius?: number
}

export const MediaPreview = React.memo(
({info, showPlaceholder, style = {}, height, width, contentFit = 'cover', blurRadius}: MediaPreviewProps) => {
const {network} = useSelectedWallet()
const [isLoading, setIsLoading] = React.useState(true)

const [policy, name] = info.id.split('.')
const uri = showPlaceholder
? placeholder
: `https://${network}.processed-media.yoroiwallet.com/${policy}/${name}?width=256&height=256&kind=metadata&fit=${contentFit}`

return (
<View style={{width, height, overflow: 'hidden'}}>
{isLoading && (
<SkeletonPlaceholder enabled={true}>
<View style={{width, height}} />
</SkeletonPlaceholder>
)}

<Image
source={{uri, headers}}
contentFit={contentFit}
style={{width, height, ...style}}
onLoadStart={() => setIsLoading(true)}
onLoadEnd={() => setIsLoading(false)}
blurRadius={blurRadius}
placeholder={blurhash}
/>
</View>
)
},
)

const blurhash =
'|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj['

const headers = {
Accept: 'image/webp',
} as const
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {storiesOf} from '@storybook/react-native'
import {tokenMocks} from '@yoroi/portfolio'
import {Chain} from '@yoroi/types'
import React from 'react'
import {Text, View} from 'react-native'

Expand All @@ -20,7 +21,7 @@ storiesOf('TokenAmountItem', module).add('Gallery', () => (

<TokenAmountItem
privacyPlaceholder="-"
isMainnet={true}
network={Chain.Network.Mainnet}
isPrivacyOff={false}
amount={primaryAmount}
style={{backgroundColor: 'white', padding: 16, borderRadius: 8}}
Expand All @@ -32,7 +33,7 @@ storiesOf('TokenAmountItem', module).add('Gallery', () => (

<TokenAmountItem
privacyPlaceholder="-"
isMainnet={true}
network={Chain.Network.Mainnet}
isPrivacyOff={false}
amount={secondaryAmount}
style={{backgroundColor: 'white', padding: 16, borderRadius: 8}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {isPrimaryToken} from '@yoroi/portfolio'
import {useTheme} from '@yoroi/theme'
import {Chain, Portfolio} from '@yoroi/types'
import {Image} from 'expo-image'
Expand All @@ -7,38 +8,41 @@ import {StyleSheet, View} from 'react-native'
import {Icon} from '../../../../components/Icon'
import {isEmptyString} from '../../../../utils'

const headers = {
Accept: 'image/webp',
} as const

const blurhash =
'|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj['

type TokenInfoIconProps = {
info: Portfolio.Token.Info
network: Chain.Network
size: 'sm' | 'md'
}
export const TokenInfoIcon = React.memo(({info, network, size = 'md'}: TokenInfoIconProps) => {
const {styles} = useStyles()
const [isLoading, setIsLoading] = React.useState(false)

if (info.nature === Portfolio.Token.Nature.Primary) return <PrimaryIcon size={size} />
if (isPrimaryToken(info)) return <PrimaryIcon size={size} />

if (!isEmptyString(info.icon)) {
return (
<Image
source={{uri: `data:image/png;base64,${info.icon}`}}
style={[size === 'sm' ? styles.iconSmall : styles.iconMedium]}
placeholder={blurhash}
onLoad={() => setIsLoading(false)}
/>
)
}

const [policy, name] = info.id.split('.')
const uri = `https://${network}.processed-media.yoroiwallet.com/${policy}/${name}?width=64&height=64&kind=metadata&fit=cover`

if (isLoading) return <TokenIconPlaceholder size={size} />

return (
<Image source={{uri, headers}} contentFit="cover" style={[size === 'sm' ? styles.iconSmall : styles.iconMedium]} />
<Image
source={{uri, headers}}
contentFit="cover"
style={[size === 'sm' ? styles.iconSmall : styles.iconMedium]}
onLoadStart={() => setIsLoading(true)}
onLoadEnd={() => setIsLoading(false)}
/>
)
})

Expand All @@ -60,6 +64,13 @@ export const TokenIconPlaceholder = ({size = 'md'}: {size?: 'sm' | 'md'}) => {
)
}

const headers = {
Accept: 'image/webp',
} as const

const blurhash =
'|rF?hV%2WCj[ayj[a|j[az_NaeWBj@ayfRayfQfQM{M|azj[azf6fQfQfQIpWXofj[ayj[j[fQayWCoeoeaya}j[ayfQa{oLj?j[WVj[ayayj[fQoff7azayj[ayj[j[ayofayayayj[fQj[ayayj[ayfjj[j[ayjuayj['

const useStyles = () => {
const {color} = useTheme()
const styles = StyleSheet.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import React from 'react'
import {Alert, StyleSheet, TouchableOpacity, View} from 'react-native'

import {Spacer, Text} from '../../../../../components'
import {NftImageGallery} from '../../../../../components/NftImageGallery'
import {useMetrics} from '../../../../../metrics/metricsManager'
import {TxHistoryRouteNavigation} from '../../../../../navigation'
import {useSearch, useSearchOnNavBar} from '../../../../../Search/SearchContext'
import {limitOfSecondaryAmountsPerTx} from '../../../../../yoroi-wallets/contants'
import {usePortfolioBalances} from '../../../../Portfolio/common/hooks/usePortfolioBalances'
import {MediaGallery} from '../../../../Portfolio/common/MediaGallery/MediaGallery'
import {TokenAmountItem} from '../../../../Portfolio/common/TokenAmountItem/TokenAmountItem'
import {useSelectedWallet} from '../../../../WalletManager/Context'
import {useOverridePreviousSendTxRoute} from '../../../common/navigation'
Expand Down Expand Up @@ -151,8 +151,8 @@ const ListSpendableNfts = ({
}

return (
<NftImageGallery
nfts={spendableAmounts}
<MediaGallery
amounts={spendableAmounts}
onRefresh={() => undefined}
onSelect={handleOnSelect}
readOnly={!canAddAmount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react'
import {ScrollView, StyleSheet, Text, TouchableOpacity, View, ViewProps} from 'react-native'

import {Button, KeyboardAvoidingView, Spacer, TextInput} from '../../../../../components'
import {PairedBalance} from '../../../../../components/PairedBalance/PairedBalance'
import {useLanguage} from '../../../../../i18n'
import {Logger} from '../../../../../yoroi-wallets/logging'
import {editedFormatter, pastedFormatter} from '../../../../../yoroi-wallets/utils'
Expand Down Expand Up @@ -96,7 +97,7 @@ export const EditAmountScreen = () => {
<AmountInput onChange={onChangeQuantity} value={inputValue} ticker={amount.info.ticker} />

<Center>
{/* {isPrimary && <PairedBalance amount={{tokenId: tokenInfo.id, quantity}} />} */}
{isPrimary && <PairedBalance amount={amount} privacyPlaceholder="" isPrivacyOff />}

<Spacer height={22} />

Expand Down

0 comments on commit f9ca4fd

Please sign in to comment.