Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
- added: Foreground push notifications displayed in app
- added: `ExpandableList` component, replacing the address hint dropdown in `AddressFormScene`
- changed: Added Iraq to list of Visa/MC supported countries
- changed: Updated ACH supported US states
- fixed: Inconsistent content of address hint dropdown between iOS and Android in `AddressFormScene`
- changed: Updated ACH supported US stat- fixed: Inconsistent content of address hint dropdown between iOS and Android in `AddressFormScene`
- changed: Use new platform-specific `assetStatsCards2` info server data
- changed: Display Asset Status cards in the same style as Promo Cards
- fixed: Inconsistent corners in `SideMenu`
- fixed: Crash on HomeScene when logging while in airplane mode

Expand Down
22 changes: 11 additions & 11 deletions src/__tests__/components/PromoCards.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, expect, test } from '@jest/globals'
import { PromoCard2 } from 'edge-info-server'

import { filterPromoCards } from '../../components/cards/PromoCards'
import { filterInfoCards } from '../../components/cards/InfoCardCarousel'

const dummyCard: PromoCard2 = {
localeMessages: { en: 'hello' },
Expand Down Expand Up @@ -33,12 +33,12 @@ const currentDate = new Date('2024-06-13T20:53:33.013Z')
describe('filterPromoCards', () => {
test('No cards', () => {
const cards: PromoCard2[] = []
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber, osType, version, osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber, osType, version, osVersion, currentDate })
expect(result.length).toBe(0)
})
test('Card no filters', () => {
const cards: PromoCard2[] = [{ ...dummyCard }]
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber, osType, version, osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber, osType, version, osVersion, currentDate })
expect(result.length).toBe(1)
expect(result[0].localeMessages.en).toBe('hello')
})
Expand All @@ -49,7 +49,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, osTypes: ['web'], localeMessages: { en: 'Web Message' } },
{ ...dummyCard, osTypes: ['ios'], localeMessages: { en: 'Another iOS Message' } }
]
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber, osType: 'ios', version, osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber, osType: 'ios', version, osVersion, currentDate })
expect(result.length).toBe(2)
expect(result[0].localeMessages.en).toBe('iOS Message')
expect(result[1].localeMessages.en).toBe('Another iOS Message')
Expand All @@ -61,7 +61,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, exactBuildNum: '432', osTypes: ['web'], localeMessages: { en: 'Web Message' } },
{ ...dummyCard, exactBuildNum: '432', osTypes: ['android'], localeMessages: { en: 'Another Android Message' } }
]
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber: '432', osType: 'android', version: '1.2.3', osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber: '432', osType: 'android', version: '1.2.3', osVersion, currentDate })
expect(result.length).toBe(1)
expect(result[0].localeMessages.en).toBe('Another Android Message')
})
Expand All @@ -72,7 +72,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, osTypes: ['web'], localeMessages: { en: 'Web Message' } },
{ ...dummyCard, osTypes: ['android'], localeMessages: { en: 'Another Android Message' }, appVersion: '1.2.4' }
]
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber: '432', osType: 'android', version: '1.2.3', osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber: '432', osType: 'android', version: '1.2.3', osVersion, currentDate })
expect(result.length).toBe(1)
expect(result[0].localeMessages.en).toBe('Android message')
})
Expand All @@ -83,7 +83,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, minBuildNum: '4', maxBuildNum: '5', localeMessages: { en: '4-5' } },
{ ...dummyCard, minBuildNum: '1', maxBuildNum: '4', localeMessages: { en: '1-4' } }
]
const result = filterPromoCards({ cards, countryCode: 'US', buildNumber: '4', osType, version: '1.2.3', osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'US', buildNumber: '4', osType, version: '1.2.3', osVersion, currentDate })
expect(result.length).toBe(3)
expect(result[0].localeMessages.en).toBe('3-5')
expect(result[1].localeMessages.en).toBe('4-5')
Expand All @@ -97,7 +97,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, countryCodes: ['uk'], localeMessages: { en: 'UK message' } },
{ ...dummyCard, countryCodes: ['es'], localeMessages: { en: 'ES message' } }
]
const result = filterPromoCards({ cards, buildNumber, osType, version, osVersion, currentDate })
const result = filterInfoCards({ cards, buildNumber, osType, version, osVersion, currentDate })
expect(result.length).toBe(1)
expect(result[0].localeMessages.en).toBe('no country')
})
Expand All @@ -108,7 +108,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, excludeCountryCodes: ['uk'], localeMessages: { en: 'UK message' } },
{ ...dummyCard, excludeCountryCodes: ['es'], localeMessages: { en: 'ES message' } }
]
const result = filterPromoCards({ cards, countryCode: 'us', buildNumber: '4', osType, version, osVersion, currentDate })
const result = filterInfoCards({ cards, countryCode: 'us', buildNumber: '4', osType, version, osVersion, currentDate })
expect(result.length).toBe(2)
expect(result[0].localeMessages.en).toBe('UK message')
expect(result[1].localeMessages.en).toBe('ES message')
Expand All @@ -120,7 +120,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, promoId: 'bob3', localeMessages: { en: 'Bob3 Message' } },
{ ...dummyCard, promoId: 'bob4', localeMessages: { en: 'Bob4 Message' } }
]
const result = filterPromoCards({
const result = filterInfoCards({
cards,
countryCode: 'US',
buildNumber,
Expand All @@ -140,7 +140,7 @@ describe('filterPromoCards', () => {
{ ...dummyCard, promoId: 'bob3', localeMessages: { en: 'Bob3 Message' } },
{ ...dummyCard, promoId: 'bob4', localeMessages: { en: 'Bob4 Message' } }
]
const result = filterPromoCards({
const result = filterInfoCards({
cards,
countryCode: 'US',
buildNumber,
Expand Down
47 changes: 0 additions & 47 deletions src/components/cards/AssetStatusCard.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { cacheStyles, Theme, useTheme } from '../services/ThemeContext'
import { EdgeText } from '../themed/EdgeText'
import { EdgeCard } from './EdgeCard'

export interface FilteredPromoCard {
export interface FilteredInfoCard {
background: PromoCard2['background']
ctaButton: PromoCard2['ctaButton']
dismissable: PromoCard2['dismissable']
Expand All @@ -26,11 +26,11 @@ export interface FilteredPromoCard {

interface Props {
navigation: NavigationBase
promoInfo: FilteredPromoCard
promoInfo: FilteredInfoCard
onClose: () => Promise<void>
}

export function PromoCard(props: Props) {
export function InfoCard(props: Props) {
const theme = useTheme()
const styles = getStyles(theme)
const dispatch = useDispatch()
Expand All @@ -49,7 +49,7 @@ export function PromoCard(props: Props) {
const { localeUrls } = ctaButton
const url = getLocaleOrDefaultString(localeUrls)
if (url == null) {
showError('No PromoCard URL found')
showError('No Carousel Card URL found')
return
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,46 @@
import { asDate } from 'cleaners'
import { PromoCard2 } from 'edge-info-server'
import { AssetStatus2, PromoCard2 } from 'edge-info-server'
import * as React from 'react'
import { ListRenderItem, Platform } from 'react-native'
import { getBuildNumber, getVersion } from 'react-native-device-info'
import shajs from 'sha.js'

import { hideMessageTweak } from '../../actions/AccountReferralActions'
import { useHandler } from '../../hooks/useHandler'
import { useWatch } from '../../hooks/useWatch'
import { useIsAccountFunded } from '../../hooks/useIsAccountFunded'
import { useDispatch, useSelector } from '../../types/reactRedux'
import { AccountReferral } from '../../types/ReferralTypes'
import { NavigationBase } from '../../types/routerTypes'
import { infoServerData } from '../../util/network'
import { getOsVersion, zeroString } from '../../util/utils'
import { EdgeAnim, fadeInUp110 } from '../common/EdgeAnim'
import { getOsVersion } from '../../util/utils'
import { Anim, EdgeAnim } from '../common/EdgeAnim'
import { EdgeCarousel } from '../common/EdgeCarousel'
import { useTheme } from '../services/ThemeContext'
import { FilteredPromoCard, PromoCard } from './PromoCard'
import { FilteredInfoCard, InfoCard } from './InfoCard'

interface Props {
navigation: NavigationBase
enterAnim: Anim
screenWidth: number
// TODO: Add info server InfoCard export
cards?: PromoCard2[] | AssetStatus2[]
countryCode?: string
}

export const PromoCards = (props: Props) => {
const { countryCode, navigation, screenWidth } = props
export const InfoCardCarousel = (props: Props) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Danger. Don't rename the file AND make changes in the same commit. Many times git can't tell it was a rename and you'll have a diff that shows a file deletion and file creation making a near impossible review. It happened to work out in this case

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the diff worked out, or else I would have separated the commits. Will
default to separating to be safe in the future

const { enterAnim, countryCode, navigation, screenWidth, cards } = props
const theme = useTheme()
const dispatch = useDispatch()

const account = useSelector(state => state.core.account)
const accountReferral = useSelector(state => state.account.accountReferral)

const currencyWallets = useWatch(account, 'currencyWallets')

const [filteredCards, setFilteredCards] = React.useState<FilteredPromoCard[]>([])
const [accountFunded, setAccountFunded] = React.useState<boolean>()

const walletsSynced = useSelector(state => {
const { currencyWallets } = state.core.account
const { userPausedWalletsSet } = state.ui.settings
const unPausedWallets = Object.values(currencyWallets).filter(wallet => !userPausedWalletsSet?.has(wallet.id))
const unSyncedWallets = unPausedWallets.filter(wallet => wallet.syncRatio < 1)

return unSyncedWallets.length === 0
})
const [filteredCards, setFilteredCards] = React.useState<FilteredInfoCard[]>([])

// Set account funded status
React.useEffect(() => {
if (!walletsSynced) return
setAccountFunded(Object.values(currencyWallets).some(wallet => [...wallet.balanceMap.values()].some(balanceVal => !zeroString(balanceVal))))
}, [currencyWallets, walletsSynced])
const accountFunded = useIsAccountFunded()

// Check for PromoCard2 from info server:
React.useEffect(() => {
const cards = infoServerData.rollup?.promoCards2 ?? []

if (cards == null) return
// We want to show cards even if balances aren't ready yet. We'll just
// skip over balance-dependent cards until balances are ready
const currentDate = new Date()
Expand All @@ -65,7 +50,7 @@ export const PromoCards = (props: Props) => {
const osVersion = getOsVersion()

setFilteredCards(
filterPromoCards({
filterInfoCards({
cards,
countryCode,
accountFunded,
Expand All @@ -77,34 +62,34 @@ export const PromoCards = (props: Props) => {
currentDate
})
)
}, [accountFunded, accountReferral, countryCode])
}, [accountFunded, accountReferral, cards, countryCode])

const hiddenAccountMessages = useSelector(state => state.account.accountReferral.hiddenAccountMessages)
const activeCards = React.useMemo(() => filteredCards.filter(card => !hiddenAccountMessages[card.messageId]), [filteredCards, hiddenAccountMessages])

// List rendering methods:
const keyExtractor = useHandler((item: FilteredPromoCard) => item.messageId)
const renderItem: ListRenderItem<FilteredPromoCard> = useHandler(({ item }) => {
const keyExtractor = useHandler((item: FilteredInfoCard) => item.messageId)
const renderItem: ListRenderItem<FilteredInfoCard> = useHandler(({ item }) => {
const handleClose = async (): Promise<void> => {
await dispatch(hideMessageTweak(item.messageId, { type: 'account' }))
}
return <PromoCard navigation={navigation} promoInfo={item} onClose={handleClose} />
return <InfoCard navigation={navigation} promoInfo={item} onClose={handleClose} />
})

if (activeCards == null || activeCards.length === 0) return null
return (
<EdgeAnim enter={fadeInUp110}>
<EdgeAnim enter={enterAnim}>
<EdgeCarousel data={activeCards} keyExtractor={keyExtractor} renderItem={renderItem} height={theme.rem(10)} width={screenWidth} />
</EdgeAnim>
)
}

/**
* Finds the promo cards that are relevant to our application version &
* Finds the info server cards that are relevant to our application version &
* other factors.
*/
export function filterPromoCards(params: {
cards: PromoCard2[]
export function filterInfoCards(params: {
cards: PromoCard2[] | AssetStatus2[]
countryCode?: string
buildNumber: string
osType: string
Expand All @@ -113,7 +98,7 @@ export function filterPromoCards(params: {
currentDate: Date
accountFunded?: boolean
accountReferral?: Partial<AccountReferral>
}): FilteredPromoCard[] {
}): FilteredInfoCard[] {
const { cards, countryCode, accountFunded, buildNumber, osType, version, osVersion, currentDate, accountReferral } = params

let accountPromoIds: string[] | undefined
Expand All @@ -125,7 +110,7 @@ export function filterPromoCards(params: {

// Find relevant cards:
const ccLowerCase = countryCode?.toLowerCase()
const filteredCards: FilteredPromoCard[] = []
const filteredCards: FilteredInfoCard[] = []
for (const card of cards) {
const {
appVersion,
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/EdgeAnim.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ type AnimTypeStretchIns = 'stretchInY'
type AnimTypeStretchOuts = 'stretchOutY'
type AnimType = AnimTypeFadeIns | AnimTypeFadeOuts | AnimTypeStretchIns | AnimTypeStretchOuts

interface Anim {
export interface Anim {
type: AnimType
delay?: number
duration?: number
Expand Down
4 changes: 2 additions & 2 deletions src/components/scenes/GuiPluginListScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { bestOfPlugins } from '../../util/ReferralHelpers'
import { logEvent, OnLogEvent } from '../../util/tracking'
import { base58ToUuid, getOsVersion } from '../../util/utils'
import { EdgeCard } from '../cards/EdgeCard'
import { filterPromoCards } from '../cards/PromoCards'
import { filterInfoCards } from '../cards/InfoCardCarousel'
import { EdgeAnim, fadeInUp20, fadeInUp30, fadeInUp60, fadeInUp90 } from '../common/EdgeAnim'
import { InsetStyle, SceneWrapper } from '../common/SceneWrapper'
import { SectionHeader } from '../common/SectionHeader'
Expand Down Expand Up @@ -264,7 +264,7 @@ class GuiPluginList extends React.PureComponent<Props, State> {
}
if (plugin.nativePlugin != null) {
const cards = infoServerData.rollup?.promoCards2 ?? []
const promoCards = filterPromoCards({
const promoCards = filterInfoCards({
accountReferral,
cards,
countryCode,
Expand Down
12 changes: 9 additions & 3 deletions src/components/scenes/HomeScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import { infoServerData } from '../../util/network'
import { BalanceCard } from '../cards/BalanceCard'
import { ContentPostCarousel } from '../cards/ContentPostCarousel'
import { HomeTileCard } from '../cards/HomeTileCard'
import { InfoCardCarousel } from '../cards/InfoCardCarousel'
import { MarketsCard } from '../cards/MarketsCard'
import { PromoCards } from '../cards/PromoCards'
import { SupportCard } from '../cards/SupportCard'
import { EdgeAnim, fadeInUp30, fadeInUp60, fadeInUp80, fadeInUp140 } from '../common/EdgeAnim'
import { EdgeAnim, fadeInUp30, fadeInUp60, fadeInUp80, fadeInUp110, fadeInUp140 } from '../common/EdgeAnim'
import { SceneWrapper } from '../common/SceneWrapper'
import { SectionHeader } from '../common/SectionHeader'
import { SectionView } from '../layout/SectionView'
Expand Down Expand Up @@ -141,7 +141,13 @@ export const HomeScene = (props: Props) => {
<BalanceCard onViewAssetsPress={handleViewAssetsPress} navigation={navigation} />
</EdgeAnim>
{/* Animation inside PromoCardsUi4 component */}
<PromoCards countryCode={countryCode} navigation={navigation} screenWidth={screenWidth} />
<InfoCardCarousel
enterAnim={fadeInUp110}
cards={infoServerData.rollup?.promoCards2}
countryCode={countryCode}
navigation={navigation}
screenWidth={screenWidth}
/>
<EdgeAnim style={homeRowStyle} enter={fadeInUp80}>
<HomeTileCard
title={lstrings.buy_crypto}
Expand Down
Loading
Loading