-
Notifications
You must be signed in to change notification settings - Fork 168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework reconnect logic, add "Port could not be opened" modal #1513
Changes from 17 commits
7b425dc
57d6d0b
dd0ade5
c14e3e6
2af9d25
55d3d49
cf6d324
2f5c1ec
d969eaa
a97a5c8
25426d7
8033510
aec4123
359a4d6
1978995
0550206
a9505f7
4679bd9
623eb1f
33860bd
9398e4c
7ab936a
06c817b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
src/extension/vscode/client.ts | ||
src/application/components/ClientNotFoundModal.vscode.tsx | ||
src/application/components/Modals/ClientNotFoundModal.vscode.tsx |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,7 +2,6 @@ import { useEffect, useState } from "react"; | |
import type { ReactNode } from "react"; | ||
import type { TypedDocumentNode } from "@apollo/client"; | ||
import { useReactiveVar, gql, useQuery } from "@apollo/client"; | ||
import { useMachine } from "@xstate/react"; | ||
import { ErrorBoundary } from "react-error-boundary"; | ||
|
||
import { currentScreen, Screens } from "./components/Layouts/Navigation"; | ||
|
@@ -23,8 +22,8 @@ import IconGitHubSolid from "@apollo/icons/small/IconGitHubSolid.svg"; | |
import { SettingsModal } from "./components/Layouts/SettingsModal"; | ||
import Logo from "@apollo/icons/logos/LogoSymbol.svg"; | ||
import { BannerAlert } from "./components/BannerAlert"; | ||
import { devtoolsMachine } from "./machines/devtoolsMachine"; | ||
import { ClientNotFoundModal } from "./components/ClientNotFoundModal"; | ||
import { useDevToolsActorRef } from "./machines/devtoolsMachine"; | ||
import { Modals } from "./components/Modals/Modals"; | ||
import { ButtonGroup } from "./components/ButtonGroup"; | ||
import { | ||
GitHubIssueLink, | ||
|
@@ -41,6 +40,7 @@ import { useActorEvent } from "./hooks/useActorEvent"; | |
import { removeClient } from "."; | ||
import { PageError } from "./components/PageError"; | ||
import { SidebarLayout } from "./components/Layouts/SidebarLayout"; | ||
import { ExternalLink } from "./components/ExternalLink"; | ||
|
||
const APP_QUERY: TypedDocumentNode<AppQuery, AppQueryVariables> = gql` | ||
query AppQuery { | ||
|
@@ -74,26 +74,13 @@ ${SECTIONS.devtoolsVersion} | |
`; | ||
|
||
const stableEmptyClients: Required<AppQuery["clients"]> = []; | ||
const noop = () => {}; | ||
|
||
export const App = () => { | ||
const [snapshot, send] = useMachine( | ||
devtoolsMachine.provide({ | ||
actions: { | ||
resetStore: () => { | ||
apolloClient.clearStore().catch(noop); | ||
}, | ||
}, | ||
}) | ||
); | ||
const { | ||
data, | ||
client: apolloClient, | ||
refetch, | ||
} = useQuery(APP_QUERY, { errorPolicy: "all" }); | ||
const { send } = useDevToolsActorRef(); | ||
const { data, refetch } = useQuery(APP_QUERY, { errorPolicy: "all" }); | ||
|
||
useActorEvent("registerClient", () => { | ||
send({ type: "connect" }); | ||
send({ type: "client.register" }); | ||
// Unfortunately after we clear the store above, the query ends up "stuck" | ||
// holding onto the old list of clients even if we manually write a cache | ||
// update to properly resolve the list. Instead we refetch the list again to | ||
|
@@ -102,17 +89,12 @@ export const App = () => { | |
}); | ||
|
||
useActorEvent("clientTerminated", (message) => { | ||
// Disconnect if we are terminating the last client. We assume that 1 client | ||
// means we are terminating the selected client | ||
if (clients.length === 1) { | ||
send({ type: "disconnect" }); | ||
} | ||
|
||
send({ type: "client.terminated" }); | ||
removeClient(message.clientId); | ||
}); | ||
|
||
useActorEvent("pageNavigated", () => { | ||
send({ type: "disconnect" }); | ||
send({ type: "client.setCount", count: 0 }); | ||
}); | ||
|
||
const [settingsOpen, setSettingsOpen] = useState(false); | ||
|
@@ -149,31 +131,25 @@ export const App = () => { | |
|
||
useEffect(() => { | ||
if (clients.length) { | ||
send({ type: "connect" }); | ||
send({ type: "client.setCount", count: clients.length }); | ||
} | ||
}, [send, clients.length]); | ||
|
||
return ( | ||
<> | ||
<SettingsModal open={settingsOpen} onOpen={setSettingsOpen} /> | ||
<ClientNotFoundModal | ||
open={snapshot.context.modalOpen} | ||
onClose={() => send({ type: "closeModal" })} | ||
onRetry={() => send({ type: "retry" })} | ||
/> | ||
<Modals /> | ||
<BannerAlert /> | ||
<Tabs | ||
value={selected} | ||
onChange={(screen) => currentScreen(screen)} | ||
className="flex flex-col h-screen bg-primary dark:bg-primary-dark" | ||
> | ||
<div className="flex items-center border-b border-b-primary dark:border-b-primary-dark gap-4 px-4"> | ||
<a | ||
<ExternalLink | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
href="https://go.apollo.dev/c/docs" | ||
target="_blank" | ||
title="Apollo Client developer documentation" | ||
className="block" | ||
rel="noreferrer" | ||
> | ||
<Logo | ||
role="img" | ||
|
@@ -182,7 +158,7 @@ export const App = () => { | |
fill="currentColor" | ||
className="text-icon-primary dark:text-icon-primary-dark" | ||
/> | ||
</a> | ||
</ExternalLink> | ||
<Divider orientation="vertical" /> | ||
<Tabs.List className="-mb-px"> | ||
<Tabs.Trigger value={Screens.Queries}> | ||
|
@@ -197,21 +173,19 @@ export const App = () => { | |
<div className="ml-auto flex-1 justify-end flex items-center gap-2 h-full"> | ||
{client?.version && ( | ||
<GitHubReleaseHoverCard version={client.version}> | ||
<a | ||
<ExternalLink | ||
className="no-underline" | ||
href={ | ||
isSnapshotRelease(client.version) | ||
? `https://github.com/apollographql/apollo-client/pull/${parseSnapshotRelease(client.version).prNumber}` | ||
: `https://github.com/apollographql/apollo-client/releases/tag/v${client.version}` | ||
} | ||
target="_blank" | ||
rel="noreferrer" | ||
> | ||
<Badge variant="info" className="cursor-pointer"> | ||
Apollo Client <span className="lowercase">v</span> | ||
{client.version} | ||
</Badge> | ||
</a> | ||
</ExternalLink> | ||
</GitHubReleaseHoverCard> | ||
)} | ||
{clients.length > 1 && ( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { type ComponentProps, forwardRef } from "react"; | ||
|
||
export const ExternalLink = forwardRef< | ||
HTMLAnchorElement, | ||
ComponentProps<"a"> & { href: string } | ||
>((props, ref) => { | ||
return <a target="_blank" rel="noopener noreferrer" {...props} ref={ref} />; | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { type ComponentProps, forwardRef } from "react"; | ||
import { getPanelActor } from "../../extension/devtools/panelActor"; | ||
import { expectTypeOf } from "expect-type"; | ||
|
||
expectTypeOf<typeof import("./ExternalLink.jsx")>().toMatchTypeOf< | ||
typeof import("./ExternalLink.vscode.jsx") | ||
>(); | ||
|
||
/** | ||
* A link that opens links using a vscode command. | ||
* | ||
* Required because sometimes VSCode blocks links from being opened.: | ||
* | ||
* > Blocked opening 'https://...' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set. | ||
*/ | ||
export const ExternalLink = forwardRef< | ||
HTMLAnchorElement, | ||
ComponentProps<"a"> & { href: string } | ||
>((props, ref) => { | ||
return ( | ||
<a | ||
{...props} | ||
ref={ref} | ||
onClick={(e) => { | ||
if (props.onClick) { | ||
props.onClick(e); | ||
} | ||
if (e.isDefaultPrevented()) return; | ||
|
||
getPanelActor(window).send({ | ||
type: "vscode:openExternal", | ||
uri: props.href, | ||
}); | ||
|
||
e.nativeEvent.preventDefault(); | ||
}} | ||
/> | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
import type { ReactNode } from "react"; | ||
import { forwardRef } from "react"; | ||
import { ExternalLink } from "./ExternalLink"; | ||
|
||
declare const VERSION: string; | ||
|
||
|
@@ -21,7 +22,7 @@ export const SECTIONS = { | |
<!-- Please provide the version of \`@apollo/client\` you are using. --> | ||
`, | ||
devtoolsVersion: `### Apollo Client Devtools version | ||
${VERSION} | ||
${VERSION} (${__IS_FIREFOX__ ? "Firefox" : __IS_VSCODE__ ? "VSCode" : "Chrome"}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some additional info can be very helpful here to distinguish the different builds in bug reports. |
||
`, | ||
reproduction: `### Link to Reproduction | ||
<!-- Please provide a link to the reproduction of the issue. --> | ||
|
@@ -58,15 +59,13 @@ export const GitHubIssueLink = forwardRef< | |
} | ||
|
||
return ( | ||
<a | ||
<ExternalLink | ||
{...props} | ||
ref={ref} | ||
className={className} | ||
rel="noreferrer noopener" | ||
target="_blank" | ||
href={`https://github.com/apollographql/${repository}/issues/new?${params}`} | ||
> | ||
{children} | ||
</a> | ||
</ExternalLink> | ||
); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All modals live in that file now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we name this something like
ErrorModals
? Ideally we have some namespace that describes that these are the modals opened when the clients can't connect in some way.Otherwise it looks a little bit weird to have
SettingsModal
right next toModals
😂.