Skip to content

Commit 8993554

Browse files
feat: implement wallet activity account selection with toggle functionality
1 parent 81cdd3a commit 8993554

9 files changed

Lines changed: 380 additions & 114 deletions

app/components/Views/Settings/NotificationsSettings/AccountsList.hooks.test.tsx

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@ import {
1010
useAccountProps,
1111
useNotificationAccountListProps,
1212
useNotificationWalletAccountGroups,
13+
useWalletActivityAccountSelection,
1314
} from './AccountsList.hooks';
1415
import { selectInternalAccountsById } from '../../../../selectors/accountsController';
1516
import { InternalAccount } from '@metamask/keyring-internal-api';
1617
import { selectAccountGroupsByWallet } from '../../../../selectors/multichainAccounts/accountTreeController';
1718
import { AccountGroupType, AccountWalletType } from '@metamask/account-api';
1819
import { KeyringTypes } from '@metamask/keyring-controller';
20+
import { toFormattedAddress } from '../../../../util/address';
1921

2022
jest.mock('../../../../selectors/notifications', () => ({
2123
getValidNotificationAccounts: jest.fn(),
@@ -35,6 +37,15 @@ jest.mock(
3537
);
3638

3739
const MOCK_KEYRING_TYPE = 'HD Key Tree' as KeyringTypes;
40+
const EVM_ADDRESSES = [
41+
'0xb2B92547A92C1aC55EAe3F6632Fa1aF87dc05a29',
42+
'0x700CcD8172BC3807D893883a730A1E0E6630F8EC',
43+
'0xb2B92547A92C1aC55EAe3F6632Fa1aF87dc05a20',
44+
'0x700CcD8172BC3807D893883a730A1E0E6630F8E0',
45+
];
46+
const FORMATTED_EVM_ADDRESSES = EVM_ADDRESSES.map((address) =>
47+
toFormattedAddress(address),
48+
);
3849

3950
const createNotificationAccountsMap = () =>
4051
({
@@ -431,3 +442,77 @@ describe('useAccountProps', () => {
431442
);
432443
});
433444
});
445+
446+
describe('useWalletActivityAccountSelection', () => {
447+
const arrangeMocks = (notificationData: Record<string, boolean>) => {
448+
arrangeMockUseAccounts();
449+
jest
450+
.mocked(selectInternalAccountsById)
451+
.mockReturnValue(createNotificationAccountsMap());
452+
jest.mocked(getValidNotificationAccounts).mockReturnValue(EVM_ADDRESSES);
453+
454+
const mockUpdate = jest.fn();
455+
jest
456+
.spyOn(UseSwitchNotificationsModule, 'useFetchAccountNotifications')
457+
.mockReturnValue({
458+
accountsBeingUpdated: [],
459+
data: notificationData,
460+
error: null,
461+
initialLoading: false,
462+
update: mockUpdate,
463+
});
464+
465+
const mockOnToggle = jest.fn();
466+
jest
467+
.spyOn(UseSwitchNotificationsModule, 'useAccountNotificationsToggle')
468+
.mockReturnValue({
469+
onToggle: mockOnToggle,
470+
error: null,
471+
loading: false,
472+
});
473+
474+
return {
475+
mockOnToggle,
476+
mockUpdate,
477+
};
478+
};
479+
480+
beforeEach(() => jest.clearAllMocks());
481+
482+
it('deselects all visible EVM accounts when any account is enabled', async () => {
483+
const mocks = arrangeMocks({
484+
[FORMATTED_EVM_ADDRESSES[0]]: true,
485+
});
486+
487+
const { result } = renderHookWithProvider(() =>
488+
useWalletActivityAccountSelection(),
489+
);
490+
491+
expect(result.current.hasEnabledAccount).toBe(true);
492+
493+
await act(async () => result.current.toggleAllAccounts());
494+
495+
expect(mocks.mockOnToggle).toHaveBeenCalledWith(
496+
FORMATTED_EVM_ADDRESSES,
497+
false,
498+
);
499+
expect(mocks.mockUpdate).toHaveBeenCalledWith(EVM_ADDRESSES);
500+
});
501+
502+
it('selects all visible EVM accounts when every account is disabled', async () => {
503+
const mocks = arrangeMocks({});
504+
505+
const { result } = renderHookWithProvider(() =>
506+
useWalletActivityAccountSelection(),
507+
);
508+
509+
expect(result.current.hasEnabledAccount).toBe(false);
510+
511+
await act(async () => result.current.toggleAllAccounts());
512+
513+
expect(mocks.mockOnToggle).toHaveBeenCalledWith(
514+
FORMATTED_EVM_ADDRESSES,
515+
true,
516+
);
517+
});
518+
});

app/components/Views/Settings/NotificationsSettings/AccountsList.hooks.tsx

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { useCallback, useMemo } from 'react';
22
import { useSelector } from 'react-redux';
3-
import { useFetchAccountNotifications } from '../../../../util/notifications/hooks/useSwitchNotifications';
3+
import {
4+
useAccountNotificationsToggle,
5+
useFetchAccountNotifications,
6+
} from '../../../../util/notifications/hooks/useSwitchNotifications';
47
import { getValidNotificationAccounts } from '../../../../selectors/notifications';
58
import { toFormattedAddress } from '../../../../util/address';
69
import { selectAvatarAccountType } from '../../../../selectors/settings';
@@ -120,3 +123,55 @@ export function useAccountProps() {
120123
accountAvatarType,
121124
};
122125
}
126+
127+
export function useWalletActivityAccountSelection() {
128+
const accountProps = useAccountProps();
129+
const notificationAccountListProps = useNotificationAccountListProps();
130+
const { onToggle, loading } = useAccountNotificationsToggle();
131+
132+
const accountAddresses = useMemo(
133+
() =>
134+
accountProps.accountWalletGroups.flatMap((walletGroup) =>
135+
walletGroup.data
136+
.map((accountGroup) =>
137+
notificationAccountListProps.getEvmAddress(accountGroup.accounts),
138+
)
139+
.filter((address): address is string => Boolean(address)),
140+
),
141+
[accountProps.accountWalletGroups, notificationAccountListProps],
142+
);
143+
144+
const hasEnabledAccount = useMemo(
145+
() =>
146+
accountProps.accountWalletGroups.some((walletGroup) =>
147+
walletGroup.data.some((accountGroup) =>
148+
notificationAccountListProps.isAccountEnabled(accountGroup.accounts),
149+
),
150+
),
151+
[accountProps.accountWalletGroups, notificationAccountListProps],
152+
);
153+
154+
const toggleAllAccounts = useCallback(async () => {
155+
if (accountAddresses.length === 0) {
156+
return;
157+
}
158+
159+
await onToggle(accountAddresses, !hasEnabledAccount);
160+
await notificationAccountListProps.refetchAccountSettings();
161+
}, [
162+
accountAddresses,
163+
hasEnabledAccount,
164+
notificationAccountListProps,
165+
onToggle,
166+
]);
167+
168+
return {
169+
accountProps,
170+
notificationAccountListProps,
171+
hasEnabledAccount,
172+
hasNotificationAccounts: accountAddresses.length > 0,
173+
isUpdatingAllAccounts:
174+
loading || notificationAccountListProps.shouldDisableSwitches,
175+
toggleAllAccounts,
176+
};
177+
}

0 commit comments

Comments
 (0)