Skip to content

Commit

Permalink
feat(dw): sync state between all tabs (#2663)
Browse files Browse the repository at this point in the history
* feat(dw): sync state between all tabs

* chore(dw): clean up

* fix(dw): session timeout

* feat(dw): add boot status

* fix(dw): boot status

* fix(dw): loaidng content

* refactor(dw): renaming
  • Loading branch information
javadkh2 authored Nov 14, 2024
1 parent ee38a9e commit 929d23c
Show file tree
Hide file tree
Showing 29 changed files with 873 additions and 241 deletions.
4 changes: 2 additions & 2 deletions packages/apps/dev-wallet/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
<link rel="stylesheet" href="./boot.css" />
</head>
<body class="boot">
<div id="root"></div>
<!-- Welcome message will be removed after wallet is loaded -->
<div id="welcome-message" class="welcome-wrapper">
<div class="welcome-message-content">
Expand All @@ -19,9 +18,10 @@
style="margin: 0"
/>
<h1 style="margin: 0; font-weight: 400">Chainweaver v3</h1>
<p style="margin: 0">Loading</p>
<div id="loading-content">Loading...</div>
</div>
</div>
<div id="root"></div>

<script type="module" src="/src/index.ts"></script>
</body>
Expand Down
38 changes: 33 additions & 5 deletions packages/apps/dev-wallet/public/boot.css
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
*,
*::before,
*::after {
box-sizing: border-box;
}

.welcome-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100vh;
background: #050e1b;
opacity: 0;
}
.welcome-message-content {
display: flex;
padding: 40px 100px;
padding: 40px;
max-width: 455px;
width: 455px;
justify-content: center;
align-items: center;
flex-direction: column;
Expand All @@ -27,8 +33,30 @@
text-align: center;
-webkit-font-smoothing: antialiased;
}
body.boot.boot-theme-light .welcome-wrapper {
background: #f5f5f5;

#loading-content {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-direction: column;
font-family: 'Roboto', sans-serif;
font-smooth: antialiased;
line-height: 1rem;
text-align: center;
-webkit-font-smoothing: antialiased;
width: 300px;
background: black;
height: 80px;
padding: 10px;
box-sizing: border-box;
text-align: left;
font-size: 1rem;
gap: 4px;
border-radius: 4px;
}

body.boot.boot-theme-light #loading-content {
background: #f0f0f0;
}

body.boot.boot-theme-light .welcome-wrapper .welcome-message-content {
Expand Down
8 changes: 6 additions & 2 deletions packages/apps/dev-wallet/src/App/Layout/SideBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ import {
import { NetworkSelector } from '@/Components/NetworkSelector/NetworkSelector';

import { useWallet } from '@/modules/wallet/wallet.hook';
import { getWebAuthnPass } from '@/modules/wallet/wallet.service';
import { getInitials } from '@/utils/get-initials';
import { unlockWithWebAuthn } from '@/utils/unlockWithWebAuthn';
import {
Avatar,
Button,
Expand Down Expand Up @@ -193,7 +193,11 @@ export const SideBar: FC = () => {
onClick={async () => {
if (prf.uuid === profile?.uuid) return;
if (prf.options.authMode === 'WEB_AUTHN') {
await unlockWithWebAuthn(prf, unlockProfile);
const pass = await getWebAuthnPass(prf);
if (pass) {
lockProfile();
await unlockProfile(prf.uuid, pass);
}
} else {
navigate(`/unlock-profile/${prf.uuid}`);
}
Expand Down
1 change: 1 addition & 0 deletions packages/apps/dev-wallet/src/App/Layout/style.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const isExpandedMainClass = style({

export const mainContainerClass = style({
display: 'flex',
padding: '0 10px',
flexDirection: 'column',
maxWidth: '100vw',
width: '100%',
Expand Down
23 changes: 12 additions & 11 deletions packages/apps/dev-wallet/src/App/app.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import { DatabaseProvider } from '@/modules/db/db.provider';
import { WalletProvider } from '@/modules/wallet/wallet.provider';
import { MediaContextProvider } from '@kadena/kode-ui';
import { MediaContextProvider, useTheme } from '@kadena/kode-ui';
import { LayoutProvider } from '@kadena/kode-ui/patterns';
import { useEffect } from 'react';
import { PromptProvider } from '../Components/PromptProvider/Prompt';
import { Routes } from './routes';
import { SessionProvider } from './session';

function Providers({ children }: { children: React.ReactNode }) {
useTheme();
useEffect(() => {
if (!localStorage.getItem('theme')) {
localStorage.setItem('theme', 'dark');
}
}, []);
return (
<MediaContextProvider>
<SessionProvider>
<PromptProvider>
<DatabaseProvider>
<WalletProvider>
<LayoutProvider>
<LayoutProvider>
<SessionProvider>
<PromptProvider>
<DatabaseProvider>
<WalletProvider>
{/* TODO: fixed the issue with prompt and remove this one in favor of the one above */}
<PromptProvider>{children}</PromptProvider>
</LayoutProvider>
</WalletProvider>
</DatabaseProvider>
</PromptProvider>
</SessionProvider>
</WalletProvider>
</DatabaseProvider>
</PromptProvider>
</SessionProvider>
</LayoutProvider>
</MediaContextProvider>
);
}
Expand Down
10 changes: 9 additions & 1 deletion packages/apps/dev-wallet/src/App/session.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { BootContent } from '@/Components/BootContent/BootContent';
import { Session } from '@/utils/session';
import { Text } from '@kadena/kode-ui';
import {
FC,
PropsWithChildren,
Expand Down Expand Up @@ -42,7 +44,13 @@ export const SessionProvider: FC<PropsWithChildren> = ({ children }) => {

return (
<sessionContext.Provider value={Session}>
{loaded ? children : 'Loading session...'}
{loaded ? (
children
) : (
<BootContent>
<Text>Loading session...</Text>
</BootContent>
)}
</sessionContext.Provider>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Stack } from '@kadena/kode-ui';
import { createPortal } from 'react-dom';

const loadingContent = document.getElementById('loading-content');

export function BootContent({ children }: { children: React.ReactNode }) {
if (!loadingContent) {
return children;
}
return createPortal(
<Stack justifyContent={'flex-start'} alignItems={'flex-start'}>
{children}
</Stack>,
loadingContent,
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useWallet } from '@/modules/wallet/wallet.hook';
import { IProfilePicked, unlockWithWebAuthn } from '@/utils/unlockWithWebAuthn';
import { IProfile } from '@/modules/wallet/wallet.repository';
import { getWebAuthnPass } from '@/modules/wallet/wallet.service';
import { MonoMoreHoriz } from '@kadena/kode-icons/system';
import {
Button,
Expand All @@ -26,9 +27,12 @@ export const ProfileChanger: FC = () => {
} = useWallet();
const navigate = useNavigate();

const handleSelect = async (profile: IProfilePicked) => {
const handleSelect = async (profile: Pick<IProfile, 'options' | 'uuid'>) => {
if (profile.options.authMode === 'WEB_AUTHN') {
await unlockWithWebAuthn(profile, unlockProfile);
const pass = await getWebAuthnPass(profile);
if (pass) {
await unlockProfile(profile.uuid, pass);
}
} else {
navigate(`/unlock-profile/${profile.uuid}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { unlockPrompt } from './style.css.ts';
export const UnlockPrompt: React.FC<{
showPassword?: boolean;
rememberPassword?: IProfile['options']['rememberPassword'];
profile: IProfile;
resolve: ({
password,
keepOpen,
Expand All @@ -24,7 +25,7 @@ export const UnlockPrompt: React.FC<{
keepOpen: 'session' | 'short-time' | 'never';
}) => void;
reject: (reason: any) => void;
}> = ({ resolve, reject, showPassword, rememberPassword }) => {
}> = ({ resolve, reject, showPassword, rememberPassword, profile }) => {
const { control, register, handleSubmit } = useForm({
defaultValues: {
keepOpen: rememberPassword || 'session',
Expand All @@ -49,6 +50,12 @@ export const UnlockPrompt: React.FC<{
You need to unlock the security module in order to use it for
sensitive actions (e.g. sign or account creation)
</Text>
<Text>
Profile:{' '}
<Text bold color="emphasize">
{profile.name}
</Text>
</Text>
{showPassword && (
<TextField
type="password"
Expand Down
7 changes: 7 additions & 0 deletions packages/apps/dev-wallet/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,11 @@ export const config = {
// a migration script
DB_WIPE_ON_VERSION_CHANGE: true,
},
ACCOUNTS: {
SYNC_INTERVAL: 5 * 60 * 1000, // 5 minutes
},
SESSION: {
TTL: 5 * 60 * 1000, // 30 minutes
ENCRYPT_SESSION: false,
},
};
48 changes: 47 additions & 1 deletion packages/apps/dev-wallet/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,23 @@ const removeBootTheme = () => {
document.body.classList.remove(`boot-theme-${getTheme()}`);
};

const loadingContent = document.getElementById('loading-content');

// the entry file for the dev wallet app
// TODO: we need to do setup app here like service worker, etc
async function bootstrap() {
await registerServiceWorker();
addBootTheme();
import('./App/main').then(async ({ renderApp }) => {
if (loadingContent) {
loadingContent.innerHTML = '';
}
renderApp();
globalThis.addEventListener('wallet-loaded', function () {
document.getElementById('welcome-message')?.remove();
const welcomeMessage = document.getElementById('welcome-message');
if (welcomeMessage) {
welcomeMessage.style.display = 'none';
}
removeBootTheme();
});
});
Expand All @@ -27,4 +36,41 @@ async function bootstrap() {
}, 200);
}

async function registerServiceWorker() {
if (loadingContent) {
loadingContent.innerHTML = 'Loading Service Worker...';
}
if ('serviceWorker' in navigator) {
await navigator.serviceWorker
.register('/sw.js')
.then((registration) => {
console.log(
'Service Worker registered with scope:',
registration.scope,
);
if (loadingContent) {
loadingContent.innerHTML =
'<div>Service Worker registered!</div><div>Loading components...</div>';
}
registration.onupdatefound = () => {
const newWorker = registration.installing;
if (!newWorker) return;
newWorker.onstatechange = () => {
if (newWorker.state === 'activated') {
// If the service worker is activated, reload the page
window.location.reload();
}
};
};
})
.catch((error) => {
if (loadingContent) {
loadingContent.innerHTML =
'<div>Service Worker registration failed!</div><div>using fallback mode</div><div>Loading components...</div>';
}
console.error('Service Worker registration failed:', error);
});
}
}

bootstrap();
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface IAccount {
}>;
keyset?: IKeySet;
alias?: string;
syncTime?: number;
}

export type IWatchedAccount = Omit<IAccount, 'keysetId' | 'keyset'> & {
Expand Down Expand Up @@ -72,7 +73,7 @@ const createAccountRepository = ({
...account,
keyset: await getKeyset(account.keysetId),
});
return {
const actions = {
async getKeysetByPrincipal(
principal: string,
profileId: string,
Expand Down Expand Up @@ -148,6 +149,28 @@ const createAccountRepository = ({
updateWatchedAccount: async (account: IWatchedAccount): Promise<void> => {
return update('watched-account', account);
},

patchAccount: async (
uuid: string,
patch: Partial<IAccount>,
): Promise<IAccount> => {
const account = await actions.getAccount(uuid);
const updatedAccount = { ...account, ...patch };
await actions.updateAccount(updatedAccount);
return updatedAccount;
},
patchWatchedAccount: async (
uuid: string,
patch: Partial<IWatchedAccount>,
): Promise<IWatchedAccount> => {
const account = (await getOne(
'watched-account',
uuid,
)) as IWatchedAccount;
const updatedAccount = { ...account, ...patch };
await actions.updateWatchedAccount(updatedAccount);
return updatedAccount;
},
async getWatchedAccountsByProfileId(profileId: string, networkUUID: UUID) {
const accounts: Array<IWatchedAccount> = await getAll(
'watched-account',
Expand All @@ -157,6 +180,7 @@ const createAccountRepository = ({
return accounts;
},
};
return actions;
};

export const chainIds = [...Array(20).keys()].map((key) => `${key}` as ChainId);
Expand Down
Loading

0 comments on commit 929d23c

Please sign in to comment.