Skip to content
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

Allow users to permanently dismiss the referral banners #34842

Merged
merged 28 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8c718e1
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 19, 2024
b8ed1e1
Add new types to account object
tgolen Jan 19, 2024
dad285a
Add action method which calls the API
tgolen Jan 22, 2024
ae53491
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 22, 2024
c38713e
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 22, 2024
5113259
Move API call to search page
tgolen Jan 22, 2024
85a998f
Do not show friend banner if it's been dismissed
tgolen Jan 22, 2024
ba74381
Perma dismiss banner from new chat page
tgolen Jan 22, 2024
bb9101c
Add perma dismiss to the create request page
tgolen Jan 22, 2024
f03be9c
Add perma dismiss to the edit request page
tgolen Jan 22, 2024
872cf94
Make action optimistic
tgolen Jan 22, 2024
c6cd3b5
Fix style and TS
tgolen Jan 22, 2024
0d8e169
Update lottie packages
tgolen Jan 23, 2024
530a3a6
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 25, 2024
f6cf0df
Update src/pages/SearchPage.js
tgolen Jan 29, 2024
ac75241
Update src/pages/NewChatPage.js
tgolen Jan 29, 2024
14055e8
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 29, 2024
73448b8
Update package lock file
tgolen Jan 29, 2024
a32bdf6
Fix style and types
tgolen Jan 29, 2024
e21861c
revert package.json changes
tgolen Jan 29, 2024
993724e
Update lottie react player
tgolen Jan 29, 2024
20645fc
Revert package.json again
tgolen Jan 29, 2024
354042e
Add more TS fixes
tgolen Jan 29, 2024
3a43633
Remove changes from file that is no longer referenced
tgolen Jan 29, 2024
b9b53bd
Put search page footer back, fix prop method name
tgolen Jan 29, 2024
7d28270
prettier
tgolen Jan 29, 2024
bf31586
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Jan 30, 2024
c5feb7e
Merge branch 'main' into tgolen-perma-dismiss-banners
tgolen Feb 2, 2024
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
11 changes: 8 additions & 3 deletions src/components/OptionsSelector/BaseOptionsSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ const propTypes = {
/** Whether referral CTA should be displayed */
shouldShowReferralCTA: PropTypes.bool,

/** A method triggered when the user closes the call to action banner */
onCallToActionClosed: PropTypes.func,

/** Referral content type */
referralContentType: PropTypes.string,

Expand All @@ -53,6 +56,7 @@ const propTypes = {
const defaultProps = {
shouldDelayFocus: false,
shouldShowReferralCTA: false,
onCallToActionClosed: () => {},
referralContentType: CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND,
safeAreaPaddingBottomStyle: {},
contentContainerStyles: [],
Expand All @@ -68,7 +72,7 @@ class BaseOptionsSelector extends Component {
this.updateFocusedIndex = this.updateFocusedIndex.bind(this);
this.scrollToIndex = this.scrollToIndex.bind(this);
this.selectRow = this.selectRow.bind(this);
this.handleReferralModal = this.handleReferralModal.bind(this);
this.closeReferralModal = this.closeReferralModal.bind(this);
this.selectFocusedOption = this.selectFocusedOption.bind(this);
this.addToSelection = this.addToSelection.bind(this);
this.updateSearchValue = this.updateSearchValue.bind(this);
Expand Down Expand Up @@ -262,8 +266,9 @@ class BaseOptionsSelector extends Component {
this.props.onChangeText(value);
}

handleReferralModal() {
closeReferralModal() {
this.setState((prevState) => ({shouldShowReferralModal: !prevState.shouldShowReferralModal}));
this.props.onCallToActionClosed(this.props.referralContentType);
}

handleFocusIn() {
Expand Down Expand Up @@ -652,7 +657,7 @@ class BaseOptionsSelector extends Component {
<View style={[this.props.themeStyles.ph5, this.props.themeStyles.pb5, this.props.themeStyles.flexShrink0]}>
<ReferralProgramCTA
referralContentType={this.props.referralContentType}
onCloseButtonPress={this.handleReferralModal}
onCloseButtonPress={this.closeReferralModal}
/>
</View>
)}
Expand Down
10 changes: 10 additions & 0 deletions src/libs/API/parameters/DismissReferralBannerParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';

type ContentTypes = ValueOf<typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES>;

type DismissReferralBannerParams = {
type: ContentTypes;
};

export default DismissReferralBannerParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type {default as ConnectBankAccountWithPlaidParams} from './ConnectBankAc
export type {default as DeleteContactMethodParams} from './DeleteContactMethodParams';
export type {default as DeletePaymentBankAccountParams} from './DeletePaymentBankAccountParams';
export type {default as DeletePaymentCardParams} from './DeletePaymentCardParams';
export type {default as DismissReferralBannerParams} from './DismissReferralBannerParams';
export type {default as ExpandURLPreviewParams} from './ExpandURLPreviewParams';
export type {default as GetMissingOnyxMessagesParams} from './GetMissingOnyxMessagesParams';
export type {default as GetNewerActionsParams} from './GetNewerActionsParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type UpdateBeneficialOwnersForBankAccountParams from './parameters/Update
type ApiRequest = ValueOf<typeof CONST.API_REQUEST_TYPE>;

const WRITE_COMMANDS = {
DISMISS_REFERRAL_BANNER: 'DismissReferralBanner',
UPDATE_PREFERRED_LOCALE: 'UpdatePreferredLocale',
RECONNECT_APP: 'ReconnectApp',
OPEN_PROFILE: 'OpenProfile',
Expand Down Expand Up @@ -120,6 +121,7 @@ const WRITE_COMMANDS = {
type WriteCommand = ValueOf<typeof WRITE_COMMANDS>;

type WriteCommandParameters = {
[WRITE_COMMANDS.DISMISS_REFERRAL_BANNER]: Parameters.DismissReferralBannerParams;
[WRITE_COMMANDS.UPDATE_PREFERRED_LOCALE]: Parameters.UpdatePreferredLocaleParams;
[WRITE_COMMANDS.RECONNECT_APP]: Parameters.ReconnectAppParams;
[WRITE_COMMANDS.OPEN_PROFILE]: Parameters.OpenProfileParams;
Expand Down
22 changes: 22 additions & 0 deletions src/libs/actions/User.ts
Original file line number Diff line number Diff line change
Expand Up @@ -843,9 +843,31 @@ function clearDraftCustomStatus() {
Onyx.merge(ONYXKEYS.CUSTOM_STATUS_DRAFT, {text: '', emojiCode: '', clearAfter: ''});
}

function dismissReferralBanner(type: ValueOf<typeof CONST.REFERRAL_PROGRAM.CONTENT_TYPES>) {
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.ACCOUNT,
value: {
dismissedReferralBanners: {
[type]: true,
},
},
},
];
API.write(
WRITE_COMMANDS.DISMISS_REFERRAL_BANNER,
{type},
{
optimisticData,
},
);
}

export {
clearFocusModeNotification,
closeAccount,
dismissReferralBanner,
resendValidateCode,
requestContactMethodValidateCode,
updateNewsletterSubscription,
Expand Down
18 changes: 16 additions & 2 deletions src/pages/NewChatPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import variables from '@styles/variables';
import * as Report from '@userActions/Report';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import personalDetailsPropType from './personalDetailsPropType';
Expand All @@ -36,6 +37,9 @@ const propTypes = {
/** All reports shared with the user */
reports: PropTypes.objectOf(reportPropTypes),

/** An object that holds data about which referral banners have been dismissed */
dismissedReferralBanners: PropTypes.objectOf(PropTypes.bool),

...windowDimensionsPropTypes,

...withLocalizePropTypes,
Expand All @@ -46,14 +50,15 @@ const propTypes = {

const defaultProps = {
betas: [],
dismissedReferralBanners: {},
personalDetails: {},
reports: {},
isSearchingForReports: false,
};

const excludedGroupEmails = _.without(CONST.EXPENSIFY_EMAILS, CONST.EMAIL.CONCIERGE);

function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, isSearchingForReports}) {
function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, isSearchingForReports, dismissedReferralBanners}) {
const styles = useThemeStyles();
const [searchTerm, setSearchTerm] = useState('');
const [filteredRecentReports, setFilteredRecentReports] = useState([]);
Expand Down Expand Up @@ -230,6 +235,10 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i
updateOptions();
}, [didScreenTransitionEnd, updateOptions]);

const dismissCallToAction = (referralContentType) => {
User.dismissReferralBanner(referralContentType);
};

const {inputCallbackRef} = useAutoFocusInput();

return (
Expand Down Expand Up @@ -265,8 +274,9 @@ function NewChatPage({betas, isGroupChat, personalDetails, reports, translate, i
shouldPreventDefaultFocusOnSelectRow={!DeviceCapabilities.canUseTouchScreen()}
shouldShowOptions={isOptionsDataReady && didScreenTransitionEnd}
shouldShowConfirmButton
shouldShowReferralCTA
shouldShowReferralCTA={!dismissedReferralBanners[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT]}
referralContentType={CONST.REFERRAL_PROGRAM.CONTENT_TYPES.START_CHAT}
onCallToActionClosed={dismissCallToAction}
confirmButtonText={selectedOptions.length > 1 ? translate('newChatPage.createGroup') : translate('newChatPage.createChat')}
textInputAlert={isOffline ? `${translate('common.youAppearToBeOffline')} ${translate('search.resultsAreLimited')}` : ''}
onConfirmSelection={createGroup}
Expand All @@ -291,6 +301,10 @@ export default compose(
withLocalize,
withWindowDimensions,
withOnyx({
dismissedReferralBanners: {
key: ONYXKEYS.ACCOUNT,
selector: (data) => data.dismissedReferralBanners || {},
},
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
Expand Down
25 changes: 21 additions & 4 deletions src/pages/SearchPage/SearchPageFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import React, {useState} from 'react';
import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import ReferralProgramCTA from '@components/ReferralProgramCTA';
import useThemeStyles from '@hooks/useThemeStyles';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {DismissedReferralBanners} from '@src/types/onyx/Account';

function SearchPageFooter() {
const [shouldShowReferralCTA, setShouldShowReferralCTA] = useState(true);
type SearchPageFooterOnyxProps = {
dismissedReferralBanners: DismissedReferralBanners;
};
function SearchPageFooter({dismissedReferralBanners}: SearchPageFooterOnyxProps) {
const [shouldShowReferralCTA, setShouldShowReferralCTA] = useState(!dismissedReferralBanners[CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND]);
const themeStyles = useThemeStyles();

const closeCallToActionBanner = () => {
setShouldShowReferralCTA(false);
User.dismissReferralBanner(CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND);
};

return (
<>
{shouldShowReferralCTA && (
<View style={[themeStyles.pb5, themeStyles.flexShrink0]}>
<ReferralProgramCTA
referralContentType={CONST.REFERRAL_PROGRAM.CONTENT_TYPES.REFER_FRIEND}
onCloseButtonPress={() => setShouldShowReferralCTA(false)}
onCloseButtonPress={closeCallToActionBanner}
/>
</View>
)}
Expand All @@ -24,4 +36,9 @@ function SearchPageFooter() {

SearchPageFooter.displayName = 'SearchPageFooter';

export default SearchPageFooter;
export default withOnyx<SearchPageFooterOnyxProps, SearchPageFooterOnyxProps>({
dismissedReferralBanners: {
key: ONYXKEYS.ACCOUNT,
selector: (data) => data?.dismissedReferralBanners ?? {},
},
})(SearchPageFooter);
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import reportPropTypes from '@pages/reportPropTypes';
import * as User from '@userActions/User';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';

const propTypes = {
/** Beta features list */
betas: PropTypes.arrayOf(PropTypes.string),

/** An object that holds data about which referral banners have been dismissed */
dismissedReferralBanners: PropTypes.objectOf(PropTypes.bool),

/** Callback to request parent modal to go to next step, which should be split */
onFinish: PropTypes.func.isRequired,

Expand Down Expand Up @@ -64,6 +68,7 @@ const defaultProps = {
safeAreaPaddingBottomStyle: {},
reports: {},
betas: [],
dismissedReferralBanners: {},
didScreenTransitionEnd: false,
};

Expand All @@ -76,12 +81,14 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
safeAreaPaddingBottomStyle,
iouType,
iouRequestType,
dismissedReferralBanners,
didScreenTransitionEnd,
}) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const [searchTerm, setSearchTerm] = useState('');
const [shouldShowReferralCTA, setShouldShowReferralCTA] = useState(true);
const referralContentType = iouType === CONST.IOU.TYPE.SEND ? CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY : CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST;
const [shouldShowReferralCTA, setShouldShowReferralCTA] = useState(!dismissedReferralBanners[referralContentType]);
const {isOffline} = useNetwork();
const personalDetails = usePersonalDetails();

Expand Down Expand Up @@ -251,7 +258,6 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
const hasPolicyExpenseChatParticipant = _.some(participants, (participant) => participant.isPolicyExpenseChat);
const shouldShowSplitBillErrorMessage = participants.length > 1 && hasPolicyExpenseChatParticipant;
const isAllowedToSplit = iouRequestType !== CONST.IOU.REQUEST_TYPE.DISTANCE;
const referralContentType = iouType === CONST.IOU.TYPE.SEND ? CONST.REFERRAL_PROGRAM.CONTENT_TYPES.SEND_MONEY : CONST.REFERRAL_PROGRAM.CONTENT_TYPES.MONEY_REQUEST;

const handleConfirmSelection = useCallback(() => {
if (shouldShowSplitBillErrorMessage) {
Expand All @@ -261,14 +267,19 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
onFinish();
}, [shouldShowSplitBillErrorMessage, onFinish]);

const closeCallToActionBanner = useCallback(() => {
setShouldShowReferralCTA(false);
User.dismissReferralBanner(referralContentType);
}, [referralContentType]);

const footerContent = useMemo(
() => (
<View>
{shouldShowReferralCTA && (
<View style={[styles.flexShrink0, !!participants.length && !shouldShowSplitBillErrorMessage && styles.pb5]}>
<ReferralProgramCTA
referralContentType={referralContentType}
onCloseButtonPress={() => setShouldShowReferralCTA(false)}
onCloseButtonPress={closeCallToActionBanner}
/>
</View>
)}
Expand All @@ -292,7 +303,7 @@ function MoneyTemporaryForRefactorRequestParticipantsSelector({
)}
</View>
),
[handleConfirmSelection, participants.length, referralContentType, shouldShowSplitBillErrorMessage, shouldShowReferralCTA, styles, translate],
[handleConfirmSelection, participants.length, referralContentType, shouldShowSplitBillErrorMessage, shouldShowReferralCTA, styles, translate, closeCallToActionBanner],
);

const itemRightSideComponent = useCallback(
Expand Down Expand Up @@ -356,6 +367,10 @@ MoneyTemporaryForRefactorRequestParticipantsSelector.defaultProps = defaultProps
MoneyTemporaryForRefactorRequestParticipantsSelector.displayName = 'MoneyTemporaryForRefactorRequestParticipantsSelector';

export default withOnyx({
dismissedReferralBanners: {
key: ONYXKEYS.ACCOUNT,
selector: (data) => data.dismissedReferralBanners || {},
},
reports: {
key: ONYXKEYS.COLLECTION.REPORT,
},
Expand Down
Loading
Loading