From 8312790ec55bc8ac7142b7fa36c7198b1d5a5a0a Mon Sep 17 00:00:00 2001 From: Steven Straatemans Date: Fri, 8 Nov 2024 10:15:12 +0100 Subject: [PATCH] change profile --- .changeset/bright-falcons-exercise.md | 2 + packages/apps/dev-wallet/package.json | 1 + .../dev-wallet/src/App/Layout/SideBar.tsx | 21 +++- .../ProfileChanger/ProfileChanger.css.ts | 70 +++++++++++++ .../ProfileChanger/ProfileChanger.tsx | 98 +++++++++++++++++++ .../ProfileChanger/components/Profile.tsx | 40 ++++++++ .../pages/select-profile/select-profile.tsx | 24 +---- .../src/utils/unlockWithWebAuthn.ts | 43 ++++++++ .../components/ContextMenu/ContextMenu.tsx | 1 + .../src/patterns/SideBarLayout/sidebar.css.ts | 2 +- pnpm-lock.yaml | 9 +- 11 files changed, 282 insertions(+), 29 deletions(-) create mode 100644 .changeset/bright-falcons-exercise.md create mode 100644 packages/apps/dev-wallet/src/Components/ProfileChanger/ProfileChanger.css.ts create mode 100644 packages/apps/dev-wallet/src/Components/ProfileChanger/ProfileChanger.tsx create mode 100644 packages/apps/dev-wallet/src/Components/ProfileChanger/components/Profile.tsx create mode 100644 packages/apps/dev-wallet/src/utils/unlockWithWebAuthn.ts diff --git a/.changeset/bright-falcons-exercise.md b/.changeset/bright-falcons-exercise.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/bright-falcons-exercise.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/apps/dev-wallet/package.json b/packages/apps/dev-wallet/package.json index f14dcd047e..31232e12dc 100644 --- a/packages/apps/dev-wallet/package.json +++ b/packages/apps/dev-wallet/package.json @@ -40,6 +40,7 @@ "elliptic": "^6.5.5", "js-yaml": "~4.1.0", "react": "^18.2.0", + "react-aria": "^3.31.1", "react-console-emulator": "^5.0.2", "react-dom": "^18.2.0", "react-hook-form": "^7.45.4", diff --git a/packages/apps/dev-wallet/src/App/Layout/SideBar.tsx b/packages/apps/dev-wallet/src/App/Layout/SideBar.tsx index 4d0cadaef2..f04a474667 100644 --- a/packages/apps/dev-wallet/src/App/Layout/SideBar.tsx +++ b/packages/apps/dev-wallet/src/App/Layout/SideBar.tsx @@ -6,6 +6,7 @@ import { MonoDarkMode, MonoKey, MonoLightMode, + MonoLogout, MonoNetworkCheck, MonoSignature, MonoSwapHoriz, @@ -14,6 +15,8 @@ import { import { NetworkSelector } from '@/Components/NetworkSelector/NetworkSelector'; +import { ProfileChanger } from '@/Components/ProfileChanger/ProfileChanger'; +import { useWallet } from '@/modules/wallet/wallet.hook'; import { Button, Themes, useTheme } from '@kadena/kode-ui'; import { SideBarItem, @@ -27,6 +30,7 @@ import { KLogo } from './KLogo'; export const SideBar: FC = () => { const { theme, setTheme } = useTheme(); + const { lockProfile } = useWallet(); const { isExpanded } = useLayout(); const toggleTheme = (): void => { @@ -37,9 +41,12 @@ export const SideBar: FC = () => { return ( - - + <> + + + + + } appContext={ } label="Select network"> @@ -105,6 +112,14 @@ export const SideBar: FC = () => { context={ <> + } label="Logout"> + + } + > + {profileList.map((profile) => { + return ( + { + handleSelect(profile); + }} + /> + ); + })} + + + + )} + + {filteredProfile && ( + handleSelect(filteredProfile)} + > + {getInitial(filteredProfile.name)} + + )} + + {currentProfile && ( + handleSelect(currentProfile)} + > + {getInitial(currentProfile.name)} + + )} + + ); +}; diff --git a/packages/apps/dev-wallet/src/Components/ProfileChanger/components/Profile.tsx b/packages/apps/dev-wallet/src/Components/ProfileChanger/components/Profile.tsx new file mode 100644 index 0000000000..8d9790f870 --- /dev/null +++ b/packages/apps/dev-wallet/src/Components/ProfileChanger/components/Profile.tsx @@ -0,0 +1,40 @@ +import { IProfile } from '@/modules/wallet/wallet.repository'; +import { Stack } from '@kadena/kode-ui'; +import { FC, PropsWithChildren } from 'react'; +import { profileClass } from '../ProfileChanger.css'; + +interface IProps extends PropsWithChildren { + idx?: number; + color: string; + isActive: boolean; + onClick: () => void; + hasMoreOptions: boolean; +} + +export const Profile: FC = ({ + children, + color, + idx, + isActive, + onClick, + hasMoreOptions, +}) => { + return ( + onClick()} + className={profileClass({ isActive })} + style={{ + backgroundColor: color, + zIndex: idx ?? 0 + 1, + transform: + idx && hasMoreOptions + ? `translateX(-${60 * idx}%)` + : `translateX(-100%)`, + }} + > + {children} + + ); +}; diff --git a/packages/apps/dev-wallet/src/pages/select-profile/select-profile.tsx b/packages/apps/dev-wallet/src/pages/select-profile/select-profile.tsx index 893d28bf88..3d966dbfd8 100644 --- a/packages/apps/dev-wallet/src/pages/select-profile/select-profile.tsx +++ b/packages/apps/dev-wallet/src/pages/select-profile/select-profile.tsx @@ -1,5 +1,6 @@ import { useWallet } from '@/modules/wallet/wallet.hook'; import { IProfile } from '@/modules/wallet/wallet.repository'; +import { unlockWithWebAuthn } from '@/utils/unlockWithWebAuthn'; import { recoverPublicKey, retrieveCredential } from '@/utils/webAuthn'; import { MonoAdd } from '@kadena/kode-icons'; import { Box, Heading, Stack } from '@kadena/kode-ui'; @@ -20,27 +21,6 @@ export function SelectProfile() { const { profileList, unlockProfile } = useWallet(); const [params] = useSearchParams(); - const unlockWithWebAuthn = async ( - profile: Pick, - ) => { - if (profile.options.authMode !== 'WEB_AUTHN') { - throw new Error('Profile does not support WebAuthn'); - } - const credentialId = profile.options.webAuthnCredential; - const credential = await retrieveCredential(credentialId); - if (!credential) { - throw new Error('Failed to retrieve credential'); - } - const keys = await recoverPublicKey(credential); - for (const key of keys) { - const result = await unlockProfile(profile.uuid, key); - if (result) { - return; - } - } - console.error('Failed to unlock profile'); - }; - const redirect = params.get('redirect'); return ( @@ -65,7 +45,7 @@ export function SelectProfile() { key={profile.uuid} className={cardClass} onClick={() => { - unlockWithWebAuthn(profile); + unlockWithWebAuthn(profile, unlockProfile); }} > diff --git a/packages/apps/dev-wallet/src/utils/unlockWithWebAuthn.ts b/packages/apps/dev-wallet/src/utils/unlockWithWebAuthn.ts new file mode 100644 index 0000000000..2c9b134751 --- /dev/null +++ b/packages/apps/dev-wallet/src/utils/unlockWithWebAuthn.ts @@ -0,0 +1,43 @@ +import { + IAccount, + IWatchedAccount, +} from '@/modules/account/account.repository'; +import { IKeySource, IProfile } from '@/modules/wallet/wallet.repository'; +import { recoverPublicKey, retrieveCredential } from '@/utils/webAuthn'; + +export type IProfilePicked = Pick< + IProfile, + 'name' | 'uuid' | 'accentColor' | 'options' +>; + +type IUnlockType = ( + uuid: string, + key: string, +) => Promise<{ + profile: IProfile; + accounts: Array; + watchedAccounts: Array; + keySources: IKeySource[]; +} | null>; + +export const unlockWithWebAuthn = async ( + profile: IProfilePicked, + unlockProfile: IUnlockType, +) => { + if (profile.options.authMode !== 'WEB_AUTHN') { + throw new Error('Profile does not support WebAuthn'); + } + const credentialId = profile.options.webAuthnCredential; + const credential = await retrieveCredential(credentialId); + if (!credential) { + throw new Error('Failed to retrieve credential'); + } + const keys = await recoverPublicKey(credential); + for (const key of keys) { + const result = await unlockProfile(profile.uuid, key); + if (result) { + return; + } + } + console.error('Failed to unlock profile'); +}; diff --git a/packages/libs/kode-ui/src/components/ContextMenu/ContextMenu.tsx b/packages/libs/kode-ui/src/components/ContextMenu/ContextMenu.tsx index d4f8a676db..2a1e516108 100644 --- a/packages/libs/kode-ui/src/components/ContextMenu/ContextMenu.tsx +++ b/packages/libs/kode-ui/src/components/ContextMenu/ContextMenu.tsx @@ -34,6 +34,7 @@ export const ContextMenu: FC = ({ } as AriaMenuProps<{}>); const { menuProps } = useMenu({ ...newMenuWrapperProps }, treeState, ref); + console.log({ trigger }); return ( <> {React.cloneElement(trigger, { diff --git a/packages/libs/kode-ui/src/patterns/SideBarLayout/sidebar.css.ts b/packages/libs/kode-ui/src/patterns/SideBarLayout/sidebar.css.ts index 0ebdf189e3..041d81cc9e 100644 --- a/packages/libs/kode-ui/src/patterns/SideBarLayout/sidebar.css.ts +++ b/packages/libs/kode-ui/src/patterns/SideBarLayout/sidebar.css.ts @@ -265,7 +265,7 @@ export const headerWrapperClass = recipe({ justifyContent: 'flex-start', height: minHeaderHeight, gridArea: 'sidebarlayout-header', - zIndex: 1, + zIndex: 2, }, ], variants: { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 967403e1ae..acddd6614a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -115,6 +115,9 @@ importers: react: specifier: ^18.2.0 version: 18.3.1 + react-aria: + specifier: ^3.31.1 + version: 3.33.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-console-emulator: specifier: ^5.0.2 version: 5.0.2(@types/react@18.3.3)(react@18.3.1) @@ -2662,10 +2665,10 @@ importers: version: 8.57.0 eslint-import-resolver-typescript: specifier: 3.5.5 - version: 3.5.5(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.27.5)(eslint@8.57.0) + version: 3.5.5(eslint-plugin-import@2.27.5)(eslint@8.57.0) eslint-plugin-import: specifier: ~2.27.5 - version: 2.27.5(@typescript-eslint/parser@6.21.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) + version: 2.27.5(eslint-import-resolver-typescript@3.5.5)(eslint@8.57.0) eslint-plugin-storybook: specifier: ^0.8.0 version: 0.8.0(eslint@8.57.0)(typescript@5.4.5) @@ -31522,7 +31525,7 @@ snapshots: pathe: 1.1.2 picocolors: 1.1.0 sirv: 2.0.4 - vitest: 1.6.0(@types/node@20.14.9)(@vitest/ui@1.6.0)(happy-dom@12.10.3)(jsdom@22.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.25.1)(terser@5.31.1) + vitest: 1.6.0(@types/node@20.16.5)(@vitest/ui@1.6.0)(happy-dom@12.10.3)(jsdom@22.1.0(canvas@2.11.2(encoding@0.1.13)))(lightningcss@1.25.1)(terser@5.31.1) '@vitest/utils@1.3.1': dependencies: