Skip to content

Commit 73cbca0

Browse files
committed
refactor: update BackupNudgeModal with Figma design, primary icon color and close support
1 parent 12b9b87 commit 73cbca0

34 files changed

Lines changed: 273 additions & 105 deletions
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import React from "react"
2+
import { render, fireEvent } from "@testing-library/react-native"
3+
4+
import { BackupNudgeModal } from "@app/components/backup-nudge-modal"
5+
6+
const mockNavigate = jest.fn()
7+
8+
jest.mock("@react-navigation/native", () => ({
9+
...jest.requireActual("@react-navigation/native"),
10+
useNavigation: () => ({ navigate: mockNavigate }),
11+
}))
12+
13+
jest.mock("@rn-vui/themed", () => {
14+
const colors = {
15+
grey0: "#ccc",
16+
grey2: "#999",
17+
grey5: "#f5f5f5",
18+
primary: "#fc5805",
19+
black: "#000",
20+
white: "#fff",
21+
}
22+
return {
23+
makeStyles:
24+
(fn: (...args: unknown[]) => Record<string, object>) => (props?: unknown) =>
25+
fn({ colors }, props ?? {}),
26+
Text: ({ children, ...props }: { children: React.ReactNode }) =>
27+
React.createElement("Text", props, children),
28+
useTheme: () => ({ theme: { colors, mode: "light" } }),
29+
}
30+
})
31+
32+
const mockGaloyIcon = jest.fn<null, [Record<string, unknown>]>(() => null)
33+
34+
jest.mock("@app/components/atomic/galoy-icon", () => ({
35+
GaloyIcon: (props: Record<string, unknown>) => {
36+
mockGaloyIcon(props)
37+
return null
38+
},
39+
}))
40+
41+
jest.mock("@app/components/atomic/galoy-icon-button", () => ({
42+
GaloyIconButton: ({ onPress }: { onPress: () => void }) =>
43+
React.createElement("Pressable", { onPress, testID: "close-button" }),
44+
}))
45+
46+
jest.mock("@app/components/atomic/galoy-primary-button", () => ({
47+
GaloyPrimaryButton: ({ onPress, title }: { onPress: () => void; title: string }) =>
48+
React.createElement(
49+
"Pressable",
50+
{ onPress, testID: "secure-button" },
51+
React.createElement("Text", {}, title),
52+
),
53+
}))
54+
55+
jest.mock("@app/components/atomic/galoy-secondary-button", () => ({
56+
GaloySecondaryButton: () => null,
57+
}))
58+
59+
jest.mock("react-native-modal", () => {
60+
const MockModal = ({
61+
children,
62+
isVisible,
63+
}: {
64+
children: React.ReactNode
65+
isVisible: boolean
66+
}) => (isVisible ? React.createElement("View", { testID: "modal" }, children) : null)
67+
MockModal.displayName = "MockModal"
68+
return MockModal
69+
})
70+
71+
jest.mock("@app/utils/testProps", () => ({
72+
testProps: (id: string) => ({ testID: id }),
73+
}))
74+
75+
jest.mock("@app/i18n/i18n-react", () => ({
76+
useI18nContext: () => ({
77+
LL: {
78+
BackupNudge: {
79+
modalTitle: () => "Secure your funds",
80+
modalDescription: () =>
81+
"We highly recommend you backup your wallet to prevent a complete loss of funds in case you lose this device.",
82+
secureMe: () => "Secure wallet",
83+
},
84+
},
85+
}),
86+
}))
87+
88+
describe("BackupNudgeModal", () => {
89+
beforeEach(() => {
90+
jest.clearAllMocks()
91+
})
92+
93+
it("renders when visible", () => {
94+
const { getByTestId } = render(
95+
<BackupNudgeModal isVisible={true} onClose={jest.fn()} />,
96+
)
97+
98+
expect(getByTestId("modal")).toBeTruthy()
99+
})
100+
101+
it("does not render when not visible", () => {
102+
const { queryByTestId } = render(
103+
<BackupNudgeModal isVisible={false} onClose={jest.fn()} />,
104+
)
105+
106+
expect(queryByTestId("modal")).toBeNull()
107+
})
108+
109+
it("renders title and description", () => {
110+
const { getByText } = render(
111+
<BackupNudgeModal isVisible={true} onClose={jest.fn()} />,
112+
)
113+
114+
expect(getByText("Secure your funds")).toBeTruthy()
115+
expect(
116+
getByText(
117+
"We highly recommend you backup your wallet to prevent a complete loss of funds in case you lose this device.",
118+
),
119+
).toBeTruthy()
120+
})
121+
122+
it("renders secure wallet button", () => {
123+
const { getByText } = render(
124+
<BackupNudgeModal isVisible={true} onClose={jest.fn()} />,
125+
)
126+
127+
expect(getByText("Secure wallet")).toBeTruthy()
128+
})
129+
130+
it("navigates to backup method screen and closes on button press", () => {
131+
const onClose = jest.fn()
132+
const { getByTestId } = render(
133+
<BackupNudgeModal isVisible={true} onClose={onClose} />,
134+
)
135+
136+
fireEvent.press(getByTestId("secure-button"))
137+
138+
expect(onClose).toHaveBeenCalledTimes(1)
139+
expect(mockNavigate).toHaveBeenCalledWith("sparkBackupMethodScreen")
140+
})
141+
142+
it("uses primary color for warning icon", () => {
143+
render(<BackupNudgeModal isVisible={true} onClose={jest.fn()} />)
144+
145+
expect(mockGaloyIcon).toHaveBeenCalledWith(
146+
expect.objectContaining({
147+
name: "warning",
148+
size: 52,
149+
color: "#fc5805",
150+
}),
151+
)
152+
})
153+
})

app/components/backup-nudge-modal/backup-nudge-modal.tsx

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from "react"
22

3-
import { makeStyles, Text } from "@rn-vui/themed"
3+
import { makeStyles, Text, useTheme } from "@rn-vui/themed"
44
import { useNavigation } from "@react-navigation/native"
55
import { StackNavigationProp } from "@react-navigation/stack"
66

@@ -13,23 +13,38 @@ import CustomModal from "../custom-modal/custom-modal"
1313

1414
type BackupNudgeModalProps = {
1515
isVisible: boolean
16+
onClose: () => void
1617
}
1718

18-
export const BackupNudgeModal: React.FC<BackupNudgeModalProps> = ({ isVisible }) => {
19+
export const BackupNudgeModal: React.FC<BackupNudgeModalProps> = ({
20+
isVisible,
21+
onClose,
22+
}) => {
1923
const styles = useStyles()
24+
const {
25+
theme: { colors },
26+
} = useTheme()
2027
const { LL } = useI18nContext()
2128
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>()
2229

2330
const handleSecure = () => {
31+
onClose()
2432
navigation.navigate("sparkBackupMethodScreen")
2533
}
2634

2735
return (
2836
<CustomModal
2937
isVisible={isVisible}
30-
toggleModal={() => {}}
31-
showCloseIconButton={false}
32-
image={<GaloyIcon name="warning" size={40} {...testProps("nudge-warning-icon")} />}
38+
toggleModal={onClose}
39+
showCloseIconButton={true}
40+
image={
41+
<GaloyIcon
42+
name="warning"
43+
size={52}
44+
color={colors.primary}
45+
{...testProps("nudge-warning-icon")}
46+
/>
47+
}
3348
title={LL.BackupNudge.modalTitle()}
3449
body={<Text style={styles.description}>{LL.BackupNudge.modalDescription()}</Text>}
3550
primaryButtonTitle={LL.BackupNudge.secureMe()}
@@ -42,8 +57,8 @@ export const BackupNudgeModal: React.FC<BackupNudgeModalProps> = ({ isVisible })
4257
const useStyles = makeStyles(({ colors }) => ({
4358
description: {
4459
textAlign: "center",
45-
fontSize: 14,
46-
lineHeight: 20,
47-
color: colors.grey2,
60+
fontSize: 16,
61+
lineHeight: 22,
62+
color: colors.black,
4863
},
4964
}))

app/i18n/en/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3685,10 +3685,10 @@ const en: BaseTranslation = {
36853685
description: "Secure your wallet now. It only takes a minute.",
36863686
cta: "Secure wallet",
36873687
settingsWarning: "Backup your wallet. If you lose this device, you will lose your funds.",
3688-
modalTitle: "Your funds need protection",
3688+
modalTitle: "Secure your funds",
36893689
modalDescription:
3690-
"You have a significant balance. Back up your wallet to prevent loss.",
3691-
secureMe: "Secure me",
3690+
"We highly recommend you backup your wallet to prevent a complete loss of funds in case you lose this device.",
3691+
secureMe: "Secure wallet",
36923692
trustModelTitle: "You are in control",
36933693
trustModelDescription:
36943694
"Your keys control your funds. Transactions are processed by Spark operators, not validated directly on Bitcoin L1.",

app/i18n/i18n-types.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11670,15 +11670,15 @@ type RootTranslation = {
1167011670
*/
1167111671
settingsWarning: string
1167211672
/**
11673-
* Y​o​u​r​ ​f​u​n​d​s​ ​n​e​e​d​ ​p​r​o​t​e​c​t​i​o​n
11673+
* S​e​c​u​r​e​ ​y​o​u​r​ ​f​u​n​d​s
1167411674
*/
1167511675
modalTitle: string
1167611676
/**
11677-
* Y​o​u​ ​h​a​v​e​ ​a​ ​s​i​g​n​i​f​i​c​a​n​t​ ​b​a​l​a​n​c​e​.​ ​B​a​c​k​u​p​ ​y​o​u​r​ ​w​a​l​l​e​t​ ​t​o​ ​p​r​e​v​e​n​t​ ​l​o​s​s​.
11677+
* W​e​ ​h​i​g​h​l​y​ ​r​e​c​o​m​m​e​n​d​ ​y​o​u​ ​b​a​c​k​u​p​ ​y​o​u​r​ ​w​a​l​l​e​t​ ​t​o​ ​p​r​e​v​e​n​t​ ​a​ ​c​o​m​p​l​e​t​e​ ​l​o​s​s​ ​o​f​ ​f​u​n​d​s​ ​i​n​ ​c​a​s​e​ ​y​o​u​ ​l​o​s​e​ ​t​h​i​s​ ​d​e​v​i​c​e​.
1167811678
*/
1167911679
modalDescription: string
1168011680
/**
11681-
* S​e​c​u​r​e​ ​m​e
11681+
* S​e​c​u​r​e​ ​w​a​l​l​e​t
1168211682
*/
1168311683
secureMe: string
1168411684
/**
@@ -23256,15 +23256,15 @@ export type TranslationFunctions = {
2325623256
*/
2325723257
settingsWarning: () => LocalizedString
2325823258
/**
23259-
* Your funds need protection
23259+
* Secure your funds
2326023260
*/
2326123261
modalTitle: () => LocalizedString
2326223262
/**
23263-
* You have a significant balance. Back up your wallet to prevent loss.
23263+
* We highly recommend you backup your wallet to prevent a complete loss of funds in case you lose this device.
2326423264
*/
2326523265
modalDescription: () => LocalizedString
2326623266
/**
23267-
* Secure me
23267+
* Secure wallet
2326823268
*/
2326923269
secureMe: () => LocalizedString
2327023270
/**

app/i18n/raw-i18n/source/en.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3532,9 +3532,9 @@
35323532
"description": "Secure your wallet now. It only takes a minute.",
35333533
"cta": "Secure wallet",
35343534
"settingsWarning": "Backup your wallet. If you lose this device, you will lose your funds.",
3535-
"modalTitle": "Your funds need protection",
3536-
"modalDescription": "You have a significant balance. Back up your wallet to prevent loss.",
3537-
"secureMe": "Secure me",
3535+
"modalTitle": "Secure your funds",
3536+
"modalDescription": "We highly recommend you backup your wallet to prevent a complete loss of funds in case you lose this device.",
3537+
"secureMe": "Secure wallet",
35383538
"trustModelTitle": "You are in control",
35393539
"trustModelDescription": "Your keys control your funds. Transactions are processed by Spark operators, not validated directly on Bitcoin L1.",
35403540
"trustModelWarning": "Very small balances may not be economical to recover to the Bitcoin base chain.",

app/i18n/raw-i18n/translations/af.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3583,9 +3583,9 @@
35833583
"description": "Beveilig jou beursie nou. Dit neem net 'n minuut.",
35843584
"cta": "Beveilig beursie",
35853585
"settingsWarning": "Rugsteun jou beursie. As jy hierdie toestel verloor, verloor jy jou fondse.",
3586-
"modalTitle": "Jou fondse het beskerming nodig",
3587-
"modalDescription": "Jy het 'n beduidende balans. Rugsteun jou beursie om verlies te voorkom.",
3588-
"secureMe": "Beveilig my",
3586+
"modalTitle": "Beveilig jou fondse",
3587+
"modalDescription": "Ons beveel sterk aan dat u u beursie rugsteun om 'n algehele verlies van fondse te voorkom indien u hierdie toestel verloor.",
3588+
"secureMe": "Beveilig beursie",
35893589
"trustModelTitle": "Jy is in beheer",
35903590
"trustModelDescription": "Jou sleutels beheer jou fondse. Transaksies word verwerk deur Spark-operateurs, nie direk op Bitcoin L1 geverifieer nie.",
35913591
"trustModelWarning": "Baie klein balanse is dalk nie ekonomies om na die Bitcoin-basisketting te herstel nie.",

app/i18n/raw-i18n/translations/ar.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3580,9 +3580,9 @@
35803580
"description": "قم بتأمين محفظتك الآن. لن يستغرق الأمر سوى دقيقة واحدة.",
35813581
"cta": "تأمين المحفظة",
35823582
"settingsWarning": "قم بنسخ محفظتك احتياطياً. إذا فقدت هذا الجهاز، ستفقد أموالك.",
3583-
"modalTitle": "أموالك تحتاج حماية",
3584-
"modalDescription": "لديك رصيد كبير. قم بنسخ محفظتك احتياطياً لمنع الخسارة.",
3585-
"secureMe": "تأمين",
3583+
"modalTitle": "قم بتأمين أموالك",
3584+
"modalDescription": "نوصي بشدة بعمل نسخة احتياطية لمحفظتك لمنع فقدان كامل للأموال في حال فقدت هذا الجهاز.",
3585+
"secureMe": "تأمين المحفظة",
35863586
"trustModelTitle": "أنت المتحكم",
35873587
"trustModelDescription": "مفاتيحك تتحكم في أموالك. تتم معالجة المعاملات بواسطة مشغلي Spark، وليس مباشرة على Bitcoin L1.",
35883588
"trustModelWarning": "قد لا يكون استرداد الأرصدة الصغيرة جداً إلى سلسلة Bitcoin الأساسية اقتصادياً.",

app/i18n/raw-i18n/translations/ca.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3542,9 +3542,9 @@
35423542
"description": "Assegura la teva cartera ara. Només triga un minut.",
35433543
"cta": "Assegurar cartera",
35443544
"settingsWarning": "Fes una còpia de seguretat de la teva cartera. Si perds aquest dispositiu, perdràs els teus fons.",
3545-
"modalTitle": "Els teus fons necessiten protecció",
3546-
"modalDescription": "Tens un balanç significatiu. Fes una còpia de seguretat per evitar pèrdues.",
3547-
"secureMe": "Assegura'm",
3545+
"modalTitle": "Assegura els teus fons",
3546+
"modalDescription": "Et recomanem fermament que facis una còpia de seguretat de la teva cartera per evitar una pèrdua total de fons en cas que perdis aquest dispositiu.",
3547+
"secureMe": "Assegurar cartera",
35483548
"trustModelTitle": "Tu tens el control",
35493549
"trustModelDescription": "Les teves claus controlen els teus fons. Les transaccions són processades pels operadors de Spark, no es validen directament a Bitcoin L1.",
35503550
"trustModelWarning": "Els balanços molt petits poden no ser econòmics de recuperar a la cadena base de Bitcoin.",

app/i18n/raw-i18n/translations/cs.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3583,9 +3583,9 @@
35833583
"description": "Zabezpečte svou peněženku nyní. Zabere to jen minutu.",
35843584
"cta": "Zabezpečit peněženku",
35853585
"settingsWarning": "Zálohujte svou peněženku. Pokud ztratíte toto zařízení, přijdete o své prostředky.",
3586-
"modalTitle": "Vaše prostředky potřebují ochranu",
3587-
"modalDescription": "Máte významný zůstatek. Zálohujte svou peněženku, abyste předešli ztrátě.",
3588-
"secureMe": "Zabezpečit",
3586+
"modalTitle": "Zabezpečte své prostředky",
3587+
"modalDescription": "Důrazně doporučujeme zálohovat peněženku, abyste předešli úplné ztrátě prostředků v případě ztráty tohoto zařízení.",
3588+
"secureMe": "Zabezpečit peněženku",
35893589
"trustModelTitle": "Máte kontrolu",
35903590
"trustModelDescription": "Vaše klíče řídí vaše prostředky. Transakce zpracovávají operátoři Spark, nikoliv přímo na Bitcoin L1.",
35913591
"trustModelWarning": "Obnova velmi malých zůstatků na základní řetězec Bitcoinu nemusí být ekonomická.",

app/i18n/raw-i18n/translations/da.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3560,9 +3560,9 @@
35603560
"description": "Sikr din tegnebog nu. Det tager kun et minut.",
35613561
"cta": "Sikr tegnebog",
35623562
"settingsWarning": "Sikkerhedskopiér din tegnebog. Hvis du mister denne enhed, mister du dine midler.",
3563-
"modalTitle": "Dine midler har brug for beskyttelse",
3564-
"modalDescription": "Du har en betydelig saldo. Sikkerhedskopiér din tegnebog for at undgå tab.",
3565-
"secureMe": "Sikr mig",
3563+
"modalTitle": "Sikr dine midler",
3564+
"modalDescription": "Vi anbefaler stærkt, at du sikkerhedskopierer din tegnebog for at forhindre et fuldstændigt tab af midler, hvis du mister denne enhed.",
3565+
"secureMe": "Sikr tegnebog",
35663566
"trustModelTitle": "Du har kontrollen",
35673567
"trustModelDescription": "Dine nøgler styrer dine midler. Transaktioner behandles af Spark-operatører, ikke direkte valideret på Bitcoin L1.",
35683568
"trustModelWarning": "Meget små saldi er muligvis ikke økonomiske at gendanne til Bitcoin-basiskæden.",

0 commit comments

Comments
 (0)