diff --git a/src/index.ts b/src/index.ts index 278fb3ff..4016ea9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,7 @@ import type { Options } from "@storybook/types"; import { type Configuration, getConfiguration, getGitInfo, type GitInfo } from "chromatic/node"; import { + ADDON_ID, CHROMATIC_BASE_URL, CONFIG_INFO, GIT_INFO, @@ -212,6 +213,8 @@ async function serverChannel(channel: Channel, options: Options & { configFile?: configInfoState.value = await getConfigInfo(configuration, options); }); + setInterval(() => channel.emit(`${ADDON_ID}/heartbeat`), 1000); + return channel; } diff --git a/src/manager.tsx b/src/manager.tsx index d5f4c3d1..4a330653 100644 --- a/src/manager.tsx +++ b/src/manager.tsx @@ -1,4 +1,6 @@ -import { addons, types } from "@storybook/manager-api"; +import { addons, type API } from "@storybook/manager-api"; +import { color } from "@storybook/theming"; +import { Addon_TypesEnum } from "@storybook/types"; import React from "react"; import { ADDON_ID, PANEL_ID, SIDEBAR_BOTTOM_ID, SIDEBAR_TOP_ID } from "./constants"; @@ -6,21 +8,48 @@ import { Panel } from "./Panel"; import { SidebarBottom } from "./SidebarBottom"; import { SidebarTop } from "./SidebarTop"; +let heartbeatTimeout: NodeJS.Timeout; +const expectHeartbeat = (api: API) => { + heartbeatTimeout = setTimeout(() => expectHeartbeat(api), 30000); +}; + addons.register(ADDON_ID, (api) => { addons.add(PANEL_ID, { - type: types.PANEL, + type: Addon_TypesEnum.PANEL, title: "Visual Tests", match: ({ viewMode }) => viewMode === "story", render: ({ active }) => , }); addons.add(SIDEBAR_TOP_ID, { - type: types.experimental_SIDEBAR_TOP, + type: Addon_TypesEnum.experimental_SIDEBAR_TOP, render: () => , }); addons.add(SIDEBAR_BOTTOM_ID, { - type: types.experimental_SIDEBAR_BOTTOM, + type: Addon_TypesEnum.experimental_SIDEBAR_BOTTOM, render: () => , }); + + const channel = api.getChannel(); + if (!channel) return; + + channel.on(`${ADDON_ID}/heartbeat`, () => { + clearTimeout(heartbeatTimeout); + heartbeatTimeout = setTimeout(() => { + api.addNotification({ + id: `${ADDON_ID}/connection-lost`, + content: { + headline: "Connection lost", + subHeadline: "Lost connection to the Storybook server. Try refreshing the page.", + }, + icon: { + name: "failed", + color: color.negative, + }, + // @ts-expect-error SB needs a proper API for no link + link: undefined, + }); + }, 3000); + }); });