From 4b9fe040e6783dfc9fdf38b0c45047e398298c1e Mon Sep 17 00:00:00 2001 From: Andrew Ortwein Date: Fri, 8 Mar 2024 00:55:28 -0500 Subject: [PATCH 1/4] Persist the last user-selected mode name --- src/utils/useTests.ts | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/utils/useTests.ts b/src/utils/useTests.ts index ce5c1370..b4fa0b0b 100644 --- a/src/utils/useTests.ts +++ b/src/utils/useTests.ts @@ -1,6 +1,7 @@ -import { useGlobals, useGlobalTypes } from "@storybook/manager-api"; +import { useAddonState, useGlobals, useGlobalTypes } from "@storybook/manager-api"; import { useCallback, useState } from "react"; +import { ADDON_ID } from "../constants"; import { BrowserInfo, StoryTestFieldsFragment, TestMode, TestStatus } from "../gql/graphql"; type BrowserData = Pick; @@ -25,15 +26,28 @@ export function useTests(tests: StoryTestFieldsFragment[]) { const test = tests.find(({ status }) => status !== TestStatus.Passed) || tests[0]; return test?.comparisons[0]?.browser.id; }); + + const [userSelectedModeName, setUserSelectedModeName] = useAddonState( + `${ADDON_ID}/userSelectedModeName`, + "" + ); + const [selectedModeName, onSelectModeName] = useState(() => { const changed = tests.filter(({ status }) => status !== TestStatus.Passed); const candidates = changed.length ? changed : tests; - const test = candidates.find(({ mode }) => mode.globals.theme === theme) || candidates[0]; + // const test = candidates.find(({ mode }) => mode.globals.theme === theme) || candidates[0]; + const test = candidates.find(({ mode }) => mode.name === userSelectedModeName) || candidates[0]; return test?.mode.name; }); const onSelectBrowser = useCallback(({ id }: BrowserData) => onSelectBrowserId(id), []); - const onSelectMode = useCallback(({ name }: ModeData) => onSelectModeName(name), []); + const onSelectMode = useCallback( + ({ name }: ModeData) => { + setUserSelectedModeName(name); + onSelectModeName(name); + }, + [setUserSelectedModeName] + ); const selectedTest = tests.find(({ mode }) => mode.name === selectedModeName) || tests[0]; const selectedComparison = From 20f40dc5784ec9dcde8b949d37a3fa4ab6c6e5d8 Mon Sep 17 00:00:00 2001 From: Andrew Ortwein Date: Fri, 8 Mar 2024 01:12:26 -0500 Subject: [PATCH 2/4] Use useSharedState instead of useAddonState --- src/utils/useTests.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/utils/useTests.ts b/src/utils/useTests.ts index b4fa0b0b..f547e4ee 100644 --- a/src/utils/useTests.ts +++ b/src/utils/useTests.ts @@ -1,8 +1,8 @@ -import { useAddonState, useGlobals, useGlobalTypes } from "@storybook/manager-api"; +import { useGlobals, useGlobalTypes } from "@storybook/manager-api"; import { useCallback, useState } from "react"; -import { ADDON_ID } from "../constants"; import { BrowserInfo, StoryTestFieldsFragment, TestMode, TestStatus } from "../gql/graphql"; +import { useSharedState } from "./useSharedState"; type BrowserData = Pick; type ModeData = Pick; @@ -27,10 +27,7 @@ export function useTests(tests: StoryTestFieldsFragment[]) { return test?.comparisons[0]?.browser.id; }); - const [userSelectedModeName, setUserSelectedModeName] = useAddonState( - `${ADDON_ID}/userSelectedModeName`, - "" - ); + const [userSelectedModeName, setUserSelectedModeName] = useSharedState(""); const [selectedModeName, onSelectModeName] = useState(() => { const changed = tests.filter(({ status }) => status !== TestStatus.Passed); From 0b0c83ebe299a0a7072d1af5c01a8a398c672f99 Mon Sep 17 00:00:00 2001 From: Andrew Ortwein Date: Fri, 8 Mar 2024 01:19:53 -0500 Subject: [PATCH 3/4] Reset user selected mode if it doesn't apply to current story --- src/utils/useTests.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/utils/useTests.ts b/src/utils/useTests.ts index f547e4ee..e0c471fe 100644 --- a/src/utils/useTests.ts +++ b/src/utils/useTests.ts @@ -33,7 +33,11 @@ export function useTests(tests: StoryTestFieldsFragment[]) { const changed = tests.filter(({ status }) => status !== TestStatus.Passed); const candidates = changed.length ? changed : tests; // const test = candidates.find(({ mode }) => mode.globals.theme === theme) || candidates[0]; - const test = candidates.find(({ mode }) => mode.name === userSelectedModeName) || candidates[0]; + let test = candidates.find(({ mode }) => mode.name === userSelectedModeName); + if (!test) { + setUserSelectedModeName(""); + [test] = candidates; + } return test?.mode.name; }); From 8725b9b1dcf2492b887928cc5cf008f05a229058 Mon Sep 17 00:00:00 2001 From: Andrew Ortwein Date: Fri, 8 Mar 2024 17:48:11 -0500 Subject: [PATCH 4/4] Use shared state constants, clean up --- src/constants.ts | 2 ++ src/utils/useTests.ts | 51 ++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index f316b0e0..d415af52 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -21,6 +21,8 @@ export const IS_OUTDATED = `${ADDON_ID}/isOutdated`; export const START_BUILD = `${ADDON_ID}/startBuild`; export const STOP_BUILD = `${ADDON_ID}/stopBuild`; export const LOCAL_BUILD_PROGRESS = `${ADDON_ID}/localBuildProgress`; +export const SELECTED_MODE_NAME = `${ADDON_ID}/selectedModeName`; +export const SELECTED_BROWSER_ID = `${ADDON_ID}/selectedBrowserId`; export const REMOVE_ADDON = `${ADDON_ID}/removeAddon`; diff --git a/src/utils/useTests.ts b/src/utils/useTests.ts index e0c471fe..b500f6f5 100644 --- a/src/utils/useTests.ts +++ b/src/utils/useTests.ts @@ -1,6 +1,7 @@ import { useGlobals, useGlobalTypes } from "@storybook/manager-api"; import { useCallback, useState } from "react"; +import { SELECTED_BROWSER_ID, SELECTED_MODE_NAME } from "../constants"; import { BrowserInfo, StoryTestFieldsFragment, TestMode, TestStatus } from "../gql/graphql"; import { useSharedState } from "./useSharedState"; @@ -22,38 +23,38 @@ const useGlobalValue = (key: string) => { */ export function useTests(tests: StoryTestFieldsFragment[]) { const [theme, themeType] = useGlobalValue("theme"); - const [selectedBrowserId, onSelectBrowserId] = useState(() => { - const test = tests.find(({ status }) => status !== TestStatus.Passed) || tests[0]; - return test?.comparisons[0]?.browser.id; - }); + const [selectedBrowserId, setSelectedBrowserId] = useSharedState(SELECTED_BROWSER_ID); + const [selectedModeName, setSelectedModeName] = useSharedState(SELECTED_MODE_NAME); - const [userSelectedModeName, setUserSelectedModeName] = useSharedState(""); - - const [selectedModeName, onSelectModeName] = useState(() => { - const changed = tests.filter(({ status }) => status !== TestStatus.Passed); - const candidates = changed.length ? changed : tests; - // const test = candidates.find(({ mode }) => mode.globals.theme === theme) || candidates[0]; - let test = candidates.find(({ mode }) => mode.name === userSelectedModeName); - if (!test) { - setUserSelectedModeName(""); - [test] = candidates; - } - return test?.mode.name; - }); - - const onSelectBrowser = useCallback(({ id }: BrowserData) => onSelectBrowserId(id), []); + const onSelectBrowser = useCallback( + ({ id }: BrowserData) => setSelectedBrowserId(id), + [setSelectedBrowserId] + ); const onSelectMode = useCallback( - ({ name }: ModeData) => { - setUserSelectedModeName(name); - onSelectModeName(name); - }, - [setUserSelectedModeName] + ({ name }: ModeData) => setSelectedModeName(name), + [setSelectedModeName] ); - const selectedTest = tests.find(({ mode }) => mode.name === selectedModeName) || tests[0]; + // Select the test based on the following criteria (in order of priority): + // 1. The first test with changes detected and the mode name matches the one previously selected + // 2. The first test with changes detected + // 3. The first test where the mode name matches the one previously selected + // 4. The first test + const changedTests = tests.filter(({ status }) => status !== TestStatus.Passed); + const selectedTest = + changedTests.find(({ mode }) => mode.name === selectedModeName) || + changedTests[0] || + tests.find(({ mode }) => mode.name === selectedModeName) || + tests[0]; + if (selectedTest?.mode.name !== selectedModeName) { + setSelectedModeName(selectedTest?.mode.name); + } const selectedComparison = selectedTest?.comparisons.find(({ browser }) => browser.id === selectedBrowserId) || selectedTest?.comparisons[0]; + if (selectedComparison?.browser.id !== selectedBrowserId) { + setSelectedBrowserId(selectedComparison?.browser.id); + } return { modeOrder: themeType?.toolbar?.items?.map((item: { title: string }) => item.title),