-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(points): Implement Points Home screen #5128
Conversation
1 build increased size
Celo (test) 1.81.0 (146)
|
Item | Install Size Change |
---|---|
main.jsbundle | ⬆️ 20.5 kB |
🛸 Powered by Emerge Tools
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good!! sorry i didn't quite understand the display logic but let's chat about it at our 1:1 later!
src/points/activityCards/index.tsx
Outdated
) | ||
} else { | ||
return ( | ||
<View testID={testID} style={styles.container}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of a separate component per activity, could we have a config that contains all the customisable info and render everything together? i think this is in essence what you've done, but i'm surprised by how many layers and new files there are. naively i thought it'd be as straightforward as something like
const pointsConfig = [{ // some props, like image, name }, ...]
...
render(
<>
...some other stuff
{pointsConfig.map(config => <ActivityCard {...config} />}
</>
)
the activity card would then take the name and decide on the stuff that is customised in a predictable way (e.g. we could have something like the bottomSheetTitle is always t(`points.activityCards.${activityName}.bottomSheet.title`)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should prefer using static translation keys so we can eventually use static extraction.
https://valora-app.slack.com/archives/C025V1D6F3J/p1707472640807039
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jeanregisser What are the requirements for this? Does this mean we can't store a translation key in a variable and then pass that to the translation function? I understand that we shouldn't dynamically generate the translation key itself (i.e., they should be considered opaque) but can we safely do something like?
const translationKey = condition ? 'some.key' : 'some.other.key'
...
t(translationKey)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes almost, best is like this:
const translation = condition ? t('some.key') : t('some.other.key')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome! 🚀
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5128 +/- ##
==========================================
+ Coverage 85.70% 85.75% +0.05%
==========================================
Files 730 739 +9
Lines 29862 30012 +150
Branches 5156 5178 +22
==========================================
+ Hits 25592 25738 +146
- Misses 4035 4038 +3
- Partials 235 236 +1
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
|
src/points/PointsHome.tsx
Outdated
} | ||
} | ||
return ( | ||
<SafeAreaView style={styles.outerContainer}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fun little bug encountered during development for those knowledgeable/wanting to do some sleuthing - without the outerContainer
style here, the page visually renders totally correctly, except is completely uninteractable (no scrolling, can't press on anything at all) under only the following circumstances:
- Running on Android and
- Page contents exceed screen size (meaning scrolling is required)
It all "just works" on iOS, and on Android when scrolling isn't required. Notably,_ removing either one of CustomHeader
or BottomSheet
made this issue go away... Satish and I spent some time trying to fix this, but still don't know why we were seeing this behavior 🤯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh interesting.
Not directly related to that bug, but does the ScrollView
extend to the bottom of the screen? If so the outer SafeAreaView
should only apply to the top, and we should either add another SafeAreaView
just for the bottom within the ScrollView
, or adjust it's bottom padding using useSafeAreaInsets()
.
So it doesn't hit an invisible wall on devices with a home bar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having this safeareaview outside is fine since we've now got the custom header which shouldn't scroll :) to elaborate on Jean's comment, we should have edges={['top']}
here and add a paddingBottom equivalent to the safe area bottom (or use another safe area view with the edges set to bottom only) on the scrollview contents to ensure that the end of the content isn't cut off.
weird android bug, i'm not sure i understand but perhaps you were experiencing this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! Already approved with some suggestions.
src/points/types.ts
Outdated
import React from 'react' | ||
|
||
const pointsActivities = ['create-wallet', 'swap', 'more-coming'] as const | ||
export type PointsActivities = (typeof pointsActivities)[number] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
export type PointsActivities = (typeof pointsActivities)[number] | |
export type PointsActivity = (typeof pointsActivities)[number] |
src/points/PointsHome.tsx
Outdated
} | ||
} | ||
return ( | ||
<SafeAreaView style={styles.outerContainer}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh interesting.
Not directly related to that bug, but does the ScrollView
extend to the bottom of the screen? If so the outer SafeAreaView
should only apply to the top, and we should either add another SafeAreaView
just for the bottom within the ScrollView
, or adjust it's bottom padding using useSafeAreaInsets()
.
So it doesn't hit an invisible wall on devices with a home bar.
src/points/ActivityCard.tsx
Outdated
</View> | ||
)} | ||
{cardDefinition.icon} | ||
<Text style={styles.cardTitle}>{t(cardDefinition.title)}</Text> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this static?
i.e. moving it to cardDefinition directly?
...
title: t('xxx')
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have a few more small suggestions but don't feel like i need to look at the PR again! :)
src/points/ActivityCard.tsx
Outdated
opacity: isCompleted ? 0.5 : 1, | ||
} | ||
const cardContainer = cardDefinition.bottomSheet ? ( | ||
<Touchable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit: could we get away with using Touchable always, and if there is no bottom sheet then we make the Touchable disabled + pass undefined to the onPress
? you could then move this directly into the render?
one other thing to test is when pressed on Android, does the touchable shadow stay within the bounds / corners of the card? i recently had to battle with this in SelectRecipientJumpstartButton
src/points/ActivityCard.tsx
Outdated
</> | ||
) | ||
|
||
const cardContainerStyle = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super nit, also personal preference: i think reading react components is already pretty non linear and cyclical because of hooks and stuff, i think that we can help readability along a bit by keeping render blocks together as much as possible and only create new variables when we need. i think this component would be easier to read if we collapsed some of cardContainerStyle
, cardContent
, testID
src/points/ActivityCard.tsx
Outdated
alignItems: 'center', | ||
padding: Spacing.Regular16, | ||
backgroundColor: Colors.gray1, | ||
height: 96, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just checking if we need to cap the height? this would crop content if font scaling on the device is enabled, i wonder if we should just let it scale freely and only cap the width? or if you are trying to force a minimum, maybe minHeight
?
src/points/PointsHome.tsx
Outdated
testId={`PointsActivityBottomSheet`} | ||
> | ||
{bottomSheetParams && ( | ||
<View> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe you don't need a view here, and can get away with a fragment<>
?
src/points/cardDefinitions.tsx
Outdated
icon: <SwapArrows />, | ||
defaultCompletionStatus: false, | ||
bottomSheet: { | ||
title: 'points.activityCards.swap.bottomSheet.title', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idk how serious we are about doing static extraction (we've been talking about it since i first joined and haven't really made a start on it, i'm also not sure it will work with OTA translations because once unused keys are removed, they might also be removed in Crowdin?) i saw @jeanregisser comment on this in another part of the PR, so we're not dynamically constructing the keys to keep the door for this open but i think the requirement is then also that we need to pass the t
function in here?
@@ -0,0 +1,18 @@ | |||
import * as React from 'react' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i lost the original thread but i think you mentioned that we want to create a new icon here because the checkmark is not quite the same as the other checkmark 🫠 i have a couple feelings about this, one of my triggers is stuff that looks the same but slightly different because it's just not clear the value of maintaining extra code for the subtle differences. also subtle differences = inconsistency. i'd encourage us to be gatekeepers of consistency and question designers when we see something that is same same but different, most of the time we're able to keep using existing components (or refresh existing components) - and if the answer is "we absolutely must use this slightly different thing because of reasons XYZ" then at least we feel better about the extra code :)
for this could i request that we check with Kayla if we need to use a new checkmark? and if so, perhaps we can replace the existing checkmark with this one.
i also had a thought that perhaps for these icons they're intended only for the points use case, and maybe we can put the icons in the points folder...i'd be less annoying if this icon wasn't going in the global folder which is already hard to navigate
src/points/PointsHome.tsx
Outdated
} | ||
} | ||
return ( | ||
<SafeAreaView style={styles.outerContainer}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
having this safeareaview outside is fine since we've now got the custom header which shouldn't scroll :) to elaborate on Jean's comment, we should have edges={['top']}
here and add a paddingBottom equivalent to the safe area bottom (or use another safe area view with the edges set to bottom only) on the scrollview contents to ensure that the end of the content isn't cut off.
weird android bug, i'm not sure i understand but perhaps you were experiencing this one?
Read your comment.
|
### Description For [ACT-1022](https://linear.app/valora/issue/RET-1022/[wallet]-build-points-landing-screen-add-statsig-config). Adds in the Points home screen and sets up Statsig to store points config information. See the Statsig Dynamic Config [here](https://console.statsig.com/4plizaPmWwPL21ASV4QAO0/dynamic_configs/points_config). Points visibility is gated by the feature gate [here](https://console.statsig.com/4plizaPmWwPL21ASV4QAO0/gates/show_points). Note that at the moment, this PR is complete _except_ for: * The actual Points logo/icon - I'm waiting on a high-quality vector image before adding it to the branding repo. * Some copy on the Swap bottom sheet. I added in the functionality to automatically create "sections" on the home screen for different point values - we won't need this immediately, but it was kinda fun to add to figured why not :) ### Test plan Unit and manual tested. See video below. https://github.com/valora-inc/wallet/assets/569401/c854b3d3-31c8-4d54-92f2-e65ed6bc2b76 ### Related issues - Fixes [ACT-1022](https://linear.app/valora/issue/RET-1022/[wallet]-build-points-landing-screen-add-statsig-config). ### Backwards compatibility Yes. ### Network scalability If a new NetworkId and/or Network are added in the future, the changes in this PR will: - [X] Continue to work without code changes, OR trigger a compilation error (guaranteeing we find it when a new network is added)
Description
For ACT-1022. Adds in the Points home screen and sets up Statsig to store points config information.
See the Statsig Dynamic Config here. Points visibility is gated by the feature gate here.
Note that at the moment, this PR is complete except for:
I added in the functionality to automatically create "sections" on the home screen for different point values - we won't need this immediately, but it was kinda fun to add to figured why not :)
Test plan
Unit and manual tested. See video below.
points-home-new-2024-03-21_21.31.59.mp4
Related issues
Backwards compatibility
Yes.
Network scalability
If a new NetworkId and/or Network are added in the future, the changes in this PR will: