Skip to content

Commit e8e693d

Browse files
authored
fix: market insights animation bug cp-7.70.0 (#27617)
<!-- 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? --> This PR fixes #27612 by replacing the video in the AI insights animation with a static image after the video ends. This prevents the dark rectangle from displaying when a user returns to the AI insights page from the browser. On Android, when a Video component loses focus (e.g., user opens the in-app browser via a trend link), the native video surface is destroyed and renders black. When the user navigates back, the video can't recover its last frame. By replacing the Video with a static Image of the last frame once the video finishes playing (onEnd), we avoid the black screen entirely — there's no video surface left to be destroyed. ## **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: Fixed a bug that was causing the AI summary animation from rendering. ## **Related issues** Fixes: #27612 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/b9118bfb-c6a8-496b-b41a-b61e17dce912 ### **After** https://github.com/user-attachments/assets/ab493904-ec09-4651-998b-5c37614134cd <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/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-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] 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] > **Low Risk** > Low risk UI-only change that alters how the Market Insights background animation renders after playback; main risk is visual regressions across light/dark mode or on slower devices due to the new timing/state logic. > > **Overview** > Fixes the Market Insights background animation rendering issue by **showing a static last-frame image** and **stopping the `react-native-video` component after `onEnd`** to avoid the blank/dark rectangle when returning to the screen. > > Adds light/dark last-frame PNG assets, introduces `videoEnded`/`showLastFrame` state, and layers an `Image` behind the video (enabled shortly after mount) so the background remains stable once playback completes. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit e1d7ecc. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent d876391 commit e8e693d

3 files changed

Lines changed: 46 additions & 10 deletions

File tree

app/components/UI/MarketInsights/Views/MarketInsightsView/MarketInsightsView.tsx

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@ import {
1111
Linking,
1212
Pressable,
1313
Animated,
14+
Image,
1415
useColorScheme,
1516
} from 'react-native';
1617
import Video from 'react-native-video';
1718
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-commonjs
1819
const MarketInsightsBackgroundVideoLight = require('../../animations/market-insights-background-light.mp4');
1920
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-commonjs
2021
const MarketInsightsBackgroundVideoDark = require('../../animations/market-insights-background-dark.mp4');
22+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-commonjs
23+
const MarketInsightsBackgroundLastFrameLight = require('../../animations/market-insights-background-light-last-frame.png');
24+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-commonjs
25+
const MarketInsightsBackgroundLastFrameDark = require('../../animations/market-insights-background-dark-last-frame.png');
2126
import { useNavigation, useRoute, RouteProp } from '@react-navigation/native';
2227
import { useSelector } from 'react-redux';
2328
import { useTailwind } from '@metamask/design-system-twrnc-preset';
@@ -200,6 +205,27 @@ const MarketInsightsView: React.FC = () => {
200205
const { trackEvent, createEventBuilder } = useAnalytics();
201206
const { toastRef } = useContext(ToastContext);
202207
const theme = useAppThemeFromContext();
208+
const [videoEnded, setVideoEnded] = useState(false);
209+
const [showLastFrame, setShowLastFrame] = useState(false);
210+
const lastFrameImage = useMemo(
211+
() =>
212+
isDarkMode
213+
? MarketInsightsBackgroundLastFrameDark
214+
: MarketInsightsBackgroundLastFrameLight,
215+
[isDarkMode],
216+
);
217+
218+
useEffect(() => {
219+
const timeout = setTimeout(() => {
220+
setShowLastFrame(true);
221+
}, 100);
222+
return () => clearTimeout(timeout);
223+
}, []);
224+
225+
const handleVideoEnd = useCallback(() => {
226+
setVideoEnded(true);
227+
}, []);
228+
203229
const hasTrackedViewRef = useRef(false);
204230
const [selectedTrend, setSelectedTrend] =
205231
useState<MarketInsightsTrend | null>(null);
@@ -507,16 +533,26 @@ const MarketInsightsView: React.FC = () => {
507533
showsVerticalScrollIndicator={false}
508534
>
509535
<Box twClassName="w-full" style={{ aspectRatio: 786 / 340 }}>
510-
<Video
511-
source={backgroundVideo}
512-
style={tw.style('w-full h-full')}
513-
resizeMode="cover"
514-
muted
515-
paused={false}
516-
controls={false}
517-
disableFocus
518-
testID={MarketInsightsSelectorsIDs.BACKGROUND_ANIMATION}
519-
/>
536+
{showLastFrame && (
537+
<Image
538+
source={lastFrameImage}
539+
style={tw.style('absolute w-full h-full')}
540+
resizeMode="cover"
541+
/>
542+
)}
543+
{!videoEnded && (
544+
<Video
545+
source={backgroundVideo}
546+
style={tw.style('w-full h-full')}
547+
resizeMode="cover"
548+
muted
549+
paused={false}
550+
controls={false}
551+
disableFocus
552+
onEnd={handleVideoEnd}
553+
testID={MarketInsightsSelectorsIDs.BACKGROUND_ANIMATION}
554+
/>
555+
)}
520556
</Box>
521557
<AnimatedSection delay={SECTION_ANIMATION_DELAYS_MS.topArticle}>
522558
<Box twClassName="px-4 pt-4 pb-3">
70.1 KB
Loading
39.8 KB
Loading

0 commit comments

Comments
 (0)