Skip to content

Commit

Permalink
Move user alerts to the store
Browse files Browse the repository at this point in the history
  • Loading branch information
OKendigelyan committed Dec 20, 2024
1 parent 3b4da04 commit 12e5b90
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 20 deletions.
4 changes: 4 additions & 0 deletions apps/desktop-e2e/src/steps/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ Given(/I have accounts?/, async function (this: CustomWorld, table: DataTable) {
items: [],
seedPhrases: {},
secretKeys: {},
alerts: {
isSocialLoginWarningShown: false,
isExtensionsWarningShown: false,
},
};

for (const data of table.hashes() as any[]) {
Expand Down
3 changes: 1 addition & 2 deletions apps/desktop-e2e/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
"preserveSymlinks": true
},
"ts-node": {
"esm": true,
"files": true
"esm": true
},
"include": ["src", ".eslintrc.cjs", "cucumber.cjs"]
}
6 changes: 4 additions & 2 deletions apps/desktop/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useDataPolling } from "@umami/data-polling";
import {
WalletClient,
useCurrentAccount,
useGetUserAlerts,
useImplicitAccounts,
useResetBeaconConnections,
} from "@umami/state";
Expand Down Expand Up @@ -42,12 +43,13 @@ const LoggedInRouterWithPolling = () => {
useDataPolling();
const modalDisclosure = useDynamicModal();
const currentUser = useCurrentAccount();
const getUserAlerts = useGetUserAlerts();

useEffect(() => {
if (currentUser?.type === "social") {
const isInformed = localStorage.getItem("user:isSocialLoginWarningShown");
const isInformed = getUserAlerts("isSocialLoginWarningShown");

if (!isInformed || !JSON.parse(isInformed)) {
if (!isInformed) {
void modalDisclosure.openWith(<SocialLoginWarningModal />, { closeOnEsc: false });
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { type UmamiStore, makeStore } from "@umami/state";

import { SocialLoginWarningModal } from "./SocialLoginWarningModal";
import {
act,
Expand All @@ -8,13 +10,15 @@ import {
waitFor,
} from "../../mocks/testUtils";

let store: UmamiStore;

beforeEach(() => {
localStorage.clear();
store = makeStore();
});

describe("<SocialLoginWarningModal />", () => {
it("renders the modal with correct title and content", async () => {
render(<SocialLoginWarningModal />);
render(<SocialLoginWarningModal />, { store });

await waitFor(() => {
expect(screen.getByText("Important notice about your social account wallet")).toBeVisible();
Expand All @@ -28,15 +32,15 @@ describe("<SocialLoginWarningModal />", () => {
});

it("disables 'Continue' button when checkbox is not checked", () => {
render(<SocialLoginWarningModal />);
render(<SocialLoginWarningModal />, { store });

const button = screen.getByRole("button", { name: "Continue" });
expect(button).toBeDisabled();
});

it("enables 'Continue' button when checkbox is checked", async () => {
const user = userEvent.setup();
render(<SocialLoginWarningModal />);
render(<SocialLoginWarningModal />, { store });

const checkbox = screen.getByRole("checkbox", {
name: "I understand and accept the risks.",
Expand All @@ -50,7 +54,7 @@ describe("<SocialLoginWarningModal />", () => {
it("sets localStorage and closes modal when 'Continue' is clicked", async () => {
const { onClose } = dynamicModalContextMock;
const user = userEvent.setup();
render(<SocialLoginWarningModal />);
render(<SocialLoginWarningModal />, { store });

const checkbox = screen.getByRole("checkbox", {
name: "I understand and accept the risks.",
Expand All @@ -61,15 +65,15 @@ describe("<SocialLoginWarningModal />", () => {
await act(() => user.click(continueButton));

await waitFor(() => {
expect(localStorage.getItem("user:isSocialLoginWarningShown")).toBe("true");
expect(store.getState().accounts.alerts.isSocialLoginWarningShown).toBe(true);
});

expect(onClose).toHaveBeenCalled();
});

it("toggles checkbox state correctly", async () => {
const user = userEvent.setup();
render(<SocialLoginWarningModal />);
render(<SocialLoginWarningModal />, { store });

const checkbox = screen.getByRole("checkbox", {
name: "I understand and accept the risks.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Text,
} from "@chakra-ui/react";
import { useDynamicModalContext } from "@umami/components";
import { accountsActions, useAppDispatch } from "@umami/state";
import { useState } from "react";

import { WarningIcon } from "../../assets/icons";
Expand All @@ -19,9 +20,10 @@ import colors from "../../style/colors";
export const SocialLoginWarningModal = () => {
const { onClose } = useDynamicModalContext();
const [isAgreed, setIsAgreed] = useState(false);
const dispatch = useAppDispatch();

const handleInform = () => {
localStorage.setItem("user:isSocialLoginWarningShown", "true");
dispatch(accountsActions.setAlerts({ key: "isSocialLoginWarningShown", value: true }));
onClose();
};

Expand Down
16 changes: 9 additions & 7 deletions apps/web/src/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Grid, GridItem } from "@chakra-ui/react";
import { useDynamicModalContext } from "@umami/components";
import { useDataPolling } from "@umami/data-polling";
import { useCurrentAccount } from "@umami/state";
import { accountsActions, useAppDispatch, useCurrentAccount, useGetUserAlerts } from "@umami/state";
import { useEffect } from "react";

import { Footer } from "./components/Footer";
Expand All @@ -16,28 +16,30 @@ export const Layout = () => {
useDataPolling();
const { openWith } = useDynamicModalContext();
const currentUser = useCurrentAccount();
const getUserAlerts = useGetUserAlerts();
const dispatch = useAppDispatch();

useEffect(() => {
const CLOSING_DELAY = 300;

const warnings = [
{
key: "user:isSocialLoginWarningShown",
key: "isSocialLoginWarningShown",
component: <SocialLoginWarningModal />,
options: { closeOnEsc: false },
isEnabled: () => currentUser?.type === "social",
},
{
key: "user:isExtensionsWarningShown",
key: "isExtensionsWarningShown",
component: <SecurityWarningModal />,
options: { closeOnEsc: false, size: "xl" },
isEnabled: () => true,
},
];
] as const;

const warningsToShow = warnings.filter(warning => {
const isInformed = localStorage.getItem(warning.key);
return (!isInformed || !JSON.parse(isInformed)) && warning.isEnabled();
const isInformed = getUserAlerts(warning.key);
return !isInformed && warning.isEnabled();
});

const showWarnings = async () => {
Expand All @@ -47,7 +49,7 @@ export const Layout = () => {
void openWith(warning.component, {
...warning.options,
onClose: () => {
localStorage.setItem(warning.key, "true");
dispatch(accountsActions.setAlerts({ key: warning.key, value: true }));
resolve(true);
},
})
Expand Down
8 changes: 7 additions & 1 deletion packages/state/src/hooks/getAccountData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { useDispatch } from "react-redux";
import { useGetAccountBalance } from "./assets";
import { useMultisigAccounts } from "./multisig";
import { useAppSelector } from "./useAppSelector";
import { accountsActions } from "../slices";
import { type AccountsState, accountsActions } from "../slices";

export const useSeedPhrases = () => useAppSelector(s => s.accounts.seedPhrases);

Expand Down Expand Up @@ -215,3 +215,9 @@ export const useGetDecryptedMnemonic = () => {
return decrypt(encryptedMnemonic, password);
};
};

export const useGetUserAlerts = () => {
const alerts = useAppSelector(s => s.accounts.alerts);

return (key: keyof AccountsState["alerts"]) => alerts[key];
};
4 changes: 4 additions & 0 deletions packages/state/src/slices/accounts/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ export type AccountsState = {
secretKeys: Record<RawPkh, EncryptedData | undefined>;
current?: RawPkh | undefined;
password?: string | undefined;
alerts: {
isSocialLoginWarningShown: boolean;
isExtensionsWarningShown: boolean;
};
};
13 changes: 13 additions & 0 deletions packages/state/src/slices/accounts/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export const accountsInitialState: AccountsState = {
seedPhrases: {},
secretKeys: {},
password: "",
alerts: {
isSocialLoginWarningShown: false,
isExtensionsWarningShown: false,
},
};

/**
Expand Down Expand Up @@ -144,6 +148,15 @@ export const accountsSlice = createSlice({
setPassword: (state, { payload }: { payload: string }) => {
state.password = payload;
},
setAlerts: (
state,
{ payload }: { payload: { key: keyof AccountsState["alerts"]; value: boolean } }
) => {
state.alerts = {
...state.alerts,
[payload.key]: payload.value,
};
},
},
});

Expand Down

0 comments on commit 12e5b90

Please sign in to comment.