From 21fe557157c56a628d75ac09f4ffda92ee1caa15 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Thu, 24 Oct 2024 12:49:04 +0200 Subject: [PATCH] Use the debug info port to check the port forwarding --- src/components/Debug/Debug.tsx | 30 +--- .../OnBoarding/OnBoardingStepThree.css | 5 + .../OnBoarding/OnBoardingStepThree.tsx | 148 +++++++++++------- src/hooks/useDebug.ts | 31 ++++ src/hooks/usePortForwarding.tsx | 17 +- src/routes/index.css | 4 + src/routes/index.tsx | 5 +- src/utils/debug.ts | 23 +++ src/utils/echo.ts | 2 +- src/utils/onboarding.ts | 9 ++ 10 files changed, 188 insertions(+), 86 deletions(-) create mode 100644 src/hooks/useDebug.ts create mode 100644 src/utils/debug.ts create mode 100644 src/utils/onboarding.ts diff --git a/src/components/Debug/Debug.tsx b/src/components/Debug/Debug.tsx index 339724b..9036a8b 100644 --- a/src/components/Debug/Debug.tsx +++ b/src/components/Debug/Debug.tsx @@ -1,32 +1,10 @@ -import { useQuery } from "@tanstack/react-query"; -import { CodexSdk } from "../../sdk/codex"; -import { Promises } from "../../utils/promises"; import { Spinner } from "@codex-storage/marketplace-ui-components"; +import { useDebug } from "../../hooks/useDebug"; + +const throwOnError = true; export function Debug() { - const { data, isPending } = useQuery({ - queryFn: () => - CodexSdk.debug() - .info() - .then((s) => Promises.rejectOnError(s)), - - queryKey: ["debug"], - - // No need to retry because if the connection to the node - // is back again, all the queries will be invalidated. - retry: false, - - // The client node should be local, so display the cache value while - // making a background request looks good. - staleTime: 0, - - // Refreshing when focus returns can be useful if a user comes back - // to the UI after performing an operation in the terminal. - refetchOnWindowFocus: true, - - // Throw the error to the error boundary - throwOnError: true, - }); + const { data, isPending } = useDebug(throwOnError); if (isPending) { return ( diff --git a/src/components/OnBoarding/OnBoardingStepThree.css b/src/components/OnBoarding/OnBoardingStepThree.css index 6f38f14..0d49e69 100644 --- a/src/components/OnBoarding/OnBoardingStepThree.css +++ b/src/components/OnBoarding/OnBoardingStepThree.css @@ -38,6 +38,11 @@ margin-bottom: 0.5rem; } +.onboarding-codex { + margin-top: 1rem; + padding-left: 1rem; +} + @keyframes rotate { from { transform: rotate(0deg); /* Start at 0 degrees */ diff --git a/src/components/OnBoarding/OnBoardingStepThree.tsx b/src/components/OnBoarding/OnBoardingStepThree.tsx index 06ac5d3..c104a8b 100644 --- a/src/components/OnBoarding/OnBoardingStepThree.tsx +++ b/src/components/OnBoarding/OnBoardingStepThree.tsx @@ -4,6 +4,7 @@ import "./OnBoardingStepThree.css"; import { usePortForwarding } from "../../hooks/usePortForwarding"; import { useCodexConnection } from "../../hooks/useCodexConnection"; import { + Alert, ButtonIcon, Input, SimpleText, @@ -12,28 +13,33 @@ import { useEffect, useState } from "react"; import { CodexSdk } from "../../sdk/codex"; import { useQueryClient } from "@tanstack/react-query"; import { usePersistence } from "../../hooks/usePersistence"; +import { useDebug } from "../../hooks/useDebug"; +import { DebugUtils } from "../../utils/debug"; type Props = { online: boolean; onStepValid: (valid: boolean) => void; }; +const throwOnError = false; +const defaultPort = 8070; + export function OnBoardingStepThree({ online, onStepValid }: Props) { - const portForwarding = usePortForwarding(online); - const codex = useCodexConnection(); - const persistence = usePersistence(codex.enabled); + const codex = useDebug(throwOnError); + const portForwarding = usePortForwarding(codex.data); + const persistence = usePersistence(codex.isSuccess); const [url, setUrl] = useState(CodexSdk.url); const queryClient = useQueryClient(); useEffect(() => { - onStepValid(online && portForwarding.enabled && codex.enabled); - }, [portForwarding.enabled, codex.enabled, onStepValid, online]); + onStepValid(online && portForwarding.enabled && codex.isSuccess); + }, [portForwarding.enabled, codex.isSuccess, onStepValid, online]); useEffect(() => { - if (codex.enabled) { + if (codex.isSuccess) { persistence.refetch(); } - }, [codex.enabled]); + }, [codex.isSuccess]); const onChange = (e: React.FormEvent) => { const value = e.currentTarget.value; @@ -49,9 +55,22 @@ export function OnBoardingStepThree({ online, onStepValid }: Props) { const InternetIcon = online ? CheckIcon : X; const PortForWarningIcon = portForwarding.enabled ? CheckIcon : X; - const CodexIcon = codex.enabled ? CheckIcon : X; + const CodexIcon = codex.isSuccess ? CheckIcon : X; const PersistenceIcon = persistence.enabled ? CheckIcon : ShieldAlert; + let hasPortForwarningWarning = false; + let portValue = 0; + + if (codex.isSuccess && codex.data) { + const port = DebugUtils.getTcpPort(codex.data); + if (port.error === false && port.data !== defaultPort) { + hasPortForwarningWarning = true; + } + if (!port.error) { + portValue = port.data; + } + } + return (
@@ -102,6 +121,14 @@ export function OnBoardingStepThree({ online, onStepValid }: Props) { Status indicator for port forwarding activation. + {portValue && ( + <> +
+ + TCP Port detected: {portValue}. + + + )}
{!portForwarding.enabled && (
-
- Codex

+
+
- -
- -
-
-

Marketplace

- - Status indicator for the marketplace on the Codex node. - + ["onboarding-check"], + ["onboarding-check--valid", persistence.enabled] + )}> + +
+
+

Marketplace

+ + Status indicator for the marketplace on the Codex node. + +
+ + {hasPortForwarningWarning && ( + + + It seems like you are using a different port than the default one ( + {defaultPort}). Be sure the port forwarning is enabled for the port + you are running. + + + )}
); } diff --git a/src/hooks/useDebug.ts b/src/hooks/useDebug.ts new file mode 100644 index 0000000..1b9d08a --- /dev/null +++ b/src/hooks/useDebug.ts @@ -0,0 +1,31 @@ +import { useQuery } from "@tanstack/react-query"; +import { CodexSdk } from "../sdk/codex"; +import { Promises } from "../utils/promises"; + +export function useDebug(throwOnError: boolean) { + const { data, isError, isPending, refetch, isSuccess } = useQuery({ + queryFn: () => + CodexSdk.debug() + .info() + .then((s) => Promises.rejectOnError(s)), + + queryKey: ["debug"], + + // No need to retry because if the connection to the node + // is back again, all the queries will be invalidated. + retry: false, + + // The client node should be local, so display the cache value while + // making a background request looks good. + staleTime: 0, + + // Refreshing when focus returns can be useful if a user comes back + // to the UI after performing an operation in the terminal. + refetchOnWindowFocus: true, + + // Throw the error to the error boundary + throwOnError, + }); + + return { data, isPending, isError, isSuccess, refetch }; +} diff --git a/src/hooks/usePortForwarding.tsx b/src/hooks/usePortForwarding.tsx index c68e8d1..0c66fec 100644 --- a/src/hooks/usePortForwarding.tsx +++ b/src/hooks/usePortForwarding.tsx @@ -1,19 +1,28 @@ import { useQuery } from "@tanstack/react-query"; import { Echo } from "../utils/echo"; import { Errors } from "../utils/errors"; +import { CodexDebugInfo } from "@codex-storage/sdk-js"; +import { DebugUtils } from "../utils/debug"; type PortForwardingResponse = { reachable: boolean }; -export function usePortForwarding(online: boolean) { +export function usePortForwarding(info: CodexDebugInfo | undefined) { const { data, isFetching, refetch } = useQuery({ - queryFn: (): Promise => - Echo.portForwarding().catch((e) => Errors.report(e)), + queryFn: (): Promise => { + const port = DebugUtils.getTcpPort(info!); + if (port.error) { + Errors.report(port); + return Promise.resolve({ reachable: false }); + } else { + return Echo.portForwarding(port.data).catch((e) => Errors.report(e)); + } + }, queryKey: ["port-forwarding"], initialData: { reachable: false }, // Enable only when the use has an internet connection - enabled: !!online, + enabled: !!info, // No need to retry because we provide a retry button retry: false, diff --git a/src/routes/index.css b/src/routes/index.css index 4329ad9..164581f 100644 --- a/src/routes/index.css +++ b/src/routes/index.css @@ -138,6 +138,10 @@ justify-content: space-between; } +.index-column-section { + max-width: 450px; +} + .index-column-section:not(:first-child) { flex: 1; } diff --git a/src/routes/index.tsx b/src/routes/index.tsx index a0a9ef3..e0b5fe0 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -12,6 +12,7 @@ import { OnBoardingStepThree } from "../components/OnBoarding/OnBoardingStepThre import { attributes } from "../utils/attributes"; import { CodexLogo } from "../components/CodexLogo/CodexLogo"; import { OnBoardingImage } from "../components/OnBoarding/OnBoardingImage"; +import { OnBoardingUtils } from "../utils/onboarding"; export const Route = createFileRoute("/")({ component: Index, @@ -24,7 +25,7 @@ export const Route = createFileRoute("/")({ function Index() { const [isStepValid, setIsStepValid] = useState(true); - const [step, setStep] = useState(0); + const [step, setStep] = useState(OnBoardingUtils.getStep()); const online = useNetwork(); const navigate = useNavigate({ from: "/" }); const onStepValid = (valid: boolean) => setIsStepValid(valid); @@ -39,6 +40,8 @@ function Index() { return; } + OnBoardingUtils.setStep(step + 1); + setStep(step + 1); setIsStepValid(false); }; diff --git a/src/utils/debug.ts b/src/utils/debug.ts new file mode 100644 index 0000000..3e4ca68 --- /dev/null +++ b/src/utils/debug.ts @@ -0,0 +1,23 @@ +import { CodexDebugInfo, CodexError, SafeValue } from "@codex-storage/sdk-js"; + +export const DebugUtils = { + getTcpPort(info: CodexDebugInfo): SafeValue { + if (info.addrs.length === 0) { + return { error: true, data: new CodexError("Not existing address") } + } + + const parts = info.addrs[0].split("/") + + if (parts.length < 2) { + return { error: true, data: new CodexError("Address misformated") } + } + + const port = parseInt(parts[parts.length - 1], 10) + + if (isNaN(port)) { + return { error: true, data: new CodexError("Port misformated") } + } + + return { error: false, data: port } + } +} \ No newline at end of file diff --git a/src/utils/echo.ts b/src/utils/echo.ts index 4577f5c..e582a60 100644 --- a/src/utils/echo.ts +++ b/src/utils/echo.ts @@ -1,5 +1,5 @@ export const Echo = { - portForwarding: () => fetch(import.meta.env.VITE_GEO_IP_URL + "/port/8070") + portForwarding: (port: number) => fetch(import.meta.env.VITE_GEO_IP_URL + "/port/" + port) .then((res) => res.json()) } \ No newline at end of file diff --git a/src/utils/onboarding.ts b/src/utils/onboarding.ts new file mode 100644 index 0000000..e09adae --- /dev/null +++ b/src/utils/onboarding.ts @@ -0,0 +1,9 @@ +export const OnBoardingUtils = { + getStep() { + return parseInt(localStorage.getItem("onboarding-step") || "0", 10) + }, + + setStep(step: number) { + localStorage.setItem("onboarding-step", step.toString()) + } +} \ No newline at end of file