Skip to content

Commit 4e1f85a

Browse files
authored
fix: stop reloading of animation & browser back option cp-13.9.0 (#37581)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until the template has been completely filled out, and PR status checks have passed at least once. --> ## **Description** <!-- Write a short description of the changes included in this pull request, also include relevant motivation and context. Have in mind the following questions: 1. What is the reason for the change? 2. What is the improvement/solution? --> In this PR, we have added the logic to stop the animation once completed. Also added a browser back logic for login options. Jira Link: https://consensyssoftware.atlassian.net/browse/SL-278 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/37581?quickstart=1) ## **Changelog** <!-- If this PR is not End-User-Facing and should not show up in the CHANGELOG, you can choose to either: 1. Write `CHANGELOG entry: null` 2. Label with `no-changelog` If this PR is End-User-Facing, please write a short User-Facing description in the past tense like: `CHANGELOG entry: Added a new tab for users to see their NFTs` `CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker` (This helps the Release Engineer do their job more quickly and accurately) --> CHANGELOG entry: stopped reloading of animation once completed ## **Related issues** Fixes: ## **Manual testing steps** 1. Open Extension 2. validate animation reloading 3. ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/7c01d5bc-2aeb-4591-84e6-c359e73a71c1 https://github.com/user-attachments/assets/1ccacae4-1aec-4fbd-b170-e879e54970b5 ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Extension Coding Standards](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-extension/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [x] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [x] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Persists Rive animation completion to skip replays, switches welcome flow to context-based skipping, and syncs login option visibility via the `?login` query param; updates navigation and tests. > > - **Onboarding animations**: > - Add `animationCompleted` map and `setIsAnimationCompleted` to `RiveWasmContext` (`ui/contexts/rive-wasm/index.tsx`). > - `MetamaskWordMarkAnimation` sets completion on unmount and consumes the new setter; updates effect deps (`ui/pages/onboarding-flow/welcome/metamask-wordmark-animation.tsx`). > - `welcome` uses `animationCompleted.MetamaskWordMarkAnimation` to decide `shouldSkipAnimation` (replaces URL-based check) (`ui/pages/onboarding-flow/welcome/welcome.js`). > - **Login flow URL syncing**: > - `WelcomeLogin` reads `?login=` to control option view and writes it on selection via `navigate` (`ui/pages/onboarding-flow/welcome/welcome-login.tsx`). > - **Navigation adjustments**: > - `AccountExist` returns to `ONBOARDING_WELCOME_ROUTE` without `?from=...`; tests updated accordingly (`ui/pages/onboarding-flow/account-exist/*`). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 709317b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent eec2e91 commit 4e1f85a

File tree

6 files changed

+68
-16
lines changed

6 files changed

+68
-16
lines changed

ui/contexts/rive-wasm/index.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,21 @@ const RiveWasmContext = createContext<{
5454
error: Error | undefined;
5555
urlBufferMap: Record<string, ArrayBuffer>;
5656
setUrlBufferCache: (url: string, buffer: ArrayBuffer) => void;
57+
animationCompleted: Record<string, boolean>;
58+
setIsAnimationCompleted: (
59+
animationName: string,
60+
isAnimationCompleted: boolean,
61+
) => void;
5762
}>({
5863
isWasmReady: false,
5964
loading: false,
6065
error: undefined,
6166
urlBufferMap: {},
6267
// eslint-disable-next-line no-empty-function
6368
setUrlBufferCache: () => {},
69+
animationCompleted: {},
70+
// eslint-disable-next-line no-empty-function
71+
setIsAnimationCompleted: () => {},
6472
});
6573

6674
// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860
@@ -73,18 +81,40 @@ export default function RiveWasmProvider({
7381
const [urlBufferMap, setUrlBufferMap] = useState<Record<string, ArrayBuffer>>(
7482
{},
7583
);
84+
const [animationCompleted, setAnimationCompleted] = useState<
85+
Record<string, boolean>
86+
>({});
87+
7688
const setUrlBufferCache = useCallback(
7789
(url: string, buffer: ArrayBuffer) => {
7890
setUrlBufferMap((prev) => ({ ...prev, [url]: buffer }));
7991
},
8092
[setUrlBufferMap],
8193
);
8294

95+
const setIsAnimationCompleted = useCallback(
96+
(animationName: string, isAnimationCompleted: boolean) => {
97+
setAnimationCompleted((prev) => ({
98+
...prev,
99+
[animationName]: isAnimationCompleted,
100+
}));
101+
},
102+
[setAnimationCompleted],
103+
);
104+
83105
const { isWasmReady, loading, error } = useRiveWasmReady();
84106

85107
return (
86108
<RiveWasmContext.Provider
87-
value={{ isWasmReady, loading, error, urlBufferMap, setUrlBufferCache }}
109+
value={{
110+
isWasmReady,
111+
loading,
112+
error,
113+
urlBufferMap,
114+
setUrlBufferCache,
115+
animationCompleted,
116+
setIsAnimationCompleted,
117+
}}
88118
>
89119
{children}
90120
</RiveWasmContext.Provider>

ui/pages/onboarding-flow/account-exist/account-exist.test.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,9 @@ describe('Account Exist Seedless Onboarding View', () => {
9595
fireEvent.click(loginButton);
9696

9797
await waitFor(() => {
98-
expect(mockUseNavigate).toHaveBeenCalledWith(
99-
`${ONBOARDING_WELCOME_ROUTE}?from=account-exist`,
100-
{
101-
replace: true,
102-
},
103-
);
98+
expect(mockUseNavigate).toHaveBeenCalledWith(ONBOARDING_WELCOME_ROUTE, {
99+
replace: true,
100+
});
104101
expect(resetOnboardingSpy).toHaveBeenCalled();
105102
});
106103
});

ui/pages/onboarding-flow/account-exist/account-exist.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export default function AccountExist() {
5959
// reset onboarding flow
6060
await dispatch(resetOnboarding());
6161
await forceUpdateMetamaskState(dispatch);
62-
navigate(`${ONBOARDING_WELCOME_ROUTE}?from=account-exist`, {
62+
navigate(ONBOARDING_WELCOME_ROUTE, {
6363
replace: true,
6464
});
6565
};

ui/pages/onboarding-flow/welcome/metamask-wordmark-animation.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default function MetamaskWordMarkAnimation({
3131
const theme = useTheme();
3232
const isTestEnvironment = Boolean(process.env.IN_TEST);
3333
const context = useRiveWasmContext();
34-
const { isWasmReady, error: wasmError } = context;
34+
const { isWasmReady, error: wasmError, setIsAnimationCompleted } = context;
3535
const {
3636
buffer,
3737
error: bufferError,
@@ -122,9 +122,18 @@ export default function MetamaskWordMarkAnimation({
122122
return () => {
123123
if (animationTimeoutRef.current) {
124124
clearTimeout(animationTimeoutRef.current);
125+
setIsAnimationCompleted('MetamaskWordMarkAnimation', true);
125126
}
126127
};
127-
}, [rive, theme, isWasmReady, skipTransition, bufferLoading, buffer]);
128+
}, [
129+
rive,
130+
theme,
131+
isWasmReady,
132+
skipTransition,
133+
bufferLoading,
134+
buffer,
135+
setIsAnimationCompleted,
136+
]);
128137

129138
// Don't render Rive component until ready or if loading/failed
130139
if (

ui/pages/onboarding-flow/welcome/welcome-login.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useCallback, useEffect, useRef, useState } from 'react';
22
import { useDispatch } from 'react-redux';
3+
import { useSearchParams, useNavigate } from 'react-router-dom-v5-compat';
34
import {
45
Box,
56
Button,
@@ -16,6 +17,7 @@ import { getIsSeedlessOnboardingFeatureEnabled } from '../../../../shared/module
1617
import { ThemeType } from '../../../../shared/constants/preferences';
1718
import { setTermsOfUseLastAgreed } from '../../../store/actions';
1819
import { useTheme } from '../../../hooks/useTheme';
20+
import { ONBOARDING_WELCOME_ROUTE } from '../../../helpers/constants/routes';
1921
import LoginOptions from './login-options';
2022
import { LOGIN_OPTION, LOGIN_TYPE, LoginOptionType, LoginType } from './types';
2123

@@ -39,6 +41,9 @@ export default function WelcomeLogin({
3941
const dispatch = useDispatch();
4042
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
4143
const theme = useTheme();
44+
const navigate = useNavigate();
45+
const [searchParams] = useSearchParams();
46+
const loginParam = searchParams.get('login');
4247

4348
// Cleanup timeout on unmount
4449
useEffect(() => {
@@ -49,6 +54,16 @@ export default function WelcomeLogin({
4954
};
5055
}, []);
5156

57+
useEffect(() => {
58+
if (loginParam) {
59+
setShowLoginOptions(true);
60+
setLoginOption(loginParam as LoginOptionType);
61+
} else {
62+
setShowLoginOptions(false);
63+
setLoginOption(null);
64+
}
65+
}, [loginParam]);
66+
5267
const handleLogin = useCallback(
5368
async (loginType: LoginType) => {
5469
if (!loginOption) {
@@ -79,6 +94,7 @@ export default function WelcomeLogin({
7994
setLoginOption(option);
8095
setIsTransitioning(false);
8196
timeoutRef.current = null;
97+
navigate(`${ONBOARDING_WELCOME_ROUTE}?login=${option}`);
8298
}, 100);
8399
} else {
84100
setShowLoginOptions(true);

ui/pages/onboarding-flow/welcome/welcome.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import React, {
77
Suspense,
88
} from 'react';
99
import { useDispatch, useSelector } from 'react-redux';
10-
import { useNavigate, useSearchParams } from 'react-router-dom-v5-compat';
10+
import { useNavigate } from 'react-router-dom-v5-compat';
1111
import log from 'loglevel';
1212
import { Box } from '../../../components/component-library';
1313
import {
@@ -50,6 +50,7 @@ import {
5050
JustifyContent,
5151
BlockSize,
5252
} from '../../../helpers/constants/design-system';
53+
import { useRiveWasmContext } from '../../../contexts/rive-wasm';
5354
import { getIsWalletResetInProgress } from '../../../ducks/metamask/metamask';
5455
import WelcomeLogin from './welcome-login';
5556
import { LOGIN_ERROR, LOGIN_OPTION, LOGIN_TYPE } from './types';
@@ -64,7 +65,6 @@ const FoxAppearAnimation = lazy(() => import('./fox-appear-animation'));
6465
export default function OnboardingWelcome() {
6566
const dispatch = useDispatch();
6667
const navigate = useNavigate();
67-
const [searchParams] = useSearchParams();
6868
const currentKeyring = useSelector(getCurrentKeyring);
6969
const isSeedlessOnboardingFeatureEnabled =
7070
getIsSeedlessOnboardingFeatureEnabled();
@@ -83,10 +83,10 @@ export default function OnboardingWelcome() {
8383
const [loginError, setLoginError] = useState(null);
8484
const isTestEnvironment = Boolean(process.env.IN_TEST);
8585

86-
// Check if user is returning from another page (skip animations)
87-
const fromParam = searchParams.get('from');
88-
const shouldSkipAnimation =
89-
fromParam === 'unlock' || fromParam === 'account-exist';
86+
const { animationCompleted } = useRiveWasmContext();
87+
const shouldSkipAnimation = Boolean(
88+
animationCompleted?.MetamaskWordMarkAnimation,
89+
);
9090

9191
// In test environments or when returning from another page, skip animations
9292
const [isAnimationComplete, setIsAnimationComplete] = useState(

0 commit comments

Comments
 (0)