From 2f4fce4596f6fc8450cf2296b13d159bc8bfa05a Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Tue, 19 Mar 2024 21:28:10 +0100 Subject: [PATCH 1/4] dont directly dispatch updatePropertyControlsInfo --- .../src/components/canvas/canvas-globals.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/editor/src/components/canvas/canvas-globals.ts b/editor/src/components/canvas/canvas-globals.ts index 579717e841a8..4afb3be84fca 100644 --- a/editor/src/components/canvas/canvas-globals.ts +++ b/editor/src/components/canvas/canvas-globals.ts @@ -11,6 +11,10 @@ import type { Either } from '../../core/shared/either' import { forEachRight } from '../../core/shared/either' import { mapArrayToDictionary } from '../../core/shared/array-utils' import { fastForEach } from '../../core/shared/utils' +import { + PropertyControlsInfoKeepDeepEquality, + PropertyControlsKeepDeepEquality, +} from '../editor/store/store-deep-equality-instances' export type ControlsToCheck = Promise>> @@ -25,6 +29,7 @@ let controlsRegisteredByFileInLastRender: Map< string, Array > = new Map() +export let registeredPropertyControlsInfo: PropertyControlsInfo = {} export function addRegisteredControls( sourceFile: string, @@ -126,6 +131,19 @@ export async function validateControlsToCheck( previousRegisteredModules = allRegisteredModules if (shouldDispatch) { - dispatch([updatePropertyControlsInfo(updatedPropertyControlsInfo, moduleNamesOrPathsToDelete)]) + // dispatch([updatePropertyControlsInfo(updatedPropertyControlsInfo, moduleNamesOrPathsToDelete)]) + + let wipPropertyControlsInfo: PropertyControlsInfo = { + ...registeredPropertyControlsInfo, + ...updatedPropertyControlsInfo, + } + for (const moduleNameOrPathToDelete of moduleNamesOrPathsToDelete) { + delete wipPropertyControlsInfo[moduleNameOrPathToDelete] + } + + registeredPropertyControlsInfo = PropertyControlsInfoKeepDeepEquality( + registeredPropertyControlsInfo, + wipPropertyControlsInfo, + ).value } } From 415ed6b31dc54d31f3a87c96b3d9713d997884f8 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:27:18 +0100 Subject: [PATCH 2/4] adding stub hook usePropertyControlsInfo --- .../canvas/canvas-external-store.tsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 editor/src/components/canvas/canvas-external-store.tsx diff --git a/editor/src/components/canvas/canvas-external-store.tsx b/editor/src/components/canvas/canvas-external-store.tsx new file mode 100644 index 000000000000..1c52c09ad9b2 --- /dev/null +++ b/editor/src/components/canvas/canvas-external-store.tsx @@ -0,0 +1,20 @@ +import { DefaultThirdPartyControlDefinitions } from '../../core/third-party/third-party-controls' +import type { PropertyControlsInfo } from '../custom-code/code-file' +import { Substores, useEditorState } from '../editor/store/store-hook' + +export const PropertyControlsExportedForTestInspection: { current: PropertyControlsInfo } = { + current: {}, +} + +export function usePropertyControlsInfo(): PropertyControlsInfo { + const override = useEditorState( + Substores.restOfEditor, + (store) => store.editor.propertyControlsInfoOverride, + 'usePropertyControlsInfo override', + ) + + // TODO don't forget about DefaultThirdPartyControlDefinitions + const defaultControls = DefaultThirdPartyControlDefinitions + + return override ?? (null as any) +} From 88b168ae42f431169f6c4b4c4f8b8ec84dca9662 Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:49:47 +0100 Subject: [PATCH 3/4] adding a skeleton external store --- .../canvas/canvas-external-store.tsx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/editor/src/components/canvas/canvas-external-store.tsx b/editor/src/components/canvas/canvas-external-store.tsx index 1c52c09ad9b2..85d18b4056a2 100644 --- a/editor/src/components/canvas/canvas-external-store.tsx +++ b/editor/src/components/canvas/canvas-external-store.tsx @@ -6,6 +6,30 @@ export const PropertyControlsExportedForTestInspection: { current: PropertyContr current: {}, } +let listeners: Array<() => void> = [] + +export const propControlsStore = { + setPropertyControls(propertyControls: PropertyControlsInfo) { + PropertyControlsExportedForTestInspection.current = propertyControls + emitChange() + }, + subscribe(listener: () => void) { + listeners = [...listeners, listener] + return () => { + listeners = listeners.filter((l) => l !== listener) + } + }, + getSnapshot(): PropertyControlsInfo { + return PropertyControlsExportedForTestInspection.current + }, +} + +function emitChange() { + for (let listener of listeners) { + listener() + } +} + export function usePropertyControlsInfo(): PropertyControlsInfo { const override = useEditorState( Substores.restOfEditor, From c3b6f9e1d5e1a3a9c3de687488acf4445854be2c Mon Sep 17 00:00:00 2001 From: Balazs Bajorics <2226774+balazsbajorics@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:21:37 +0100 Subject: [PATCH 4/4] useDispatchWhenPropertyControlsInfoChanges() --- .../canvas/canvas-external-store.tsx | 23 ++++++++++++------- .../src/components/canvas/canvas-globals.ts | 3 +++ editor/src/components/editor/action-types.ts | 1 - .../editor/actions/action-creators.ts | 2 -- .../src/components/editor/actions/actions.tsx | 9 +------- .../components/editor/editor-component.tsx | 4 ++++ 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/editor/src/components/canvas/canvas-external-store.tsx b/editor/src/components/canvas/canvas-external-store.tsx index 85d18b4056a2..3ecc9c958b9e 100644 --- a/editor/src/components/canvas/canvas-external-store.tsx +++ b/editor/src/components/canvas/canvas-external-store.tsx @@ -1,6 +1,9 @@ +import React from 'react' import { DefaultThirdPartyControlDefinitions } from '../../core/third-party/third-party-controls' import type { PropertyControlsInfo } from '../custom-code/code-file' import { Substores, useEditorState } from '../editor/store/store-hook' +import { useDispatch } from '../editor/store/dispatch-context' +import { updatePropertyControlsInfo } from '../editor/actions/action-creators' export const PropertyControlsExportedForTestInspection: { current: PropertyControlsInfo } = { current: {}, @@ -31,14 +34,18 @@ function emitChange() { } export function usePropertyControlsInfo(): PropertyControlsInfo { - const override = useEditorState( - Substores.restOfEditor, - (store) => store.editor.propertyControlsInfoOverride, - 'usePropertyControlsInfo override', - ) - // TODO don't forget about DefaultThirdPartyControlDefinitions - const defaultControls = DefaultThirdPartyControlDefinitions + return React.useSyncExternalStore(propControlsStore.subscribe, propControlsStore.getSnapshot) +} + +export function useDispatchWhenPropertyControlsInfoChanges() { + const dispatch = useDispatch() + + const previousPropControls = React.useRef(null) + const propControls = usePropertyControlsInfo() + if (previousPropControls.current !== propControls) { + dispatch([updatePropertyControlsInfo(propControls)]) + } - return override ?? (null as any) + previousPropControls.current = propControls } diff --git a/editor/src/components/canvas/canvas-globals.ts b/editor/src/components/canvas/canvas-globals.ts index 4afb3be84fca..1d5c126c7915 100644 --- a/editor/src/components/canvas/canvas-globals.ts +++ b/editor/src/components/canvas/canvas-globals.ts @@ -15,6 +15,7 @@ import { PropertyControlsInfoKeepDeepEquality, PropertyControlsKeepDeepEquality, } from '../editor/store/store-deep-equality-instances' +import { propControlsStore } from './canvas-external-store' export type ControlsToCheck = Promise>> @@ -145,5 +146,7 @@ export async function validateControlsToCheck( registeredPropertyControlsInfo, wipPropertyControlsInfo, ).value + + propControlsStore.setPropertyControls(registeredPropertyControlsInfo) } } diff --git a/editor/src/components/editor/action-types.ts b/editor/src/components/editor/action-types.ts index d729e5b14f6d..64ae95c1c0bd 100644 --- a/editor/src/components/editor/action-types.ts +++ b/editor/src/components/editor/action-types.ts @@ -860,7 +860,6 @@ export interface SetShortcut { export interface UpdatePropertyControlsInfo { action: 'UPDATE_PROPERTY_CONTROLS_INFO' propertyControlsInfo: PropertyControlsInfo - moduleNamesOrPathsToDelete: Array } export interface UpdateText { diff --git a/editor/src/components/editor/actions/action-creators.ts b/editor/src/components/editor/actions/action-creators.ts index ad5b7ffe7754..94a9c19ae3e3 100644 --- a/editor/src/components/editor/actions/action-creators.ts +++ b/editor/src/components/editor/actions/action-creators.ts @@ -1352,12 +1352,10 @@ export function setShortcut(shortcutName: string, newKey: Key): SetShortcut { export function updatePropertyControlsInfo( propertyControlsInfo: PropertyControlsInfo, - moduleNamesOrPathsToDelete: Array, ): UpdatePropertyControlsInfo { return { action: 'UPDATE_PROPERTY_CONTROLS_INFO', propertyControlsInfo: propertyControlsInfo, - moduleNamesOrPathsToDelete: moduleNamesOrPathsToDelete, } } diff --git a/editor/src/components/editor/actions/actions.tsx b/editor/src/components/editor/actions/actions.tsx index c2f960f6fa69..3244d4c977af 100644 --- a/editor/src/components/editor/actions/actions.tsx +++ b/editor/src/components/editor/actions/actions.tsx @@ -4387,16 +4387,9 @@ export const UPDATE_FNS = { action: UpdatePropertyControlsInfo, editor: EditorState, ): EditorState => { - let updatedPropertyControlsInfo: PropertyControlsInfo = { - ...editor.propertyControlsInfo, - ...action.propertyControlsInfo, - } - for (const moduleNameOrPathToDelete of action.moduleNamesOrPathsToDelete) { - delete updatedPropertyControlsInfo[moduleNameOrPathToDelete] - } return { ...editor, - propertyControlsInfo: updatedPropertyControlsInfo, + propertyControlsInfo: action.propertyControlsInfo, } }, UPDATE_TEXT: (action: UpdateText, editorStore: EditorStoreUnpatched): EditorStoreUnpatched => { diff --git a/editor/src/components/editor/editor-component.tsx b/editor/src/components/editor/editor-component.tsx index 0913275c7a16..4af1f9091a37 100644 --- a/editor/src/components/editor/editor-component.tsx +++ b/editor/src/components/editor/editor-component.tsx @@ -74,6 +74,7 @@ import { CommentMaintainer } from '../../core/commenting/comment-maintainer' import { useIsLoggedIn, useLiveblocksConnectionListener } from '../../core/shared/multiplayer-hooks' import { ForkSearchParamKey, ProjectForkFlow } from './project-fork-flow' import { isRoomId, projectIdToRoomId } from '../../utils/room-id' +import { useDispatchWhenPropertyControlsInfoChanges } from '../canvas/canvas-external-store' const liveModeToastId = 'play-mode-toast' @@ -102,6 +103,9 @@ export interface EditorProps {} export const EditorComponentInner = React.memo((props: EditorProps) => { const room = useRoom() const dispatch = useDispatch() + + useDispatchWhenPropertyControlsInfoChanges() + const editorStoreRef = useRefEditorState((store) => store) const metadataRef = useRefEditorState((store) => store.editor.jsxMetadata) const navigatorTargetsRef = useRefEditorState((store) => store.derived.navigatorTargets)