Skip to content

Commit d5c2f24

Browse files
sophieqguVGR-GITclaude
authored
chore(rewards): add toast to enable push notification (#29531)
<!-- Please submit this PR as a draft initially. Do not mark it as "Ready for review" until this PR meets the canonical Definition of Ready For Review in `docs/readme/ready-for-review.md`. In short: the template must be materially complete (not just section titles present), all status checks must be currently passing, and the only expected follow-up commits must be reviewer-driven. --> ## **Description** https://consensyssoftware.atlassian.net/browse/RWDS-1160 Add toast to enable notifications <!-- 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? --> ## **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: Add rewards toast to enable notifications ## **Related issues** Fixes: ## **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] --> ### **After** <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-05-01 at 11 06 23" src="https://github.com/user-attachments/assets/8874e05d-48c3-4fce-b4cc-69a4dea9a08f" /> <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-04-29 at 19 33 52" src="https://github.com/user-attachments/assets/e4921243-394b-4435-be32-5b83af2c3035" /> <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-04-29 at 19 41 06" src="https://github.com/user-attachments/assets/3f25d391-9e73-4cf8-bf16-452008a0dbc4" /> <img width="1179" height="2556" alt="Simulator Screenshot - E2E Test - 2026-05-05 at 14 23 53" src="https://github.com/user-attachments/assets/89ffe7f4-2187-4bae-aa61-2bb6f4d38df1" /> <!-- [screenshots/recordings] --> ## **Pre-merge author checklist** <!-- Every checklist item must be consciously assessed before marking this PR as "Ready for review". A checked box means you deliberately considered that responsibility, not that you literally performed every action listed. Unchecked boxes are ambiguous: they are not an implicit "N/A" and they are not a silent "skip". See `docs/readme/ready-for-review.md` for the full checklist semantics. --> - [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. #### Performance checks (if applicable) - [x] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [x] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [x] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [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] > **Medium Risk** > Medium risk because it adds new notification-enablement flow that interacts with OS permissions/AppState and changes Rewards navigation behavior to show/close a session-scoped nudge toast based on nested routes. > > **Overview** > Adds a new `useRewardsNotificationsNudge` hook that can show a persistent “enable notifications” toast, drive the enable flow (including OS settings redirect on denied permission), and optionally defer actions until notifications become enabled. > > Integrates the nudge into `RewardsNavigator` so it is shown once per session when viewing campaign routes and notifications are off, then explicitly closed when navigating away; also shows a success toast when notifications become enabled. > > Refactors campaign reminder logic into `useCampaignReminderActions`, making “Notify me”/reminder subscription conditional on the notifications feature flag and current notification state, and updates/rebalances toast styling (`flex-start` alignment) plus adds/updates tests and new `en.json` strings for the nudge/loading/success messages. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 1b24e0f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Rik Van Gulck <vangulckrik@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3e8cfca commit d5c2f24

21 files changed

Lines changed: 2554 additions & 169 deletions

app/component-library/components/Toast/Toast.styles.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ const styleSheet = (params: { theme: Theme }) => {
2626
borderRadius: 12,
2727
padding,
2828
flexDirection: 'row',
29-
alignItems: 'center',
29+
alignItems: 'flex-start',
3030
},
3131
avatar: {
32+
marginTop: -4,
3233
marginRight: 16,
3334
},
3435
labelsContainer: {
3536
flex: 1,
36-
justifyContent: 'center',
37+
justifyContent: 'flex-start',
3738
},
3839
label: {
3940
color: colors.text.default,

app/component-library/components/Toast/Toast.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
// Third party dependencies.
22
import React, { createRef } from 'react';
3+
import { StyleSheet } from 'react-native';
34
import { render, screen, act } from '@testing-library/react-native';
45

56
// Internal dependencies.
67
import Toast from './Toast';
78
import { ToastRef, ToastVariants, ToastOptions } from './Toast.types';
9+
import { ToastSelectorsIDs } from './ToastModal.testIds';
810

911
// react-native-reanimated is already mocked globally via setUpTests() in testSetup.js
1012

@@ -163,4 +165,24 @@ describe('Toast', () => {
163165
expect(screen.queryByText('In Progress')).toBeNull();
164166
expect(screen.getByText('Success')).toBeOnTheScreen();
165167
});
168+
169+
it('uses flex-start justifyContent on labels container by default', async () => {
170+
const toastOptions: ToastOptions = {
171+
variant: ToastVariants.Plain,
172+
labelOptions: [{ label: 'Aligned label' }],
173+
hasNoTimeout: true,
174+
};
175+
176+
render(<Toast ref={toastRef} />);
177+
178+
await act(async () => {
179+
toastRef.current?.showToast(toastOptions);
180+
jest.runAllTimers();
181+
});
182+
183+
const labelsContainer = screen.getByTestId(ToastSelectorsIDs.CONTAINER);
184+
const flat = StyleSheet.flatten(labelsContainer.props.style);
185+
186+
expect(flat.justifyContent).toBe('flex-start');
187+
});
166188
});

0 commit comments

Comments
 (0)