From 1ef4ef346f4f35e4aa346472d0a5ebb1dc90fb20 Mon Sep 17 00:00:00 2001 From: ghgoodreau Date: Wed, 15 Jul 2026 15:16:11 -0500 Subject: [PATCH 1/2] perf(predict): remove GTM onboarding modal --- .github/workflows/build-android-e2e.yml | 1 - .github/workflows/build-ios-e2e.yml | 1 - .../Views/CardWelcome/CardWelcome.test.tsx | 1 - .../PredictGTMModal/PredictGTMModal.styles.ts | 131 ------------- .../PredictGTMModal/PredictGTMModal.test.tsx | 146 --------------- .../PredictGTMModal.testIds.ts | 5 - .../PredictGTMModal/PredictGTMModal.tsx | 175 ------------------ .../components/PredictGTMModal/index.ts | 1 - .../UI/Predict/constants/eventNames.ts | 8 - .../UI/Predict/routes/index.test.tsx | 15 -- app/components/UI/Predict/routes/index.tsx | 5 - .../selectors/featureFlags/index.test.ts | 49 ----- .../Predict/selectors/featureFlags/index.ts | 13 -- app/components/UI/Predict/types/navigation.ts | 1 - app/components/Views/Wallet/index.test.tsx | 14 -- app/components/Views/Wallet/index.tsx | 34 +--- app/constants/navigation/Routes.ts | 1 - app/constants/storage.ts | 2 - app/core/NavigationService/types.ts | 1 - .../AgenticService/AgenticService.test.ts | 5 - .../AgenticService/AgenticService.ts | 2 - app/images/powered-by-polymarket.png | Bin 5409 -> 0 bytes app/images/predict-marketing.png | Bin 1852174 -> 0 bytes app/util/generateSkipOnboardingState.ts | 4 - docs/predict/architecture-overview.md | 4 +- docs/predict/refactoring-tasks.md | 2 - locales/languages/de.json | 6 - locales/languages/el.json | 6 - locales/languages/en.json | 6 - locales/languages/es.json | 6 - locales/languages/fr.json | 6 - locales/languages/hi.json | 6 - locales/languages/id.json | 6 - locales/languages/ja.json | 6 - locales/languages/ko.json | 6 - locales/languages/pt.json | 6 - locales/languages/ru.json | 6 - locales/languages/tl.json | 6 - locales/languages/tr.json | 6 - locales/languages/vi.json | 6 - locales/languages/zh.json | 6 - .../mock-responses/feature-flags-mocks.ts | 17 -- tests/feature-flags/feature-flag-registry.ts | 11 -- tests/flows/wallet.flow.ts | 120 +----------- .../fixtures/json/default-fixture.json | 1 - .../page-objects/Predict/PredictModalView.ts | 30 --- tests/performance/README.md | 10 - .../onboarding/import-wallet.spec.ts | 34 ---- .../new-wallet-account-creation.spec.ts | 20 -- .../seedless-apple-onboarding.spec.ts | 26 +-- .../seedless-google-onboarding.spec.ts | 26 +-- .../seedless/google-login-add-srp.spec.ts | 4 - .../wallet/analytics/import-wallet.spec.ts | 8 +- .../smoke/wallet/analytics/new-wallet.spec.ts | 15 -- 54 files changed, 13 insertions(+), 1020 deletions(-) delete mode 100644 app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.styles.ts delete mode 100644 app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.test.tsx delete mode 100644 app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.testIds.ts delete mode 100644 app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.tsx delete mode 100644 app/components/UI/Predict/components/PredictGTMModal/index.ts delete mode 100644 app/images/powered-by-polymarket.png delete mode 100644 app/images/predict-marketing.png delete mode 100644 tests/page-objects/Predict/PredictModalView.ts diff --git a/.github/workflows/build-android-e2e.yml b/.github/workflows/build-android-e2e.yml index dfb127783a5..bd6158501d1 100644 --- a/.github/workflows/build-android-e2e.yml +++ b/.github/workflows/build-android-e2e.yml @@ -560,7 +560,6 @@ jobs: GOOGLE_SERVICES_B64_IOS: ${{ secrets.GOOGLE_SERVICES_B64_IOS }} GOOGLE_SERVICES_B64_ANDROID: ${{ secrets.GOOGLE_SERVICES_B64_ANDROID }} MM_INFURA_PROJECT_ID: ${{ secrets.MM_INFURA_PROJECT_ID }} - MM_PREDICT_GTM_MODAL_ENABLED: 'false' - name: Record Namespace E2E APK cache marker if: ${{ inputs.runner_provider == 'namespace' && steps.gate.outputs.needs-native-build == 'true' && inputs.source-fingerprint != '' && inputs.include_arm64 == false }} diff --git a/.github/workflows/build-ios-e2e.yml b/.github/workflows/build-ios-e2e.yml index f4b0c553e3a..f4501937c87 100644 --- a/.github/workflows/build-ios-e2e.yml +++ b/.github/workflows/build-ios-e2e.yml @@ -80,7 +80,6 @@ jobs: GOOGLE_SERVICES_B64_IOS: ${{ secrets.GOOGLE_SERVICES_B64_IOS }} GOOGLE_SERVICES_B64_ANDROID: ${{ secrets.GOOGLE_SERVICES_B64_ANDROID }} MM_INFURA_PROJECT_ID: ${{ secrets.MM_INFURA_PROJECT_ID }} - MM_PREDICT_GTM_MODAL_ENABLED: 'false' steps: # Get the source code from the repository diff --git a/app/components/UI/Card/Views/CardWelcome/CardWelcome.test.tsx b/app/components/UI/Card/Views/CardWelcome/CardWelcome.test.tsx index b484e6d0d06..f06cb054c6a 100644 --- a/app/components/UI/Card/Views/CardWelcome/CardWelcome.test.tsx +++ b/app/components/UI/Card/Views/CardWelcome/CardWelcome.test.tsx @@ -76,7 +76,6 @@ jest.mock('../../../../../../locales/i18n', () => ({ 'card.card_onboarding.description': 'Change your spending token and network by signing in with your Crypto Life email and password.', 'card.card_onboarding.apply_now_button': 'Sign in', - 'predict.gtm_content.not_now': 'Not now', }; return map[key] || key; }, diff --git a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.styles.ts b/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.styles.ts deleted file mode 100644 index 2927e7d8645..00000000000 --- a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.styles.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { Platform, StyleSheet, Dimensions } from 'react-native'; -import { colors as importedColors } from '../../../../../styles/common'; -import { Theme } from '@metamask/design-tokens'; - -// Responsive scaling utilities -const { width: screenWidth, height: screenHeight } = Dimensions.get('window'); - -// Platform-specific base dimensions -const BASE_WIDTH = 375; -const BASE_HEIGHT_IOS = 812; // iPhone X/11/12/13/14/15 Pro base -const BASE_HEIGHT_ANDROID = 736; // Common Android base - -const MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES = 750; - -// Calculate platform-aware scaling factors -const isIOS = Platform.OS === 'ios'; -const baseHeight = isIOS ? BASE_HEIGHT_IOS : BASE_HEIGHT_ANDROID; - -const widthScale = screenWidth / BASE_WIDTH; -const heightScale = screenHeight / baseHeight; - -// Use more conservative scaling to prevent excessive padding -const scale = Math.min(widthScale, heightScale); -const conservativeScale = Math.min(scale, 1.2); // Cap scaling at 120% - -// Platform-aware responsive scaling functions -const scaleSize = (size: number) => Math.ceil(size * conservativeScale); -const scaleFont = (size: number) => Math.ceil(size * conservativeScale); - -// For vertical spacing, use percentage of available height instead of pure scaling -const scaleVertical = (size: number) => { - // Use percentage of screen height for more consistent spacing - const percentage = size / baseHeight; - return Math.ceil(screenHeight * percentage); -}; - -const scaleHorizontal = (size: number) => Math.ceil(size * widthScale); - -const createStyles = (theme: Theme) => - StyleSheet.create({ - pageContainer: { - flex: 1, - position: 'relative', - maxHeight: '100%', - width: '100%', - }, - backgroundImage: { - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - width: screenWidth * 1.07, // 7% wider for edge coverage - height: - screenHeight * - (screenHeight < MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES - ? 1.12 - : 1.14), // 12% taller for edge coverage - resizeMode: 'cover', - }, - contentContainer: { - flex: 1, - }, - headerContainer: { - alignItems: 'center', - paddingHorizontal: scaleHorizontal(16), - paddingVertical: scaleVertical(16), - }, - poweredByImage: { - width: scaleHorizontal(200), - height: scaleVertical(24), - marginBottom: 8, - }, - spacer: { - flex: 1, - }, - title: { - fontFamily: 'MMPoly-Regular', - fontWeight: '400', - // make it smaller on smaller screens - fontSize: - screenHeight < MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES ? 40 : 50, - lineHeight: - screenHeight < MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES ? 40 : 50, // 100% of font size - letterSpacing: 0, - textAlign: 'center', - paddingTop: scaleVertical( - screenHeight < MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES ? 8 : 12, - ), - color: theme.colors.accent02.light, - }, - titleDescription: { - // make it smaller on smaller screens - fontSize: - screenHeight < MIN_SCREEN_HEIGHT_FOR_SMALL_SCREEN_STYLES ? 14 : 16, - paddingTop: scaleVertical(10), - paddingHorizontal: scaleHorizontal(8), - textAlign: 'center', - fontFamily: Platform.OS === 'ios' ? 'System' : 'Roboto', // Default system font - fontWeight: '500', - lineHeight: 24, // Line Height BodyMd - letterSpacing: 0, - color: theme.colors.accent02.light, - }, - footerContainer: { - display: 'flex', - rowGap: scaleVertical(8), - paddingHorizontal: scaleHorizontal(30), - }, - getStartedButton: { - borderRadius: scaleSize(12), - backgroundColor: importedColors.white, - }, - getStartedButtonText: { - color: importedColors.btnBlack, - fontWeight: '600', - fontSize: scaleFont(16), - }, - notNowButton: { - borderRadius: scaleSize(12), - backgroundColor: importedColors.transparent, - borderWidth: 0, - }, - notNowButtonText: { - color: importedColors.white, - fontWeight: '500', - fontSize: scaleFont(16), - }, - }); - -export default createStyles; diff --git a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.test.tsx b/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.test.tsx deleted file mode 100644 index 6bb877f8785..00000000000 --- a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.test.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import React from 'react'; -import { fireEvent, waitFor } from '@testing-library/react-native'; -import PredictGTMModal from './PredictGTMModal'; -import StorageWrapper from '../../../../../store/storage-wrapper'; -import Routes from '../../../../../constants/navigation/Routes'; -import { MetaMetricsEvents } from '../../../../../core/Analytics'; -import { PREDICT_GTM_MODAL_SHOWN } from '../../../../../constants/storage'; -import renderWithProvider from '../../../../../util/test/renderWithProvider'; -import { backgroundState } from '../../../../../util/test/initial-root-state'; -import { useAnalytics } from '../../../../../components/hooks/useAnalytics/useAnalytics'; -import { createMockUseAnalyticsHook } from '../../../../../util/test/analyticsMock'; - -jest.mock('../../../../../util/theme', () => { - const { mockTheme } = jest.requireActual('../../../../../util/theme'); - return { - useTheme: jest.fn(() => mockTheme), - }; -}); - -jest.mock('../../../../../../locales/i18n', () => ({ - strings: (key: string) => key, -})); - -jest.mock('../../../../../store/storage-wrapper', () => ({ - getItem: jest.fn(), - setItem: jest.fn(), -})); - -const mockNavigate = jest.fn(); -jest.mock('@react-navigation/native', () => { - const actualNav = jest.requireActual('@react-navigation/native'); - return { - ...actualNav, - useNavigation: () => ({ - navigate: mockNavigate, - goBack: jest.fn(), - }), - }; -}); - -const mockTrackEvent = jest.fn(); -const mockCreateEventBuilder = jest.fn().mockReturnValue({ - addProperties: jest.fn().mockReturnThis(), - build: jest.fn().mockReturnValue({}), -}); -jest.mock('../../../../../components/hooks/useAnalytics/useAnalytics'); - -jest.mock('../../../../../util/metrics', () => ({ - __esModule: true, - default: jest.fn(() => ({ - platform: 'ios', - deviceModel: 'iPhone 14', - })), -})); - -const initialState = { - engine: { - backgroundState, - }, -}; - -describe('PredictGTMModal', () => { - beforeEach(() => { - jest.clearAllMocks(); - jest.mocked(useAnalytics).mockReturnValue( - createMockUseAnalyticsHook({ - trackEvent: mockTrackEvent, - createEventBuilder: mockCreateEventBuilder, - }), - ); - jest.mocked(StorageWrapper.getItem).mockResolvedValue('false'); - }); - - it('renders correctly with all main elements', async () => { - const { getByText, getByTestId } = renderWithProvider(, { - state: initialState, - }); - - await waitFor(() => { - expect(getByText('predict.gtm_content.title')).toBeTruthy(); - expect(getByText('predict.gtm_content.title_description')).toBeTruthy(); - expect(getByText('predict.gtm_content.get_started')).toBeTruthy(); - expect(getByText('predict.gtm_content.not_now')).toBeTruthy(); - expect(getByTestId('predict-gtm-modal-container')).toBeTruthy(); - }); - }); - - it('handles close button press correctly', async () => { - const { getByText } = renderWithProvider(, { - state: initialState, - }); - - await waitFor(() => { - const notNowButton = getByText('predict.gtm_content.not_now'); - fireEvent.press(notNowButton); - }); - - expect(StorageWrapper.setItem).toHaveBeenCalledWith( - PREDICT_GTM_MODAL_SHOWN, - 'true', - ); - expect(mockTrackEvent).toHaveBeenCalled(); - expect(mockCreateEventBuilder).toHaveBeenCalledWith( - MetaMetricsEvents.WHATS_NEW_LINK_CLICKED, - ); - expect(mockNavigate).toHaveBeenCalledWith(Routes.WALLET.HOME); - }); - - it('handles get started button press correctly', async () => { - const { getByText } = renderWithProvider(, { - state: initialState, - }); - - await waitFor(() => { - const getStartedButton = getByText('predict.gtm_content.get_started'); - fireEvent.press(getStartedButton); - }); - - expect(StorageWrapper.setItem).toHaveBeenCalledWith( - PREDICT_GTM_MODAL_SHOWN, - 'true', - { emitEvent: false }, - ); - expect(mockTrackEvent).toHaveBeenCalled(); - expect(mockCreateEventBuilder).toHaveBeenCalledWith( - MetaMetricsEvents.WHATS_NEW_LINK_CLICKED, - ); - expect(mockNavigate).toHaveBeenCalledWith(Routes.WALLET.HOME); - expect(mockNavigate).toHaveBeenCalledWith(Routes.PREDICT.ROOT, { - screen: Routes.PREDICT.MARKET_LIST, - params: { - entryPoint: expect.any(String), - }, - }); - }); - - it('renders image correctly', async () => { - const { getByTestId } = renderWithProvider(, { - state: initialState, - }); - - await waitFor(() => { - expect(getByTestId('predict-gtm-modal-container')).toBeTruthy(); - }); - }); -}); diff --git a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.testIds.ts b/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.testIds.ts deleted file mode 100644 index daf34be298f..00000000000 --- a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.testIds.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const PREDICT_GTM_MODAL_TEST_IDS = { - CONTAINER: 'predict-gtm-modal-container', - GET_STARTED_BUTTON: 'predict-gtm-get-started-button', - NOT_NOW_BUTTON: 'predict-gtm-not-now-button', -} as const; diff --git a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.tsx b/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.tsx deleted file mode 100644 index fe31f0e12aa..00000000000 --- a/app/components/UI/Predict/components/PredictGTMModal/PredictGTMModal.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { useNavigation } from '@react-navigation/native'; -import React, { useState, useEffect } from 'react'; -import { Image, View } from 'react-native'; -import Animated, { - useSharedValue, - useAnimatedStyle, - withTiming, -} from 'react-native-reanimated'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { strings } from '../../../../../../locales/i18n'; -import ButtonBase from '../../../../../component-library/components/Buttons/Button/foundation/ButtonBase'; -import Button, { - ButtonSize, - ButtonVariants, - ButtonWidthTypes, -} from '../../../../../component-library/components/Buttons/Button'; -import Text, { - TextVariant, -} from '../../../../../component-library/components/Texts/Text'; -import { useAnalytics } from '../../../../../components/hooks/useAnalytics/useAnalytics'; -import Routes from '../../../../../constants/navigation/Routes'; -import { MetaMetricsEvents } from '../../../../../core/Analytics'; -import PredictMarketingImage from '../../../../../images/predict-marketing.png'; -import PoweredByPolymarketImage from '../../../../../images/powered-by-polymarket.png'; -import StorageWrapper from '../../../../../store/storage-wrapper'; -import { PREDICT_GTM_MODAL_SHOWN } from '../../../../../constants/storage'; -import { useTheme } from '../../../../../util/theme'; -import generateDeviceAnalyticsMetaData from '../../../../../util/metrics'; -import createStyles from './PredictGTMModal.styles'; -import { - PREDICT_GTM_MODAL_DECLINE, - PREDICT_GTM_MODAL_ENGAGE, - PREDICT_GTM_WHATS_NEW_MODAL, - PredictEventValues, -} from '../../constants/eventNames'; -import { PREDICT_GTM_MODAL_TEST_IDS } from './PredictGTMModal.testIds'; - -const PredictGTMModal = () => { - const { trackEvent, createEventBuilder } = useAnalytics(); - const { navigate } = useNavigation(); - const theme = useTheme(); - const [imageLoaded, setImageLoaded] = useState(false); - const opacity = useSharedValue(0); - - const titleText = strings('predict.gtm_content.title'); - const subtitleText = strings('predict.gtm_content.title_description'); - - const styles = createStyles(theme); - - // Animate content fade-in when image loads - useEffect(() => { - if (imageLoaded) { - opacity.value = withTiming(1, { duration: 500 }); - } - }, [imageLoaded, opacity]); - - const animatedStyle = useAnimatedStyle(() => ({ - opacity: opacity.value, - })); - - const handleClose = async () => { - await StorageWrapper.setItem(PREDICT_GTM_MODAL_SHOWN, 'true'); - - trackEvent( - createEventBuilder(MetaMetricsEvents.WHATS_NEW_LINK_CLICKED) - .addProperties({ - ...generateDeviceAnalyticsMetaData(), - feature: PREDICT_GTM_WHATS_NEW_MODAL, - action: PREDICT_GTM_MODAL_DECLINE, - }) - .build(), - ); - - navigate(Routes.WALLET.HOME); - }; - - const handleGetStarted = async () => { - trackEvent( - createEventBuilder(MetaMetricsEvents.WHATS_NEW_LINK_CLICKED) - .addProperties({ - ...generateDeviceAnalyticsMetaData(), - feature: PREDICT_GTM_WHATS_NEW_MODAL, - action: PREDICT_GTM_MODAL_ENGAGE, - }) - .build(), - ); - - await StorageWrapper.setItem(PREDICT_GTM_MODAL_SHOWN, 'true', { - emitEvent: false, - }); - - navigate(Routes.WALLET.HOME); - - navigate(Routes.PREDICT.ROOT, { - screen: Routes.PREDICT.MARKET_LIST, - params: { - entryPoint: PredictEventValues.ENTRY_POINT.GTM_MODAL, - }, - }); - }; - - return ( - - {/* Background Image - Full Screen */} - setImageLoaded(true)} - /> - - {/* Content Overlay */} - - {/* Header Section */} - - - - {titleText} - - - {subtitleText} - - - - {/* Spacer to push footer to bottom */} - - - {/* Footer Section */} - - handleGetStarted()} - testID={PREDICT_GTM_MODAL_TEST_IDS.GET_STARTED_BUTTON} - size={ButtonSize.Lg} - width={ButtonWidthTypes.Full} - style={styles.getStartedButton} - activeOpacity={0.6} - label={ - - {strings('predict.gtm_content.get_started')} - - } - /> -