-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Add Download app promo banner on desktop upload expense flow #61885
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
Conversation
I've started a new Slack discussion here to confirm the translation |
@mananjadhav Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Sorry if my issue was poorly explained, but I think we'd wanna show it on Desktop web as well: Here it's not showing 🤔 @jamesdeanexpensify @Expensify/design for visibility |
I’ve updated the PR to include desktop web as well |
Just so I'm clear - where are we going to add this? Web, mobile web, and desktop? I feel like we add it to everywhere but the mobile app, personally, but curious for thoughts! |
That makes sense, and I feel pretty strongly we shouldn't show this to users who already have the apps installed. |
Agreed! |
Agree, especially if there's no way to dismiss it. |
Ah, fair! So just desktop and web web then? Or what do you call it when you are on a computer and go on the world wide web? Just web? |
Desktop app and desktop web 😄 I do like web web too though 😂❤️ |
@@ -968,6 +970,24 @@ function IOURequestStepScan({ | |||
receiptImageTopPosition={receiptImageTopPosition} | |||
/> | |||
)} | |||
{platform !== CONST.PLATFORM.MOBILEWEB && !isMobile() && ( |
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.
@nyomanjyotisa It would be better to have this in platform specific files.
@nyomanjyotisa Can you please resolve the conflicts? |
I like the small button, but that orphan on the copy is killing me. Maybe we can add a word or two so the sentence feels more balanced? "Scan receipts directly from your phone" or something? |
|
I think |
LGTM 👍 |
@@ -977,6 +993,25 @@ function IOURequestStepScan({ | |||
receiptImageTopPosition={receiptImageTopPosition} | |||
/> | |||
)} | |||
{!isMobile() && isLastAppLoginLoaded && !hasInstalledApp && ( |
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.
With these many changes and checks, I think it makes sense to make it a resuable component.
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.
Left a few comments.
PR updated |
src/hooks/useHasInstalledApp.ts
Outdated
import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
||
const useHasInstalledApp = () => { | ||
const [lastIOSLogin] = useOnyx(ONYXKEYS.NVP_LAST_ECASH_IOS_LOGIN, {canBeMissing: true}); |
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.
@nyomanjyotisa We should use const [lastIOSLogin, lastIOSLoginResult] = useOnyx(ONYXKEYS.NVP_LAST_ECASH_IOS_LOGIN, {canBeMissing: true});
and get rid of the setTimeout.
src/hooks/useHasInstalledApp.ts
Outdated
const [isLastAppLoginLoaded, setIsLastAppLoginLoaded] = useState(false); | ||
|
||
useEffect(() => { | ||
const timer = setTimeout(() => { |
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.
As I mentioned earlier this isn't needed, we should rely on loaded/loading
status from useOnyx hook.
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.
PR updated!
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 you post revised screenshots based on these changes? To esnure it doesn't have any flicker or something.
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.
Sure, I've updated the screenshots
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppiOS: mWeb Safarimweb-safari-hide-download-banner.movMacOS: Desktopdesktop-show-download-banner.mov |
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.
Issues with my Android setup. Tests well. Uploaded screenshots for rest of the platforms.
Quick bump @puneetlath |
src/ONYXKEYS.ts
Outdated
/** Timestamp of the last login on iOS */ | ||
NVP_LAST_ECASH_IOS_LOGIN: 'nvp_lastECashIOSLogin', | ||
|
||
/** Timestamp of the last login on Android */ | ||
NVP_LAST_ECASH_ANDROID_LOGIN: 'nvp_lastECashAndroidLogin', |
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 think we should also add the lastAndroidLogin
and lastiPhoneLogin
nvps here. Since those are also for our mobile apps.
@@ -977,6 +978,7 @@ function IOURequestStepScan({ | |||
receiptImageTopPosition={receiptImageTopPosition} | |||
/> | |||
)} | |||
{!isMobile() && <DownloadAppBanner />} |
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.
Generally, we should be avoiding using isMobile() checks and instead having a separate index.web.ts
and index.ts
file, no?
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.
@puneetlath Here I felt it was okay because we don't want to show on Mobile Web as well as Native app. Even if we did add index.web.ts
, we'll need to add a check for isMobile
to hide it on mWeb.
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, in this case, we do need the isMobile
checks for mWeb
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.
Ok that makes sense to me. Can we add a comment explaining why we are using it here?
src/hooks/useHasInstalledApp.ts
Outdated
import {useOnyx} from 'react-native-onyx'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
||
const useHasInstalledApp = () => { |
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 a suggestion to make this even more explicit to what it is.
const useHasInstalledApp = () => { | |
const useHasLoggedIntoMobileApp = () => { |
src/hooks/useHasInstalledApp.ts
Outdated
|
||
const isLastAppLoginLoaded = lastIOSLoginResult.status !== 'loading' && lastAndroidLoginResult.status !== 'loading'; | ||
|
||
const hasInstalledApp = !!lastIOSLogin || !!lastAndroidLogin; |
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.
const hasInstalledApp = !!lastIOSLogin || !!lastAndroidLogin; | |
const hasLoggedIntoMobileApp = !!lastIOSLogin || !!lastAndroidLogin; |
src/hooks/useHasInstalledApp.ts
Outdated
const [lastIOSLogin, lastIOSLoginResult] = useOnyx(ONYXKEYS.NVP_LAST_ECASH_IOS_LOGIN, {canBeMissing: true}); | ||
const [lastAndroidLogin, lastAndroidLoginResult] = useOnyx(ONYXKEYS.NVP_LAST_ECASH_ANDROID_LOGIN, {canBeMissing: true}); | ||
|
||
const isLastAppLoginLoaded = lastIOSLoginResult.status !== 'loading' && lastAndroidLoginResult.status !== 'loading'; |
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.
const isLastAppLoginLoaded = lastIOSLoginResult.status !== 'loading' && lastAndroidLoginResult.status !== 'loading'; | |
const isLastMobileAppLoginLoaded = lastIOSLoginResult.status !== 'loading' && lastAndroidLoginResult.status !== 'loading'; |
@nyomanjyotisa Can you fix the conflicts? and also look at the comments. |
PR updated and retested |
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.
Thanks for the update @nyomanjyotisa. Test the latest change again.
@puneetlath All yours.
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.
Almost there!
@@ -977,6 +978,7 @@ function IOURequestStepScan({ | |||
receiptImageTopPosition={receiptImageTopPosition} | |||
/> | |||
)} | |||
{!isMobile() && <DownloadAppBanner />} |
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.
Ok that makes sense to me. Can we add a comment explaining why we are using it here?
import {useOnyx} from 'react-native-onyx'; | ||
import ONYXKEYS from '@src/ONYXKEYS'; | ||
|
||
const useHasLoggedIntoMobileApp = () => { |
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 add a comment explaining what this hook does? Like that it returns whether the user has ever logged into one of the Expensify mobile apps.
PR updated! |
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.
Thanks @puneetlath.
Thanks for the updates @nyomanjyotisa.
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to staging by https://github.com/puneetlath in version: 9.1.54-0 🚀
|
🚀 Deployed to production by https://github.com/roryabraham in version: 9.1.54-7 🚀
|
Explanation of Change
Fixed Issues
$ #61422
PROPOSAL: #61422 (comment)
Tests
Same as QA Steps
Offline tests
Same as QA Steps
QA Steps
Test 1
Download app
promo banner displayed correctlyTest 2
Download app
promo banner is not displayedPR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectioncanBeMissing
param foruseOnyx
toggleReport
and notonIconClick
)src/languages/*
files and using the translation methodSTYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)Design
label and/or tagged@Expensify/design
so the design team can review the changes.ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
User without the app installed / not logged in
MacOS-Chrome.mp4
User with the app installed / logged in
MacOS-Chrome-2.mp4
MacOS: Desktop
User without the app installed / not logged in
MacOS-Desktop.mp4
User with the app installed / logged in
MacOS-Desktop-2.mp4