From 8c89a9d3fdfd2368bc6712e340d4d1b9e2a4b1bd Mon Sep 17 00:00:00 2001 From: Todd Schiller Date: Fri, 21 Jun 2024 10:31:25 -0400 Subject: [PATCH] Rename extension actions --- ...eRecipe.test.ts => useActivateMod.test.ts} | 42 +++++----- ...useActivateRecipe.ts => useActivateMod.ts} | 73 +++++++++-------- src/background/deploymentUpdater.ts | 2 +- src/background/messenger/api.ts | 4 +- src/background/messenger/registration.ts | 4 +- src/background/modUpdater.ts | 4 +- .../activateMod/ActivateModCard.test.tsx | 12 +-- .../pages/activateMod/ActivateModCard.tsx | 4 +- .../pages/deployments/activateDeployments.ts | 8 +- .../mods/hooks/useModsPageActions.test.tsx | 10 +-- .../ConvertToModModalBody.tsx | 6 +- .../pages/mods/utils/useReinstall.test.ts | 4 +- .../pages/mods/utils/useReinstall.ts | 4 +- src/mods/hooks/useDeactivateAction.ts | 6 +- src/mods/useModViewItems.test.tsx | 6 +- src/mods/useMods.test.ts | 8 +- .../hooks/useCreateModFromModComponent.ts | 2 +- src/pageEditor/hooks/useDeactivateMod.tsx | 2 +- .../useRemoveModComponentFromStorage.test.ts | 16 ++-- .../useRemoveModComponentFromStorage.tsx | 20 ++--- src/pageEditor/hooks/useSaveMod.ts | 4 +- src/pageEditor/panes/save/useSavingWizard.ts | 6 +- .../sidebar/DraftModComponentListItem.tsx | 4 +- .../sidebar/modals/AddToRecipeModal.tsx | 2 +- .../activateMod/ActivateModPanel.test.tsx | 8 +- src/sidebar/activateMod/ActivateModPanel.tsx | 4 +- .../activateMod/ActivateMultipleModsPanel.tsx | 6 +- src/store/extensionsSlice.ts | 80 +++++++++++++------ .../sessionChangesListenerMiddleware.ts | 8 +- src/store/uninstallUtils.ts | 41 +++++----- src/tsconfig.strictNullChecks.json | 2 +- 31 files changed, 220 insertions(+), 182 deletions(-) rename src/activation/{useActivateRecipe.test.ts => useActivateMod.test.ts} (89%) rename src/activation/{useActivateRecipe.ts => useActivateMod.ts} (72%) diff --git a/src/activation/useActivateRecipe.test.ts b/src/activation/useActivateMod.test.ts similarity index 89% rename from src/activation/useActivateRecipe.test.ts rename to src/activation/useActivateMod.test.ts index 7c4209b3ad..35acba279c 100644 --- a/src/activation/useActivateRecipe.test.ts +++ b/src/activation/useActivateMod.test.ts @@ -17,11 +17,11 @@ import { type WizardValues } from "@/activation/wizardTypes"; import { renderHook } from "@/pageEditor/testHelpers"; -import useActivateRecipe from "./useActivateRecipe"; +import useActivateMod from "./useActivateMod"; import { validateRegistryId } from "@/types/helpers"; import { type StarterBrickDefinitionLike } from "@/starterBricks/types"; import { type ContextMenuDefinition } from "@/starterBricks/contextMenu/types"; -import { uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallMod } from "@/store/uninstallUtils"; import { type ModDefinition } from "@/types/modDefinitionTypes"; import extensionsSlice from "@/store/extensionsSlice"; import { type InnerDefinitions } from "@/types/registryTypes"; @@ -43,7 +43,7 @@ import type MockAdapter from "axios-mock-adapter"; jest.mock("@/contentScript/messenger/api"); const checkPermissionsMock = jest.mocked(checkModDefinitionPermissions); -const uninstallRecipeMock = jest.mocked(uninstallRecipe); +const uninstallModMock = jest.mocked(uninstallMod); const reactivateEveryTabMock = jest.mocked(reactivateEveryTab); function setupInputs(): { @@ -56,13 +56,13 @@ function setupInputs(): { optionsArgs: {}, }; - const extensionPointId = validateRegistryId("test/starter-brick-1"); + const starterBrickId = validateRegistryId("test/starter-brick-1"); const modComponentDefinition = modComponentDefinitionFactory({ - id: extensionPointId, + id: starterBrickId, }); const starterBrickDefinition = starterBrickDefinitionFactory({ metadata: metadataFactory({ - id: extensionPointId, + id: starterBrickId, name: "Text Starter Brick 1", }), definition: { @@ -82,7 +82,7 @@ function setupInputs(): { const modDefinition = defaultModDefinitionFactory({ extensionPoints: [modComponentDefinition], definitions: { - [extensionPointId]: starterBrickDefinition, + [starterBrickId]: starterBrickDefinition, } as unknown as InnerDefinitions, }); @@ -92,7 +92,7 @@ function setupInputs(): { }; } -function setRecipeHasPermissions(hasPermissions: boolean) { +function setModHasPermissions(hasPermissions: boolean) { checkPermissionsMock.mockResolvedValue({ hasPermissions, // The exact permissions don't matter because we're mocking the check also @@ -104,20 +104,20 @@ function setUserAcceptedPermissions(accepted: boolean) { jest.mocked(browser.permissions.request).mockResolvedValue(accepted); } -describe("useActivateRecipe", () => { +describe("useActivateMod", () => { beforeEach(() => { reactivateEveryTabMock.mockClear(); }); it("returns error if permissions are not granted", async () => { const { formValues, modDefinition } = setupInputs(); - setRecipeHasPermissions(false); + setModHasPermissions(false); setUserAcceptedPermissions(false); const { result: { current: activateRecipe }, getReduxStore, - } = renderHook(() => useActivateRecipe("marketplace"), { + } = renderHook(() => useActivateMod("marketplace"), { setupRedux(dispatch, { store }) { jest.spyOn(store, "dispatch"); }, @@ -131,19 +131,19 @@ describe("useActivateRecipe", () => { const { dispatch } = getReduxStore(); expect(dispatch).not.toHaveBeenCalled(); - expect(uninstallRecipeMock).not.toHaveBeenCalled(); + expect(uninstallModMock).not.toHaveBeenCalled(); expect(reactivateEveryTabMock).not.toHaveBeenCalled(); }); it("ignores permissions if flag set", async () => { const { formValues, modDefinition } = setupInputs(); - setRecipeHasPermissions(false); + setModHasPermissions(false); setUserAcceptedPermissions(false); const { result: { current: activateRecipe }, } = renderHook( - () => useActivateRecipe("marketplace", { checkPermissions: false }), + () => useActivateMod("marketplace", { checkPermissions: false }), { setupRedux(dispatch, { store }) { jest.spyOn(store, "dispatch"); @@ -159,14 +159,14 @@ describe("useActivateRecipe", () => { it("calls uninstallRecipe, installs to extensionsSlice, and calls reactivateEveryTab, if permissions are granted", async () => { const { formValues, modDefinition } = setupInputs(); - setRecipeHasPermissions(false); + setModHasPermissions(false); setUserAcceptedPermissions(true); const { result: { current: activateRecipe }, getReduxStore, act, - } = renderHook(() => useActivateRecipe("extensionConsole"), { + } = renderHook(() => useActivateMod("extensionConsole"), { setupRedux(dispatch, { store }) { jest.spyOn(store, "dispatch"); }, @@ -185,7 +185,7 @@ describe("useActivateRecipe", () => { const { dispatch } = getReduxStore(); - expect(uninstallRecipeMock).toHaveBeenCalledWith( + expect(uninstallModMock).toHaveBeenCalledWith( modDefinition.metadata.id, expect.toBeArray(), dispatch, @@ -230,7 +230,7 @@ describe("useActivateRecipe", () => { uiSchema: inputModDefinition.options?.uiSchema, }, }; - setRecipeHasPermissions(true); + setModHasPermissions(true); setUserAcceptedPermissions(true); const createdDatabase = databaseFactory({ name: databaseName }); @@ -240,7 +240,7 @@ describe("useActivateRecipe", () => { result: { current: activateRecipe }, getReduxStore, act, - } = renderHook(() => useActivateRecipe("marketplace"), { + } = renderHook(() => useActivateMod("marketplace"), { setupRedux(dispatch, { store }) { jest.spyOn(store, "dispatch"); }, @@ -307,13 +307,13 @@ describe("useActivateRecipe", () => { format: "preview", }, ); - setRecipeHasPermissions(true); + setModHasPermissions(true); const errorMessage = "Error creating database"; const { result: { current: activateRecipe }, act, - } = renderHook(() => useActivateRecipe("marketplace"), { + } = renderHook(() => useActivateMod("marketplace"), { setupRedux(dispatch, { store }) { jest.spyOn(store, "dispatch"); }, diff --git a/src/activation/useActivateRecipe.ts b/src/activation/useActivateMod.ts similarity index 72% rename from src/activation/useActivateRecipe.ts rename to src/activation/useActivateMod.ts index 0d9b5b552e..d913cfb830 100644 --- a/src/activation/useActivateRecipe.ts +++ b/src/activation/useActivateMod.ts @@ -22,7 +22,7 @@ import { useDispatch, useSelector } from "react-redux"; import extensionsSlice from "@/store/extensionsSlice"; import reportEvent from "@/telemetry/reportEvent"; import { getErrorMessage } from "@/errors/errorHelpers"; -import { uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallMod } from "@/store/uninstallUtils"; import { selectActivatedModComponents } from "@/store/extensionsSelectors"; import { ensurePermissionsFromUserGesture } from "@/permissions/permissionsUtils"; import { checkModDefinitionPermissions } from "@/modDefinitions/modDefinitionPermissionsHelpers"; @@ -36,47 +36,50 @@ export type ActivateResult = { error?: string; }; -export type ActivateRecipeFormCallback = +export type ActivateModFormCallback = /** - * Callback for activating a recipe. + * Callback for activating a mod. * - * @param formValues The form values for recipe configuration options - * @param recipe The recipe definition to install + * @param formValues The form values for mod configuration options + * @param modDefinition The mod definition to activate * @returns a promise that resolves to an ActivateResult */ - (formValues: WizardValues, recipe: ModDefinition) => Promise; + ( + formValues: WizardValues, + modDefinition: ModDefinition, + ) => Promise; type ActivationSource = "marketplace" | "extensionConsole"; -function selectActivateEventData(recipe: ModDefinition) { +function selectActivateEventData(modDefinition: ModDefinition) { return { - blueprintId: recipe.metadata.id, - extensions: recipe.extensionPoints.map((x) => x.label), + blueprintId: modDefinition.metadata.id, + extensions: modDefinition.extensionPoints.map((x) => x.label), }; } /** - * React hook to install a recipe. + * React hook to install a mod. * * Prompts the user to grant permissions if PixieBrix does not already have the required permissions. * @param source The source of the activation, only used for reporting purposes - * @param checkPermissions Whether to check for permissions before activating the recipe - * @returns A callback that can be used to activate a recipe - * @see useActivateRecipeWizard + * @param checkPermissions Whether to check for permissions before activating the mod + * @returns A callback that can be used to activate a mod + * @see useActivateModWizard */ -function useActivateRecipe( +function useActivateMod( source: ActivationSource, { checkPermissions = true }: { checkPermissions?: boolean } = {}, -): ActivateRecipeFormCallback { +): ActivateModFormCallback { const dispatch = useDispatch(); - const extensions = useSelector(selectActivatedModComponents); + const activatedModComponents = useSelector(selectActivatedModComponents); const [createDatabase] = useCreateDatabaseMutation(); return useCallback( - async (formValues: WizardValues, recipe: ModDefinition) => { - const isReactivate = extensions.some( - (extension) => extension._recipe?.id === recipe.metadata.id, + async (formValues: WizardValues, modDefinition: ModDefinition) => { + const isReactivate = activatedModComponents.some( + (x) => x._recipe?.id === modDefinition.metadata.id, ); if (source === "extensionConsole") { @@ -86,7 +89,7 @@ function useActivateRecipe( // console, to distinguish that from the workshop. // It's being kept to keep our metrics history clean. reportEvent(Events.MARKETPLACE_ACTIVATE, { - ...selectActivateEventData(recipe), + ...selectActivateEventData(modDefinition), reactivate: isReactivate, }); } @@ -96,14 +99,14 @@ function useActivateRecipe( ); try { - const recipePermissions = await checkModDefinitionPermissions( - recipe, + const modPermissions = await checkModDefinitionPermissions( + modDefinition, configuredDependencies, ); if (checkPermissions) { const isPermissionsAcceptedByUser = - await ensurePermissionsFromUserGesture(recipePermissions); + await ensurePermissionsFromUserGesture(modPermissions); if (!isPermissionsAcceptedByUser) { if (source === "extensionConsole") { @@ -113,7 +116,7 @@ function useActivateRecipe( // console, to distinguish that from the workshop. // It's being kept like this so our metrics history stays clean. reportEvent(Events.MARKETPLACE_REJECT_PERMISSIONS, { - ...selectActivateEventData(recipe), + ...selectActivateEventData(modDefinition), reactivate: isReactivate, }); } @@ -128,7 +131,7 @@ function useActivateRecipe( const { optionsArgs, integrationDependencies } = formValues; await autoCreateDatabaseOptionsArgsInPlace( - recipe, + modDefinition, optionsArgs, async (args) => { const result = await createDatabase(args).unwrap(); @@ -136,19 +139,23 @@ function useActivateRecipe( }, ); - const recipeExtensions = extensions.filter( - (extension) => extension._recipe?.id === recipe.metadata.id, + const existingModComponents = activatedModComponents.filter( + (x) => x._recipe?.id === modDefinition.metadata.id, ); - await uninstallRecipe(recipe.metadata.id, recipeExtensions, dispatch); + await uninstallMod( + modDefinition.metadata.id, + existingModComponents, + dispatch, + ); dispatch( extensionsSlice.actions.activateMod({ - modDefinition: recipe, + modDefinition, configuredDependencies: integrationDependencies, optionsArgs, screen: source, - isReactivate: recipeExtensions.length > 0, + isReactivate: existingModComponents.length > 0, }), ); @@ -156,7 +163,7 @@ function useActivateRecipe( } catch (error) { const errorMessage = getErrorMessage(error); - console.error(`Error activating mod: ${recipe.metadata.id}`, { + console.error(`Error activating mod: ${modDefinition.metadata.id}`, { error, }); @@ -172,8 +179,8 @@ function useActivateRecipe( success: true, }; }, - [createDatabase, dispatch, extensions, source], + [createDatabase, dispatch, activatedModComponents, source], ); } -export default useActivateRecipe; +export default useActivateMod; diff --git a/src/background/deploymentUpdater.ts b/src/background/deploymentUpdater.ts index 6c70858372..c2e304494c 100644 --- a/src/background/deploymentUpdater.ts +++ b/src/background/deploymentUpdater.ts @@ -103,7 +103,7 @@ function deactivateModComponentFromStates( ): { options: ModComponentState; editor: EditorState } { const options = optionsReducer( optionsState, - optionsActions.removeExtension({ extensionId: modComponentId }), + optionsActions.removeModComponent({ modComponentId }), ); const editor = editorState ? editorReducer( diff --git a/src/background/messenger/api.ts b/src/background/messenger/api.ts index f1940c7a7b..47d8b0bf47 100644 --- a/src/background/messenger/api.ts +++ b/src/background/messenger/api.ts @@ -143,8 +143,8 @@ export const contextMenus = { preload: getMethod("PRELOAD_CONTEXT_MENUS", bg), }; -export const removeExtensionForEveryTab = getNotifier( - "REMOVE_EXTENSION_EVERY_TAB", +export const removeModComponentForEveryTab = getNotifier( + "REMOVE_MOD_COMPONENT_EVERY_TAB", bg, ); export const clearServiceCache = getMethod("CLEAR_SERVICE_CACHE", bg); diff --git a/src/background/messenger/registration.ts b/src/background/messenger/registration.ts index b62e6fc44b..c2cbf0ca76 100644 --- a/src/background/messenger/registration.ts +++ b/src/background/messenger/registration.ts @@ -142,7 +142,7 @@ declare global { REQUEST_RUN_IN_OTHER_TABS: typeof requestRunInOtherTabs; REQUEST_RUN_IN_ALL_FRAMES: typeof requestRunInAllFrames; PRELOAD_CONTEXT_MENUS: typeof preloadContextMenus; - REMOVE_EXTENSION_EVERY_TAB: typeof removeExtensionForEveryTab; + REMOVE_MOD_COMPONENT_EVERY_TAB: typeof removeExtensionForEveryTab; INSTALL_STARTER_BLUEPRINTS: typeof installStarterBlueprints; } } @@ -212,7 +212,7 @@ export default function registerMessenger(): void { REQUEST_RUN_IN_OTHER_TABS: requestRunInOtherTabs, REQUEST_RUN_IN_ALL_FRAMES: requestRunInAllFrames, PRELOAD_CONTEXT_MENUS: preloadContextMenus, - REMOVE_EXTENSION_EVERY_TAB: removeExtensionForEveryTab, + REMOVE_MOD_COMPONENT_EVERY_TAB: removeExtensionForEveryTab, INSTALL_STARTER_BLUEPRINTS: installStarterBlueprints, }); } diff --git a/src/background/modUpdater.ts b/src/background/modUpdater.ts index e7ab66d951..a1e59323b7 100644 --- a/src/background/modUpdater.ts +++ b/src/background/modUpdater.ts @@ -153,7 +153,9 @@ function deactivateModComponent( newOptionsState = extensionsSlice.reducer( newOptionsState, - extensionsSlice.actions.removeExtension({ extensionId: modComponent.id }), + extensionsSlice.actions.removeModComponent({ + modComponentId: modComponent.id, + }), ); newEditorState = editorSlice.reducer( diff --git a/src/extensionConsole/pages/activateMod/ActivateModCard.test.tsx b/src/extensionConsole/pages/activateMod/ActivateModCard.test.tsx index 65e592de33..2df1f58a07 100644 --- a/src/extensionConsole/pages/activateMod/ActivateModCard.test.tsx +++ b/src/extensionConsole/pages/activateMod/ActivateModCard.test.tsx @@ -35,9 +35,9 @@ import { defaultModDefinitionFactory, } from "@/testUtils/factories/modDefinitionFactories"; import { metadataFactory } from "@/testUtils/factories/metadataFactory"; -import useActivateRecipe, { - type ActivateRecipeFormCallback, -} from "@/activation/useActivateRecipe"; +import useActivateMod, { + type ActivateModFormCallback, +} from "@/activation/useActivateMod"; import { minimalSchemaFactory } from "@/utils/schemaUtils"; registerDefaultWidgets(); @@ -46,11 +46,11 @@ const testModId = validateRegistryId("@test/mod"); const activateModCallbackMock = // eslint-disable-next-line no-restricted-syntax -- TODO - jest.fn() as jest.MockedFunction; + jest.fn() as jest.MockedFunction; -jest.mock("@/activation/useActivateRecipe.ts"); +jest.mock("@/activation/useActivateMod.ts"); -const activateRecipeHookMock = jest.mocked(useActivateRecipe); +const activateRecipeHookMock = jest.mocked(useActivateMod); jest.mock("@/extensionConsole/pages/useRegistryIdParam", () => ({ __esModule: true, diff --git a/src/extensionConsole/pages/activateMod/ActivateModCard.tsx b/src/extensionConsole/pages/activateMod/ActivateModCard.tsx index dbc49aa2de..71c44da854 100644 --- a/src/extensionConsole/pages/activateMod/ActivateModCard.tsx +++ b/src/extensionConsole/pages/activateMod/ActivateModCard.tsx @@ -32,7 +32,7 @@ import { } from "@/data/service/api"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faMagic } from "@fortawesome/free-solid-svg-icons"; -import useActivateRecipe from "@/activation/useActivateRecipe"; +import useActivateMod from "@/activation/useActivateMod"; import useMilestones from "@/hooks/useMilestones"; import Form, { type OnSubmit, type RenderBody } from "@/components/form/Form"; import { type WizardValues } from "@/activation/wizardTypes"; @@ -91,7 +91,7 @@ const ActivateModCard: React.FC = () => { error: wizardError, } = useActivateModWizard(mod); - const activateMod = useActivateRecipe("extensionConsole"); + const activateMod = useActivateMod("extensionConsole"); const [activationError, setActivationError] = useState(); const [createMilestone] = useCreateMilestoneMutation(); diff --git a/src/extensionConsole/pages/deployments/activateDeployments.ts b/src/extensionConsole/pages/deployments/activateDeployments.ts index 4b55c6a378..03b3354427 100644 --- a/src/extensionConsole/pages/deployments/activateDeployments.ts +++ b/src/extensionConsole/pages/deployments/activateDeployments.ts @@ -45,8 +45,8 @@ async function activateDeployment({ modComponent._recipe?.id === deployment.package.package_id ) { dispatch( - actions.removeExtension({ - extensionId: modComponent.id, + actions.removeModComponent({ + modComponentId: modComponent.id, }), ); @@ -119,8 +119,8 @@ export function deactivateUnassignedModComponents({ for (const modComponent of unassignedModComponents) { try { dispatch( - actions.removeExtension({ - extensionId: modComponent.id, + actions.removeModComponent({ + modComponentId: modComponent.id, }), ); deactivatedModComponents.push(modComponent); diff --git a/src/extensionConsole/pages/mods/hooks/useModsPageActions.test.tsx b/src/extensionConsole/pages/mods/hooks/useModsPageActions.test.tsx index 12e0c9895b..00243b93b9 100644 --- a/src/extensionConsole/pages/mods/hooks/useModsPageActions.test.tsx +++ b/src/extensionConsole/pages/mods/hooks/useModsPageActions.test.tsx @@ -29,7 +29,7 @@ import { import useModPermissions from "@/mods/hooks/useModPermissions"; import { uniq } from "lodash"; import { uuidv4 } from "@/types/helpers"; -import { uninstallExtensions, uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallModComponents, uninstallMod } from "@/store/uninstallUtils"; import { renderHook } from "@/extensionConsole/testHelpers"; import { actions as extensionActions } from "@/store/extensionsSlice"; import { type ModDefinition } from "@/types/modDefinitionTypes"; @@ -410,12 +410,12 @@ describe("actions", () => { deactivate(); - expect(uninstallRecipe).toHaveBeenCalledWith( + expect(uninstallMod).toHaveBeenCalledWith( (modViewItem.mod as ModDefinition).metadata.id, expect.any(Array), expect.any(Function), ); - expect(uninstallExtensions).not.toHaveBeenCalled(); + expect(uninstallModComponents).not.toHaveBeenCalled(); }); test("calls uninstallExtensions for an mod component", () => { @@ -451,8 +451,8 @@ describe("actions", () => { deactivate(); - expect(uninstallRecipe).not.toHaveBeenCalled(); - expect(uninstallExtensions).toHaveBeenCalledWith( + expect(uninstallMod).not.toHaveBeenCalled(); + expect(uninstallModComponents).toHaveBeenCalledWith( [standaloneModDefinition.id], expect.any(Function), ); diff --git a/src/extensionConsole/pages/mods/modals/convertToModModal/ConvertToModModalBody.tsx b/src/extensionConsole/pages/mods/modals/convertToModModal/ConvertToModModalBody.tsx index 79cefc5d4f..3a5ffb1e78 100644 --- a/src/extensionConsole/pages/mods/modals/convertToModModal/ConvertToModModalBody.tsx +++ b/src/extensionConsole/pages/mods/modals/convertToModModal/ConvertToModModalBody.tsx @@ -180,9 +180,9 @@ const ConvertToModModalBody: React.FunctionComponent = () => { if ("active" in modComponent && modComponent.active) { // Dealing with installed extension dispatch( - extensionsSlice.actions.attachExtension({ - extensionId: modComponent.id, - recipeMetadata: pickModDefinitionMetadata(modDefinition), + extensionsSlice.actions.setModComponentMetadata({ + modComponentId: modComponent.id, + modMetadata: pickModDefinitionMetadata(modDefinition), }), ); } else { diff --git a/src/extensionConsole/pages/mods/utils/useReinstall.test.ts b/src/extensionConsole/pages/mods/utils/useReinstall.test.ts index 920b9aed75..ba147a945c 100644 --- a/src/extensionConsole/pages/mods/utils/useReinstall.test.ts +++ b/src/extensionConsole/pages/mods/utils/useReinstall.test.ts @@ -18,7 +18,7 @@ import { renderHook } from "@/extensionConsole/testHelpers"; import useReinstall from "./useReinstall"; import { actions as extensionActions } from "@/store/extensionsSlice"; -import { uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallMod } from "@/store/uninstallUtils"; import { type ModComponentsRootState } from "@/store/extensionsTypes"; import { defaultModDefinitionFactory } from "@/testUtils/factories/modDefinitionFactories"; import { standaloneModDefinitionFactory } from "@/testUtils/factories/modComponentFactories"; @@ -62,7 +62,7 @@ test("uninstalls recipe mod components", async () => { await act(async () => reinstall(modDefinition)); - expect(uninstallRecipe).toHaveBeenCalledWith( + expect(uninstallMod).toHaveBeenCalledWith( modDefinition.metadata.id, [expectedExtension], expect.any(Function), diff --git a/src/extensionConsole/pages/mods/utils/useReinstall.ts b/src/extensionConsole/pages/mods/utils/useReinstall.ts index ee5f85cb4c..601f912433 100644 --- a/src/extensionConsole/pages/mods/utils/useReinstall.ts +++ b/src/extensionConsole/pages/mods/utils/useReinstall.ts @@ -21,7 +21,7 @@ import { selectActivatedModComponents } from "@/store/extensionsSelectors"; import { useCallback } from "react"; import { actions as extensionActions } from "@/store/extensionsSlice"; import { collectModOptions } from "@/store/extensionsUtils"; -import { uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallMod } from "@/store/uninstallUtils"; import collectExistingConfiguredDependenciesForMod from "@/integrations/util/collectExistingConfiguredDependenciesForMod"; type Reinstall = (modDefinition: ModDefinition) => Promise; @@ -49,7 +49,7 @@ function useReinstall(): Reinstall { activatedModComponents, ); - await uninstallRecipe(modId, activatedModComponents, dispatch); + await uninstallMod(modId, activatedModComponents, dispatch); dispatch( extensionActions.activateMod({ diff --git a/src/mods/hooks/useDeactivateAction.ts b/src/mods/hooks/useDeactivateAction.ts index 55b29e6b2f..54fd1c78fb 100644 --- a/src/mods/hooks/useDeactivateAction.ts +++ b/src/mods/hooks/useDeactivateAction.ts @@ -25,7 +25,7 @@ import { } from "@/utils/modUtils"; import { useCallback } from "react"; import useUserAction from "@/hooks/useUserAction"; -import { uninstallExtensions, uninstallRecipe } from "@/store/uninstallUtils"; +import { uninstallModComponents, uninstallMod } from "@/store/uninstallUtils"; import reportEvent from "@/telemetry/reportEvent"; import { Events } from "@/telemetry/events"; import { type ModComponentState } from "@/store/extensionsTypes"; @@ -56,13 +56,13 @@ function useDeactivateAction(modViewItem: ModViewItem): (() => void) | null { async () => { if (isModDefinition(mod)) { const blueprintId = mod.metadata.id; - await uninstallRecipe(blueprintId, extensionsFromMod, dispatch); + await uninstallMod(blueprintId, extensionsFromMod, dispatch); reportEvent(Events.MOD_REMOVE, { blueprintId, }); } else { - await uninstallExtensions( + await uninstallModComponents( extensionsFromMod.map(({ id }) => id), dispatch, ); diff --git a/src/mods/useModViewItems.test.tsx b/src/mods/useModViewItems.test.tsx index 82e397b0ff..d251ff20e6 100644 --- a/src/mods/useModViewItems.test.tsx +++ b/src/mods/useModViewItems.test.tsx @@ -49,7 +49,7 @@ describe("useModViewItems", () => { { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ modComponent as unknown as ActivatedModComponent, ]), ); @@ -76,7 +76,7 @@ describe("useModViewItems", () => { { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ activatedModComponent, ]), ); @@ -107,7 +107,7 @@ describe("useModViewItems", () => { { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ activatedModComponent, ]), ); diff --git a/src/mods/useMods.test.ts b/src/mods/useMods.test.ts index 4cfddb6638..8c266163c7 100644 --- a/src/mods/useMods.test.ts +++ b/src/mods/useMods.test.ts @@ -61,7 +61,7 @@ describe("useMods", () => { const wrapper = renderHook(() => useMods(), { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ activatedModComponentFactory({ _recipe: { ...metadataFactory(), @@ -92,7 +92,7 @@ describe("useMods", () => { const wrapper = renderHook(() => useMods(), { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions( + extensionsSlice.actions.UNSAFE_setModComponents( range(3).map(() => activatedModComponentFactory({ _recipe: { @@ -130,7 +130,7 @@ describe("useMods", () => { const wrapper = renderHook(() => useMods(), { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ activatedModComponentFactory({ _recipe: { ...metadata, @@ -186,7 +186,7 @@ describe("useMods", () => { const wrapper = renderHook(() => useMods(), { setupRedux(dispatch) { dispatch( - extensionsSlice.actions.UNSAFE_setExtensions([ + extensionsSlice.actions.UNSAFE_setModComponents([ // Content doesn't matter, just need to match the ID activatedModComponentFactory({ id: standaloneModDefinition.id }), ]), diff --git a/src/pageEditor/hooks/useCreateModFromModComponent.ts b/src/pageEditor/hooks/useCreateModFromModComponent.ts index 8f6fee9ab6..d9501412d5 100644 --- a/src/pageEditor/hooks/useCreateModFromModComponent.ts +++ b/src/pageEditor/hooks/useCreateModFromModComponent.ts @@ -105,7 +105,7 @@ function useCreateModFromModComponent( if (!keepLocalCopy) { await removeModComponentFromStorage({ - extensionId: activeModComponent.uuid, + modComponentId: activeModComponent.uuid, }); } diff --git a/src/pageEditor/hooks/useDeactivateMod.tsx b/src/pageEditor/hooks/useDeactivateMod.tsx index 8e832b65ec..e1a62f94e1 100644 --- a/src/pageEditor/hooks/useDeactivateMod.tsx +++ b/src/pageEditor/hooks/useDeactivateMod.tsx @@ -63,7 +63,7 @@ function useDeactivateMod(): (useDeactivateConfig: Config) => Promise { await Promise.all( modComponentIds.map(async (modComponentId) => removeModComponentFromStorage({ - extensionId: modComponentId, + modComponentId, }), ), ); diff --git a/src/pageEditor/hooks/useRemoveModComponentFromStorage.test.ts b/src/pageEditor/hooks/useRemoveModComponentFromStorage.test.ts index 46ef517af3..3e53d2c420 100644 --- a/src/pageEditor/hooks/useRemoveModComponentFromStorage.test.ts +++ b/src/pageEditor/hooks/useRemoveModComponentFromStorage.test.ts @@ -16,20 +16,20 @@ */ import { renderHook } from "@/pageEditor/testHelpers"; -import { removeExtensionsFromAllTabs } from "@/store/uninstallUtils"; +import { removeModComponentsFromAllTabs } from "@/store/uninstallUtils"; import { useRemoveModComponentFromStorage } from "./useRemoveModComponentFromStorage"; import { actions as editorActions } from "@/pageEditor/slices/editorSlice"; import { actions as extensionsActions } from "@/store/extensionsSlice"; import { clearDraftModComponents } from "@/contentScript/messenger/api"; -import { uuidSequence } from "@/testUtils/factories/stringFactories"; +import { autoUUIDSequence } from "@/testUtils/factories/stringFactories"; beforeEach(() => { jest.resetAllMocks(); }); test("useRemoveModComponentFromStorage", async () => { - const extensionId = uuidSequence(1); + const modComponentId = autoUUIDSequence(); const { result: { current: removeExtension }, @@ -41,19 +41,19 @@ test("useRemoveModComponentFromStorage", async () => { }); await removeExtension({ - extensionId, + modComponentId, }); const { dispatch } = getReduxStore(); expect(dispatch).toHaveBeenCalledWith( - editorActions.removeModComponentFormState(extensionId), + editorActions.removeModComponentFormState(modComponentId), ); expect(dispatch).toHaveBeenCalledWith( - extensionsActions.removeExtension({ extensionId }), + extensionsActions.removeModComponent({ modComponentId }), ); expect(clearDraftModComponents).toHaveBeenCalledWith(expect.any(Object), { - uuid: extensionId, + uuid: modComponentId, }); - expect(removeExtensionsFromAllTabs).toHaveBeenCalledWith([extensionId]); + expect(removeModComponentsFromAllTabs).toHaveBeenCalledWith([modComponentId]); }); diff --git a/src/pageEditor/hooks/useRemoveModComponentFromStorage.tsx b/src/pageEditor/hooks/useRemoveModComponentFromStorage.tsx index e4fa450e42..2d56ce7a0d 100644 --- a/src/pageEditor/hooks/useRemoveModComponentFromStorage.tsx +++ b/src/pageEditor/hooks/useRemoveModComponentFromStorage.tsx @@ -29,11 +29,11 @@ import notify from "@/utils/notify"; import { actions as editorActions } from "@/pageEditor/slices/editorSlice"; import { actions as extensionsActions } from "@/store/extensionsSlice"; import { clearDraftModComponents } from "@/contentScript/messenger/api"; -import { removeExtensionsFromAllTabs } from "@/store/uninstallUtils"; +import { removeModComponentsFromAllTabs } from "@/store/uninstallUtils"; import { allFramesInInspectedTab } from "@/pageEditor/context/connection"; type Config = { - extensionId: UUID; + modComponentId: UUID; // Show a confirmation modal with the specified modal props before removing the mod component if defined showConfirmationModal?: ConfirmationModalProps; }; @@ -82,8 +82,10 @@ export function useRemoveModComponentFromStorage(): ( const { showConfirmation } = useModals(); return useCallback( - async ({ extensionId, showConfirmationModal }) => { - console.debug(`pageEditor: remove mod component with id ${extensionId}`); + async ({ modComponentId, showConfirmationModal }) => { + console.debug( + `pageEditor: remove mod component with id ${modComponentId}`, + ); if (showConfirmationModal) { const confirm = await showConfirmation(showConfirmationModal); @@ -95,27 +97,27 @@ export function useRemoveModComponentFromStorage(): ( reportEvent(Events.PAGE_EDITOR_REMOVE, { sessionId, - extensionId, + extensionId: modComponentId, }); try { // Remove the mod component form state from the Page Editor - dispatch(editorActions.removeModComponentFormState(extensionId)); + dispatch(editorActions.removeModComponentFormState(modComponentId)); // Remove from options slice / extension storage - dispatch(extensionsActions.removeExtension({ extensionId })); + dispatch(extensionsActions.removeModComponent({ modComponentId })); // Remove from the host page try { clearDraftModComponents(allFramesInInspectedTab, { - uuid: extensionId, + uuid: modComponentId, }); } catch (error) { // Element might not be on the page anymore console.info("Cannot clear draft mod component from page", { error }); } - removeExtensionsFromAllTabs([extensionId]); + removeModComponentsFromAllTabs([modComponentId]); } catch (error) { notify.error({ message: "Error removing mod", diff --git a/src/pageEditor/hooks/useSaveMod.ts b/src/pageEditor/hooks/useSaveMod.ts index 73fbc64c0a..d1839fc105 100644 --- a/src/pageEditor/hooks/useSaveMod.ts +++ b/src/pageEditor/hooks/useSaveMod.ts @@ -170,7 +170,7 @@ function useSaveMod(): ModSaver { ); // Update the mod metadata on mod components in the options slice - dispatch(optionsActions.updateRecipeMetadataForExtensions(newModMetadata)); + dispatch(optionsActions.updateModMetadata(newModMetadata)); dispatch( editorActions.updateModMetadataOnModComponentFormStates(newModMetadata), @@ -178,7 +178,7 @@ function useSaveMod(): ModSaver { // Remove any deleted mod component form states from the extensions slice for (const modComponentId of getDeletedComponentIdsForMod(modId)) { - dispatch(optionsActions.removeExtension({ extensionId: modComponentId })); + dispatch(optionsActions.removeModComponent({ modComponentId })); } // Clear the dirty states diff --git a/src/pageEditor/panes/save/useSavingWizard.ts b/src/pageEditor/panes/save/useSavingWizard.ts index 6b4ed3f8f0..bc7a996da0 100644 --- a/src/pageEditor/panes/save/useSavingWizard.ts +++ b/src/pageEditor/panes/save/useSavingWizard.ts @@ -169,8 +169,8 @@ const useSavingWizard = () => { ), ); dispatch( - optionsActions.removeExtension({ - extensionId: activeModComponentFormState.uuid, + optionsActions.removeModComponent({ + modComponentId: activeModComponentFormState.uuid, }), ); } @@ -334,7 +334,7 @@ const useSavingWizard = () => { ...extraUpdate, }; - dispatch(optionsActions.updateExtension(update)); + dispatch(optionsActions.updateModComponent(update)); } // 2) Update the extensions in the Redux editorSlice (the slice for the page editor) diff --git a/src/pageEditor/sidebar/DraftModComponentListItem.tsx b/src/pageEditor/sidebar/DraftModComponentListItem.tsx index 1bdc6e9e5f..adf1a192aa 100644 --- a/src/pageEditor/sidebar/DraftModComponentListItem.tsx +++ b/src/pageEditor/sidebar/DraftModComponentListItem.tsx @@ -112,14 +112,14 @@ const DraftModComponentListItem: React.FunctionComponent< const deleteModComponent = async () => removeModComponentFromStorage({ - extensionId: modComponentFormState.uuid, + modComponentId: modComponentFormState.uuid, showConfirmationModal: modId ? DELETE_STARTER_BRICK_MODAL_PROPS : DELETE_STANDALONE_MOD_COMPONENT_MODAL_PROPS, }); const deactivateModComponent = async () => removeModComponentFromStorage({ - extensionId: modComponentFormState.uuid, + modComponentId: modComponentFormState.uuid, showConfirmationModal: DEACTIVATE_MOD_MODAL_PROPS, }); diff --git a/src/pageEditor/sidebar/modals/AddToRecipeModal.tsx b/src/pageEditor/sidebar/modals/AddToRecipeModal.tsx index ad5ef5e3d2..0d6e81f382 100644 --- a/src/pageEditor/sidebar/modals/AddToRecipeModal.tsx +++ b/src/pageEditor/sidebar/modals/AddToRecipeModal.tsx @@ -110,7 +110,7 @@ const AddToRecipeModal: React.FC = () => { ); if (!keepLocalCopy) { await removeModComponentFromStorage({ - extensionId: modComponentId, + modComponentId, }); } diff --git a/src/sidebar/activateMod/ActivateModPanel.test.tsx b/src/sidebar/activateMod/ActivateModPanel.test.tsx index a42463d834..0f1f4744f6 100644 --- a/src/sidebar/activateMod/ActivateModPanel.test.tsx +++ b/src/sidebar/activateMod/ActivateModPanel.test.tsx @@ -46,9 +46,9 @@ import { clear, find, syncPackages } from "@/registry/packageRegistry"; import { refreshRegistries } from "@/hooks/useRefreshRegistries"; import { refreshServices } from "@/background/locator"; import { type WizardValues } from "@/activation/wizardTypes"; -import useActivateRecipe, { +import useActivateMod, { type ActivateResult, -} from "@/activation/useActivateRecipe"; +} from "@/activation/useActivateMod"; import brickRegistry from "@/bricks/registry"; import { registryIdFactory } from "@/testUtils/factories/stringFactories"; import { propertiesToSchema } from "@/utils/schemaUtils"; @@ -86,12 +86,12 @@ jest.mock("@/registry/internal", () => ({ const useQuickbarShortcutMock = jest.mocked(useQuickbarShortcut); -jest.mock("@/activation/useActivateRecipe", () => ({ +jest.mock("@/activation/useActivateMod", () => ({ __esModule: true, default: jest.fn().mockReturnValue(async () => ({ success: true })), })); -const useActivateRecipeMock = jest.mocked(useActivateRecipe); +const useActivateRecipeMock = jest.mocked(useActivateMod); let activateRecipeSpy: jest.MockedFunction< (formValues: WizardValues, recipe: ModDefinition) => Promise >; diff --git a/src/sidebar/activateMod/ActivateModPanel.tsx b/src/sidebar/activateMod/ActivateModPanel.tsx index 168123d64c..a8e8c9b528 100644 --- a/src/sidebar/activateMod/ActivateModPanel.tsx +++ b/src/sidebar/activateMod/ActivateModPanel.tsx @@ -35,7 +35,7 @@ import { isEmpty } from "lodash"; import ActivateModInputs from "@/sidebar/activateMod/ActivateModInputs"; import useQuickbarShortcut from "@/hooks/useQuickbarShortcut"; import { Button } from "react-bootstrap"; -import useActivateRecipe from "@/activation/useActivateRecipe"; +import useActivateMod from "@/activation/useActivateMod"; import { type WizardValues } from "@/activation/wizardTypes"; import { createSlice, type PayloadAction } from "@reduxjs/toolkit"; import useActivateModWizard, { @@ -223,7 +223,7 @@ const ActivateModPanelContent: React.FC< isActive, }) => { const reduxDispatch = useDispatch(); - const marketplaceActivateRecipe = useActivateRecipe("marketplace"); + const marketplaceActivateRecipe = useActivateMod("marketplace"); const [state, stateDispatch] = useReducer( activationSlice.reducer, diff --git a/src/sidebar/activateMod/ActivateMultipleModsPanel.tsx b/src/sidebar/activateMod/ActivateMultipleModsPanel.tsx index b6ed871776..5b161d74f1 100644 --- a/src/sidebar/activateMod/ActivateMultipleModsPanel.tsx +++ b/src/sidebar/activateMod/ActivateMultipleModsPanel.tsx @@ -27,9 +27,9 @@ import { selectActivatedModComponents } from "@/store/extensionsSelectors"; import useDeriveAsyncState from "@/hooks/useDeriveAsyncState"; import { type Option } from "@/components/form/widgets/SelectWidget"; import { wizardStateFactory } from "@/activation/useActivateModWizard"; -import useActivateRecipe, { +import useActivateMod, { type ActivateResult, -} from "@/activation/useActivateRecipe"; +} from "@/activation/useActivateMod"; import { SuccessPanel } from "@/sidebar/activateMod/ActivateModPanel"; import sidebarSlice from "@/store/sidebar/sidebarSlice"; import type { ModActivationConfig } from "@/types/modTypes"; @@ -68,7 +68,7 @@ const AutoActivatePanel: React.FC<{ mods: RequiredModDefinition[] }> = ({ // Assume mods work without all permissions. Currently, the only optional permission is `clipboardWrite`, which isn't // actually enforced by Chrome. (Mods can still copy to the clipboard.). The only way a mod would not have all // permissions is if their Enterprise policy has disabled some permissions. - const activate = useActivateRecipe("marketplace", { + const activate = useActivateMod("marketplace", { checkPermissions: false, }); diff --git a/src/store/extensionsSlice.ts b/src/store/extensionsSlice.ts index 767535754b..8dfd2c2dec 100644 --- a/src/store/extensionsSlice.ts +++ b/src/store/extensionsSlice.ts @@ -72,7 +72,7 @@ const extensionsSlice = createSlice({ reducers: { // Helper method to directly update extensions in tests. Can't use activateStandaloneModDefinition because // StandaloneModDefinition doesn't have the _recipe field - UNSAFE_setExtensions( + UNSAFE_setModComponents( state, { payload }: PayloadAction, ) { @@ -98,20 +98,25 @@ const extensionsSlice = createSlice({ void contextMenus.preload([extension]); }, - attachExtension( + /** + * Set the mod metadata associated with the given activated mod component id. + */ + setModComponentMetadata( state, { payload, }: PayloadAction<{ - extensionId: UUID; - recipeMetadata: ModComponentBase["_recipe"]; + modComponentId: UUID; + modMetadata: ModComponentBase["_recipe"]; }>, ) { - const { extensionId, recipeMetadata } = payload; - const extension = state.extensions.find((x) => x.id === extensionId); + const { modComponentId, modMetadata } = payload; + const modComponent = state.extensions.find( + (x) => x.id === modComponentId, + ); - if (extension != null) { - extension._recipe = recipeMetadata; + if (modComponent != null) { + modComponent._recipe = modMetadata; } }, @@ -255,17 +260,21 @@ const extensionsSlice = createSlice({ state.extensions.push(modComponent); } }, - updateExtension( + + /** + * Update an activated mod component. + */ + updateModComponent( state, action: PayloadAction<{ id: UUID } & Partial>, ) { - const { id, ...extensionUpdate } = action.payload; + const { id, ...modComponentUpdate } = action.payload; const index = state.extensions.findIndex((x) => x.id === id); if (index === -1) { reportError( new Error( - `Can't find extension in optionsSlice to update. Target extension id: ${id}.`, + `Can't find mod component in optionsSlice to update. Target mod component id: ${id}.`, ), ); return; @@ -274,48 +283,67 @@ const extensionsSlice = createSlice({ // eslint-disable-next-line security/detect-object-injection -- index is number state.extensions[index] = { ...state.extensions.at(index), - ...extensionUpdate, + ...modComponentUpdate, } as ActivatedModComponent; }, - updateRecipeMetadataForExtensions( + /** + * Update the mod metadata of all mod components associated with the given mod id. + */ + updateModMetadata( state, action: PayloadAction, ) { const metadata = action.payload; - const recipeExtensions = state.extensions.filter( + const modComponents = state.extensions.filter( (extension) => extension._recipe?.id === metadata?.id, ); - for (const extension of recipeExtensions) { - extension._recipe = metadata; + for (const modComponent of modComponents) { + modComponent._recipe = metadata; } }, - removeRecipeById(state, { payload: recipeId }: PayloadAction) { + /** + * Deactivate mod components associated with the given mod id + */ + removeModById(state, { payload: modId }: PayloadAction) { const [, extensions] = partition( state.extensions, - (x) => x._recipe?.id === recipeId, + (x) => x._recipe?.id === modId, ); state.extensions = extensions; }, - removeExtensions( + /** + * Deactivate the given mod components by id. + */ + removeModComponents( state, - { payload: { extensionIds } }: PayloadAction<{ extensionIds: UUID[] }>, + { + payload: { modComponentIds }, + }: PayloadAction<{ modComponentIds: UUID[] }>, ) { - // NOTE: We aren't deleting the extension on the server. The user must do that separately from the dashboard + // NOTE: We aren't deleting the mod components on the server. + // The user must do that separately from the mods screen state.extensions = state.extensions.filter( - (x) => !extensionIds.includes(x.id), + (x) => !modComponentIds.includes(x.id), ); }, - removeExtension( + /** + * Deactivate a single mod component by id. + * @see removeModComponents + */ + removeModComponent( state, - { payload: { extensionId } }: PayloadAction<{ extensionId: UUID }>, + { payload: { modComponentId } }: PayloadAction<{ modComponentId: UUID }>, ) { - // NOTE: We aren't deleting the extension on the server. The user must do that separately from the dashboard - state.extensions = state.extensions.filter((x) => x.id !== extensionId); + // NOTE: We aren't deleting the mod component/definition on the server. + // The user must do that separately from the dashboard + state.extensions = state.extensions.filter( + (x) => x.id !== modComponentId, + ); }, }, extraReducers(builder) { diff --git a/src/store/sessionChanges/sessionChangesListenerMiddleware.ts b/src/store/sessionChanges/sessionChangesListenerMiddleware.ts index a06fe32ed6..40c6f43389 100644 --- a/src/store/sessionChanges/sessionChangesListenerMiddleware.ts +++ b/src/store/sessionChanges/sessionChangesListenerMiddleware.ts @@ -39,11 +39,11 @@ sessionChangesListenerMiddleware.startListening({ actions.removeRecipeData, extensionsSlice.actions.activateStandaloneModDefinition, - extensionsSlice.actions.removeExtension, - extensionsSlice.actions.removeExtensions, - extensionsSlice.actions.attachExtension, + extensionsSlice.actions.removeModComponent, + extensionsSlice.actions.removeModComponents, + extensionsSlice.actions.setModComponentMetadata, extensionsSlice.actions.activateMod, - extensionsSlice.actions.removeRecipeById, + extensionsSlice.actions.removeModById, ), effect(action, { dispatch, getState }) { const { sessionId } = (getState() as SessionRootState).session; diff --git a/src/store/uninstallUtils.ts b/src/store/uninstallUtils.ts index 6eec130ff4..702bd98d47 100644 --- a/src/store/uninstallUtils.ts +++ b/src/store/uninstallUtils.ts @@ -21,58 +21,57 @@ import { removeDraftModComponentsForMod, } from "@/store/editorStorage"; import { actions as extensionActions } from "@/store/extensionsSlice"; -import { removeExtensionForEveryTab } from "@/background/messenger/api"; +import { removeModComponentForEveryTab } from "@/background/messenger/api"; import { uniq } from "lodash"; import { type UnresolvedModComponent } from "@/types/modComponentTypes"; import { type RegistryId } from "@/types/registryTypes"; import { type UUID } from "@/types/stringTypes"; /** - * Use this helper outside the Page Editor context to uninstall a recipe and all of its extensions. + * Use this helper outside the Page Editor context to uninstall a mod and all of its mod components. * * Uninstalls from: * - Extension Options slice - * - draft mod components slice (i.e., Page Editor state) - * - Notifies all tabs to remove the extensions + * - Draft mod components slice (i.e., Page Editor state) + * - Notifies all tabs to remove the mod components */ -export async function uninstallRecipe( - recipeId: RegistryId, - recipeExtensions: UnresolvedModComponent[], +export async function uninstallMod( + modId: RegistryId, + modComponents: UnresolvedModComponent[], dispatch: Dispatch, ): Promise { const draftModComponentsToDeactivate = - await removeDraftModComponentsForMod(recipeId); + await removeDraftModComponentsForMod(modId); - dispatch(extensionActions.removeRecipeById(recipeId)); + dispatch(extensionActions.removeModById(modId)); - removeExtensionsFromAllTabs( + removeModComponentsFromAllTabs( uniq([ - ...recipeExtensions.map(({ id }) => id), + ...modComponents.map(({ id }) => id), ...draftModComponentsToDeactivate, ]), ); } /** - * Use this helper outside the Page Editor context - * to uninstall a collections of extensions. + * Use this helper outside the Page Editor context to uninstall a collections of mod components. */ -export async function uninstallExtensions( - extensionIds: UUID[], +export async function uninstallModComponents( + modComponentIds: UUID[], dispatch: Dispatch, ): Promise { - await removeDraftModComponents(extensionIds); + await removeDraftModComponents(modComponentIds); - dispatch(extensionActions.removeExtensions({ extensionIds })); + dispatch(extensionActions.removeModComponents({ modComponentIds })); - removeExtensionsFromAllTabs(extensionIds); + removeModComponentsFromAllTabs(modComponentIds); } /** * Uninstalls the extensions from all open tabs */ -export function removeExtensionsFromAllTabs(extensionIds: UUID[]): void { - for (const extensionId of extensionIds) { - removeExtensionForEveryTab(extensionId); +export function removeModComponentsFromAllTabs(modComponentIds: UUID[]): void { + for (const modComponentId of modComponentIds) { + removeModComponentForEveryTab(modComponentId); } } diff --git a/src/tsconfig.strictNullChecks.json b/src/tsconfig.strictNullChecks.json index f9c822a9b6..d80a8a222f 100644 --- a/src/tsconfig.strictNullChecks.json +++ b/src/tsconfig.strictNullChecks.json @@ -45,7 +45,7 @@ "./activation/activationLinkUtils.ts", "./activation/getActivatedModComponentFromDefinition.ts", "./activation/modOptionsHelpers.ts", - "./activation/useActivateRecipe.ts", + "./activation/useActivateMod.ts", "./activation/wizardTypes.ts", "./analysis/AnalysisAnnotationsContext.ts", "./analysis/ReduxAnalysisManager.ts",