Skip to content

Commit

Permalink
chore: more app updates for UK compliance (#6221)
Browse files Browse the repository at this point in the history
### Description

This PR contains all the requested changes described in the task. Some
features that were required to be hidden to UK users could be done
through existing feature flags, but I opted to consolidate the UK
changes under the `SHOW_UK_COMPLIANT_VARIANT` flag for readability.

### Test plan

User with activity:


https://github.com/user-attachments/assets/e294569d-1165-45d1-be25-b810014468a5


User with no activity:


https://github.com/user-attachments/assets/d61054df-7445-4753-a804-7de065554e2c


### Related issues

- Fixes RET-1239

### Backwards compatibility

Y

### Network scalability

If a new NetworkId and/or Network are added in the future, the changes
in this PR will:

- [ ] Continue to work without code changes, OR trigger a compilation
error (guaranteeing we find it when a new network is added)
  • Loading branch information
kathaypacific authored Nov 14, 2024
1 parent ab5e17a commit e34ca3b
Show file tree
Hide file tree
Showing 18 changed files with 305 additions and 152 deletions.
4 changes: 2 additions & 2 deletions e2e/src/Discover.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ describe('Discover tab', () => {
})
await waitForElementByIdAndTap('Tab/Discover')

await scrollIntoView('Explore All', 'DiscoverScrollView')
await element(by.text('Explore All')).tap()
await scrollIntoView('View All', 'DiscoverScrollView')
await element(by.text('View All')).tap()

await waitFor(element(by.id(`DappsScreen/DappsList`)))
})
Expand Down
11 changes: 7 additions & 4 deletions locales/base/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -1460,14 +1460,15 @@
"dappsScreen": {
"title": "Dapps",
"titleDiscover": "Discover",
"exploreDapps": "Explore Dapps",
"exploreAll": "Explore All",
"exploreDapps": "Dapps",
"exploreAll": "View All",
"message": "Explore ways to use your assets",
"errorMessage": "There was an error loading dapps",
"featuredDapp": "Featured",
"allDapps": "All",
"favoriteDapps": "My Favorites",
"mostPopularDapps": "Most Popular",
"mostPopularDapps_UK": "Other Dapps",
"favoriteDappsAndAll": "My Favorites & All",
"searchPlaceHolder": "Search dapps",
"noFavorites": {
Expand All @@ -1483,7 +1484,8 @@
"message": "<0>{{filter}}</0> filter applied",
"removeFilter": "Remove filter",
"searchMessage": "No matching results found for <0>\"{{searchTerm}}\"</0>"
}
},
"disclaimer_UK": "This is a list of third-party Dapps. The description for each Dapp is purely informational, and not an invitation to use them."
},
"dappRankings": {
"title": "Dapp rankings",
Expand Down Expand Up @@ -2298,7 +2300,8 @@
"claimRewardSubtitle_noTxAppName": "from unknown app",
"error": {
"fetchError": "Oops, there was an issue refreshing your feed. Your transaction history may be incomplete for now."
}
},
"noTransactions": "Congratulations, you've successfully created a {{appName}} wallet!"
},
"transactionDetails": {
"descriptionLabel": "Details",
Expand Down
23 changes: 19 additions & 4 deletions src/dapps/DappsScreen.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { fireEvent, render, within } from '@testing-library/react-native'
import * as React from 'react'
import { Provider } from 'react-redux'
import { DappExplorerEvents } from 'src/analytics/Events'
import AppAnalytics from 'src/analytics/AppAnalytics'
import { DappExplorerEvents } from 'src/analytics/Events'
import DappsScreen from 'src/dapps/DappsScreen'
import { dappSelected, favoriteDapp, fetchDappsList, unfavoriteDapp } from 'src/dapps/slice'
import { DappCategory, DappSection } from 'src/dapps/types'
import DappsScreen from 'src/dapps/DappsScreen'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import MockedNavigator from 'test/MockedNavigator'
import { createMockStore } from 'test/utils'
import { mockDappListWithCategoryNames } from 'test/values'
Expand Down Expand Up @@ -45,7 +46,6 @@ describe('DappsScreen', () => {
beforeEach(() => {
defaultStore.clearActions()
jest.clearAllMocks()
jest.mocked(getFeatureGate).mockReturnValue(false)
})

it('renders correctly and fires the correct actions on press dapp', () => {
Expand All @@ -59,6 +59,7 @@ describe('DappsScreen', () => {
expect(queryByText('featuredDapp')).toBeFalsy()
expect(getByText('Dapp 1')).toBeTruthy()
expect(getByText('Dapp 2')).toBeTruthy()
expect(queryByText('dappsScreen.disclaimer_UK')).toBeFalsy()

fireEvent.press(getByText('Dapp 1'))

Expand All @@ -68,6 +69,20 @@ describe('DappsScreen', () => {
])
})

it('renders the disclaimer for UK compliance', () => {
jest
.mocked(getFeatureGate)
.mockImplementation((gate) => gate === StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

const { getByText } = render(
<Provider store={defaultStore}>
<MockedNavigator component={DappsScreen} />
</Provider>
)

expect(getByText('dappsScreen.disclaimer_UK')).toBeTruthy()
})

it('renders correctly and fires the correct actions on press deep linked dapp', () => {
const { getByText, queryByText } = render(
<Provider store={defaultStore}>
Expand All @@ -88,7 +103,7 @@ describe('DappsScreen', () => {
])
})

it('pens dapps directly', () => {
it('opens dapps directly', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
Expand Down
26 changes: 18 additions & 8 deletions src/dapps/DappsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ import { Screens } from 'src/navigator/Screens'
import useScrollAwareHeader from 'src/navigator/ScrollAwareHeader'
import { StackParamList } from 'src/navigator/types'
import { useDispatch, useSelector } from 'src/redux/hooks'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import Colors from 'src/styles/colors'
import { typeScale } from 'src/styles/fonts'
import { Spacing } from 'src/styles/styles'
Expand Down Expand Up @@ -86,6 +88,8 @@ function DappsScreen({ navigation }: Props) {
const { onSelectDapp } = useOpenDapp()
const { onFavoriteDapp, DappFavoritedToast } = useDappFavoritedToast(sectionListRef)

const showUKCompliantVariant = getFeatureGate(StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

const removeFilter = (filter: BooleanFilterChip<DappWithCategoryNames>) => {
AppAnalytics.track(DappExplorerEvents.dapp_filter, {
filterId: filter.id,
Expand Down Expand Up @@ -215,15 +219,21 @@ function DappsScreen({ navigation }: Props) {
// @ts-expect-error
ref={sectionListRef}
ListFooterComponent={
<Text style={styles.disclaimer}>{t('dappsDisclaimerAllDapps')}</Text>
<Text style={[styles.disclaimer, { textAlign: 'center' }]}>
{t('dappsDisclaimerAllDapps')}
</Text>
}
ListHeaderComponent={
<>
{
<View style={styles.titleContainer}>
<Text onLayout={handleMeasureTitleHeight} style={styles.title}>
{t('dappsScreen.exploreDapps')}
</Text>
}
{showUKCompliantVariant && (
<Text style={styles.disclaimer}>{t('dappsScreen.disclaimer_UK')}</Text>
)}
</View>

<DappFeaturedActions />
<SearchInput
onChangeText={(text) => {
Expand Down Expand Up @@ -335,18 +345,18 @@ const styles = StyleSheet.create({
disclaimer: {
...typeScale.bodyXSmall,
color: Colors.gray4,
textAlign: 'center',
marginTop: Spacing.Large32,
marginBottom: Spacing.Regular16,
},
listFooterComponent: {
flex: 1,
justifyContent: 'flex-end',
marginTop: Spacing.Large32,
marginBottom: Spacing.Regular16,
},
title: {
...typeScale.titleMedium,
color: Colors.black,
},
titleContainer: {
marginBottom: Spacing.Thick24,
gap: Spacing.Tiny4,
},
dappCard: {
marginTop: Spacing.Regular16,
Expand Down
24 changes: 22 additions & 2 deletions src/dappsExplorer/DiscoverDappsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import useOpenDapp from 'src/dappsExplorer/useOpenDapp'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { useDispatch, useSelector } from 'src/redux/hooks'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import Colors from 'src/styles/colors'
import { typeScale } from 'src/styles/fonts'
import { Spacing } from 'src/styles/styles'
Expand All @@ -36,6 +38,8 @@ function DiscoverDappsCard() {

const { onSelectDapp } = useOpenDapp()

const showUKCompliantVariant = getFeatureGate(StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

useEffect(() => {
dispatch(fetchDappsList())
AppAnalytics.track(DappExplorerEvents.dapp_screen_open)
Expand All @@ -57,7 +61,9 @@ function DiscoverDappsCard() {
data: mostPopularDapps
.filter((dapp) => !favoriteDappIds.includes(dapp.id))
.slice(0, MAX_DAPPS - favoriteDapps.length),
sectionName: t('dappsScreen.mostPopularDapps'),
sectionName: t('dappsScreen.mostPopularDapps', {
context: showUKCompliantVariant ? 'UK' : '',
}),
dappSection: DappSection.MostPopular,
testID: 'DiscoverDappsCard/MostPopularSection',
},
Expand Down Expand Up @@ -91,7 +97,14 @@ function DiscoverDappsCard() {
<SectionList
ref={sectionListRef}
scrollEnabled={false}
ListHeaderComponent={<Text style={styles.title}>{t('dappsScreen.exploreDapps')}</Text>}
ListHeaderComponent={
<View style={styles.titleContainer}>
<Text style={styles.title}>{t('dappsScreen.exploreDapps')}</Text>
{showUKCompliantVariant && (
<Text style={styles.disclaimer}>{t('dappsScreen.disclaimer_UK')}</Text>
)}
</View>
}
ListFooterComponent={
<View>
<Text style={styles.footer}>{t('dappsScreen.exploreAll')}</Text>
Expand Down Expand Up @@ -150,7 +163,14 @@ const styles = StyleSheet.create({
title: {
...typeScale.labelSemiBoldMedium,
color: Colors.black,
},
titleContainer: {
marginBottom: Spacing.Smallest8,
gap: Spacing.Tiny4,
},
disclaimer: {
...typeScale.bodyXSmall,
color: Colors.gray3,
},
})

Expand Down
19 changes: 18 additions & 1 deletion src/earn/EarnEntrypoint.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,31 @@
import { fireEvent, render } from '@testing-library/react-native'
import React from 'react'
import { EarnEvents } from 'src/analytics/Events'
import AppAnalytics from 'src/analytics/AppAnalytics'
import { EarnEvents } from 'src/analytics/Events'
import EarnEntrypoint from 'src/earn/EarnEntrypoint'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'

jest.mock('src/statsig')

describe('EarnEntrypoint', () => {
beforeEach(() => {
jest.clearAllMocks()
jest
.mocked(getFeatureGate)
.mockImplementation((gate) => gate !== StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)
})

it('renders nothing for UK compliant variant', () => {
jest
.mocked(getFeatureGate)
.mockImplementation((gate) => gate === StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

const { toJSON } = render(<EarnEntrypoint />)

expect(toJSON()).toBeNull()
})

it('renders correctly', () => {
Expand Down
9 changes: 8 additions & 1 deletion src/earn/EarnEntrypoint.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import React from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, Text, View } from 'react-native'
import { EarnEvents } from 'src/analytics/Events'
import AppAnalytics from 'src/analytics/AppAnalytics'
import { EarnEvents } from 'src/analytics/Events'
import Touchable from 'src/components/Touchable'
import CircledIcon from 'src/icons/CircledIcon'
import EarnCoins from 'src/icons/EarnCoins'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import Colors from 'src/styles/colors'
import { typeScale } from 'src/styles/fonts'
import { Spacing } from 'src/styles/styles'

export default function EarnEntrypoint() {
const { t } = useTranslation()
const showUKCompliantVariant = getFeatureGate(StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

if (showUKCompliantVariant) {
return null
}

return (
<View style={styles.container}>
Expand Down
35 changes: 35 additions & 0 deletions src/images/Celebration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react'
import Svg, { Path } from 'react-native-svg'

interface Props {
width?: number
height?: number
testID?: string
}

export default function Celebration({ width = 58, height = 53, testID }: Props) {
return (
<Svg width={width} height={height} viewBox="0 0 58 53" fill="none" testID={testID}>
<Path fill="#FD56B5" d="M11.617 22.922 1 52.267l30.61-10.395" />
<Path
stroke="#000"
strokeLinecap="round"
strokeLinejoin="round"
d="M11.617 22.922 1 52.267l30.61-10.395"
/>
<Path
fill="#6E75EE"
stroke="#000"
strokeLinecap="round"
strokeLinejoin="round"
d="M27.69 26.477c5.654 5.464 8.058 12 5.373 14.598-.74.715-1.794 1.06-3.045 1.064-3.29.015-7.967-2.296-12.062-6.257-5.654-5.464-8.058-12-5.373-14.598 2.688-2.598 9.452-.276 15.106 5.193Z"
/>
<Path
stroke="#000"
strokeLinecap="round"
strokeLinejoin="round"
d="M15.148 32.76s8.669-9.555 9.322-18.02M17.952 35.882S37.232 18.483 40.12 6.066M21.187 38.592s15.388-12.395 30.899-11.966M30.719 12.173l1.853-3.9M50.3 20.645l4.411-.474M18.895 14.74l.003-1.205M34.445 25.46l.919-.816M38.931 43.845l1.212.284M25.175 9.514c-3.54-1.826-2.253-4.24-.123-4.367 3.251-.19 3.338-4.909-3.318-4.04M41.038 20.955c-1.644-3.28-.523-5.51 2.257-5.296 2.97.23 7.484 2.323 7.013-3.038-.539-6.13 3.385-6.7 6.692-5.063M41.065 36.892c1.382-3.168 4.289-2.77 5.295-.076 1.005 2.694 4.803 3.838 6.7-.402"
/>
</Svg>
)
}
26 changes: 25 additions & 1 deletion src/points/PointsDiscoverCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import PointsDiscoverCard from 'src/points/PointsDiscoverCard'
import { pointsDataRefreshStarted } from 'src/points/slice'
import { RootState } from 'src/redux/store'
import { getFeatureGate } from 'src/statsig/index'
import { StatsigFeatureGates } from 'src/statsig/types'
import { RecursivePartial, createMockStore } from 'test/utils'

jest.mock('src/analytics/AppAnalytics')
Expand All @@ -32,8 +33,31 @@ const renderPointsDiscoverCard = (storeOverrides?: RecursivePartial<RootState>)
describe('PointsDiscoverCard', () => {
beforeEach(() => {
jest.clearAllMocks()
jest.mocked(getFeatureGate).mockImplementation((gate) => {
if (gate === StatsigFeatureGates.SHOW_POINTS) {
return true
}
if (gate === StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT) {
return false
}
throw new Error('Unexpected gate')
})
})

it('renders nothing for UK compliant variant', () => {
jest.mocked(getFeatureGate).mockImplementation((gate) => {
if (gate === StatsigFeatureGates.SHOW_POINTS) {
return true
}
if (gate === StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT) {
return true
}
throw new Error('Unexpected gate')
})

const { toJSON } = renderPointsDiscoverCard()

jest.mocked(getFeatureGate).mockReturnValue(true)
expect(toJSON()).toBeNull()
})

it('renders when feature gate is enabled', () => {
Expand Down
3 changes: 2 additions & 1 deletion src/points/PointsDiscoverCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Spacing } from 'src/styles/styles'

export default function PointsDiscoverCard() {
const showPoints = getFeatureGate(StatsigFeatureGates.SHOW_POINTS)
const showUKCompliantVariant = getFeatureGate(StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT)

const dispatch = useDispatch()
const { t } = useTranslation()
Expand All @@ -38,7 +39,7 @@ export default function PointsDiscoverCard() {
dispatch(pointsDataRefreshStarted())
}, [])

if (!showPoints) {
if (!showPoints || showUKCompliantVariant) {
return null
}

Expand Down
Loading

0 comments on commit e34ca3b

Please sign in to comment.