Skip to content

Commit

Permalink
feat: IAP Migration Message (#2512)
Browse files Browse the repository at this point in the history
* feat: IAP Migration Message wip

* fix: Now only shows once

* chore: New design and copy

* chore: Updated date
  • Loading branch information
jimhunty authored Oct 24, 2024
1 parent 186a09b commit b5368eb
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 4 deletions.
13 changes: 12 additions & 1 deletion projects/Mallard/src/AppNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NavigationContainer } from '@react-navigation/native';
import type { NavigationContainerRef } from '@react-navigation/native';
import { NavigationContainer } from '@react-navigation/native';
import type { StackCardInterpolationProps } from '@react-navigation/stack';
import {
CardStyleInterpolators,
Expand All @@ -9,6 +9,7 @@ import {
import React, { useRef } from 'react';
import { Animated } from 'react-native';
import { isTablet } from 'react-native-device-info';
import { IAPAppMigrationModal } from './components/Modals/IAPAppMigration';
import {
MissingIAPRestoreError,
MissingIAPRestoreMissing,
Expand Down Expand Up @@ -366,6 +367,16 @@ const MainStack = () => {
},
}}
/>
<Main.Screen
name={RouteNames.IAPAppMigrationModal}
component={IAPAppMigrationModal}
options={{
cardStyleInterpolator: forFade,
cardStyle: {
backgroundColor: 'rgba(0,0,0,0.6)',
},
}}
/>
</Main.Group>
</Main.Navigator>
);
Expand Down
31 changes: 31 additions & 0 deletions projects/Mallard/src/components/Modals/IAPAppMigration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useNavigation } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import React from 'react';
import { logEvent } from '../../helpers/analytics';
import { hasSeenIapMigrationMessage } from '../../helpers/storage';
import type { MainStackParamList } from '../../navigation/NavigationModels';
import { RouteNames } from '../../navigation/NavigationModels';
import { CenterWrapper } from '../CenterWrapper/CenterWrapper';
import { IAPAppMigrationModalCard } from '../iap-app-migration-modal-card';

const IAPAppMigrationModal = () => {
const { navigate } =
useNavigation<NativeStackNavigationProp<MainStackParamList>>();
return (
<CenterWrapper>
<IAPAppMigrationModalCard
onDismiss={() => {
navigate(RouteNames.Issue);

logEvent({
name: 'iap_app_migration_modal',
value: 'iap_app_migration_modal_dismissed',
});
hasSeenIapMigrationMessage.set(true);
}}
/>
</CenterWrapper>
);
};

export { IAPAppMigrationModal };
30 changes: 30 additions & 0 deletions projects/Mallard/src/components/iap-app-migration-modal-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { copy } from '../helpers/words';
import { color } from '../theme/color';
import { CardAppearance, OnboardingCard } from './onboarding/onboarding-card';
import { UiBodyCopy } from './styled-text';

const style = StyleSheet.create({
bodyCopy: {
color: color.palette.neutral[100],
},
});

const IAPAppMigrationModalCard = ({ onDismiss }: { onDismiss: () => void }) => {
return (
<OnboardingCard
onDismissThisCard={onDismiss}
title={copy.iAPMigration.title}
appearance={CardAppearance.Clashy}
size="medium"
bottomContent={
<UiBodyCopy style={style.bodyCopy}>
{copy.iAPMigration.body}
</UiBodyCopy>
}
/>
);
};

export { IAPAppMigrationModalCard };
12 changes: 11 additions & 1 deletion projects/Mallard/src/components/onboarding/onboarding-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum CardAppearance {
Tomato,
Apricot,
Blue,
Clashy,
}

const styles = StyleSheet.create({
Expand Down Expand Up @@ -76,6 +77,11 @@ const appearances: {
titleText: { color: color.palette.neutral[100] },
subtitleText: { color: color.primary },
}),
[CardAppearance.Clashy]: StyleSheet.create({
background: { backgroundColor: color.ui.sea },
titleText: { color: color.ui.brightYellow },
subtitleText: { color: color.palette.neutral[100] },
}),
};

const OnboardingCard = ({
Expand Down Expand Up @@ -144,7 +150,11 @@ const OnboardingCard = ({
onPress={onDismissThisCard}
accessibilityHint="This will dismiss the onboarding card"
accessibilityLabel={`Dismiss the ${title} onboarding card`}
appearance={ButtonAppearance.SkeletonBlue}
appearance={
appearance === CardAppearance.Clashy
? ButtonAppearance.SkeletonLight
: ButtonAppearance.SkeletonBlue
}
/>
</View>
)}
Expand Down
5 changes: 5 additions & 0 deletions projects/Mallard/src/helpers/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ const hasShownRatingCache = createAsyncCache<boolean>(
'@Setting_hasShownRating',
);

const hasSeenIapMigrationMessage = createAsyncCache<boolean>(
'@Setting_hasSeenIapMigrationMessage',
);

const issueSummaryCache = createAsyncCache<string>('issueSummary');
/**
* Creates a simple store (wrapped around the keychain) for tokens.
Expand Down Expand Up @@ -209,4 +213,5 @@ export {
hasShownRatingCache,
oktaDataCache,
issueSummaryCache,
hasSeenIapMigrationMessage,
};
6 changes: 6 additions & 0 deletions projects/Mallard/src/helpers/words.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,11 @@ const enableAll = 'Enable all';
const rejectAll = 'Reject all';
const andContinue = 'and continue';

const iAPMigration = {
title: 'The app is changing...',
body: 'On 16/12/2024, we will be switching to a new app. Your subscription will be transferred automatically, so you don’t need to do anything. The new app will feel more like a digital version of our newspaper, and we hope it delivers an intuitive reading experience you continue to enjoy.\n\n Thank you for your ongoing support.',
};

export const copy = {
alreadySubscribed,
andContinue,
Expand All @@ -259,6 +264,7 @@ export const copy = {
externalSubscription,
failedSignIn,
homeScreen,
iAPMigration,
issueListFooter,
manageDownloads,
newEditionWords,
Expand Down
2 changes: 2 additions & 0 deletions projects/Mallard/src/navigation/NavigationModels.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type MainStackParamList = {
OnboardingConsent: undefined;
PrivacyPolicyInline: undefined;
OnboardingConsentInline: undefined;
IAPAppMigrationModal: undefined;
};

export enum RouteNames {
Expand Down Expand Up @@ -86,4 +87,5 @@ export enum RouteNames {
MissingIAPRestoreError = 'MissingIAPRestoreError',
MissingIAPRestoreMissing = 'MissingIAPRestoreMissing',
ManageEditionsFromSettings = 'ManageEditionsFromSettings',
IAPAppMigrationModal = 'IAPAppMigrationModal',
}
24 changes: 22 additions & 2 deletions projects/Mallard/src/screens/issue-screen.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,26 @@
import { useNavigation, useRoute } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';
import type { MutableRefObject, ReactElement } from 'react';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import React, {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,

Check warning on line 10 in projects/Mallard/src/screens/issue-screen.tsx

View workflow job for this annotation

GitHub Actions / build

'useState' is defined but never used

Check warning on line 10 in projects/Mallard/src/screens/issue-screen.tsx

View workflow job for this annotation

GitHub Actions / build

'useState' is defined but never used

Check warning on line 10 in projects/Mallard/src/screens/issue-screen.tsx

View workflow job for this annotation

GitHub Actions / build

'useState' is defined but never used
} from 'react';
import type { StyleProp, ViewStyle } from 'react-native';
import { FlatList, StyleSheet, View } from 'react-native';
import Image from 'react-native-fast-image';
import RNRestart from 'react-native-restart';
import SplashScreen from 'react-native-splash-screen';
import { PageLayoutSizes } from '../common';
import { AccessContext } from '../authentication/AccessContext';
import type {
IssueWithFronts,
SpecialEditionHeaderStyles,
Front as TFront,
} from '../common';
import { PageLayoutSizes } from '../common';
import { ReloadButton } from '../components/Button/ReloadButton';
import { Front } from '../components/front';
import { FlexCenter } from '../components/layout/flex-center';
Expand All @@ -30,6 +38,7 @@ import {
} from '../components/weather';
import { deleteIssueFiles } from '../download-edition/clear-issues-and-editions';
import { logPageView } from '../helpers/analytics';
import { hasSeenIapMigrationMessage } from '../helpers/storage';
import type { FlatCard } from '../helpers/transform';
import {
flattenCollectionsToCards,
Expand Down Expand Up @@ -61,6 +70,7 @@ import {
type MainStackParamList,
RouteNames,
} from '../navigation/NavigationModels';
import { remoteConfigService } from '../services/remote-config';
import { Breakpoints } from '../theme/breakpoints';
import { metrics } from '../theme/spacing';
import { SLIDER_FRONT_HEIGHT } from './article/slider/SliderTitle';
Expand Down Expand Up @@ -442,6 +452,16 @@ export const IssueScreen = React.memo(() => {
const { hasSetGdpr } = useGdprSettings();
const { navigate } =
useNavigation<NativeStackNavigationProp<MainStackParamList>>();
const { iapData } = useContext(AccessContext);

useEffect(() => {
hasSeenIapMigrationMessage.get().then((hasSeen) => {
!hasSeen &&
iapData &&
remoteConfigService.getBoolean('is_iap_message_enabled') &&
navigate(RouteNames.IAPAppMigrationModal);
});
}, []);

// This is only returning true or false so keep reverting. Need an onboarding state
const isOnboarded = hasSetGdpr();
Expand Down
8 changes: 8 additions & 0 deletions projects/Mallard/src/screens/settings/dev-zone.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { locale } from '../../helpers/locale';
import { isInBeta, isInTestFlight } from '../../helpers/release-stream';
import { imageForScreenSize } from '../../helpers/screen';
import {
hasSeenIapMigrationMessage,
issueSummaryCache,
pushRegisteredTokens,
showAllEditionsCache,
Expand Down Expand Up @@ -243,6 +244,13 @@ const DevZone = () => {
Add legacy IAP receipt
</Button>
)}
<Button
onPress={() =>
hasSeenIapMigrationMessage.set(false)
}
>
Reset IAP migration message
</Button>
<Button
onPress={() => {
Alert.alert(
Expand Down
2 changes: 2 additions & 0 deletions projects/Mallard/src/services/remote-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const remoteConfigDefaults = {
download_parallel_ssr_bundle: false,
rating: false,
is_editions_menu_enabled: true,
is_iap_message_enabled: true,
};

const RemoteConfigProperties = [
Expand All @@ -27,6 +28,7 @@ const RemoteConfigProperties = [
'download_parallel_ssr_bundle',
'rating',
'is_editions_menu_enabled',
'is_iap_message_enabled',
] as const;

type RemoteConfigProperty = (typeof RemoteConfigProperties)[number];
Expand Down
1 change: 1 addition & 0 deletions projects/Mallard/src/theme/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export const color = {
shark: sport[400],
sea: '#279DDC',
supportBlue: '#41A9E0',
brightYellow: '#FFE500',
},

/*
Expand Down

0 comments on commit b5368eb

Please sign in to comment.