Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: notify about needed account re import #1452

Merged
merged 1 commit into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 79 additions & 45 deletions apps/extension/src/App/Accounts/ParentAccounts.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useContext } from "react";
import { useNavigate } from "react-router-dom";
import { useContext, useEffect } from "react";
import { Outlet, useNavigate } from "react-router-dom";

import {
ActionButton,
GapPatterns,
KeyListItem,
Stack,
} from "@namada/components";
import { DerivedAccount } from "@namada/types";
import { AccountType, DerivedAccount } from "@namada/types";
import { ParentAccountsFooter } from "App/Accounts/ParentAccountsFooter";
import { PageHeader } from "App/Common";
import routes from "App/routes";
Expand All @@ -20,8 +20,37 @@ import { openSetupTab } from "utils";
*/
export const ParentAccounts = (): JSX.Element => {
const navigate = useNavigate();
const { activeAccountId, parentAccounts, changeActiveAccountId } =
useContext(AccountContext);
const {
activeAccountId,
parentAccounts,
accounts: allAccounts,
changeActiveAccountId,
} = useContext(AccountContext);

// We check which accounts need to be re-imported
const accounts = allAccounts
.filter(
(account) => account.parentId || account.type === AccountType.Ledger
)
.map((account) => {
const outdated =
account.type !== AccountType.Ledger &&
typeof account.pseudoExtendedKey === "undefined";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We ignore ledger for now


// The only account without a parent is the ledger account
const parent =
parentAccounts.find((pa) => pa.id === account.parentId) || account;

return { ...parent, outdated };
});

useEffect(() => {
const hasOutdatedAccounts = accounts.some((account) => account.outdated);
// If there are outdated accounts, we redirect to the update required page
if (hasOutdatedAccounts) {
navigate(routes.accountsUpdateRequired());
}
}, []);

const goToSetupPage = async (): Promise<void> => {
await openSetupTab();
Expand All @@ -44,47 +73,52 @@ export const ParentAccounts = (): JSX.Element => {
};

return (
<Stack
gap={GapPatterns.TitleContent}
full
className="max-h-[calc(100vh-40px)]"
>
<PageHeader title="Select Account" />
<Stack gap={4} className="flex-1 overflow-auto">
<nav className="grid items-end grid-cols-[auto_min-content]">
<p className="text-white font-medium text-xs">Set default keys</p>
<div className="w-26">
<ActionButton size="xs" onClick={goToSetupPage}>
Add Keys
</ActionButton>
</div>
</nav>
<Stack as="ul" gap={3} className="flex-1 overflow-auto">
{[...parentAccounts].reverse().map((account, idx) => (
<KeyListItem
key={`key-listitem-${account.id}`}
as="li"
alias={account.alias}
type={account.type}
dropdownPosition={
idx > 2 && idx > parentAccounts.length - 4 ? "bottom" : "top"
}
isMainKey={activeAccountId === account.id}
onRename={() => goToRenameAccount(account)}
onDelete={() => goToDeletePage(account)}
onViewAccount={() => goToViewAccount(account)}
onViewRecoveryPhrase={() => goToViewRecoveryPhrase(account)}
onSelectAccount={() => {
changeActiveAccountId(
account.id,
account.type as ParentAccount
);
}}
/>
))}
<>
<Stack
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I only wrapped everything in fragment to add Outlet

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't need to excuse in advanced, we can see it if we hide the whitespaces 😁

Screenshot 2024-12-30 at 16 43 58

gap={GapPatterns.TitleContent}
full
className="max-h-[calc(100vh-40px)]"
>
<PageHeader title="Select Account" />
<Stack gap={4} className="flex-1 overflow-auto">
<nav className="grid items-end grid-cols-[auto_min-content]">
<p className="text-white font-medium text-xs">Set default keys</p>
<div className="w-26">
<ActionButton size="xs" onClick={goToSetupPage}>
Add Keys
</ActionButton>
</div>
</nav>
<Stack as="ul" gap={3} className="flex-1 overflow-auto">
{[...accounts].reverse().map((account, idx) => (
<KeyListItem
key={`key-listitem-${account.id}`}
as="li"
alias={account.alias}
type={account.type}
outdated={account.outdated}
dropdownPosition={
idx > 2 && idx > accounts.length - 4 ? "bottom" : "top"
}
isMainKey={activeAccountId === account.id}
onRename={() => goToRenameAccount(account)}
onDelete={() => goToDeletePage(account)}
onViewAccount={() => goToViewAccount(account)}
onViewRecoveryPhrase={() => goToViewRecoveryPhrase(account)}
onSelectAccount={() => {
changeActiveAccountId(
account.id,
account.type as ParentAccount
);
}}
/>
))}
</Stack>
<ParentAccountsFooter />
</Stack>
<ParentAccountsFooter />
</Stack>
</Stack>

<Outlet />
</>
);
};
88 changes: 88 additions & 0 deletions apps/extension/src/App/Accounts/UpdateRequired.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import clsx from "clsx";
import { IoClose } from "react-icons/io5";
import { PiWarning } from "react-icons/pi";
import { useNavigate } from "react-router-dom";

import { Modal, Stack } from "@namada/components";
import routes from "App/routes";
import updateRequried from "./assets/update-required.png";

export const UpdateRequired = (): JSX.Element => {
const navigate = useNavigate();

const onCloseModal = (): void => {
navigate(routes.viewAccountList());
};

return (
<Modal
onClose={onCloseModal}
className={clsx(
"w-full left-auto right-0 top-0 bottom-0 translate-x-0",
"translate-y-0 pointer-events-none",
"p-5"
)}
>
<div
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of this was copied from namadillo's ModalContainer 😛

className={clsx(
"flex flex-col pointer-events-auto",
"w-full h-full",
"bg-rblack border rounded-md border-yellow-300 p-3"
)}
>
<header className="relative">
<button
onClick={onCloseModal}
className="absolute right-0 top-3 flex items-center h-full text-2xl text-white hover:text-yellow"
>
<IoClose />
</button>
</header>
<div className="flex flex-1">
<Stack className="px-5">
<Stack gap={1}>
<img
src={updateRequried}
alt=""
className="w-[108px] self-center mt-2"
/>
<h1 className="text-white text-center text-md">
Account update required!
</h1>
</Stack>
<p className="text-yellow text-center">
Accounts marked with an exclamation symbol
<br />
<span className="font-md">
(<PiWarning className="inline w-[14px] h-[14px]" />){" "}
</span>
need to be re-imported to support shielded transfers.*
</p>
<Stack className="p-5 rounded-md bg-neutral-900 text-white" gap={2}>
<h2 className="font-medium">To Re-import your account:</h2>
<ol className="list-decimal pl-3 pr-1 space-y-2">
<li>
If necessary. Re-copy and note
down your seed phrase / private
key
<br />
<span className="text-yellow">
Accounts CAN NOT be re-imported without the seed phrase
</span>
</li>
<li>Delete the marked account from 
the keychain</li>
<li>
Re-Import the account using your seed phrase / private key
</li>
</ol>
</Stack>
<p className="text-yellow text-center leading-3">
* Ledger accounts will receive shielded
<br /> functions in a separate update in an
<br /> upcoming release
</p>
</Stack>
</div>
</div>
</Modal>
);
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions apps/extension/src/App/Accounts/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./DeleteAccount";
export * from "./RenameAccount";
export * from "./UpdateRequired";
export * from "./ViewAccount";
export * from "./ViewMnemonic";
11 changes: 7 additions & 4 deletions apps/extension/src/App/AppContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { openSetupTab } from "utils";
import {
DeleteAccount,
RenameAccount,
UpdateRequired,
ViewAccount,
ViewMnemonic,
} from "./Accounts";
Expand Down Expand Up @@ -86,10 +87,12 @@ export const AppContent = ({ warnings }: Props): JSX.Element => {
path={routes.viewAccountMnemonic()}
element={<ViewMnemonic />}
/>
<Route
path={routes.viewAccountList()}
element={<ParentAccounts />}
/>
<Route path={routes.viewAccountList()} element={<ParentAccounts />}>
<Route
path={routes.accountsUpdateRequired()}
element={<UpdateRequired />}
/>
</Route>
</>
)}
</Routes>
Expand Down
1 change: 1 addition & 0 deletions apps/extension/src/App/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default {
network: (): string => `/network`,
warnings: (): string => `/warnings`,
viewAccountList: () => `/accounts/view`,
accountsUpdateRequired: () => `/accounts/view/update-required`,
viewAccountMnemonic: (accountId: string = ":accountId") =>
`/accounts/mnemonic/${accountId}`,
viewAccount: (accountId: string = ":accountId") =>
Expand Down
1 change: 1 addition & 0 deletions apps/extension/src/react-app.env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "*.png";
8 changes: 8 additions & 0 deletions apps/extension/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ module.exports = {
and: [/\.(ts|tsx|md)$/],
},
},
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: require.resolve("file-loader"),
},
],
},
],
},
resolve: {
Expand Down
Loading
Loading