Skip to content

Commit

Permalink
Add link to frontend in popup (#915)
Browse files Browse the repository at this point in the history
* Simplify Network component

* Add an optional href prop for Network

* Use a component-specific selector

* Refactor state quite a bit

* Add filtering to selector

* Update tests

* Refactor to prevent unnecessary renders

* Refactor a bit

* Convert Tailwind config to TypeScript; use it to make a constant with resolved config

* Render a button for setting the frontend

* Set a default frontend URL; tweak the Network component

* Fix some spacing issues

* Fix some lint issues

* Remove unused prop

* Move const to tailwind config package

* Only allow approved sites to be selected as the frontend URL

* Remove unused method; update tests

* Fix imports

* Point the network link to the status page

* Redesign index page

* Default to the first available frontend if the current one is deleted
  • Loading branch information
jessepinho authored Apr 12, 2024
1 parent a1b1371 commit 5bc8311
Show file tree
Hide file tree
Showing 21 changed files with 385 additions and 290 deletions.
4 changes: 2 additions & 2 deletions apps/extension/src/routes/popup/home/block-sync.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { LargeBlockSyncStatus } from '@penumbra-zone/ui/components/ui/block-sync-status/large';
import { CondensedBlockSyncStatus } from '@penumbra-zone/ui/components/ui/block-sync-status/condensed';
import { useSyncProgress } from '../../../hooks/full-sync-height';

export const BlockSync = () => {
const { latestBlockHeight, fullSyncHeight, error } = useSyncProgress();

return (
<LargeBlockSyncStatus
<CondensedBlockSyncStatus
fullSyncHeight={fullSyncHeight}
latestKnownBlockHeight={latestBlockHeight}
error={error}
Expand Down
11 changes: 7 additions & 4 deletions apps/extension/src/routes/popup/home/index-header.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import { HamburgerMenuIcon } from '@radix-ui/react-icons';
import { usePopupNav } from '../../../utils/navigate';
import { PopupPath } from '../paths';
import { NetworksPopover } from '@penumbra-zone/ui/components/ui/networks-popover';
import { Network } from '@penumbra-zone/ui/components/ui/network';
import { useChainIdQuery } from '../../../hooks/chain-id';
import { motion } from 'framer-motion';
import { useStore } from '../../../state';

export const IndexHeader = () => {
const navigate = usePopupNav();
const { chainId } = useChainIdQuery();
const statusPageUrl = useStore(state => state.network.grpcEndpoint);

return (
<header className='top-0 z-40 w-full'>
<div className='flex items-center justify-between pt-4'>
<div className='flex items-center justify-between gap-4 pt-4'>
<HamburgerMenuIcon
onClick={() => navigate(PopupPath.SETTINGS)}
className='size-6 cursor-pointer hover:opacity-50'
className='size-6 shrink-0 cursor-pointer hover:opacity-50'
/>
{chainId ? (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { duration: 0.5, ease: 'easeOut' } }}
className='overflow-hidden'
>
<NetworksPopover name={chainId} connectIndicator={false} />
<Network name={chainId} connectIndicator={false} href={statusPageUrl} />
</motion.div>
) : (
<div className='m-[19px]' />
Expand Down
27 changes: 21 additions & 6 deletions apps/extension/src/routes/popup/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { BlockSync } from './block-sync';
import { localExtStorage } from '@penumbra-zone/storage/chrome/local';
import { addrByIndexSelector, getActiveWallet } from '../../../state/wallets';
import { needsLogin } from '../popup-needs';
import { Button } from '@penumbra-zone/ui/components/ui/button';
import { ExternalLink } from 'lucide-react';

export interface PopupLoaderData {
fullSyncHeight?: number;
Expand All @@ -25,14 +27,27 @@ export const popupIndexLoader = async (): Promise<Response | PopupLoaderData> =>
export const PopupIndex = () => {
const activeWallet = useStore(getActiveWallet);
const getAddrByIndex = useStore(addrByIndexSelector);
const frontendUrl = useStore(state => state.connectedSites.frontendUrl);

return (
<div className='flex h-full grow flex-col items-stretch justify-start bg-logo bg-left-bottom px-[30px]'>
<IndexHeader />
<div className='my-32'>
{activeWallet && <SelectAccount getAddrByIndex={getAddrByIndex} />}
</div>
<>
<BlockSync />
</div>

<div className='flex h-full grow flex-col items-stretch justify-between bg-logo bg-left-bottom px-[30px] pb-[30px]'>
<IndexHeader />

<div className='flex flex-col gap-8'>
{activeWallet && <SelectAccount getAddrByIndex={getAddrByIndex} />}
</div>

{!!frontendUrl && (
<a href={frontendUrl} target='_blank' rel='noreferrer'>
<Button className='flex w-full items-center gap-2' variant='gradient'>
Manage portfolio <ExternalLink size={16} />
</Button>
</a>
)}
</div>
</>
);
};
148 changes: 0 additions & 148 deletions apps/extension/src/routes/popup/settings/settings-connected-sites.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Button } from '@penumbra-zone/ui/components/ui/button';
import {
TooltipProvider,
Tooltip,
TooltipTrigger,
TooltipContent,
} from '@penumbra-zone/ui/components/ui/tooltip';
import { Star } from 'lucide-react';
import { RESOLVED_TAILWIND_CONFIG } from '@penumbra-zone/tailwind-config/resolved-tailwind-config';

export const FrontendUrlButton = ({
isSelected,
onClick,
}: {
isSelected: boolean;
onClick: () => void;
}) => {
const { theme } = RESOLVED_TAILWIND_CONFIG;
const label = isSelected ? 'Primary Penumbra frontend' : 'Set as primary Penumbra frontend';

return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger className='h-[16px]'>
<Button aria-label={label} className='h-auto bg-transparent' onClick={onClick}>
<Star
fill={isSelected ? theme.colors.muted.foreground : 'transparent'}
className='text-muted-foreground'
size={16}
/>
</Button>
</TooltipTrigger>
<TooltipContent side='left'>{label}</TooltipContent>
</Tooltip>
</TooltipProvider>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { MagnifyingGlassIcon } from '@radix-ui/react-icons';
import { Input } from '@penumbra-zone/ui/components/ui/input';
import { LinkGradientIcon } from '../../../../icons/link-gradient';
import { OriginRecord } from '@penumbra-zone/storage/chrome/types';
import { AllSlices, useStore } from '../../../../state';
import { UserChoice } from '@penumbra-zone/types/src/user-choice';
import { SettingsScreen } from '../settings-screen';
import { useStoreShallow } from '../../../../utils/use-store-shallow';
import { allSitesFilteredOutSelector } from '../../../../state/connected-sites';
import Map from '@penumbra-zone/polyfills/src/Map.groupBy';
import { KnownSitesGroup } from './known-sites-group';

const settingsConnectedSitesSelector = (state: AllSlices) => ({
filter: state.connectedSites.filter,
setFilter: state.connectedSites.setFilter,
knownSites: state.connectedSites.knownSites,
});

const getGroupedSites = (knownSites: OriginRecord[], filter?: string) => {
const groupedSites = Map.groupBy(knownSites, ({ choice }) => choice);
const filterFn = (site: OriginRecord) => !filter || site.origin.includes(filter);

return {
approvedSites: groupedSites.get(UserChoice.Approved)?.filter(filterFn) ?? [],
deniedSites: groupedSites.get(UserChoice.Denied)?.filter(filterFn) ?? [],
ignoredSites: groupedSites.get(UserChoice.Ignored)?.filter(filterFn) ?? [],
};
};

export const SettingsConnectedSites = () => {
const { filter, setFilter, knownSites } = useStoreShallow(settingsConnectedSitesSelector);
const allSitesFilteredOut = useStore(allSitesFilteredOutSelector);
const { approvedSites, deniedSites, ignoredSites } = getGroupedSites(knownSites, filter);

return (
<SettingsScreen title='Connected sites' IconComponent={LinkGradientIcon}>
<div className='relative mt-5 flex w-full items-center justify-center'>
<div className='absolute inset-y-0 left-3 flex items-center'>
<MagnifyingGlassIcon className='size-5 text-muted-foreground' />
</div>
<Input
disabled={!knownSites.length}
variant={allSitesFilteredOut ? 'warn' : null}
className='pl-10'
onChange={e => setFilter(e.target.value)}
placeholder='Search by origin...'
/>
</div>
<div className='text-muted-foreground'>
{!knownSites.length ? (
<div className='py-[2em] text-center text-lg font-bold'>no known sites</div>
) : allSitesFilteredOut ? (
<div className='py-[2em] text-center text-lg font-bold text-yellow-500'>
all known sites filtered
</div>
) : (
<div className='mt-4 flex flex-col gap-4'>
{!!approvedSites.length && (
<KnownSitesGroup label='Approved sites' sites={approvedSites} />
)}
{!!deniedSites.length && <KnownSitesGroup label='Denied sites' sites={deniedSites} />}
{!!ignoredSites.length && (
<>
{!!(approvedSites.length || deniedSites.length) && <hr className='my-2' />}
<KnownSitesGroup label='Ignored sites' sites={ignoredSites} />
</>
)}
</div>
)}
</div>
</SettingsScreen>
);
};
Loading

0 comments on commit 5bc8311

Please sign in to comment.