Skip to content

Commit

Permalink
feat: improve connector install detection page (#276)
Browse files Browse the repository at this point in the history
  • Loading branch information
luizstacio authored Sep 23, 2024
1 parent 17838cf commit 507c73f
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 50 deletions.
5 changes: 5 additions & 0 deletions packages/evm-connector/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ export interface EIP1193Provider extends EventEmitter {
params?: unknown[];
}): Promise<unknown | unknown[]>;
}

export interface SignatureData {
message: string;
signature: string;
}
73 changes: 61 additions & 12 deletions packages/react/src/providers/FuelUIProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Fuel, FuelConfig, FuelConnector } from 'fuels';
import type { FuelConfig, FuelConnector } from 'fuels';
import {
type ReactNode,
createContext,
Expand All @@ -21,6 +21,11 @@ export type FuelUIProviderProps = {
theme?: string;
};

export enum Routes {
INSTALL = 'install',
CONNECTING = 'connecting',
}

export type FuelUIContextType = {
fuelConfig: FuelConfig;
theme: string;
Expand All @@ -37,6 +42,11 @@ export type FuelUIContextType = {
isOpen: boolean;
back: () => void;
connect: (connector: FuelConnector) => void;
retryConnect: () => Promise<void>;
// @TODO: Remove this to use tiny router library
// react-router maybe too big for the bundle
route: Routes;
setRoute: (state: Routes) => void;
};
};

Expand Down Expand Up @@ -80,51 +90,87 @@ export function FuelUIProvider({
theme,
}: FuelUIProviderProps) {
const { fuel } = useFuel();
const { isPending: isConnecting, isError, connect } = useConnect();
const {
isPending: isConnecting,
data: isConnected,
isError,
connectAsync,
} = useConnect();
const { connectors, isLoading: isLoadingConnectors } = useConnectors({
query: { select: sortConnectors },
});
const [connector, setConnector] = useState<FuelConnector | null>(null);
const [dialogRoute, setDialogRoute] = useState<Routes>(Routes.INSTALL);
const [isOpen, setOpen] = useState(false);
const [error, setError] = useState<Error | null>(null);

const handleCancel = () => {
// If connectors list is updated we need to update the data of the current
// selected connector and change routes depending on the dialog route
useEffect(() => {
if (!connectors.length) return;
const selectedConnector = connectors.find((c: FuelConnector) => {
return c.name === connector?.name;
});
if (selectedConnector) {
setConnector(selectedConnector);
if (selectedConnector.installed && dialogRoute === Routes.INSTALL) {
setDialogRoute(Routes.CONNECTING);
}
}
}, [connectors, dialogRoute, connector]);

const handleCancel = useCallback(() => {
setOpen(false);
setConnector(null);
};
setError(null);
}, []);

const handleConnect = () => {
setOpen(true);
};

const handleBack = () => {
setConnector(null);
setError(null);
};

useEffect(() => {
if (connector?.installed) {
handleBack();
if (!isConnected) return;
handleCancel();
}, [isConnected, handleCancel]);

const handleRetryConnect = useCallback(async () => {
if (!connector) return;
try {
setError(null);
await connectAsync(connector.name);
} catch (err) {
setError(err as Error);
}
}, [connector?.installed, handleBack]);
}, [connectAsync, connector]);

const handleSelectConnector = useCallback(
async (connector: FuelConnector) => {
if (!fuel) return setConnector(connector);

setConnector(connector);
if (connector.installed) {
handleCancel();
setDialogRoute(Routes.CONNECTING);
try {
await connect(connector.name);
await connectAsync(connector.name);
} catch (err) {
setError(err as Error);
}
} else {
setConnector(connector);
setDialogRoute(Routes.INSTALL);
}
},
[fuel, connect, handleCancel],
[fuel, connectAsync],
);

const setRoute = useCallback((state: Routes) => {
setDialogRoute(state);
}, []);

const isLoading = useMemo(() => {
const hasLoadedConnectors =
(fuelConfig.connectors || []).length > connectors.length;
Expand All @@ -145,9 +191,12 @@ export function FuelUIProvider({
connect: handleConnect,
cancel: handleCancel,
dialog: {
route: dialogRoute,
setRoute,
connector,
isOpen,
connect: handleSelectConnector,
retryConnect: handleRetryConnect,
back: handleBack,
},
}}
Expand Down
58 changes: 58 additions & 0 deletions packages/react/src/ui/Connect/components/Connector/Connecting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { FuelConnector } from 'fuels';

import { useConnectUI } from '../../../../providers/FuelUIProvider';
import { ConnectorIcon } from '../ConnectorIcon';

import { Spinner } from '../Spinner/Spinner';
import {
ConnectorButton,
ConnectorContent,
ConnectorDescription,
ConnectorDescriptionError,
ConnectorImage,
ConnectorTitle,
} from './styles';

type ConnectorProps = {
theme?: string;
className?: string;
connector: FuelConnector;
};

export function Connecting({ className, connector, theme }: ConnectorProps) {
const {
error,
isConnecting,
dialog: { retryConnect },
} = useConnectUI();

return (
<div className={className}>
<ConnectorImage>
<ConnectorIcon
connectorMetadata={connector.metadata}
connectorName={connector.name}
size={100}
theme={theme}
/>
</ConnectorImage>
<ConnectorContent>
<ConnectorTitle>{connector.name}</ConnectorTitle>
{error ? (
<ConnectorDescriptionError>{error.message}</ConnectorDescriptionError>
) : (
<ConnectorDescription>
Requesting connection to <br /> {connector.name}.
</ConnectorDescription>
)}
</ConnectorContent>
<ConnectorButton onClick={retryConnect}>
{isConnecting ? (
<Spinner size={26} color="var(--fuel-loader-background)" />
) : (
'Connect'
)}
</ConnectorButton>
</div>
);
}
51 changes: 22 additions & 29 deletions packages/react/src/ui/Connect/components/Connector/Connector.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import type { FuelConnector } from 'fuels';
import { useEffect, useState } from 'react';

import { useConnectUI } from '../../../../providers/FuelUIProvider';
import { ConnectorIcon } from '../ConnectorIcon';

import { Spinner } from '../Spinner/Spinner';
import { useQuery } from '@tanstack/react-query';
import { useConnectUI } from '../../../../providers';
import { Routes } from '../../../../providers/FuelUIProvider';
import {
ConnectorButton,
ConnectorContent,
ConnectorDescription,
ConnectorFooterHelper,
ConnectorImage,
ConnectorTitle,
} from './styles';
Expand All @@ -20,30 +21,23 @@ type ConnectorProps = {
};

export function Connector({ className, connector, theme }: ConnectorProps) {
const {
dialog: { setRoute },
} = useConnectUI();
const {
install: { action, link, description },
} = connector.metadata;

const {
setError,
dialog: { connect },
} = useConnectUI();
const [isLoading, setLoading] = useState(!connector.installed);

useEffect(() => {
const ping = async () => {
try {
await connector.ping();
connector.installed = true;
connect(connector);
} catch (error) {
setLoading(false);
setError(error as Error);
}
};

ping();
}, [connector, connect, setError]);
// Ping exetensin if it's installed it will trigger connector
useQuery({
queryKey: ['CONNECTOR_PING', connector.name, connector.installed],
queryFn: async () => {
const isInstall = await connector.ping();
if (isInstall) setRoute(Routes.CONNECTING);
return isInstall;
},
staleTime: Number.POSITIVE_INFINITY,
});

const actionText = action || 'Install';

Expand All @@ -61,13 +55,12 @@ export function Connector({ className, connector, theme }: ConnectorProps) {
<ConnectorTitle>{connector.name}</ConnectorTitle>
<ConnectorDescription>{description}</ConnectorDescription>
</ConnectorContent>
<ConnectorButton href={link} target="_blank" aria-disabled={isLoading}>
{isLoading ? (
<Spinner size={26} color="var(--fuel-loader-background)" />
) : (
actionText
)}
<ConnectorButton href={link} target="_blank">
{actionText}
</ConnectorButton>
<ConnectorFooterHelper>
If you have install and is not detected <br /> try to refresh the page.
</ConnectorFooterHelper>
</div>
);
}
20 changes: 19 additions & 1 deletion packages/react/src/ui/Connect/components/Connector/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,42 @@ export const ConnectorTitle = styled.h2`
`;

export const ConnectorDescription = styled.p`
font-weight: 400;
text-align: center;
margin: 0 1.2em;
line-height: 1.2em;
padding: 0 2em;
opacity: 0.8;
`;

export const ConnectorFooterHelper = styled.p`
font-size: 0.8em;
font-weight: 400;
text-align: center;
margin: 0.6em 1.2em;
line-height: 1.2em;
padding: 0 2em;
opacity: 0.5;
`;

export const ConnectorDescriptionError = styled(ConnectorDescription)`
color: var(--fuel-color-error);
`;

export const ConnectorImage = styled.div`
display: flex;
justify-content: center;
height: 6.2em;
width: 100%;
margin-top: 1.4em;
margin-top: 1.6em;
margin-bottom: 1.2em;
`;

export const ConnectorButton = styled.a`
display: flex;
box-sizing: border-box;
text-decoration: none;
cursor: pointer;
justify-content: center;
align-items: center;
margin: 1.4em 1em 0;
Expand Down
Loading

0 comments on commit 507c73f

Please sign in to comment.