diff --git a/client/web/src/components/login-toggle.tsx b/client/web/src/components/login-toggle.tsx index 360a0065c..d96f71ca3 100644 --- a/client/web/src/components/login-toggle.tsx +++ b/client/web/src/components/login-toggle.tsx @@ -1,5 +1,5 @@ import cx from "classnames" -import React, { useCallback, useState } from "react" +import React, { useCallback, useEffect, useState } from "react" import { AuthResponse, AuthType } from "src/hooks/auth" import { NodeData } from "src/hooks/node-data" import { ReactComponent as ChevronDown } from "src/icons/chevron-down.svg" @@ -81,6 +81,49 @@ function LoginPopoverContent({ auth: AuthResponse newSession: () => Promise }) { + /** + * canConnectOverTS indicates whether the current viewer + * is able to hit the node's web client that's being served + * at http://${node.IP}:5252. If false, this means that the + * viewer must connect to the correct tailnet before being + * able to sign in. + */ + const [canConnectOverTS, setCanConnectOverTS] = useState(false) + const [isRunningCheck, setIsRunningCheck] = useState(false) + + const checkTSConnection = useCallback(() => { + if (auth.viewerIdentity) { + setCanConnectOverTS(true) // already connected over ts + return + } + // Otherwise, test connection to the ts IP. + if (isRunningCheck) { + return // already checking + } + setIsRunningCheck(true) + fetch(`http://${node.IP}:5252/ok`, { mode: "no-cors" }) + .then(() => { + setIsRunningCheck(false) + setCanConnectOverTS(true) + }) + .catch(() => setIsRunningCheck(false)) + }, [ + auth.viewerIdentity, + isRunningCheck, + setCanConnectOverTS, + setIsRunningCheck, + ]) + + /** + * Checking connection for first time on page load. + * + * While not connected, we check again whenever the mouse + * enters the popover component, to pick up on the user + * leaving to turn on Tailscale then returning to the view. + * See `onMouseEnter` on the div below. + */ + useEffect(() => checkTSConnection(), []) + const handleSignInClick = useCallback(() => { if (auth.viewerIdentity) { newSession() @@ -93,7 +136,7 @@ function LoginPopoverContent({ }, [node.IP, auth.viewerIdentity, newSession]) return ( - <> +
{!auth.canManageNode ? "Viewing" : "Managing"} {auth.viewerIdentity && ` as ${auth.viewerIdentity.loginName}`} @@ -117,9 +160,15 @@ function LoginPopoverContent({ @@ -144,6 +193,6 @@ function LoginPopoverContent({
)} - +
) }