diff --git a/frontend/src/components/layouts/TwoColumnFullScreenLayout.tsx b/frontend/src/components/layouts/TwoColumnFullScreenLayout.tsx index fce027b9..d2f2c62e 100644 --- a/frontend/src/components/layouts/TwoColumnFullScreenLayout.tsx +++ b/frontend/src/components/layouts/TwoColumnFullScreenLayout.tsx @@ -4,6 +4,7 @@ import { Outlet, useLocation, useNavigate } from "react-router"; import { AlbyHubLogo } from "src/components/icons/AlbyHubLogo"; import { Button } from "src/components/ui/button.tsx"; import { useInfo } from "src/hooks/useInfo"; +import { cn } from "src/lib/utils"; import AntonopoulosSVG from "public/images/quotes/antonopoulos.svg"; import BackSVG from "public/images/quotes/back.svg"; @@ -65,6 +66,7 @@ export default function TwoColumnFullScreenLayout() { const { data: info } = useInfo(); const navigate = useNavigate(); const { pathname } = useLocation(); + const anchorFirstChannelExpansion = pathname === "/setup/first-channel"; const [quote, setQuote] = useState( // eslint-disable-next-line react-hooks/purity quotes[Math.floor(Math.random() * quotes.length)] @@ -100,9 +102,15 @@ export default function TwoColumnFullScreenLayout() { -
+
{pathname.startsWith("/setup") && - !pathname.startsWith("/setup/finish") && ( + !pathname.startsWith("/setup/finish") && + !pathname.startsWith("/setup/first-channel") && ( // show the back button on setup pages, except the setup finish page
); diff --git a/frontend/src/components/redirects/SetupRedirect.tsx b/frontend/src/components/redirects/SetupRedirect.tsx index 709aee94..b775bfac 100644 --- a/frontend/src/components/redirects/SetupRedirect.tsx +++ b/frontend/src/components/redirects/SetupRedirect.tsx @@ -13,6 +13,13 @@ export function SetupRedirect() { return; } if (info.setupCompleted && info.running) { + if (location.pathname.startsWith("/setup/first-channel")) { + return; + } + if (location.pathname.startsWith("/setup/finish")) { + navigate("/setup/first-channel", { replace: true }); + return; + } navigate("/"); return; } diff --git a/frontend/src/hooks/useOnboardingData.ts b/frontend/src/hooks/useOnboardingData.ts index 318d4762..6f3ac777 100644 --- a/frontend/src/hooks/useOnboardingData.ts +++ b/frontend/src/hooks/useOnboardingData.ts @@ -45,8 +45,12 @@ export const useOnboardingData = (): UseOnboardingDataResponse => { !!albyMe && nodeConnectionInfo && albyMe?.keysend_pubkey === nodeConnectionInfo?.pubkey; - const hasChannel = - !hasChannelManagement || (hasChannelManagement && channels.length > 0); + const hasOpenedChannel = + !hasChannelManagement || + channels.some( + (channel) => + channel.active || ["online", "offline"].includes(channel.status) + ); const hasBackedUp = hasMnemonic === true && info && @@ -64,7 +68,7 @@ export const useOnboardingData = (): UseOnboardingDataResponse => { title: "Open your first channel", description: "Establish a new Lightning channel to enable fast and low-fee Bitcoin transactions.", - checked: hasChannel, + checked: hasOpenedChannel, to: "/channels/first", }, ] diff --git a/frontend/src/routes.tsx b/frontend/src/routes.tsx index 41f25ce0..d2511e7d 100644 --- a/frontend/src/routes.tsx +++ b/frontend/src/routes.tsx @@ -575,6 +575,31 @@ const routes: RouteObject[] = [ path: "finish", element: , }, + { + path: "first-channel", + handle: { crumb: () => "Your First Channel" }, + children: [ + { + index: true, + element: , + }, + { + path: "opening", + element: ( + + ), + }, + { + path: "opened", + element: ( + + ), + }, + ], + }, ], }, ], diff --git a/frontend/src/screens/channels/first/OpenedFirstChannel.tsx b/frontend/src/screens/channels/first/OpenedFirstChannel.tsx index 2061ffda..3ea195b8 100644 --- a/frontend/src/screens/channels/first/OpenedFirstChannel.tsx +++ b/frontend/src/screens/channels/first/OpenedFirstChannel.tsx @@ -2,7 +2,15 @@ import TickSVG from "public/images/illustrations/tick.svg"; import TwoColumnLayoutHeader from "src/components/TwoColumnLayoutHeader"; import { LinkButton } from "src/components/ui/custom/link-button"; -export function OpenedFirstChannel() { +type OpenedFirstChannelProps = { + ctaLabel?: string; + ctaTo?: string; +}; + +export function OpenedFirstChannel({ + ctaLabel = "Receive Your First Payment", + ctaTo = "/wallet/receive", +}: OpenedFirstChannelProps) { return (
- - Receive Your First Payment + + {ctaLabel}
); diff --git a/frontend/src/screens/channels/first/OpeningFirstChannel.tsx b/frontend/src/screens/channels/first/OpeningFirstChannel.tsx index 73c6ac20..3428effa 100644 --- a/frontend/src/screens/channels/first/OpeningFirstChannel.tsx +++ b/frontend/src/screens/channels/first/OpeningFirstChannel.tsx @@ -4,7 +4,13 @@ import { ChannelWaitingForConfirmations } from "src/components/channels/ChannelW import { useChannels } from "src/hooks/useChannels"; import { useSyncWallet } from "src/hooks/useSyncWallet"; -export function OpeningFirstChannel() { +type OpeningFirstChannelProps = { + openedPath?: string; +}; + +export function OpeningFirstChannel({ + openedPath = "/channels/first/opened", +}: OpeningFirstChannelProps) { useSyncWallet(); const { data: channels } = useChannels(true); const navigate = useNavigate(); @@ -13,9 +19,9 @@ export function OpeningFirstChannel() { React.useEffect(() => { if (firstChannel?.active) { - navigate("/channels/first/opened"); + navigate(openedPath); } - }, [firstChannel, navigate]); + }, [firstChannel, navigate, openedPath]); return ; } diff --git a/frontend/src/screens/setup/SetupFinish.tsx b/frontend/src/screens/setup/SetupFinish.tsx index f38da094..28680616 100644 --- a/frontend/src/screens/setup/SetupFinish.tsx +++ b/frontend/src/screens/setup/SetupFinish.tsx @@ -57,6 +57,12 @@ export function SetupFinish() { }; }, [loading]); + useEffect(() => { + if (info?.setupCompleted && info.running) { + navigate("/setup/first-channel", { replace: true }); + } + }, [info?.setupCompleted, info?.running, navigate]); + useEffect(() => { if (!info) { return;