From 9dccaa90c36af01de8cc7487bf8376381aded3c2 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 12:57:24 +0200 Subject: [PATCH 01/32] Follow naming conventions for refs --- packages/dashboard/src/app/api/useStoryApi.js | 8 ++-- .../content/templateGridView.js | 8 ++-- .../myStories/content/storyGridView/index.js | 8 ++-- .../src/app/views/myStories/index.js | 6 +-- .../src/components/cardGallery/index.js | 6 +-- .../src/components/interfaceSkeleton/index.js | 10 +++-- packages/dashboard/src/utils/useStoryView.js | 8 ++-- .../contextMenu/components/subMenuTrigger.tsx | 10 ++--- .../src/components/datalist/list/list.tsx | 8 ++-- .../src/components/input/useNumericInput.tsx | 20 +++++----- .../src/components/popup/popup.tsx | 14 +++---- .../src/components/tooltip/tooltip.tsx | 40 +++++++++---------- .../src/utils/useForwardedRef.ts | 12 +++--- packages/element-library/src/media/edit.tsx | 20 +++++----- packages/rich-text/src/provider.tsx | 10 ++--- .../rich-text/src/useSelectionManipulation.ts | 14 +++---- .../components/storyPicker/selectStories.js | 8 ++-- .../story-editor/src/app/api/apiProvider.tsx | 8 ++-- .../src/app/canvas/canvasProvider.tsx | 12 +++--- .../src/app/font/fontProvider.tsx | 8 ++-- .../src/app/history/historyProvider.tsx | 6 +-- .../media/local/useContextValueProvider.js | 8 ++-- .../media/uploadQueue/useMediaUploadQueue.ts | 26 ++++++------ .../src/components/autoSaveHandler/index.js | 6 +-- .../src/components/canvas/editLayer.js | 12 +++--- .../src/components/canvas/eyedropperLayer.js | 32 +++++++-------- .../src/components/canvas/layout.js | 8 ++-- .../src/components/colorPicker/colorPicker.js | 6 +-- .../colorPicker/currentColorPicker.js | 8 ++-- .../colorPicker/customColorPicker.js | 6 +-- .../components/colorPicker/gradientLine.js | 4 +- .../colorPicker/usePointerMoveStop.js | 10 ++--- .../src/components/floatingMenu/layer.js | 9 +++-- .../carouselContext/carouselProvider.tsx | 6 +-- .../components/footer/gridview/gridView.js | 6 +-- .../src/components/form/hierarchical/index.js | 16 ++++---- .../panes/media/common/innerElement.js | 14 +++---- .../panes/media/common/mediaElement.js | 14 +++---- .../panes/pageTemplates/templateList.js | 8 ++-- .../library/panes/shared/chipGroup/index.js | 6 +-- .../library/panes/shared/libraryMoveable.js | 16 ++++---- .../library/panes/text/textSets/textSets.js | 6 +-- .../panes/text/textSets/textSetsPane.js | 8 ++-- .../library/panes/text/useInsertPreset.js | 21 +++++----- .../localAutoSaveHandler/localAutoSave.js | 22 +++++----- .../src/components/mediaRecording/useTrim.js | 8 ++-- .../panels/panel/useDragHandlers.js | 8 ++-- .../components/reorderable/useReordering.js | 10 ++--- .../src/components/reorderable/useScroll.js | 12 +++--- .../components/styleManager/useApplyStyle.js | 8 ++-- .../src/utils/useIdleTaskQueue.ts | 18 ++++----- .../editorSettings/publisherLogo/index.js | 14 +++---- .../src/components/ga4Banner/index.js | 8 ++-- .../src/components/telemetryBanner/index.js | 26 ++++++------ .../src/components/updateBanner/index.js | 8 ++-- .../src/components/metaBoxes/metaBoxes.js | 8 ++-- .../src/components/postLock/postLock.js | 6 +-- 57 files changed, 332 insertions(+), 324 deletions(-) diff --git a/packages/dashboard/src/app/api/useStoryApi.js b/packages/dashboard/src/app/api/useStoryApi.js index 9cca0e5c039a..1428842f945c 100644 --- a/packages/dashboard/src/app/api/useStoryApi.js +++ b/packages/dashboard/src/app/api/useStoryApi.js @@ -51,13 +51,13 @@ const useStoryApi = () => { const [state, dispatch] = useReducer(storyReducer, defaultStoriesState); const { apiCallbacks } = useConfig(); - const isMounted = useRef(false); + const isMountedRef = useRef(false); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); @@ -78,7 +78,7 @@ const useStoryApi = () => { const { stories, fetchedStoryIds, totalPages, totalStoriesByStatus } = await apiCallbacks.fetchStories(queryParams); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } diff --git a/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js b/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js index 4a37c7882317..194c9b9ee3e6 100644 --- a/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js +++ b/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js @@ -48,7 +48,7 @@ function TemplateGridView({ const { isRTL, apiCallbacks } = useConfig(); const containerRef = useRef(); const gridRef = useRef(); - const itemRefs = useRef({}); + const itemsRef = useRef({}); const [activeGridItemId, setActiveGridItemId] = useState(null); const { handleDetailsToggle, createStoryFromTemplate } = templateActions || {}; @@ -58,7 +58,7 @@ function TemplateGridView({ useGridViewKeys({ containerRef, gridRef, - itemRefs, + itemRefs: itemsRef, isRTL, currentItemId: activeGridItemId, items: filteredTemplates, @@ -69,7 +69,7 @@ function TemplateGridView({ // for legibility, it's based on the FOCUS_TEMPLATE_CLASS useEffect(() => { if (activeGridItemId) { - itemRefs.current?.[activeGridItemId] + itemsRef.current?.[activeGridItemId] ?.querySelector(`.${FOCUS_TEMPLATE_CLASS}`) ?.focus(); } @@ -97,7 +97,7 @@ function TemplateGridView({ key={slug} posterSrc={posterSrc} ref={(el) => { - itemRefs.current[id] = el; + itemsRef.current[id] = el; }} slug={slug} status={status} diff --git a/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js b/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js index 606044a686d3..9cc3fc3d0733 100644 --- a/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js +++ b/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js @@ -62,7 +62,7 @@ const StoryGridView = ({ const { isRTL } = useConfig(); const containerRef = useRef(); const gridRef = useRef(); - const itemRefs = useRef({}); + const itemsRef = useRef({}); const [activeGridItemId, setActiveGridItemId] = useState(); const activeGridItemIdRef = useRef(); const gridItemIds = useMemo(() => stories.map(({ id }) => id), [stories]); @@ -70,7 +70,7 @@ const StoryGridView = ({ useGridViewKeys({ containerRef, gridRef, - itemRefs, + itemRefs: itemsRef, isRTL, currentItemId: activeGridItemId, items: stories, @@ -90,7 +90,7 @@ const StoryGridView = ({ const newFocusId = returnStoryFocusId?.value; setActiveGridItemId(newFocusId); // grab the menu button and refocus - const firstFocusableElement = itemRefs.current?.[ + const firstFocusableElement = itemsRef.current?.[ newFocusId ]?.querySelectorAll(['button', 'a'])?.[0]; @@ -171,7 +171,7 @@ const StoryGridView = ({ onFocus={() => setActiveGridItemId(story.id)} isActive={activeGridItemId === story.id} ref={(el) => { - itemRefs.current[story.id] = el; + itemsRef.current[story.id] = el; }} key={story.id} pageSize={pageSize} diff --git a/packages/dashboard/src/app/views/myStories/index.js b/packages/dashboard/src/app/views/myStories/index.js index 0797034ff964..97b1a5228b4f 100644 --- a/packages/dashboard/src/app/views/myStories/index.js +++ b/packages/dashboard/src/app/views/myStories/index.js @@ -79,13 +79,13 @@ function MyStoriesView() { ); const { apiCallbacks, canViewDefaultTemplates } = useConfig(); - const isMounted = useRef(false); + const isMountedRef = useRef(false); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); diff --git a/packages/dashboard/src/components/cardGallery/index.js b/packages/dashboard/src/components/cardGallery/index.js index 8810f7e108b6..47386b21c433 100644 --- a/packages/dashboard/src/components/cardGallery/index.js +++ b/packages/dashboard/src/components/cardGallery/index.js @@ -55,7 +55,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) { const [focusedGridItemIndex, setFocusedGridItemIndex] = useState(); const containerRef = useRef(); const gridRef = useRef(); - const posterRefs = useRef({}); + const postersRef = useRef({}); const handleMiniCardClick = useCallback((index) => { setSelectedGridItemIndex(index); @@ -77,7 +77,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) { useGridViewKeys({ containerRef, gridRef, - itemRefs: posterRefs, + itemRefs: postersRef, isRTL, currentItemId: focusedGridItemIndex, items: galleryPosters, @@ -96,7 +96,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) {
{ - posterRefs.current[index] = el; + postersRef.current[index] = el; }} onFocus={() => handleGalleryItemFocus(index)} > diff --git a/packages/dashboard/src/components/interfaceSkeleton/index.js b/packages/dashboard/src/components/interfaceSkeleton/index.js index b0779e19ef02..811e839ad5d1 100644 --- a/packages/dashboard/src/components/interfaceSkeleton/index.js +++ b/packages/dashboard/src/components/interfaceSkeleton/index.js @@ -72,9 +72,11 @@ const InterfaceSkeleton = ({ additionalRoutes }) => { addInitialFetchListener, }) ); - const isFirstLoadOnMyStories = useRef(currentPath === APP_ROUTES.DASHBOARD); + const isFirstLoadOnMyStoriesRef = useRef( + currentPath === APP_ROUTES.DASHBOARD + ); const [isRedirectComplete, setIsRedirectComplete] = useState( - !isFirstLoadOnMyStories.current + !isFirstLoadOnMyStoriesRef.current ); // Direct user to templates on first load if they @@ -83,11 +85,11 @@ const InterfaceSkeleton = ({ additionalRoutes }) => { return addInitialFetchListener?.((storyStatuses) => { if ( storyStatuses?.all <= 0 && - isFirstLoadOnMyStories.current && + isFirstLoadOnMyStoriesRef.current && canViewDefaultTemplates ) { push(APP_ROUTES.TEMPLATES_GALLERY); - isFirstLoadOnMyStories.current = false; + isFirstLoadOnMyStoriesRef.current = false; } setIsRedirectComplete(true); }); diff --git a/packages/dashboard/src/utils/useStoryView.js b/packages/dashboard/src/utils/useStoryView.js index 9ba2a8f5c1d8..6ad2b96c9be3 100644 --- a/packages/dashboard/src/utils/useStoryView.js +++ b/packages/dashboard/src/utils/useStoryView.js @@ -50,7 +50,7 @@ export default function useStoryView({ const [sort, _setSort] = useState(sortObject); const [filters, _setFilters] = useState(filtersObject); const [page, setPage] = useState(1); - const showStoriesWhileLoading = useRef(false); + const showStoriesWhileLoadingRef = useRef(false); const [initialPageReady, setInitialPageReady] = useState(false); const { pageSize } = usePagePreviewSize({ @@ -90,7 +90,7 @@ export default function useStoryView({ }, [viewStyle, setViewStyle]); const requestNextPage = useCallback(() => { - showStoriesWhileLoading.current = true; + showStoriesWhileLoadingRef.current = true; setPageClamped(page + 1); }, [page, setPageClamped]); @@ -111,7 +111,7 @@ export default function useStoryView({ useEffect(() => { // reset ref state after request is finished if (!isLoading) { - showStoriesWhileLoading.current = false; + showStoriesWhileLoadingRef.current = false; } }, [isLoading]); @@ -156,7 +156,7 @@ export default function useStoryView({ requestNextPage, }, initialPageReady, - showStoriesWhileLoading, + showStoriesWhileLoading: showStoriesWhileLoadingRef, }), [ viewStyle, diff --git a/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx b/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx index 283aaf8ff327..aece08f26e3e 100644 --- a/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx +++ b/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx @@ -62,7 +62,7 @@ function SubMenuTrigger({ ...buttonProps }: SubMenuTriggerProps) { const ref = useRef(null); - const pointerTracker = useRef<{ x?: number; y?: number }>({}); + const pointerTrackerRef = useRef<{ x?: number; y?: number }>({}); const { setFocusedId } = useContextMenu(({ actions }) => ({ setFocusedId: actions.setFocusedId, @@ -70,7 +70,7 @@ function SubMenuTrigger({ const pointerIsOutside = (node: Element) => { const { x, y, width, height } = node.getBoundingClientRect(); - const { x: pointerX, y: pointerY } = pointerTracker.current; + const { x: pointerX, y: pointerY } = pointerTrackerRef.current; if (pointerX === undefined || pointerY === undefined) { return true; } @@ -118,8 +118,8 @@ function SubMenuTrigger({ const onPointerMove = (e: Event) => { if (e instanceof PointerEvent) { // Track the pointer when moving inside the menu while the submenu is open. - pointerTracker.current.x = e.clientX; - pointerTracker.current.y = e.clientY; + pointerTrackerRef.current.x = e.clientX; + pointerTrackerRef.current.y = e.clientY; maybeCloseSubMenu(); } }; @@ -162,7 +162,7 @@ function SubMenuTrigger({ onPointerEnter={openSubMenu} onPointerLeave={() => { // Reset tracker in case we moved out of the menu fully. - pointerTracker.current = {}; + pointerTrackerRef.current = {}; maybeCloseSubMenu(); }} onClick={(e: MouseEvent) => e.preventDefault()} diff --git a/packages/design-system/src/components/datalist/list/list.tsx b/packages/design-system/src/components/datalist/list/list.tsx index 713512c56b8d..b39a1777beae 100644 --- a/packages/design-system/src/components/datalist/list/list.tsx +++ b/packages/design-system/src/components/datalist/list/list.tsx @@ -81,7 +81,7 @@ function OptionListWithRef( const listRef = useForwardedRef(forwardedListRef); const optionsRef = useRef<(HTMLLIElement | null)[]>([]); const [focusIndex, setFocusIndex] = useState(-1); - const userSeenOptions = useRef([]); + const userSeenOptionsRef = useRef([]); /* * KEYWORD FILTERING @@ -134,11 +134,11 @@ function OptionListWithRef( .filter((t): t is HTMLElement => t instanceof HTMLElement) .map((target) => target.dataset.option) .filter((o): o is string => Boolean(o)); - userSeenOptions.current = addUniqueEntries( - userSeenOptions.current, + userSeenOptionsRef.current = addUniqueEntries( + userSeenOptionsRef.current, ...newlySeenOptions ); - onObserve(userSeenOptions.current); + onObserve(userSeenOptionsRef.current); } }, { diff --git a/packages/design-system/src/components/input/useNumericInput.tsx b/packages/design-system/src/components/input/useNumericInput.tsx index 7829d7835717..794569dd7bfb 100644 --- a/packages/design-system/src/components/input/useNumericInput.tsx +++ b/packages/design-system/src/components/input/useNumericInput.tsx @@ -45,8 +45,8 @@ const useNumericInput = ({ }: UseNumericInputProps) => { const _inputRef = useRef(null); const inputRef = ref && 'current' in ref ? ref : _inputRef; - const oldValue = useRef(value); - const revertToOriginal = useRef(false); + const oldValueRef = useRef(value); + const revertToOriginalRef = useRef(false); const [currentValue, setCurrentValue] = useState(value); const options = useMemo( () => ({ allowEmpty, isFloat, padZero, max, min }), @@ -58,9 +58,9 @@ const useNumericInput = ({ */ const handleBlur = useCallback( (ev: unknown) => { - let newValue = parseInput(oldValue.current, options); + let newValue = parseInput(oldValueRef.current, options); - if (!revertToOriginal.current && newValue !== null) { + if (!revertToOriginalRef.current && newValue !== null) { const parsedValue = parseInput(currentValue, options); if (parsedValue !== null) { @@ -70,11 +70,11 @@ const useNumericInput = ({ newValue = parseInput(currentValue, options); } - revertToOriginal.current = false; + revertToOriginalRef.current = false; if (newValue !== null) { // Set newly updated value. setCurrentValue(newValue); - if (newValue !== oldValue.current) { + if (newValue !== oldValueRef.current) { onChange(ev, newValue); } } else if (min !== undefined) { @@ -205,14 +205,14 @@ const useNumericInput = ({ * Blur input and revert value to original value */ const handleEsc = useCallback(() => { - setCurrentValue(oldValue.current); - revertToOriginal.current = true; + setCurrentValue(oldValueRef.current); + revertToOriginalRef.current = true; inputRef?.current?.blur(); }, [inputRef]); useEffect(() => { // update internal value when `value` prop changes - oldValue.current = value; + oldValueRef.current = value; setCurrentValue(value); }, [value]); @@ -225,7 +225,7 @@ const useNumericInput = ({ handleChange, handleEsc, handleKeyUpAndDown, - isIndeterminate: oldValue.current === currentValue, + isIndeterminate: oldValueRef.current === currentValue, }; }; diff --git a/packages/design-system/src/components/popup/popup.tsx b/packages/design-system/src/components/popup/popup.tsx index 36f11985b70e..cb3e8b3b0495 100644 --- a/packages/design-system/src/components/popup/popup.tsx +++ b/packages/design-system/src/components/popup/popup.tsx @@ -82,12 +82,12 @@ function Popup({ offset: Offset; height: number | null; } | null>(null); - const isMounted = useRef(false); + const isMountedRef = useRef(false); const popup = useRef(null); const positionPopup = useCallback( (evt?: unknown) => { - if (!isMounted.current || !anchor?.current) { + if (!isMountedRef.current || !anchor?.current) { return; } // If scrolling within the popup, ignore. @@ -182,9 +182,9 @@ function Popup({ ); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); @@ -202,18 +202,18 @@ function Popup({ if (!isOpen) { return undefined; } - isMounted.current = true; + isMountedRef.current = true; positionPopup(); // Adjust the position when scrolling. document.addEventListener('scroll', positionPopup, true); return () => { document.removeEventListener('scroll', positionPopup, true); - isMounted.current = false; + isMountedRef.current = false; }; }, [isOpen, positionPopup]); useLayoutEffect(() => { - if (!isMounted.current) { + if (!isMountedRef.current) { return; } diff --git a/packages/design-system/src/components/tooltip/tooltip.tsx b/packages/design-system/src/components/tooltip/tooltip.tsx index a68bae5db5c0..28f21c31758c 100644 --- a/packages/design-system/src/components/tooltip/tooltip.tsx +++ b/packages/design-system/src/components/tooltip/tooltip.tsx @@ -131,11 +131,11 @@ function Tooltip({ const tooltipRef = useRef(null); const placementRef = useRef(placement); const [dynamicPlacement, setDynamicPlacement] = useState(placement); - const isMounted = useRef(false); + const isMountedRef = useRef(false); const [popupState, setPopupState] = useState<{ offset?: Offset }>({}); - const isPopupMounted = useRef(false); - const popup = useRef(null); + const isPopupMountedRef = useRef(false); + const popupRef = useRef(null); const isOpen = Boolean(shown && (shortcut || title)); const [dynamicOffset, setDynamicOffset] = useState<{ x?: number }>({}); @@ -160,7 +160,7 @@ function Tooltip({ ); const positionPopup = useCallback(() => { - if (!isPopupMounted.current || !anchorRef?.current) { + if (!isPopupMountedRef.current || !anchorRef?.current) { return; } setPopupState({ @@ -169,7 +169,7 @@ function Tooltip({ placement: dynamicPlacement, spacing, anchor: getAnchor(), - popup, + popup: popupRef, isRTL, ignoreMaxOffsetY: true, }) @@ -239,10 +239,10 @@ function Tooltip({ const resetPlacement = useDebouncedCallback(() => { setDynamicPlacement(placementRef.current); }, 100); - const delay = useRef | null>(null); + const delayRef = useRef | null>(null); const onHover = useCallback(() => { const handle = () => { - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -255,11 +255,11 @@ function Tooltip({ // Show instantly handle(); } - if (delay.current) { - clearTimeout(delay.current); + if (delayRef.current) { + clearTimeout(delayRef.current); } // Invoke in DELAY_MS - delay.current = setTimeout(handle, DELAY_MS); + delayRef.current = setTimeout(handle, DELAY_MS); } else { handle(); } @@ -267,8 +267,8 @@ function Tooltip({ const onHoverOut = useCallback(() => { setShown(false); resetPlacement(); - if (isDelayed && delay.current) { - clearTimeout(delay.current); + if (isDelayed && delayRef.current) { + clearTimeout(delayRef.current); if (shown) { lastVisibleDelayedTooltip = performance.now(); } @@ -276,18 +276,18 @@ function Tooltip({ }, [resetPlacement, isDelayed, shown]); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); useEffect(() => { - isPopupMounted.current = true; + isPopupMountedRef.current = true; return () => { - isPopupMounted.current = false; + isPopupMountedRef.current = false; }; }, []); @@ -295,19 +295,19 @@ function Tooltip({ if (!isOpen) { return undefined; } - isPopupMounted.current = true; + isPopupMountedRef.current = true; positionPopup(); // Adjust the position when scrolling. document.addEventListener('scroll', positionPopup, true); return () => { document.removeEventListener('scroll', positionPopup, true); - isPopupMounted.current = false; + isPopupMountedRef.current = false; }; }, [isOpen, positionPopup]); useLayoutEffect(() => { - if (!isPopupMounted.current) { + if (!isPopupMountedRef.current) { return; } @@ -339,7 +339,7 @@ function Tooltip({ {popupState?.offset && isOpen ? createPortal( (ref: React.ForwardedRef) { const wrappedRef = useRef<{ current: T | null }>({ current: null }); - const reference = useRef(null); + const referenceRef = useRef(null); Object.defineProperty(wrappedRef.current, 'current', { - get: () => reference.current, + get: () => referenceRef.current, set: (value: T | null) => { - if (!Object.is(reference.current, value)) { - reference.current = value; + if (!Object.is(referenceRef.current, value)) { + referenceRef.current = value; if (!ref) { return; } if (typeof ref === 'function') { - ref(reference.current); + ref(referenceRef.current); } else { - ref.current = reference.current; + ref.current = referenceRef.current; } } }, diff --git a/packages/element-library/src/media/edit.tsx b/packages/element-library/src/media/edit.tsx index bf1eaf8f6b73..e3c7dded8b00 100644 --- a/packages/element-library/src/media/edit.tsx +++ b/packages/element-library/src/media/edit.tsx @@ -153,29 +153,29 @@ function MediaEdit({ const [cropBox, setCropBox] = useState(null); const elementRef = useRef(null); - const isUpdatedLocally = useRef(false); - const lastLocalProperties = useRef>({ scale } as Partial); + const isUpdatedLocallyRef = useRef(false); + const lastLocalPropertiesRef = useRef>({ scale } as Partial); const updateLocalProperties = useCallback( (properties: Partial | ((p: Partial) => Partial)) => { - lastLocalProperties.current = { - ...lastLocalProperties.current, + lastLocalPropertiesRef.current = { + ...lastLocalPropertiesRef.current, ...(typeof properties === 'function' - ? properties(lastLocalProperties.current) + ? properties(lastLocalPropertiesRef.current) : properties), }; - isUpdatedLocally.current = true; - setLocalProperties(lastLocalProperties.current); + isUpdatedLocallyRef.current = true; + setLocalProperties(lastLocalPropertiesRef.current); }, [setLocalProperties] ); const updateProperties = useCallback(() => { - if (!isUpdatedLocally.current) { + if (!isUpdatedLocallyRef.current) { return; } - isUpdatedLocally.current = false; - const properties: Partial = lastLocalProperties.current; + isUpdatedLocallyRef.current = false; + const properties: Partial = lastLocalPropertiesRef.current; updateElementById({ elementId: id, properties }); }, [id, updateElementById]); diff --git a/packages/rich-text/src/provider.tsx b/packages/rich-text/src/provider.tsx index 4acd951f7ed3..cd936797e301 100644 --- a/packages/rich-text/src/provider.tsx +++ b/packages/rich-text/src/provider.tsx @@ -58,7 +58,7 @@ export interface RichTextProviderProps { } function RichTextProvider({ children, editingState }: RichTextProviderProps) { const [editorState, setEditorState] = useState(null); - const lastKnownStyle = useRef(null); + const lastKnownStyleRef = useRef(null); const selectionInfo = useMemo(() => { if (editorState) { @@ -81,7 +81,7 @@ function RichTextProvider({ children, editingState }: RichTextProviderProps) { if (selection) { state = EditorState.forceSelection(state, selection); } - lastKnownStyle.current = state.getCurrentInlineStyle(); + lastKnownStyleRef.current = state.getCurrentInlineStyle(); setEditorState(state); }, [editingState, setEditorState] @@ -100,14 +100,14 @@ function RichTextProvider({ children, editingState }: RichTextProviderProps) { let filteredState = getFilteredState(newEditorState, editorState); const isEmpty = filteredState?.getCurrentContent().getPlainText('') === ''; - if (isEmpty && lastKnownStyle.current) { + if (isEmpty && lastKnownStyleRef.current) { // Copy last known current style as inline style filteredState = EditorState.setInlineStyleOverride( filteredState, - lastKnownStyle.current + lastKnownStyleRef.current ); } else { - lastKnownStyle.current = filteredState.getCurrentInlineStyle(); + lastKnownStyleRef.current = filteredState.getCurrentInlineStyle(); } setEditorState(filteredState); }, diff --git a/packages/rich-text/src/useSelectionManipulation.ts b/packages/rich-text/src/useSelectionManipulation.ts index 21710136c05d..481a3e8e9cc5 100644 --- a/packages/rich-text/src/useSelectionManipulation.ts +++ b/packages/rich-text/src/useSelectionManipulation.ts @@ -37,14 +37,14 @@ function useSelectionManipulation( editorState: EditorState | null, setEditorState: Dispatch> ): Record { - const lastKnownState = useRef(null); - const lastKnownSelection = useRef(null); + const lastKnownStateRef = useRef(null); + const lastKnownSelectionRef = useRef(null); useEffect(() => { - lastKnownState.current = editorState; + lastKnownStateRef.current = editorState; if (!editorState) { - lastKnownSelection.current = null; + lastKnownSelectionRef.current = null; } else if (editorState.getSelection().getHasFocus()) { - lastKnownSelection.current = editorState.getSelection(); + lastKnownSelectionRef.current = editorState.getSelection(); } }, [editorState]); @@ -53,8 +53,8 @@ function useSelectionManipulation( updater: (state: EditorState | null) => EditorState, shouldForceFocus = true ) => { - const oldState = lastKnownState.current; - const selection = lastKnownSelection.current; + const oldState = lastKnownStateRef.current; + const selection = lastKnownSelectionRef.current; const workingState = shouldForceFocus && oldState && selection ? EditorState.forceSelection(oldState, selection) diff --git a/packages/stories-block/src/block/components/storyPicker/selectStories.js b/packages/stories-block/src/block/components/storyPicker/selectStories.js index 498c7aef9e58..c1bc9165cab5 100644 --- a/packages/stories-block/src/block/components/storyPicker/selectStories.js +++ b/packages/stories-block/src/block/components/storyPicker/selectStories.js @@ -132,7 +132,7 @@ function SelectStories({ const [authorKeyword, setAuthorKeyword] = useState(''); const [order, setOrder] = useState('desc'); const [orderBy, setOrderBy] = useState('modified'); - const nextPage = useRef(1); + const nextPageRef = useRef(1); const { authors } = useSelect( (select) => { @@ -158,17 +158,17 @@ function SelectStories({ search: searchKeyword || undefined, order, orderby: orderBy, - page: nextPage.current, + page: nextPageRef.current, }); }, [searchKeyword, currentAuthor, fetchStories, order, orderBy]); useEffect(() => { - nextPage.current = 1; + nextPageRef.current = 1; fetchSelectedStories(); }, [searchKeyword, currentAuthor, order, orderBy, fetchSelectedStories]); const onLoadMoreClick = useCallback(() => { - nextPage.current++; + nextPageRef.current++; fetchSelectedStories(); }, [fetchSelectedStories]); diff --git a/packages/story-editor/src/app/api/apiProvider.tsx b/packages/story-editor/src/app/api/apiProvider.tsx index e23580815446..f3b2cd62dbeb 100644 --- a/packages/story-editor/src/app/api/apiProvider.tsx +++ b/packages/story-editor/src/app/api/apiProvider.tsx @@ -44,20 +44,20 @@ const filterTemplates = (templates: Template[], search: string): Template[] => { function APIProvider({ children }: PropsWithChildren>) { const { apiCallbacks: actions, cdnURL } = useConfig(); - const pageTemplates = useRef([]); + const pageTemplatesRef = useRef([]); actions.getPageTemplates = useCallback( async (search: string) => { // check if pageTemplates have been loaded yet - if (pageTemplates.current.length === 0) { - pageTemplates.current = filterTemplates( + if (pageTemplatesRef.current.length === 0) { + pageTemplatesRef.current = filterTemplates( await getAllTemplates({ cdnURL, }), search ); } - return filterTemplates(pageTemplates.current, search); + return filterTemplates(pageTemplatesRef.current, search); }, [cdnURL] ); diff --git a/packages/story-editor/src/app/canvas/canvasProvider.tsx b/packages/story-editor/src/app/canvas/canvasProvider.tsx index 18e1471330c6..e5f513fb8aeb 100644 --- a/packages/story-editor/src/app/canvas/canvasProvider.tsx +++ b/packages/story-editor/src/app/canvas/canvasProvider.tsx @@ -56,7 +56,7 @@ function CanvasProvider({ children }: PropsWithChildren) { const [boundingBoxes, setBoundingBoxes] = useState({}); const [lastSelectionEvent, setLastSelectionEvent] = useState(null); - const lastSelectedElementId = useRef(null); + const lastSelectedElementIdRef = useRef(null); const [canvasContainer, setCanvasContainer] = useState(null); const [pageContainer, setPageContainer] = useState(null); const [fullbleedContainer, setFullbleedContainer] = useState( @@ -158,10 +158,10 @@ function CanvasProvider({ children }: PropsWithChildren) { // Skip the focus that immediately follows mouse event. // Use the reference to the latest element because the events come in the // sequence in the same event loop. - if (lastSelectedElementId.current === elId && evt.type === 'focus') { + if (lastSelectedElementIdRef.current === elId && evt.type === 'focus') { return; } - lastSelectedElementId.current = elId; + lastSelectedElementIdRef.current = elId; if (evt.shiftKey) { toggleElementInSelection({ elementId: elId, withLinked: !evt.altKey }); } else { @@ -210,10 +210,10 @@ function CanvasProvider({ children }: PropsWithChildren) { clearEditing(); } if ( - lastSelectedElementId.current && - !selectedElementIds.includes(lastSelectedElementId.current) + lastSelectedElementIdRef.current && + !selectedElementIds.includes(lastSelectedElementIdRef.current) ) { - lastSelectedElementId.current = null; + lastSelectedElementIdRef.current = null; } }, [editingElement, selectedElementIds, clearEditing]); diff --git a/packages/story-editor/src/app/font/fontProvider.tsx b/packages/story-editor/src/app/font/fontProvider.tsx index 048df3a9764c..b507bbe8795f 100644 --- a/packages/story-editor/src/app/font/fontProvider.tsx +++ b/packages/story-editor/src/app/font/fontProvider.tsx @@ -167,22 +167,22 @@ function FontProvider({ children }: PropsWithChildren) { [recentFonts] ); - const menuFonts = useRef([]); + const menuFontsRef = useRef([]); const ensureMenuFontsLoaded = useCallback((fontsToLoad: string[]) => { const newMenuFonts = fontsToLoad.filter( - (fontName) => !menuFonts.current.includes(fontName) + (fontName) => !menuFontsRef.current.includes(fontName) ); if (!newMenuFonts?.length) { return; } - menuFonts.current = menuFonts.current.concat(newMenuFonts); + menuFontsRef.current = menuFontsRef.current.concat(newMenuFonts); // Create new in head with ref to new font families const families = encodeURIComponent(newMenuFonts.join('|')); const url = `${GOOGLE_MENU_FONT_URL}?family=${families}&subset=menu&display=swap`; loadStylesheet(url, 'web-stories-google-fonts-menu-css').catch(() => { // If they failed to load, remove from array again! - menuFonts.current = menuFonts.current.filter( + menuFontsRef.current = menuFontsRef.current.filter( (font) => !newMenuFonts.includes(font) ); }); diff --git a/packages/story-editor/src/app/history/historyProvider.tsx b/packages/story-editor/src/app/history/historyProvider.tsx index 1bd4e9d6c764..1fed04faf733 100644 --- a/packages/story-editor/src/app/history/historyProvider.tsx +++ b/packages/story-editor/src/app/history/historyProvider.tsx @@ -52,7 +52,7 @@ function HistoryProvider({ const [hasNewChanges, setHasNewChanges] = useState(false); const setPreventUnload = usePreventWindowUnload(); // The version number for the initially loaded (saved) state is 1. - const savedVersionNumber = useRef(1); + const savedVersionNumberRef = useRef(1); useEffect(() => { setPreventUnload('history', hasNewChanges); @@ -60,12 +60,12 @@ function HistoryProvider({ }, [setPreventUnload, hasNewChanges]); useEffect(() => { - setHasNewChanges(versionNumber !== savedVersionNumber.current); + setHasNewChanges(versionNumber !== savedVersionNumberRef.current); }, [versionNumber]); const resetNewChanges = useCallback(() => { // When new changes are saved, let's track which version was saved. - savedVersionNumber.current = versionNumber; + savedVersionNumberRef.current = versionNumber; setHasNewChanges(false); }, [versionNumber]); diff --git a/packages/story-editor/src/app/media/local/useContextValueProvider.js b/packages/story-editor/src/app/media/local/useContextValueProvider.js index e36a511f709e..04be9324f227 100644 --- a/packages/story-editor/src/app/media/local/useContextValueProvider.js +++ b/packages/story-editor/src/app/media/local/useContextValueProvider.js @@ -72,13 +72,13 @@ export default function useContextValueProvider(reducerState, reducerActions) { actions: { getMedia, updateMedia }, } = useAPI(); - const isMounted = useRef(false); + const isMountedRef = useRef(false); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); @@ -104,7 +104,7 @@ export default function useContextValueProvider(reducerState, reducerActions) { pagingNum: p, }) .then(({ data, headers }) => { - if (!isMounted.current) { + if (!isMountedRef.current) { return; } diff --git a/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts b/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts index 81f319cc1b75..f4ae0d2354e0 100644 --- a/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts +++ b/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts @@ -105,7 +105,7 @@ function useMediaUploadQueue() { const { uploadVideoPoster } = useUploadVideoFrame({}); - const isMounted = useRef(false); + const isMountedRef = useRef(false); const currentTranscodingItem = useRef(null); const currentPosterGenerationItem = useRef(null); @@ -150,7 +150,7 @@ function useMediaUploadQueue() { const { resource: newResource, posterFile } = await getResourceFromLocalFile(file); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -204,7 +204,7 @@ function useMediaUploadQueue() { height, }; - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -270,7 +270,7 @@ function useMediaUploadQueue() { try { const newFile = await convertGifToVideo(file); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -304,7 +304,7 @@ function useMediaUploadQueue() { const { start, end } = trimData; const newFile = await trimVideo(file, start, end); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -331,7 +331,7 @@ function useMediaUploadQueue() { try { const newFile = await stripAudioFromVideo(file); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -364,7 +364,7 @@ function useMediaUploadQueue() { const newFile = await cropResource(file, additionalData.cropParams); const posterFile = await getFirstFrameOfVideo(newFile); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -397,7 +397,7 @@ function useMediaUploadQueue() { try { const newFile = await transcodeVideo(file); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -435,7 +435,7 @@ function useMediaUploadQueue() { additionalData )) as QueueItemResource; - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -455,7 +455,7 @@ function useMediaUploadQueue() { posterFile ); - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -483,7 +483,7 @@ function useMediaUploadQueue() { additionalData )) as ImageResource; - if (!isMounted.current) { + if (!isMountedRef.current) { return; } @@ -674,10 +674,10 @@ function useMediaUploadQueue() { }, [state.queue, uploadItem]); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); diff --git a/packages/story-editor/src/components/autoSaveHandler/index.js b/packages/story-editor/src/components/autoSaveHandler/index.js index 9ca4a9b2b489..adbf758c732c 100644 --- a/packages/story-editor/src/components/autoSaveHandler/index.js +++ b/packages/story-editor/src/components/autoSaveHandler/index.js @@ -37,9 +37,9 @@ function AutoSaveHandler() { const isUploading = useIsUploadingToStory(); // Cache it to make it stable in terms of the below timeout - const cachedSaveStory = useRef(autoSave); + const cachedSaveStoryRef = useRef(autoSave); useEffect(() => { - cachedSaveStory.current = autoSave; + cachedSaveStoryRef.current = autoSave; }, [autoSave]); useEffect(() => { @@ -50,7 +50,7 @@ function AutoSaveHandler() { // back false after the save. // This timeout will thus be re-started when some new change occurs after an autosave. const timeout = setTimeout( - () => cachedSaveStory.current(), + () => cachedSaveStoryRef.current(), autoSaveInterval * 1000 ); diff --git a/packages/story-editor/src/components/canvas/editLayer.js b/packages/story-editor/src/components/canvas/editLayer.js index e344b673848b..b7b0c78af79e 100644 --- a/packages/story-editor/src/components/canvas/editLayer.js +++ b/packages/story-editor/src/components/canvas/editLayer.js @@ -106,19 +106,19 @@ function EditLayerForElement({ element, showOverflow }) { return () => focusCanvas(/* force */ false); }, [focusCanvas]); - const moveable = useRef(null); + const moveableRef = useRef(null); const setRef = useCallback( - (moveableRef) => { - moveable.current = moveableRef; - onMoveableMount?.(moveableRef); + (newMoveable) => { + moveableRef.current = newMoveable; + onMoveableMount?.(newMoveable); }, [onMoveableMount] ); const onResize = useCallback(() => { // Update moveable when resizing. - if (moveable.current) { - moveable.current.updateRect(); + if (moveableRef.current) { + moveableRef.current.updateRect(); } }, []); diff --git a/packages/story-editor/src/components/canvas/eyedropperLayer.js b/packages/story-editor/src/components/canvas/eyedropperLayer.js index eff556ca9de1..8c7cf1833a16 100644 --- a/packages/story-editor/src/components/canvas/eyedropperLayer.js +++ b/packages/story-editor/src/components/canvas/eyedropperLayer.js @@ -151,10 +151,10 @@ function EyedropperLayer() { const fullHeight = pageWidth / FULLBLEED_RATIO; const img = eyedropperImg; const imgRef = useRef(); - const magnifier = useRef(); - const magnifierInfo = useRef(); - const magnifierColor = useRef(); - const eyedropperCanvas = useRef(); + const magnifierRef = useRef(); + const magnifierInfoRef = useRef(); + const magnifierColorRef = useRef(); + const eyedropperCanvasRef = useRef(); const closeEyedropper = () => { setIsEyedropperActive(false); @@ -162,7 +162,7 @@ function EyedropperLayer() { setEyedropperPixelData(null); }; - useFocusOut(eyedropperCanvas, closeEyedropper, [isEyedropperActive, img]); + useFocusOut(eyedropperCanvasRef, closeEyedropper, [isEyedropperActive, img]); useGlobalKeyDownEffect('esc', closeEyedropper); @@ -185,7 +185,7 @@ function EyedropperLayer() { } const magnify = (x, y) => { - const canvas = magnifier.current; + const canvas = magnifierRef.current; if (canvas) { const ctx = canvas.getContext('2d'); @@ -227,14 +227,14 @@ function EyedropperLayer() { const y = (e.clientY - top) * (fullHeight / height); if (x < 0 || y < 0 || x > width || y > height) { - magnifierInfo.current.style.display = 'none'; + magnifierInfoRef.current.style.display = 'none'; return; } else { - magnifierInfo.current.style.display = 'block'; + magnifierInfoRef.current.style.display = 'block'; } // Move magnifier canvas. - magnifierInfo.current.style.transform = `translate(${ + magnifierInfoRef.current.style.transform = `translate(${ x - MAGNIFIER_SIZE / 2 }px, ${y}px)`; @@ -245,14 +245,14 @@ function EyedropperLayer() { const rgbaObject = getColorFromPixelData(eyedropperPixelData, x, y, width); const { r, g, b, a } = rgbaObject; const hex = rgba(r, g, b, a); - magnifierColor.current.style.background = `rgba(${r},${g},${b},${a})`; - magnifierColor.current.style.color = readableColor( + magnifierColorRef.current.style.background = `rgba(${r},${g},${b},${a})`; + magnifierColorRef.current.style.color = readableColor( hex, '#333', '#EDEDED', false ); - magnifierColor.current.innerText = hex; + magnifierColorRef.current.innerText = hex; }; const onClick = (e) => { @@ -278,17 +278,17 @@ function EyedropperLayer() { {/* Remove the safe zone so we don't have to move the canvas image up (we have fullbleed image). */} {/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions -- No pixel-by-pixel keyboard navigation. */} - + - + - + diff --git a/packages/story-editor/src/components/canvas/layout.js b/packages/story-editor/src/components/canvas/layout.js index dfb5ea75f78a..0f31354d156b 100644 --- a/packages/story-editor/src/components/canvas/layout.js +++ b/packages/story-editor/src/components/canvas/layout.js @@ -408,13 +408,13 @@ const PageArea = forwardRef(function PageArea( ); // We need to ref scroll, because scroll changes should not update a non-controlled layer - const scroll = useRef(); - scroll.current = { top: scrollTop, left: scrollLeft }; + const scrollRef = useRef(); + scrollRef.current = { top: scrollTop, left: scrollLeft }; // If zoom setting changes for a non-controlled layer, make sure to reset actual scroll inside container useEffect(() => { if (!isControlled) { - fullbleedRef.current.scrollTop = scroll.current.top; - fullbleedRef.current.scrollLeft = scroll.current.left; + fullbleedRef.current.scrollTop = scrollRef.current.top; + fullbleedRef.current.scrollLeft = scrollRef.current.left; } }, [isControlled, zoomSetting, fullbleedRef]); diff --git a/packages/story-editor/src/components/colorPicker/colorPicker.js b/packages/story-editor/src/components/colorPicker/colorPicker.js index 351cde0dee81..6cf6aa49de52 100644 --- a/packages/story-editor/src/components/colorPicker/colorPicker.js +++ b/packages/story-editor/src/components/colorPicker/colorPicker.js @@ -124,16 +124,16 @@ function ColorPicker({ // So, if the eyedropper is used from inside a floating menu color picker // the debounced onChange can never be seen. // this gives us a way to process that change when no longer mounted - const isMounted = useRef(true); + const isMountedRef = useRef(true); useEffect(() => { return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); const handleColorChange = useCallback( (newColor) => { - if (isMounted.current) { + if (isMountedRef.current) { onDebouncedChange(newColor); } else { onChange(newColor); diff --git a/packages/story-editor/src/components/colorPicker/currentColorPicker.js b/packages/story-editor/src/components/colorPicker/currentColorPicker.js index 5075f922f17e..40fb54a90813 100644 --- a/packages/story-editor/src/components/colorPicker/currentColorPicker.js +++ b/packages/story-editor/src/components/colorPicker/currentColorPicker.js @@ -259,23 +259,23 @@ const CurrentColorPickerContext = createContext([false, false]); const DynamicImportWrapper = () => { return (...args) => { function DynamicFetcher({ showOpacity, hasEyedropper, ...props }) { - const isMounted = useRef(false); + const isMountedRef = useRef(false); const [Picker, setPicker] = useState(null); useEffect(() => { - isMounted.current = true; + isMountedRef.current = true; import( /* webpackChunkName: "chunk-react-color" */ /* webpackExports: "CustomPicker" */ '@hello-pangea/color-picker' ).then(({ CustomPicker }) => { - if (isMounted.current) { + if (isMountedRef.current) { setPicker({ component: CustomPicker(...args) }); } }); return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); diff --git a/packages/story-editor/src/components/colorPicker/customColorPicker.js b/packages/story-editor/src/components/colorPicker/customColorPicker.js index d2b67aecfdd9..880805b348bc 100644 --- a/packages/story-editor/src/components/colorPicker/customColorPicker.js +++ b/packages/story-editor/src/components/colorPicker/customColorPicker.js @@ -65,10 +65,10 @@ function CustomColorPicker({ }, } = useColor(); - const isMounted = useRef(true); + const isMountedRef = useRef(true); useEffect(() => { return () => { - isMounted.current = false; + isMountedRef.current = false; }; }, []); @@ -96,7 +96,7 @@ function CustomColorPicker({ // check for unmount and if so, we know this change event // is from the eyedropper so we can just grab the rgb and // trigger the rest of the change for the element. - if (!isMounted.current && e?.rgb) { + if (!isMountedRef.current && e?.rgb) { handleColorChange({ color: e.rgb }); } }, diff --git a/packages/story-editor/src/components/colorPicker/gradientLine.js b/packages/story-editor/src/components/colorPicker/gradientLine.js index 83189b12850b..6023bf60bfde 100644 --- a/packages/story-editor/src/components/colorPicker/gradientLine.js +++ b/packages/story-editor/src/components/colorPicker/gradientLine.js @@ -96,7 +96,7 @@ function GradientLine({ useKeyMoveStop(line, onMove); useKeyAddStop(line, onAdd, stops, currentStopIndex); useKeyDeleteStop(line, onDelete); - const stopRefs = useKeyFocus(line, stops, currentStopIndex); + const stopsRef = useKeyFocus(line, stops, currentStopIndex); usePointerMoveStop(line, onMove); const tempPointerPosition = usePointerAddStop(line, onAdd); @@ -109,7 +109,7 @@ function GradientLine({ {stops.map(({ position, color }, index) => ( (stopRefs[index].current = ref)} + ref={(ref) => (stopsRef[index].current = ref)} key={ // eslint-disable-next-line react/no-array-index-key -- Should be OK here. index diff --git a/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js b/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js index 0d69ae0fe3c5..6dd5e1d36072 100644 --- a/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js +++ b/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js @@ -26,17 +26,17 @@ import { LINE_LENGTH } from './constants'; import { getPageX, setPointerCapture, releasePointerCapture } from './utils'; function usePointerMoveStop(ref, onMove) { - const lastPageX = useRef(null); + const lastPageXRef = useRef(null); useLayoutEffect(() => { const node = ref.current; const onPointerMove = (evt) => { - const relativeDeltaX = getPageX(evt) - lastPageX.current; - lastPageX.current = getPageX(evt); + const relativeDeltaX = getPageX(evt) - lastPageXRef.current; + lastPageXRef.current = getPageX(evt); onMove(-relativeDeltaX / LINE_LENGTH); }; const onPointerUp = (evt) => { - lastPageX.current = null; + lastPageXRef.current = null; releasePointerCapture(evt); evt.target.removeEventListener('pointermove', onPointerMove); evt.target.removeEventListener('pointerup', onPointerUp); @@ -46,7 +46,7 @@ function usePointerMoveStop(ref, onMove) { if (evt.target === node) { return; } - lastPageX.current = getPageX(evt); + lastPageXRef.current = getPageX(evt); setPointerCapture(evt); evt.target.addEventListener('pointermove', onPointerMove); evt.target.addEventListener('pointerup', onPointerUp); diff --git a/packages/story-editor/src/components/floatingMenu/layer.js b/packages/story-editor/src/components/floatingMenu/layer.js index 2899dbe281b2..7d1fb194451f 100644 --- a/packages/story-editor/src/components/floatingMenu/layer.js +++ b/packages/story-editor/src/components/floatingMenu/layer.js @@ -76,7 +76,7 @@ function FloatingMenuLayer() { const [moveable, setMoveable] = useState(null); const menuRef = useRef(); - const workspaceSize = useRef(); + const workspaceSizeRef = useRef(); const [isDismissed, setDismissed] = useState(false); const handleDismiss = useCallback(() => setDismissed(true), []); @@ -102,7 +102,10 @@ function FloatingMenuLayer() { // Whenever the workspace resizes, update size useEffect(() => { - workspaceSize.current = { width: workspaceWidth, height: workspaceHeight }; + workspaceSizeRef.current = { + width: workspaceWidth, + height: workspaceHeight, + }; // Note that we don't have to manually update our position, because the selection // frame will already be updating because of the resize, so a DOM mutation is incoming. }, [workspaceWidth, workspaceHeight]); @@ -125,7 +128,7 @@ function FloatingMenuLayer() { // If the toolbar is positioned to the top, we keep it in a fixed position. const updatePosition = () => { const frameRect = moveable.getRect(); - const { width, height } = workspaceSize.current; + const { width, height } = workspaceSizeRef.current; if (floatingMenuPosition === TOOLBAR_POSITIONS.TOP) { menu.style.left = `clamp(0px, ${ width / 2 diff --git a/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx b/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx index 37e2149b61a2..bf9654caf652 100644 --- a/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx +++ b/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx @@ -52,7 +52,7 @@ function CarouselProvider({ ); const [listElement, setListElement] = useState(null); - const pageRefs = useRef>({}); + const pagesRef = useRef>({}); const numPages = pages.length; @@ -86,10 +86,10 @@ function CarouselProvider({ pageThumbMargin, }); - useCarouselKeys({ listElement, pageRefs }); + useCarouselKeys({ listElement, pageRefs: pagesRef }); const setPageRef = useCallback((page: Page, el: HTMLElement) => { - pageRefs.current[page.id] = el; + pagesRef.current[page.id] = el; }, []); const clickPage = useCallback( diff --git a/packages/story-editor/src/components/footer/gridview/gridView.js b/packages/story-editor/src/components/footer/gridview/gridView.js index 8654d0c09e98..ea9802e755ce 100644 --- a/packages/story-editor/src/components/footer/gridview/gridView.js +++ b/packages/story-editor/src/components/footer/gridview/gridView.js @@ -182,7 +182,7 @@ function GridView({ onClose }) { const handleClickPage = (page) => () => setCurrentPage({ pageId: page.id }); const gridRef = useRef(); - const pageRefs = useRef({}); + const pagesRef = useRef({}); const arrangeItem = useCallback( (focusedPageId, nextIndex) => { @@ -194,7 +194,7 @@ function GridView({ onClose }) { useGridViewKeys({ containerRef: wrapperRef, gridRef, - itemRefs: pageRefs, + itemRefs: pagesRef, isRTL, currentItemId: currentPageId, items: pages, @@ -254,7 +254,7 @@ function GridView({ onClose }) { { - pageRefs.current[page.id] = el; + pagesRef.current[page.id] = el; }} > `hierarchical_term_${name}`; * @param {string} option.label The label of the checkbox * @param {Function} option.onChange Change event handler * @param {boolean} option.checked The value of the checkbox - * @param {Object} option.optionRefs Ref used to store refs to checkboxes. + * @param {Object} option.optionRef Ref used to store refs to checkboxes. * @param {number} option.$level The indentation level. * @return {Node} The rendered option and children. */ -const Option = ({ optionRefs = { current: {} }, $level = 0, ...option }) => { +const Option = ({ optionRef = { current: {} }, $level = 0, ...option }) => { const { id, label, onBlur, onChange, onFocus, checked, value } = option; const optionId = buildOptionId(option.id); @@ -122,7 +122,7 @@ const Option = ({ optionRefs = { current: {} }, $level = 0, ...option }) => { { - optionRefs.current[id] = node; + optionRef.current[id] = node; }} value={value} checked={checked} @@ -141,7 +141,7 @@ const OptionPropType = { checked: PropTypes.bool, label: PropTypes.string.isRequired, $level: PropTypes.number, - optionRefs: PropTypes.shape({ + optionRef: PropTypes.shape({ current: PropTypes.shape({ [PropTypes.string.isRequired]: PropTypes.node, }), @@ -179,7 +179,7 @@ const HierarchicalInput = ({ // Focus handling const [focusedCheckboxId, setFocusedCheckboxId] = useState(-1); - const optionRefs = useRef({}); + const optionRef = useRef({}); /** * Handles listbox and checkbox focus. @@ -211,7 +211,7 @@ const HierarchicalInput = ({ setFocusedCheckboxId(firstCheckedOption ? firstCheckedOption : 0); } else { // else focus the previously focused option - optionRefs.current[focusedCheckboxId]?.focus(); + optionRef.current[focusedCheckboxId]?.focus(); } } }, @@ -295,7 +295,7 @@ const HierarchicalInput = ({ useEffect(() => { // only focus checkbox if focus is in the list if (checkboxListRef.current?.contains(document.activeElement)) { - optionRefs.current[focusedCheckboxId]?.focus(); + optionRef.current[focusedCheckboxId]?.focus(); } }, [focusedCheckboxId]); @@ -334,7 +334,7 @@ const HierarchicalInput = ({ key={option.id} {...option} onChange={handleCheckboxChange} - optionRefs={optionRefs} + optionRef={optionRef} /> )) ) : ( diff --git a/packages/story-editor/src/components/library/panes/media/common/innerElement.js b/packages/story-editor/src/components/library/panes/media/common/innerElement.js index 7f4fe3455852..a58b72978924 100644 --- a/packages/story-editor/src/components/library/panes/media/common/innerElement.js +++ b/packages/story-editor/src/components/library/panes/media/common/innerElement.js @@ -104,7 +104,7 @@ function InnerElement({ }) { const newVideoPosterRef = useRef(null); // Track if we have already set the dragging resource. - const hasSetResourceTracker = useRef(null); + const hasSetResourceRef = useRef(null); // Note: This `useDropTargets` is purposefully separated from the one below since it // uses a custom function for checking for equality and is meant for `handleDrag` and `handleDrop` only. @@ -117,11 +117,11 @@ function InnerElement({ }), (prev, curr) => { // If we're dragging this element, always update the actions. - if (hasSetResourceTracker.current) { + if (hasSetResourceRef.current) { return false; // If we're rendering the first time, init `handleDrag` and `handleDrop`. - } else if (hasSetResourceTracker.current === null) { - hasSetResourceTracker.current = false; + } else if (hasSetResourceRef.current === null) { + hasSetResourceRef.current = false; return false; } // If the drop targets updated meanwhile, also update the actions, otherwise `handleDrag` won't consider those. @@ -252,14 +252,14 @@ function InnerElement({ } const dragHandler = (event) => { - if (!hasSetResourceTracker.current) { + if (!hasSetResourceRef.current) { // Drop-targets handling. resourceList.set(resource.id, { url: thumbnailURL, type: 'cached', }); setDraggingResource(resource); - hasSetResourceTracker.current = true; + hasSetResourceRef.current = true; } handleDrag(resource, event.clientX, event.clientY); }; @@ -275,7 +275,7 @@ function InnerElement({ handleDrag={dragHandler} handleDragEnd={() => { handleDrop(resource); - hasSetResourceTracker.current = false; + hasSetResourceRef.current = false; }} type={resource.type} elementProps={{ resource }} diff --git a/packages/story-editor/src/components/library/panes/media/common/mediaElement.js b/packages/story-editor/src/components/library/panes/media/common/mediaElement.js index a9a734553c51..5e17994804f7 100644 --- a/packages/story-editor/src/components/library/panes/media/common/mediaElement.js +++ b/packages/story-editor/src/components/library/panes/media/common/mediaElement.js @@ -103,7 +103,7 @@ function Element({ const width = requestedWidth || requestedHeight / oRatio; const height = requestedHeight || width / oRatio; - const mediaElement = useRef(); + const mediaElementRef = useRef(); const [showVideoDetail, setShowVideoDetail] = useState(true); const [active, setActive] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); @@ -135,10 +135,10 @@ function Element({ if (!isMenuOpen) { if (active) { setShowVideoDetail(false); - if (mediaElement.current && hoverTimer === null) { + if (mediaElementRef.current && hoverTimer === null) { const timer = setTimeout(() => { if (activeRef.current && src) { - mediaElement.current.play().catch(noop); + mediaElementRef.current.play().catch(noop); } }, AUTOPLAY_PREVIEW_VIDEO_DELAY_MS); setHoverTimer(timer); @@ -147,10 +147,10 @@ function Element({ } else { setShowVideoDetail(true); resetHoverTime(); - if (mediaElement.current && mediaElement.current?.pause && src) { + if (mediaElementRef.current && mediaElementRef.current?.pause && src) { // Stop video and reset position. - mediaElement.current.pause(); - mediaElement.current.currentTime = 0; + mediaElementRef.current.pause(); + mediaElementRef.current.currentTime = 0; } } } @@ -198,7 +198,7 @@ function Element({ { @@ -108,7 +108,7 @@ function TemplateList({ useGridViewKeys({ containerRef: parentRef, gridRef: containerRef, - itemRefs: pageRefs, + itemRefs: pagesRef, items: pages, currentItemId: currentPageId, isRTL, @@ -127,7 +127,7 @@ function TemplateList({ (pageRefs.current[page.id] = el)} + ref={(el) => (pagesRef.current[page.id] = el)} page={page} pageSize={pageSize} onClick={() => handlePageClick(page)} @@ -140,7 +140,7 @@ function TemplateList({ )) : pages.map((page) => ( (pageRefs.current[page.id] = el)} + ref={(el) => (pagesRef.current[page.id] = el)} key={page.id} data-testid={`page_template_${page.id}`} page={page} diff --git a/packages/story-editor/src/components/library/panes/shared/chipGroup/index.js b/packages/story-editor/src/components/library/panes/shared/chipGroup/index.js index d631412bcf80..6e330971c690 100644 --- a/packages/story-editor/src/components/library/panes/shared/chipGroup/index.js +++ b/packages/story-editor/src/components/library/panes/shared/chipGroup/index.js @@ -114,7 +114,7 @@ const ChipGroup = ({ const sectionRef = useRef(); const innerContainerRef = useRef(); - const itemRefs = useRef([]); + const itemsRef = useRef([]); const [focusedRowOffset, setFocusedRowOffset] = useState(0); @@ -150,7 +150,7 @@ const ChipGroup = ({ innerContainerRef, selectedItemId, setFocusedRowOffset, - itemRefs, + itemRefs: itemsRef, offsetSpacing: FOCUS_BORDER_SPACING, }); @@ -192,7 +192,7 @@ const ChipGroup = ({ key={id} role="option" ref={(el) => { - itemRefs.current[id] = el; + itemsRef.current[id] = el; }} active={selected} aria-selected={selected} diff --git a/packages/story-editor/src/components/library/panes/shared/libraryMoveable.js b/packages/story-editor/src/components/library/panes/shared/libraryMoveable.js index 3d446ffa9b3f..858a290bca75 100644 --- a/packages/story-editor/src/components/library/panes/shared/libraryMoveable.js +++ b/packages/story-editor/src/components/library/panes/shared/libraryMoveable.js @@ -72,7 +72,7 @@ function LibraryMoveable({ const [hover, setHover] = useState(false); const cloneRef = useRef(null); const targetBoxRef = useRef(null); - const targetBoxSize = useRef(null); + const targetBoxSizeRef = useRef(null); const overlayRef = useRef(null); const moveable = useRef(null); @@ -116,10 +116,10 @@ function LibraryMoveable({ const { insertTextSetByOffset } = useInsertTextSet(); - const eventTracker = useRef({}); + const eventTrackerRef = useRef({}); const startEventTracking = (evt) => { const { timeStamp, clientX, clientY } = evt; - eventTracker.current = { + eventTrackerRef.current = { timeStamp, clientX, clientY, @@ -162,7 +162,7 @@ function LibraryMoveable({ // Don't display the clone unless we're sure it's a drag gesture if ( cloneRef.current && - areEventsDragging(eventTracker.current, inputEvent) + areEventsDragging(eventTrackerRef.current, inputEvent) ) { if (cloneRef.current.style.opacity !== 1 && !activeDropTargetId) { // We're not doing it in `onDragStart` since otherwise on clicking it would appear, too. @@ -210,7 +210,7 @@ function LibraryMoveable({ const { offsetX, offsetY } = getTargetOffset(); const targetBox = targetBoxRef.current.getBoundingClientRect(); // Let's save the original targetbox size. - targetBoxSize.current = { + targetBoxSizeRef.current = { width: targetBox.width, height: targetBox.height, }; @@ -241,9 +241,9 @@ function LibraryMoveable({ return false; } // Restore the original size of the target. - targetBoxRef.current.style.width = `${targetBoxSize.current.width}px`; - targetBoxRef.current.style.height = `${targetBoxSize.current.height}px`; - if (!areEventsDragging(eventTracker.current, inputEvent)) { + targetBoxRef.current.style.width = `${targetBoxSizeRef.current.width}px`; + targetBoxRef.current.style.height = `${targetBoxSizeRef.current.height}px`; + if (!areEventsDragging(eventTrackerRef.current, inputEvent)) { resetMoveable(); onClick(); return false; diff --git a/packages/story-editor/src/components/library/panes/text/textSets/textSets.js b/packages/story-editor/src/components/library/panes/text/textSets/textSets.js index 34d6782f6444..e909774e64c7 100644 --- a/packages/story-editor/src/components/library/panes/text/textSets/textSets.js +++ b/packages/story-editor/src/components/library/panes/text/textSets/textSets.js @@ -38,7 +38,7 @@ import { TEXT_SET_PAGE_SIZE, TEXT_SET_SIZE } from './constants'; function TextSets({ paneRef, filteredTextSets }) { const containerRef = useRef(); - const textSetRefs = useRef({}); + const textSetsRef = useRef({}); const textSetIds = useMemo( () => filteredTextSets.map((textSet) => textSet.id), @@ -68,7 +68,7 @@ function TextSets({ paneRef, filteredTextSets }) { } = useVirtualizedGridNavigation({ rowVirtualizer, containerRef, - gridItemRefs: textSetRefs, + gridItemRefs: textSetsRef, gridItemIds: textSetIds, }); @@ -104,7 +104,7 @@ function TextSets({ paneRef, filteredTextSets }) { key={gridIndex} id={textSet.id} data-testid={`text_set_${textSet.id}`} - ref={(el) => (textSetRefs.current[textSet.id] = el)} + ref={(el) => (textSetsRef.current[textSet.id] = el)} translateY={virtualRow.start} translateX={virtualColumn.start} aria-label={textSet.title} diff --git a/packages/story-editor/src/components/library/panes/text/textSets/textSetsPane.js b/packages/story-editor/src/components/library/panes/text/textSets/textSetsPane.js index b65e27d92233..828dfd1535b1 100644 --- a/packages/story-editor/src/components/library/panes/text/textSets/textSetsPane.js +++ b/packages/story-editor/src/components/library/panes/text/textSets/textSetsPane.js @@ -90,7 +90,7 @@ function TextSetsPane({ paneRef }) { }) ); const [showInUse, setShowInUse] = useState(false); - const trackChange = useRef(false); + const trackChangeRef = useRef(false); const allTextSets = useMemo(() => Object.values(textSets).flat(), [textSets]); const storyPages = useStory(({ state: { pages } }) => pages); @@ -174,18 +174,18 @@ function TextSetsPane({ paneRef }) { localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TEXT_SET_SETTINGS, { selectedCategory, }); - trackChange.current = true; + trackChangeRef.current = true; }, [speak] ); const onChangeShowInUse = useCallback(() => { requestAnimationFrame(() => setShowInUse((prevVal) => !prevVal)); - trackChange.current = true; + trackChangeRef.current = true; }, [setShowInUse]); useEffect(() => { - if (trackChange.current) { + if (trackChangeRef.current) { trackEvent('search', { search_type: 'textsets', search_term: '', diff --git a/packages/story-editor/src/components/library/panes/text/useInsertPreset.js b/packages/story-editor/src/components/library/panes/text/useInsertPreset.js index 760888b3ba8b..99194b617bc8 100644 --- a/packages/story-editor/src/components/library/panes/text/useInsertPreset.js +++ b/packages/story-editor/src/components/library/panes/text/useInsertPreset.js @@ -53,30 +53,33 @@ function useInsertPreset({ shouldUseSmartColor }) { const [autoColor, setAutoColor] = useState(null); const [presetAtts, setPresetAtts] = useState(null); - const lastPreset = useRef(null); + const lastPresetRef = useRef(null); const calculateAccessibleTextColors = useCalculateAccessibleTextColors(); useEffect(() => { // Version number change is happening due to adding a preset. // If we have set the last element but not the history version number yet, // Set the version number that was the result of adding the preset. - if (lastPreset.current?.element && !lastPreset.current.versionNumber) { - lastPreset.current.versionNumber = versionNumber; - } else if (lastPreset.current?.versionNumber) { + if ( + lastPresetRef.current?.element && + !lastPresetRef.current.versionNumber + ) { + lastPresetRef.current.versionNumber = versionNumber; + } else if (lastPresetRef.current?.versionNumber) { // If the version number changes meanwhile and we already have it set // something else changed meanwhile so clear the lastPreset, too. - lastPreset.current = null; + lastPresetRef.current = null; } }, [versionNumber]); const getPosition = useCallback((element) => { const { y } = element; - if (!lastPreset.current) { + if (!lastPresetRef.current) { return y; } const { element: { height: lastHeight, y: lastY }, - } = lastPreset.current; + } = lastPresetRef.current; let positionedY = lastY + lastHeight + POSITION_MARGIN; // Let's get the width/height of the element about to be inserted. const { width, height } = getInsertedElementSize( @@ -121,7 +124,7 @@ function useInsertPreset({ shouldUseSmartColor }) { ...elementProps, height: calculateTextHeight(elementProps, elementProps.width), }); - lastPreset.current = { + lastPresetRef.current = { versionNumber: null, element: addedElement, }; @@ -153,7 +156,7 @@ function useInsertPreset({ shouldUseSmartColor }) { ...element, ...atts, }); - lastPreset.current = { + lastPresetRef.current = { versionNumber: null, element: addedElement, }; diff --git a/packages/story-editor/src/components/localAutoSaveHandler/localAutoSave.js b/packages/story-editor/src/components/localAutoSaveHandler/localAutoSave.js index 5d93e8c8dad2..e1cae32c5f5a 100644 --- a/packages/story-editor/src/components/localAutoSaveHandler/localAutoSave.js +++ b/packages/story-editor/src/components/localAutoSaveHandler/localAutoSave.js @@ -106,34 +106,34 @@ function LocalAutoSave() { setBackup(null); }; - const didAutoSaveTracker = useRef(isAutoSavingStory); + const didAutoSaveRef = useRef(isAutoSavingStory); useEffect(() => { if (isAutoSavingStory) { - didAutoSaveTracker.current = true; + didAutoSaveRef.current = true; // If we auto-saved to DB before but are not auto-saving anymore, let's delete the local backup. // No need for both local and DB backup together. - } else if (didAutoSaveTracker.current && !backup) { + } else if (didAutoSaveRef.current && !backup) { sessionStore.deleteItemByKey(getSessionStorageKey(storyId, false)); - didAutoSaveTracker.current = false; + didAutoSaveRef.current = false; } }, [isAutoSavingStory, backup, storyId]); - const hadNewChangesTracker = useRef(false); - const wasNewTracker = useRef(isNew); + const handleNewChangesRef = useRef(false); + const wasNewRef = useRef(isNew); useEffect(() => { // If we have new changes, track that we had new changes. if (hasNewChanges) { - hadNewChangesTracker.current = true; + handleNewChangesRef.current = true; // If we don't have new changes but had before, we are in a saved state. Delete existing storage. // Let's not delete the auto-draft if the restore message is currently displayed. - } else if (hadNewChangesTracker.current && !backup) { - if (wasNewTracker.current) { + } else if (handleNewChangesRef.current && !backup) { + if (wasNewRef.current) { sessionStore.deleteItemByKey(getSessionStorageKey(null, true)); } else { sessionStore.deleteItemByKey(getSessionStorageKey(storyId, false)); } - hadNewChangesTracker.current = false; - wasNewTracker.current = isNew; + handleNewChangesRef.current = false; + wasNewRef.current = isNew; } }, [hasNewChanges, backup, storyId, isNew]); diff --git a/packages/story-editor/src/components/mediaRecording/useTrim.js b/packages/story-editor/src/components/mediaRecording/useTrim.js index 826b05de2225..faaa4eb8ac1d 100644 --- a/packages/story-editor/src/components/mediaRecording/useTrim.js +++ b/packages/story-editor/src/components/mediaRecording/useTrim.js @@ -35,18 +35,18 @@ function useTrim({ setDuration, onTrimmed, file, isRecording }) { const [isAdjustingTrim, setIsAdjustingTrim] = useState(false); const [isProcessingTrim, setIsProcessingTrim] = useState(false); const { trimVideo } = useFFmpeg(); - const hasCancelledTrim = useRef(); + const hasCancelledTrimRef = useRef(); const onTrim = useCallback( async (newTrimData) => { setIsAdjustingTrim(false); if (newTrimData) { - hasCancelledTrim.current = false; + hasCancelledTrimRef.current = false; setIsProcessingTrim(true); const start = formatMsToHMS(newTrimData.start); const end = formatMsToHMS(newTrimData.end); const result = await trimVideo(file, start, end); // If it was cancelled in the meantime, just abort - if (hasCancelledTrim.current) { + if (hasCancelledTrimRef.current) { return; } setTrimData(newTrimData); @@ -63,7 +63,7 @@ function useTrim({ setDuration, onTrimmed, file, isRecording }) { setTrimData({ start: 0, end: null }); }, []); const cancelTrim = useCallback(() => { - hasCancelledTrim.current = true; + hasCancelledTrimRef.current = true; setIsProcessingTrim(false); }, []); // Whenever a new recording starts, reset any previously captured trim data diff --git a/packages/story-editor/src/components/panels/panel/useDragHandlers.js b/packages/story-editor/src/components/panels/panel/useDragHandlers.js index 23506db5aa7c..8c15f628b319 100644 --- a/packages/story-editor/src/components/panels/panel/useDragHandlers.js +++ b/packages/story-editor/src/components/panels/panel/useDragHandlers.js @@ -25,7 +25,7 @@ import { } from '@googleforcreators/react'; function useDragHandlers(handle, onDrag, onDragEnd) { - const lastPosition = useRef(); + const lastPositionRef = useRef(); const [isDragging, setIsDragging] = useState(false); // On pointer move, check difference since last record vertical pointer position @@ -33,9 +33,9 @@ function useDragHandlers(handle, onDrag, onDragEnd) { // Then record new vertical pointer position for next iteration. const handlePointerMove = useCallback( (evt) => { - const delta = lastPosition.current - evt.pageY; + const delta = lastPositionRef.current - evt.pageY; onDrag(delta); - lastPosition.current = evt.pageY; + lastPositionRef.current = evt.pageY; }, [onDrag] ); @@ -56,7 +56,7 @@ function useDragHandlers(handle, onDrag, onDragEnd) { // Also record the initial vertical pointer position on the page. const handlePointerDown = useCallback((evt) => { evt.target.setPointerCapture(evt.pointerId); - lastPosition.current = evt.pageY; + lastPositionRef.current = evt.pageY; setIsDragging(true); }, []); diff --git a/packages/story-editor/src/components/reorderable/useReordering.js b/packages/story-editor/src/components/reorderable/useReordering.js index b069d454cc17..4cb24ac53569 100644 --- a/packages/story-editor/src/components/reorderable/useReordering.js +++ b/packages/story-editor/src/components/reorderable/useReordering.js @@ -56,9 +56,9 @@ function useReordering(onPositionChange, numChildren) { [] ); - const separator = useRef(null); + const separatorRef = useRef(null); useEffect(() => { - separator.current = currentSeparator; + separatorRef.current = currentSeparator; }, [currentSeparator]); useEffect(() => { @@ -68,15 +68,15 @@ function useReordering(onPositionChange, numChildren) { const onRelease = (evt) => { evt.preventDefault(); - if (separator.current !== null) { - const newPosition = separator.current; + if (separatorRef.current !== null) { + const newPosition = separatorRef.current; const position = newPosition.position > currentPosition.position ? newPosition.position - 1 : newPosition.position; onPositionChange( currentPosition, - { ...separator.current, position }, + { ...separatorRef.current, position }, evt ); } diff --git a/packages/story-editor/src/components/reorderable/useScroll.js b/packages/story-editor/src/components/reorderable/useScroll.js index 0f2a255e176e..4fa0b07413cb 100644 --- a/packages/story-editor/src/components/reorderable/useScroll.js +++ b/packages/story-editor/src/components/reorderable/useScroll.js @@ -27,13 +27,13 @@ import { const SCROLL_PERCENT = 0.2; const MAX_SCROLL_STEP = 10; -function useScroll(mode = 'horizontal', isReordering, scrollTarget, size) { +function useScroll(mode = 'horizontal', isReordering, scrollTargetRef, size) { const [hasScrollAbove, setHasScrollAbove] = useState(false); const [hasScrollBelow, setHasScrollBelow] = useState(false); const [scrollDirection, setScrollDirection] = useState(0); const updateScrollMarkers = useBatchingCallback(() => { - const node = scrollTarget.current; + const node = scrollTargetRef.current; if (!node) { return; } @@ -56,7 +56,7 @@ function useScroll(mode = 'horizontal', isReordering, scrollTarget, size) { setHasScrollBelow(node.scrollTop < possibleScroll); } } - }, [mode, scrollTarget]); + }, [mode, scrollTargetRef]); const startScroll = useCallback( (dir) => { @@ -85,9 +85,9 @@ function useScroll(mode = 'horizontal', isReordering, scrollTarget, size) { 0 ); if (mode === 'horizontal') { - scrollTarget.current.scrollLeft += scrollDirection * scrollStep; + scrollTargetRef.current.scrollLeft += scrollDirection * scrollStep; } else { - scrollTarget.current.scrollTop += scrollDirection * scrollStep; + scrollTargetRef.current.scrollTop += scrollDirection * scrollStep; } updateScrollMarkers(); if (mounted) { @@ -106,7 +106,7 @@ function useScroll(mode = 'horizontal', isReordering, scrollTarget, size) { canScrollEnd, size, mode, - scrollTarget, + scrollTargetRef, ]); // Update scroll markers whenever isReordering changes (to true really, but no harm) diff --git a/packages/story-editor/src/components/styleManager/useApplyStyle.js b/packages/story-editor/src/components/styleManager/useApplyStyle.js index bf2de9ddfedd..0a36a33fdcc3 100644 --- a/packages/story-editor/src/components/styleManager/useApplyStyle.js +++ b/packages/story-editor/src/components/styleManager/useApplyStyle.js @@ -37,11 +37,11 @@ function useApplyStyle({ pushUpdate }) { : STABLE_ARRAY; }); - const extraPropsToAdd = useRef(null); + const extraPropsToAddRef = useRef(null); const push = useCallback( (updater) => { - const extraProps = extraPropsToAdd.current || {}; - extraPropsToAdd.current = null; + const extraProps = extraPropsToAddRef.current || {}; + extraPropsToAddRef.current = null; pushUpdate((oldProps) => { return { ...updater(oldProps), @@ -72,7 +72,7 @@ function useApplyStyle({ pushUpdate }) { letterSpacing, ...rest } = preset; - extraPropsToAdd.current = rest; + extraPropsToAddRef.current = rest; handleSetColor(color); handleSetLetterSpacing(letterSpacing); handleSelectFontWeight(fontWeight); diff --git a/packages/story-editor/src/utils/useIdleTaskQueue.ts b/packages/story-editor/src/utils/useIdleTaskQueue.ts index 25471705a868..254a579a72ad 100644 --- a/packages/story-editor/src/utils/useIdleTaskQueue.ts +++ b/packages/story-editor/src/utils/useIdleTaskQueue.ts @@ -35,8 +35,8 @@ interface Task { */ function useIdleTaskQueue() { const taskQueue = useRef([]); - const isTaskQueueRunning = useRef(false); - const currentTask = useRef({ taskId: null, task: null }); + const isTaskQueueRunningRef = useRef(false); + const currentTaskRef = useRef({ taskId: null, task: null }); /** * Recursively runs idle task queue sequentially @@ -45,10 +45,10 @@ function useIdleTaskQueue() { * @return {void} */ const runTaskQueue = useCallback(() => { - isTaskQueueRunning.current = true; + isTaskQueueRunningRef.current = true; if (!taskQueue.current.length) { - isTaskQueueRunning.current = false; + isTaskQueueRunningRef.current = false; return; } @@ -56,12 +56,12 @@ function useIdleTaskQueue() { const idleCallbackId = requestIdleCallback(() => { if (typeof task === 'function') { void task().then(() => { - currentTask.current = { taskId: null, task: null }; + currentTaskRef.current = { taskId: null, task: null }; runTaskQueue(); }); } }); - currentTask.current = { taskId, task: idleCallbackId }; + currentTaskRef.current = { taskId, task: idleCallbackId }; }, []); /** @@ -80,10 +80,10 @@ function useIdleTaskQueue() { // If the current requested task hasn't fired, clear it // and restart the queue on the next task - const { taskId, task }: Task = currentTask.current; + const { taskId, task }: Task = currentTaskRef.current; if (id === taskId && typeof task === 'number') { cancelIdleCallback(task); - currentTask.current = { taskId: null, task: null }; + currentTaskRef.current = { taskId: null, task: null }; runTaskQueue(); } }, @@ -108,7 +108,7 @@ function useIdleTaskQueue() { // If the queue has stopped processing because // it ran out of entries, restart it - if (!isTaskQueueRunning.current) { + if (!isTaskQueueRunningRef.current) { runTaskQueue(); } diff --git a/packages/wp-dashboard/src/components/editorSettings/publisherLogo/index.js b/packages/wp-dashboard/src/components/editorSettings/publisherLogo/index.js index 6a9a789adbdc..cf81eec8a11c 100644 --- a/packages/wp-dashboard/src/components/editorSettings/publisherLogo/index.js +++ b/packages/wp-dashboard/src/components/editorSettings/publisherLogo/index.js @@ -81,7 +81,7 @@ function PublisherLogoSettings({ const containerRef = useRef(); const gridRef = useRef(); - const itemRefs = useRef({}); + const itemsRef = useRef({}); const [focusedPublisherLogoId, setFocusedPublisherLogoId] = useState(null); @@ -91,14 +91,14 @@ function PublisherLogoSettings({ const hasOnlyOneLogo = publisherLogos.length === 1; - const publisherLogoCount = useRef(publisherLogos.length); + const publisherLogoCountRef = useRef(publisherLogos.length); const handleRemoveLogoClick = useCallback( (publisherLogo, idx) => { setContextMenuId(-1); onRemoveLogo?.(publisherLogo); setIndexRemoved(idx); - publisherLogoCount.current = publisherLogos.length; + publisherLogoCountRef.current = publisherLogos.length; }, [onRemoveLogo, publisherLogos.length] ); @@ -115,7 +115,7 @@ function PublisherLogoSettings({ useEffect(() => { if ( Boolean(indexRemoved?.toString()) && - publisherLogos.length !== publisherLogoCount.current + publisherLogos.length !== publisherLogoCountRef.current ) { if (publisherLogos.length === 0) { // if the user has removed their last publisher logo, the logo grid will not render @@ -130,7 +130,7 @@ function PublisherLogoSettings({ indexRemoved > 0 ? publisherLogos[indexRemoved - 1] : publisherLogos[0]; setFocusedPublisherLogoId(moveItemFocusByIndex.id); - itemRefs.current[moveItemFocusByIndex.id].firstChild.focus(); + itemsRef.current[moveItemFocusByIndex.id].firstChild.focus(); return setIndexRemoved(null); } return undefined; @@ -139,7 +139,7 @@ function PublisherLogoSettings({ useGridViewKeys({ containerRef, gridRef, - itemRefs, + itemRefs: itemsRef, isRTL, currentItemId: focusedPublisherLogoId, items: publisherLogos, @@ -180,7 +180,7 @@ function PublisherLogoSettings({ { - itemRefs.current[publisherLogo.id] = el; + itemsRef.current[publisherLogo.id] = el; }} contextMenuId={{ set: setContextMenuId, diff --git a/packages/wp-dashboard/src/components/ga4Banner/index.js b/packages/wp-dashboard/src/components/ga4Banner/index.js index 5f0ad458c63f..d455a90009ab 100644 --- a/packages/wp-dashboard/src/components/ga4Banner/index.js +++ b/packages/wp-dashboard/src/components/ga4Banner/index.js @@ -144,7 +144,7 @@ export default function GoogleAnalytics4Banner() { currentPath: state.currentPath, hasAvailableRoutes: state.availableRoutes.length > 0, })); - const headerEl = useRef(null); + const headerRef = useRef(null); const [, forceUpdate] = useState(false); useEffect(() => { @@ -159,14 +159,14 @@ export default function GoogleAnalytics4Banner() { EDITOR_SETTINGS_ROUTE, ].includes(currentPath) ) { - headerEl.current = document.getElementById('body-view-options-header'); + headerRef.current = document.getElementById('body-view-options-header'); forceUpdate((value) => !value); } }, [currentPath, hasAvailableRoutes]); - if (!headerEl.current) { + if (!headerRef.current) { return null; } - return createPortal(, headerEl.current); + return createPortal(, headerRef.current); } diff --git a/packages/wp-dashboard/src/components/telemetryBanner/index.js b/packages/wp-dashboard/src/components/telemetryBanner/index.js index 7b1011432f40..32595f446a4a 100644 --- a/packages/wp-dashboard/src/components/telemetryBanner/index.js +++ b/packages/wp-dashboard/src/components/telemetryBanner/index.js @@ -79,7 +79,7 @@ export const TelemetryOptInBanner = forwardRef( ref ) => { const checkboxRef = useRef(); - const focusOnCheckbox = useRef(false); + const focusedCheckboxRef = useRef(false); const title = checked ? __( 'Your selection has been updated. Thank you for helping to improve the editor!', @@ -88,7 +88,7 @@ export const TelemetryOptInBanner = forwardRef( : __('Help improve the editor!', 'web-stories'); useEffect(() => { - if (focusOnCheckbox.current) { + if (focusedCheckboxRef.current) { checkboxRef.current.focus(); } }); @@ -108,10 +108,10 @@ export const TelemetryOptInBanner = forwardRef( disabled={disabled} onChange={() => { onChange(); - focusOnCheckbox.current = true; + focusedCheckboxRef.current = true; }} onBlur={() => { - focusOnCheckbox.current = false; + focusedCheckboxRef.current = false; }} ref={checkboxRef} /> @@ -185,17 +185,17 @@ export function TelemetryBannerContainer(props) { } = useTelemetryOptIn(); const ref = useRef(); - const previousBannerVisible = useRef(bannerVisible); + const previousBannerVisibleRef = useRef(bannerVisible); useLayoutEffect(() => { if ( bannerVisible && - previousBannerVisible.current === false && + previousBannerVisibleRef.current === false && ref.current ) { - previousBannerVisible.current = true; - } else if (!bannerVisible && previousBannerVisible.current) { - previousBannerVisible.current = false; + previousBannerVisibleRef.current = true; + } else if (!bannerVisible && previousBannerVisibleRef.current) { + previousBannerVisibleRef.current = false; } }, [bannerVisible]); @@ -217,7 +217,7 @@ export default function TelemetryBanner() { currentPath: state.currentPath, hasAvailableRoutes: state.availableRoutes.length > 0, })); - const headerEl = useRef(null); + const headerRef = useRef(null); const [, forceUpdate] = useState(false); useEffect(() => { @@ -228,14 +228,14 @@ export default function TelemetryBanner() { if ( [APP_ROUTES.DASHBOARD, APP_ROUTES.TEMPLATES_GALLERY].includes(currentPath) ) { - headerEl.current = document.getElementById('body-view-options-header'); + headerRef.current = document.getElementById('body-view-options-header'); forceUpdate((value) => !value); } }, [currentPath, hasAvailableRoutes]); - if (!headerEl.current) { + if (!headerRef.current) { return null; } - return createPortal(, headerEl.current); + return createPortal(, headerRef.current); } diff --git a/packages/wp-dashboard/src/components/updateBanner/index.js b/packages/wp-dashboard/src/components/updateBanner/index.js index 0b367f5abfb6..394b66a8fae7 100644 --- a/packages/wp-dashboard/src/components/updateBanner/index.js +++ b/packages/wp-dashboard/src/components/updateBanner/index.js @@ -143,7 +143,7 @@ export default function UpdateBanner() { currentPath: state.currentPath, hasAvailableRoutes: state.availableRoutes.length > 0, })); - const headerEl = useRef(null); + const headerRef = useRef(null); const [, forceUpdate] = useState(false); useEffect(() => { @@ -158,14 +158,14 @@ export default function UpdateBanner() { EDITOR_SETTINGS_ROUTE, ].includes(currentPath) ) { - headerEl.current = document.getElementById('body-view-options-header'); + headerRef.current = document.getElementById('body-view-options-header'); forceUpdate((value) => !value); } }, [currentPath, hasAvailableRoutes]); - if (!headerEl.current) { + if (!headerRef.current) { return null; } - return createPortal(, headerEl.current); + return createPortal(, headerRef.current); } diff --git a/packages/wp-story-editor/src/components/metaBoxes/metaBoxes.js b/packages/wp-story-editor/src/components/metaBoxes/metaBoxes.js index a1d5c48e90ca..e6bb420a5fd5 100644 --- a/packages/wp-story-editor/src/components/metaBoxes/metaBoxes.js +++ b/packages/wp-story-editor/src/components/metaBoxes/metaBoxes.js @@ -54,7 +54,7 @@ function MetaBoxes() { metaBoxesVisible: state.metaBoxesVisible, })); const [showMenuButton, updateMenuButtonState] = useState(false); - const menuButtonContainer = useRef(null); + const menuButtonContainerRef = useRef(null); const { postType, metaBoxes = {} } = useConfig(); const { pages, isSavingStory, isAutoSavingStory, story } = useStory( ({ @@ -73,9 +73,9 @@ function MetaBoxes() { if (!showMenuButton && hasMetaBoxes && pages.length > 0) { timeout = setTimeout(() => { - menuButtonContainer.current = + menuButtonContainerRef.current = document.getElementById('primary-menu-items'); - updateMenuButtonState(null !== menuButtonContainer.current); + updateMenuButtonState(null !== menuButtonContainerRef.current); }); } @@ -116,7 +116,7 @@ function MetaBoxes() { )} {showMenuButton && - createPortal(, menuButtonContainer.current)} + createPortal(, menuButtonContainerRef.current)} ); } diff --git a/packages/wp-story-editor/src/components/postLock/postLock.js b/packages/wp-story-editor/src/components/postLock/postLock.js index fc9ddbe4edfe..61a7f1966c0c 100644 --- a/packages/wp-story-editor/src/components/postLock/postLock.js +++ b/packages/wp-story-editor/src/components/postLock/postLock.js @@ -129,9 +129,9 @@ function PostLock() { ]); // Cache it to make it stable in terms of the below timeout - const cachedDoGetStoryLock = useRef(doGetStoryLock); + const cachedDoGetStoryLockRef = useRef(doGetStoryLock); useEffect(() => { - cachedDoGetStoryLock.current = doGetStoryLock; + cachedDoGetStoryLockRef.current = doGetStoryLock; }, [doGetStoryLock, currentUserLoaded]); useEffect(() => { @@ -164,7 +164,7 @@ function PostLock() { return; } if (currentUserLoaded) { - cachedDoGetStoryLock.current(); + cachedDoGetStoryLockRef.current(); } }, postLockInterval * 1000); From 1e26606ceb8a633a42caac7cae33305caaf743a8 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:27:59 +0200 Subject: [PATCH 02/32] Storybook: Wrap reset in effect --- .storybook/stories/playground/dashboard/index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.storybook/stories/playground/dashboard/index.js b/.storybook/stories/playground/dashboard/index.js index e0424d9b601f..3ae89f7047dd 100644 --- a/.storybook/stories/playground/dashboard/index.js +++ b/.storybook/stories/playground/dashboard/index.js @@ -17,7 +17,7 @@ /** * External dependencies */ -import { useRef } from 'react'; +import { useRef, useEffect } from 'react'; import { toId } from '@storybook/csf'; import { Dashboard, InterfaceSkeleton } from '@googleforcreators/dashboard'; @@ -102,10 +102,12 @@ const getAuthors = () => Promise.resolve([{ name: 'Author', id: 1 }]); const useClearHash = () => { const isHashCleaned = useRef(false); - if (!isHashCleaned.current) { - window.location.hash = '/'; - isHashCleaned.current = true; - } + useEffect(() => { + if (!isHashCleaned.current) { + window.location.hash = '/'; + isHashCleaned.current = true; + } + }, []); }; export const _default = { From 82924197b59beb6444d67c981b78f5133442f758 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:29:08 +0200 Subject: [PATCH 03/32] Block: fix `useViewportMatch` usage --- .../src/block/block-types/single-story/edit.js | 11 +++-------- .../block/block-types/single-story/editInLoop.js | 13 +++---------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/packages/stories-block/src/block/block-types/single-story/edit.js b/packages/stories-block/src/block/block-types/single-story/edit.js index 13673b32570e..d7470431412a 100644 --- a/packages/stories-block/src/block/block-types/single-story/edit.js +++ b/packages/stories-block/src/block/block-types/single-story/edit.js @@ -28,8 +28,7 @@ import { trackEvent } from '@googleforcreators/tracking'; import { useCallback, useEffect, useRef, useState } from '@wordpress/element'; import apiFetch from '@wordpress/api-fetch'; import { ResizableBox } from '@wordpress/components'; -import * as compose from '@wordpress/compose'; -import { withViewportMatch } from '@wordpress/viewport'; +import { useViewportMatch } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { store as blockEditorStore } from '@wordpress/block-editor'; @@ -53,7 +52,6 @@ function StoryEmbedEdit({ setAttributes, className, isSelected, - _isResizable, context = {}, }) { const { @@ -86,9 +84,7 @@ function StoryEmbedEdit({ const showLoadingIndicator = isFetchingData; const showPlaceholder = !localURL || !outerURL || editingURL || cannotEmbed; - const isResizable = compose.useViewportMatch - ? compose.useViewportMatch('medium') - : _isResizable; + const isResizable = useViewportMatch('medium'); const ref = useRef(); @@ -386,11 +382,10 @@ StoryEmbedEdit.propTypes = { setAttributes: PropTypes.func.isRequired, className: PropTypes.string.isRequired, isSelected: PropTypes.bool, - _isResizable: PropTypes.bool, context: PropTypes.shape({ postType: PropTypes.string, postId: PropTypes.number, }), }; -export default withViewportMatch({ _isResizable: 'medium' })(StoryEmbedEdit); +export default StoryEmbedEdit; diff --git a/packages/stories-block/src/block/block-types/single-story/editInLoop.js b/packages/stories-block/src/block/block-types/single-story/editInLoop.js index fbca4998eba3..4f1e67e53237 100644 --- a/packages/stories-block/src/block/block-types/single-story/editInLoop.js +++ b/packages/stories-block/src/block/block-types/single-story/editInLoop.js @@ -25,8 +25,7 @@ import classNames from 'classnames'; */ import { useEffect, useRef } from '@wordpress/element'; import { Placeholder, ResizableBox } from '@wordpress/components'; -import * as compose from '@wordpress/compose'; -import { withViewportMatch } from '@wordpress/viewport'; +import { useViewportMatch } from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { store as blockEditorStore, BlockIcon } from '@wordpress/block-editor'; @@ -50,7 +49,6 @@ function StoryEmbedEditInLoop({ setAttributes, className, isSelected, - _isResizable, context = {}, }) { const { @@ -95,9 +93,7 @@ function StoryEmbedEditInLoop({ }; }, []); - const isResizable = compose.useViewportMatch - ? compose.useViewportMatch('medium') - : _isResizable; + const isResizable = useViewportMatch('medium'); const ref = useRef(); @@ -271,13 +267,10 @@ StoryEmbedEditInLoop.propTypes = { setAttributes: PropTypes.func.isRequired, className: PropTypes.string.isRequired, isSelected: PropTypes.bool, - _isResizable: PropTypes.bool, context: PropTypes.shape({ postType: PropTypes.string, postId: PropTypes.number, }), }; -export default withViewportMatch({ _isResizable: 'medium' })( - StoryEmbedEditInLoop -); +export default StoryEmbedEditInLoop; From 046d2a59e37549002af004214f7b445fc9fd460d Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:29:28 +0200 Subject: [PATCH 04/32] API Provider: use new var --- .../story-editor/src/app/api/apiProvider.tsx | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/story-editor/src/app/api/apiProvider.tsx b/packages/story-editor/src/app/api/apiProvider.tsx index f3b2cd62dbeb..e90cb7bf8199 100644 --- a/packages/story-editor/src/app/api/apiProvider.tsx +++ b/packages/story-editor/src/app/api/apiProvider.tsx @@ -46,23 +46,30 @@ function APIProvider({ children }: PropsWithChildren>) { const { apiCallbacks: actions, cdnURL } = useConfig(); const pageTemplatesRef = useRef([]); - actions.getPageTemplates = useCallback( - async (search: string) => { - // check if pageTemplates have been loaded yet - if (pageTemplatesRef.current.length === 0) { - pageTemplatesRef.current = filterTemplates( - await getAllTemplates({ - cdnURL, - }), - search - ); - } - return filterTemplates(pageTemplatesRef.current, search); - }, - [cdnURL] - ); + const newActions = { + ...actions, + getPageTemplates: useCallback( + async (search: string) => { + // check if pageTemplates have been loaded yet + if (pageTemplatesRef.current.length === 0) { + pageTemplatesRef.current = filterTemplates( + await getAllTemplates({ + cdnURL, + }), + search + ); + } + return filterTemplates(pageTemplatesRef.current, search); + }, + [cdnURL] + ), + }; - return {children}; + return ( + + {children} + + ); } export default APIProvider; From 9254d838435a47c3ecaf7c7c6a12e8662482225c Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:29:39 +0200 Subject: [PATCH 05/32] Media reducer: use new var --- packages/story-editor/src/app/media/useMediaReducer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/media/useMediaReducer.js b/packages/story-editor/src/app/media/useMediaReducer.js index 494d00595d6d..7d2bd509adb0 100644 --- a/packages/story-editor/src/app/media/useMediaReducer.js +++ b/packages/story-editor/src/app/media/useMediaReducer.js @@ -84,7 +84,7 @@ function useMediaReducer(reducer = rootReducer, actionsToWrap) { () => ({ local: localActionsToWrap, media3p: media3pActionsToWrap }), [] ); - actionsToWrap = actionsToWrap ?? defaultActionsToWrap; + const newActionsToWrap = actionsToWrap ?? defaultActionsToWrap; const initialValue = useMemo( () => reducer(undefined, { type: types.INITIAL_STATE }), @@ -93,8 +93,8 @@ function useMediaReducer(reducer = rootReducer, actionsToWrap) { const [state, dispatch] = useReducer(reducer, initialValue); const wrappedActions = useMemo( - () => wrapWithDispatch(actionsToWrap, dispatch), - [actionsToWrap] + () => wrapWithDispatch(newActionsToWrap, dispatch), + [newActionsToWrap] ); return { From de9de69eed0b2fda7e84439f17f41024ce6aab5a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:29:55 +0200 Subject: [PATCH 06/32] Do not modify var outside hook --- .../src/utils/usePerformanceTracking.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/story-editor/src/utils/usePerformanceTracking.ts b/packages/story-editor/src/utils/usePerformanceTracking.ts index 3475c8a1fd49..e76c207bfb41 100644 --- a/packages/story-editor/src/utils/usePerformanceTracking.ts +++ b/packages/story-editor/src/utils/usePerformanceTracking.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import { useEffect } from '@googleforcreators/react'; +import { useEffect, useRef } from '@googleforcreators/react'; import { trackTiming } from '@googleforcreators/tracking'; interface TraceProps { @@ -29,10 +29,8 @@ interface TraceProps { }; } -const TRACES: TraceProps = {}; const OBSERVED_EVENTS = ['click', 'pointerdown', 'pointerup']; const OBSERVED_ENTRY_TYPE = 'event'; -let performanceObserver: PerformanceObserver; interface UsePerformanceTrackingProps { node: Node; @@ -45,30 +43,34 @@ function usePerformanceTracking({ eventData, eventType = 'click', }: UsePerformanceTrackingProps) { + const performanceObserverRef = useRef(); + const tracesRef = useRef({}); const supportsPerformanceObserving = typeof PerformanceObserver !== 'undefined' && PerformanceObserver.supportedEntryTypes.includes(OBSERVED_ENTRY_TYPE); // Start observing all events if not doing so already. - if (!performanceObserver && supportsPerformanceObserving) { - performanceObserver = new PerformanceObserver((entries) => { + if (!performanceObserverRef.current && supportsPerformanceObserving) { + performanceObserverRef.current = new PerformanceObserver((entries) => { for (const entry of entries.getEntries()) { if ( OBSERVED_EVENTS.includes(entry.name) && - TRACES[entry.startTime]?.category && - !TRACES[entry.startTime]?.isReported + tracesRef.current[entry.startTime]?.category && + !tracesRef.current[entry.startTime]?.isReported ) { - TRACES[entry.startTime].isReported = true; + tracesRef.current[entry.startTime].isReported = true; trackTiming( - TRACES[entry.startTime].category, + tracesRef.current[entry.startTime].category, entry.duration, - TRACES[entry.startTime].label, + tracesRef.current[entry.startTime].label, entry.name ); } } }); - performanceObserver.observe({ entryTypes: [OBSERVED_ENTRY_TYPE] }); + performanceObserverRef.current.observe({ + entryTypes: [OBSERVED_ENTRY_TYPE], + }); } useEffect(() => { @@ -78,7 +80,7 @@ function usePerformanceTracking({ const { label = '', category } = eventData; const el = node; const traceEvent = (e: Event) => { - TRACES[e.timeStamp] = { category, label, time: e.timeStamp }; + tracesRef.current[e.timeStamp] = { category, label, time: e.timeStamp }; }; el.addEventListener(eventType, traceEvent); From f2a3f45f8e404897aaf8744784cbf0afd75794a5 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:59:45 +0200 Subject: [PATCH 07/32] Install React Compiler --- .eslintrc | 11 ++ babel.config.cjs | 1 + package-lock.json | 304 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 + 4 files changed, 321 insertions(+) diff --git a/.eslintrc b/.eslintrc index e917a3a728d1..78eb64767b96 100644 --- a/.eslintrc +++ b/.eslintrc @@ -20,6 +20,7 @@ "jsx-a11y", "markdown", "react", + "react-compiler", "react-hooks", "styled-components-a11y" ], @@ -214,6 +215,15 @@ "react/no-unused-prop-types": "error", "react/react-in-jsx-scope": "off", "react/self-closing-comp": "error", + "react-compiler/react-compiler": [ + "error", + { + "environment": { + "enableTreatRefLikeIdentifiersAsRefs": true, + "validateRefAccessDuringRender": false + } + } + ], "import/no-extraneous-dependencies": "error", "import/no-unresolved": "error", "import/order": [ @@ -425,6 +435,7 @@ "rules": { "@eslint-community/eslint-comments/require-description": "off", "react/prop-types": "off", + "react-compiler/react-compiler": "off", "jest/no-hooks": "off", "jest/no-untyped-mock-factory": "off", "jest/max-expects": "off", diff --git a/babel.config.cjs b/babel.config.cjs index 89281bae3d6a..e9f235eaa915 100644 --- a/babel.config.cjs +++ b/babel.config.cjs @@ -53,6 +53,7 @@ module.exports = function (api) { meaninglessFileNames: ['index', 'styles', 'components'], }, ], + ['babel-plugin-react-compiler', { target: '17' }], ], sourceMaps: true, env: { diff --git a/package-lock.json b/package-lock.json index 8f9360509aa1..2e392e471325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,9 @@ "name": "web-stories-wp", "hasInstallScript": true, "license": "Apache-2.0", + "dependencies": { + "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020" + }, "devDependencies": { "@ampproject/toolbox-optimizer": "^2.10.1", "@babel/core": "^7.25.8", @@ -77,6 +80,7 @@ "ajv-formats": "^3.0.1", "babel-jest": "^29.6.1", "babel-loader": "^9.1.3", + "babel-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "browserslist": "^4.22.3", @@ -101,6 +105,7 @@ "eslint-plugin-oxlint": "^0.4.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-security": "^3.0.1", "eslint-plugin-styled-components-a11y": "^2.1.35", @@ -1001,6 +1006,24 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -12297,6 +12320,194 @@ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-react-compiler": { + "version": "19.0.0-beta-8a03594-20241020", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", + "integrity": "sha512-Wk0748DZzQEmjkEN4SbBujM5al4q5TfRBapA32ax0AID/Yek3emS+eyCvPvb4zPddYJTAF4LaJNLt8uHYfdKAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/generator": "7.2.0", + "@babel/types": "^7.19.0", + "chalk": "4", + "invariant": "^2.2.4", + "pretty-format": "^24", + "zod": "^3.22.4", + "zod-validation-error": "^2.1.0" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/@babel/generator": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", + "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.2.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.10", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/@types/yargs": { + "version": "13.0.12", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", + "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-plugin-react-compiler/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/babel-plugin-react-compiler/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-plugin-react-compiler/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/babel-plugin-styled-components": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz", @@ -16215,6 +16426,40 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, + "node_modules/eslint-plugin-react-compiler": { + "version": "19.0.0-beta-8a03594-20241020", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", + "integrity": "sha512-bYg1COih1s3r14IV/AKdQs/SN7CQmNI0ZaMtPdgZ6gp1S1Q/KGP9P43w7R6dHJ4wYpuMBvekNJHQdVu+x6UM+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "hermes-parser": "^0.20.1", + "zod": "^3.22.4", + "zod-validation-error": "^3.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.0.0 || >= 18.0.0" + }, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-plugin-react-compiler/node_modules/zod-validation-error": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz", + "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, "node_modules/eslint-plugin-react-hooks": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", @@ -19072,6 +19317,23 @@ "tslib": "^2.0.3" } }, + "node_modules/hermes-estree": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", + "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.20.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", + "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.20.1" + } + }, "node_modules/highlight-words-core": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz", @@ -29031,6 +29293,15 @@ "react-dom": ">=16.8.0" } }, + "node_modules/react-compiler-runtime": { + "version": "19.0.0-beta-8a03594-20241020", + "resolved": "https://registry.npmjs.org/react-compiler-runtime/-/react-compiler-runtime-19.0.0-beta-8a03594-20241020.tgz", + "integrity": "sha512-YWl8SjxsWGU1dpxHvWS0vxTkpeLXTZ/Y7IVzwZGj6yAfXOEie1MduuAR0TFiGeV0RxFLp5jKUIWl+ZglN4dMQw==", + "license": "MIT", + "peerDependencies": { + "react": "^18.2.0 || ^19.0.0" + } + }, "node_modules/react-css-styled": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/react-css-styled/-/react-css-styled-1.1.9.tgz", @@ -33326,6 +33597,16 @@ "node": ">=8" } }, + "node_modules/trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -35873,6 +36154,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", + "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.18.0" + } + }, "packages/activation-notice": { "name": "@web-stories-wp/activation-notice", "license": "Apache-2.0", diff --git a/package.json b/package.json index 0bdb7e52a0d0..6d6519531958 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "ajv-formats": "^3.0.1", "babel-jest": "^29.6.1", "babel-loader": "^9.1.3", + "babel-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "browserslist": "^4.22.3", @@ -125,6 +126,7 @@ "eslint-plugin-oxlint": "^0.4.0", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.34.1", + "eslint-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-security": "^3.0.1", "eslint-plugin-styled-components-a11y": "^2.1.35", @@ -323,5 +325,8 @@ "dependabot", "github-actions" ] + }, + "dependencies": { + "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020" } } From 16319d78f5c73ccf53df3e0398c9eed313554a73 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 13:59:58 +0200 Subject: [PATCH 08/32] Hardening for React Compiler --- .../src/components/contextMenu/menu.tsx | 2 +- .../src/components/tooltip/tooltip.tsx | 2 +- .../src/components/header/buttons/publish.js | 39 ++++++++++--------- .../media/common/paginatedMediaGallery.js | 9 ++--- .../components/videoTrim/useVideoTrimMode.js | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/packages/design-system/src/components/contextMenu/menu.tsx b/packages/design-system/src/components/contextMenu/menu.tsx index c6faf29416d4..99402aafeaee 100644 --- a/packages/design-system/src/components/contextMenu/menu.tsx +++ b/packages/design-system/src/components/contextMenu/menu.tsx @@ -240,7 +240,7 @@ const Menu = forwardRef< const keyOut = isHorizontal ? KEYS.UP : isRTL ? KEYS.RIGHT : KEYS.LEFT; // Maybe move from submenu to parent menu. - if (isSubMenu && keyOut === key && parentMenuRef.current) { + if (isSubMenu && keyOut === key && parentMenuRef?.current) { // Get the button with expanded popup. const parentButton = parentMenuRef.current.querySelector( 'button[aria-expanded="true"]' diff --git a/packages/design-system/src/components/tooltip/tooltip.tsx b/packages/design-system/src/components/tooltip/tooltip.tsx index 28f21c31758c..63dc37688a05 100644 --- a/packages/design-system/src/components/tooltip/tooltip.tsx +++ b/packages/design-system/src/components/tooltip/tooltip.tsx @@ -191,7 +191,7 @@ function Tooltip({ const shouldMoveToTop = dynamicPlacement.startsWith('bottom') && neededVerticalSpace >= window.innerHeight; - // We can sometimes render a tooltip too far to the left, ie. in RTL mode, or with the wp-admin sidenav. + // We can sometimes render a tooltip too far to the left, i.e. in RTL mode, or with the wp-admin sidenav. // When that is the case, let's update the offset. const isOverFlowingLeft = Math.trunc(left) < (isRTL ? 0 : leftOffset); // The getOffset util has a maxOffset that prevents the tooltip from being render too far to the right. However, when diff --git a/packages/story-editor/src/components/header/buttons/publish.js b/packages/story-editor/src/components/header/buttons/publish.js index f44623417d06..10d21468af72 100644 --- a/packages/story-editor/src/components/header/buttons/publish.js +++ b/packages/story-editor/src/components/header/buttons/publish.js @@ -36,22 +36,23 @@ import { PublishModal } from '../../publishModal'; import ButtonWithChecklistWarning from './buttonWithChecklistWarning'; function PublishButton({ forceIsSaving }) { - const { date, storyId, saveStory, title, editLink, canPublish } = useStory( - ({ - state: { - story: { date, storyId, title, editLink }, - capabilities, - }, - actions: { saveStory }, - }) => ({ - date, - storyId, - saveStory, - title, - editLink, - canPublish: Boolean(capabilities?.publish), - }) - ); + const { date, storyId, saveStory, titleLength, editLink, canPublish } = + useStory( + ({ + state: { + story: { date, storyId, title, editLink }, + capabilities, + }, + actions: { saveStory }, + }) => ({ + date, + storyId, + saveStory, + titleLength: title?.length || 0, + editLink, + canPublish: Boolean(capabilities?.publish), + }) + ); const showPriorityIssues = useCheckpoint( ({ actions: { showPriorityIssues } }) => showPriorityIssues @@ -80,13 +81,13 @@ function PublishButton({ forceIsSaving }) { trackEvent('publish_story', { status: newStatus, - title_length: title.length, + title_length: titleLength, }); setShowDialog(false); saveStory({ status: newStatus }); refreshPostEditURL(); - }, [refreshPostEditURL, saveStory, hasFutureDate, title, canPublish]); + }, [refreshPostEditURL, saveStory, hasFutureDate, titleLength, canPublish]); const handlePublish = useCallback(() => { showPriorityIssues(); @@ -97,7 +98,7 @@ function PublishButton({ forceIsSaving }) { setShowDialog(false); if (focusPublishButton) { - publishButtonRef.current.focus(); + publishButtonRef.current?.focus(); } }, []); diff --git a/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js b/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js index c6af9cf50e78..ec38ef7be7f5 100644 --- a/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js +++ b/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js @@ -111,9 +111,9 @@ function PaginatedMediaGallery({ const refContainer = useRef(); const isNextPageNeeded = useCallback(() => { - // Load the next page if the container still isn't full, ie. scrollbar is not visible. + // Load the next page if the container still isn't full, i.e. scrollbar is not visible. if ( - refContainer.current.clientHeight === refContainer.current.scrollHeight + refContainer.current?.clientHeight === refContainer.current?.scrollHeight ) { return setNextPage(); } @@ -147,12 +147,11 @@ function PaginatedMediaGallery({ } // Load the next page if we are "close" (by a length of ROOT_MARGIN) to the - // bottom of of the container. + // bottom of the container. const bottom = node.scrollHeight - node.scrollTop <= node.clientHeight + ROOT_MARGIN; if (bottom) { setNextPage(); - return; } }, [ resources.length, @@ -172,7 +171,7 @@ function PaginatedMediaGallery({ const handleScrollOrResize = useDebouncedCallback(loadNextPageIfNeeded, 500); // After loading a next page, see if we need to load another, - // ie. when the page of results isn't full. + // i.e. when the page of results isn't full. useLayoutEffect(() => { async function loadNextPageIfNeededAfterGalleryRendering() { // Wait for to finish its render layout cycles first. diff --git a/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js b/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js index ef250d22f966..fbeef0f6bc46 100644 --- a/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js +++ b/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js @@ -92,7 +92,7 @@ function useVideoTrimMode() { const toggleTrimMode = useCallback(() => { if (isEditing) { clearEditing(); - } else { + } else if (selectedElement) { setEditingElementWithState(selectedElement.id, { isTrimMode: true, hasEditMenu: true, From aa2697435d1a10d41f82f501c5805ba2304f7b53 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 14:01:24 +0200 Subject: [PATCH 09/32] Webpack: prevent source map warning --- webpack.config.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.config.cjs b/webpack.config.cjs index 4951cd18f7bb..1824e4ba4705 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -88,7 +88,7 @@ const sharedConfig = { test: /\.m?js$/, use: ['source-map-loader'], // html-to-image and react-blurhash reference source maps but don't currently ship with any. - exclude: /node_modules\/html-to-image|node_modules\/react-blurhash/, + exclude: /node_modules\/html-to-image|node_modules\/react-blurhash|node_modules\/stylis-plugin-rtl/, enforce: 'pre', resolve: { fullySpecified: false, From 648d8f8c83b340522b43999fc1107ba44aac1116 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 22 Oct 2024 14:04:20 +0200 Subject: [PATCH 10/32] Inline in jsx --- .../media/common/paginatedMediaGallery.js | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js b/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js index ec38ef7be7f5..5e6127ca8afa 100644 --- a/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js +++ b/packages/story-editor/src/components/library/panes/media/common/paginatedMediaGallery.js @@ -197,23 +197,6 @@ function PaginatedMediaGallery({ }; }, [handleScrollOrResize]); - const mediaGallery = - isMediaLoaded && !resources.length && !uploadingResources.length ? ( - - {__('No media found.', 'web-stories')} - - ) : ( -
- -
- ); - const [showLoadingPill, setShowLoadingPill] = useState(false); useEffect(() => { @@ -238,7 +221,23 @@ function PaginatedMediaGallery({ data-testid="media-gallery-container" ref={refContainer} > - {mediaGallery} + + {isMediaLoaded && !resources.length && !uploadingResources.length ? ( + + {__('No media found.', 'web-stories')} + + ) : ( +
+ +
+ )} +
{showLoadingPill && ( From e581e9de52572294d94dca89341fd11858539b8a Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 24 Oct 2024 10:13:19 +0200 Subject: [PATCH 11/32] Move up Babel plugin `babel-plugin-react-compiler` should run first before other Babel plugins as the compiler requires the input source information for sound analysis. --- babel.config.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/babel.config.cjs b/babel.config.cjs index e9f235eaa915..29099dd32c83 100644 --- a/babel.config.cjs +++ b/babel.config.cjs @@ -46,6 +46,7 @@ module.exports = function (api) { '@babel/preset-typescript', ], plugins: [ + ['babel-plugin-react-compiler', { target: '17' }], '@wordpress/babel-plugin-import-jsx-pragma', [ 'babel-plugin-styled-components', @@ -53,7 +54,6 @@ module.exports = function (api) { meaninglessFileNames: ['index', 'styles', 'components'], }, ], - ['babel-plugin-react-compiler', { target: '17' }], ], sourceMaps: true, env: { From 7fcc0f10fd3c58bb339417fc623d3c16ad0bf8e4 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 25 Oct 2024 21:10:42 +0200 Subject: [PATCH 12/32] Update react-compiler-runtime --- package-lock.json | 13 ++++++------- package.json | 4 +--- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e392e471325..a9713c2e59f9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,6 @@ "name": "web-stories-wp", "hasInstallScript": true, "license": "Apache-2.0", - "dependencies": { - "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020" - }, "devDependencies": { "@ampproject/toolbox-optimizer": "^2.10.1", "@babel/core": "^7.25.8", @@ -141,6 +138,7 @@ "postcss-syntax": "^0.36.2", "prettier": "^3.3.3", "puppeteer": "^21.9.0", + "react-compiler-runtime": "0.0.0-experimental-34d04b6-20241024", "react-refresh": "^0.14.2", "react-test-renderer": "^17.0.2", "rollup": "^2.79.2", @@ -29294,12 +29292,13 @@ } }, "node_modules/react-compiler-runtime": { - "version": "19.0.0-beta-8a03594-20241020", - "resolved": "https://registry.npmjs.org/react-compiler-runtime/-/react-compiler-runtime-19.0.0-beta-8a03594-20241020.tgz", - "integrity": "sha512-YWl8SjxsWGU1dpxHvWS0vxTkpeLXTZ/Y7IVzwZGj6yAfXOEie1MduuAR0TFiGeV0RxFLp5jKUIWl+ZglN4dMQw==", + "version": "0.0.0-experimental-34d04b6-20241024", + "resolved": "https://registry.npmjs.org/react-compiler-runtime/-/react-compiler-runtime-0.0.0-experimental-34d04b6-20241024.tgz", + "integrity": "sha512-e/XD52dtC8uOPiYnixW/YDuRnYIUqdoTj+QVhP/uqSb/uFl2+0S6LfKYFnpYuPvtRExh/TA4eEowdT1FxldC/w==", + "dev": true, "license": "MIT", "peerDependencies": { - "react": "^18.2.0 || ^19.0.0" + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, "node_modules/react-css-styled": { diff --git a/package.json b/package.json index 6d6519531958..2ca7e85d4506 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "postcss-syntax": "^0.36.2", "prettier": "^3.3.3", "puppeteer": "^21.9.0", + "react-compiler-runtime": "0.0.0-experimental-34d04b6-20241024", "react-refresh": "^0.14.2", "react-test-renderer": "^17.0.2", "rollup": "^2.79.2", @@ -325,8 +326,5 @@ "dependabot", "github-actions" ] - }, - "dependencies": { - "react-compiler-runtime": "^19.0.0-beta-8a03594-20241020" } } From b4d2b25860822418ed3bdb629c14ff19a494b0ee Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 25 Oct 2024 21:35:46 +0200 Subject: [PATCH 13/32] Prettier fix --- webpack.config.cjs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webpack.config.cjs b/webpack.config.cjs index 1824e4ba4705..7580fdd1eb3d 100644 --- a/webpack.config.cjs +++ b/webpack.config.cjs @@ -88,7 +88,8 @@ const sharedConfig = { test: /\.m?js$/, use: ['source-map-loader'], // html-to-image and react-blurhash reference source maps but don't currently ship with any. - exclude: /node_modules\/html-to-image|node_modules\/react-blurhash|node_modules\/stylis-plugin-rtl/, + exclude: + /node_modules\/html-to-image|node_modules\/react-blurhash|node_modules\/stylis-plugin-rtl/, enforce: 'pre', resolve: { fullySpecified: false, From 14bb65c6937df17572384b28375ff1dd0d1b3d35 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 25 Oct 2024 21:36:29 +0200 Subject: [PATCH 14/32] Remove some unused variables --- .../story-editor/header/buttons/preview.js | 2 +- packages/e2e-test-utils/src/customFonts.js | 2 +- packages/karma-puppeteer-client/src/client.js | 2 +- packages/rich-text/src/fauxSelection.ts | 2 +- packages/rich-text/src/formatters/color.ts | 2 +- packages/rich-text/src/formatters/gradientColor.ts | 2 +- .../src/block/components/storyPicker/storyPicker.js | 2 +- .../src/app/canvas/useCanvasCopyPaste.ts | 2 +- .../app/media/media3p/useFetchCategoriesEffect.js | 2 +- .../src/app/media/utils/useDetectBaseColor.ts | 6 +++--- .../src/app/media/utils/useDetectBlurhash.js | 4 ++-- .../src/app/media/utils/useDetectVideoHasAudio.ts | 2 +- .../story-editor/src/app/media/utils/useFFmpeg.ts | 4 ++-- .../src/app/media/utils/useProcessMedia.ts | 12 ++++++------ .../src/app/story/effects/useHashState.ts | 3 +-- .../errorBoundary/copyStoryDataToClipboard.js | 2 +- .../src/components/header/buttons/preview.js | 2 +- .../library/panes/media/local/hotlink/useInsert.js | 2 +- .../library/panes/shopping/productDropdown.js | 2 +- .../src/components/mediaRecording/playbackMedia.js | 2 +- .../src/components/mediaRecording/provider.js | 2 +- .../panels/design/pageAttachment/shared.js | 2 +- packages/story-editor/src/utils/presetUtils.js | 2 +- packages/story-editor/src/utils/useCORSProxy.ts | 2 +- .../story-editor/src/utils/useRefreshPostEditURL.ts | 2 +- packages/url/src/safeDecodeUriComponent.ts | 2 +- packages/url/src/url.ts | 2 +- packages/wp-dashboard/src/api/hooks/useMediaApi.js | 2 +- packages/wp-dashboard/src/api/hooks/usePagesApi.js | 4 ++-- .../src/api/hooks/usePublisherLogosApi.js | 8 ++++---- .../wp-dashboard/src/api/hooks/useSettingsApi.js | 4 ++-- .../src/components/corsCheck/corsCheck.js | 2 +- .../mediaUpload/mediaPicker/useMediaPicker.js | 2 +- 33 files changed, 47 insertions(+), 48 deletions(-) diff --git a/.storybook/stories/playground/story-editor/header/buttons/preview.js b/.storybook/stories/playground/story-editor/header/buttons/preview.js index ddd0f452ef52..83c99ff27bed 100644 --- a/.storybook/stories/playground/story-editor/header/buttons/preview.js +++ b/.storybook/stories/playground/story-editor/header/buttons/preview.js @@ -68,7 +68,7 @@ function PreviewButton() { ` ); } - } catch (e) { + } catch { // Not interested in the error. } }; diff --git a/packages/e2e-test-utils/src/customFonts.js b/packages/e2e-test-utils/src/customFonts.js index 1fa34217a4ba..cf026178e222 100644 --- a/packages/e2e-test-utils/src/customFonts.js +++ b/packages/e2e-test-utils/src/customFonts.js @@ -59,7 +59,7 @@ export const getFontList = async () => { ) ); return parseText(optionsText); - } catch (e) { + } catch { return []; } }; diff --git a/packages/karma-puppeteer-client/src/client.js b/packages/karma-puppeteer-client/src/client.js index e7cdd6c4452a..6547baacc108 100644 --- a/packages/karma-puppeteer-client/src/client.js +++ b/packages/karma-puppeteer-client/src/client.js @@ -14,7 +14,7 @@ * limitations under the License. */ -(function (global) { +(function () { 'use strict'; function noCleanup() {} diff --git a/packages/rich-text/src/fauxSelection.ts b/packages/rich-text/src/fauxSelection.ts index f0dd553141dc..f19299acc7e5 100644 --- a/packages/rich-text/src/fauxSelection.ts +++ b/packages/rich-text/src/fauxSelection.ts @@ -116,7 +116,7 @@ export function useFauxSelection( // Save that as the next editor state return selectedState; - } catch (e) { + } catch { // If the component has unmounted/remounted, some of the above might throw // if so, just ignore it and return old state return oldEditorState; diff --git a/packages/rich-text/src/formatters/color.ts b/packages/rich-text/src/formatters/color.ts index 87470b394e2a..8a544b5dfa0b 100644 --- a/packages/rich-text/src/formatters/color.ts +++ b/packages/rich-text/src/formatters/color.ts @@ -69,7 +69,7 @@ function stylesToCSS(styles: DraftInlineStyle): null | CSSProperties { let color: Pattern; try { color = styleToColor(style); - } catch (e) { + } catch { return null; } diff --git a/packages/rich-text/src/formatters/gradientColor.ts b/packages/rich-text/src/formatters/gradientColor.ts index b5719257c846..f841ec93ca1c 100644 --- a/packages/rich-text/src/formatters/gradientColor.ts +++ b/packages/rich-text/src/formatters/gradientColor.ts @@ -71,7 +71,7 @@ function stylesToCSS(styles: DraftInlineStyle): null | CSSProperties { let color: Pattern; try { color = styleToColor(colorStyle); - } catch (e) { + } catch { return null; } diff --git a/packages/stories-block/src/block/components/storyPicker/storyPicker.js b/packages/stories-block/src/block/components/storyPicker/storyPicker.js index 3a548347f319..f6fd6e057c72 100644 --- a/packages/stories-block/src/block/components/storyPicker/storyPicker.js +++ b/packages/stories-block/src/block/components/storyPicker/storyPicker.js @@ -99,7 +99,7 @@ function StoryPicker({ setStories((existingStories) => page === 1 ? response.body : [...existingStories, ...response.body] ); - } catch (err) { + } catch { setLoadingState('error'); createErrorNotice(__('Unable to load stories', 'web-stories'), { type: 'snackbar', diff --git a/packages/story-editor/src/app/canvas/useCanvasCopyPaste.ts b/packages/story-editor/src/app/canvas/useCanvasCopyPaste.ts index 9673c8a295e9..a8f3a69394c2 100644 --- a/packages/story-editor/src/app/canvas/useCanvasCopyPaste.ts +++ b/packages/story-editor/src/app/canvas/useCanvasCopyPaste.ts @@ -238,7 +238,7 @@ function useCanvasGlobalKeys() { if (files.length > 0) { uploadWithPreview(files); } - } catch (e) { + } catch { // Ignore. } }, diff --git a/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js b/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js index 993068bf7054..c5bc753224b4 100644 --- a/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js +++ b/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js @@ -63,7 +63,7 @@ export default function useFetchCategoriesEffect({ provider: PROVIDERS[provider].provider, }); fetchCategoriesSuccess({ provider, categories: newCategories }); - } catch (e) { + } catch { fetchCategoriesError({ provider }); showSnackbar({ message: PROVIDERS[provider].fetchCategoriesErrorMessage, diff --git a/packages/story-editor/src/app/media/utils/useDetectBaseColor.ts b/packages/story-editor/src/app/media/utils/useDetectBaseColor.ts index ea37b008b43e..0baa67988bf8 100644 --- a/packages/story-editor/src/app/media/utils/useDetectBaseColor.ts +++ b/packages/story-editor/src/app/media/utils/useDetectBaseColor.ts @@ -130,7 +130,7 @@ function useDetectBaseColor({ }); } } - } catch (error) { + } catch { // This might happen as an author when trying to updateMedia() that // was uploaded by someone else. // Do nothing with the error for now. @@ -163,7 +163,7 @@ function useDetectBaseColor({ if (posterResource) { imageSrc = getSmallestUrlForWidth(0, posterResource); } - } catch (error) { + } catch { // The user might not have the permission to access the video with context=edit. // This might happen as an author when the video // was uploaded by someone else. @@ -181,7 +181,7 @@ function useDetectBaseColor({ try { const color = await getMediaBaseColor(imageSrcProxied); await saveBaseColor(resource, color); - } catch (error) { + } catch { // Do nothing for now. } }, diff --git a/packages/story-editor/src/app/media/utils/useDetectBlurhash.js b/packages/story-editor/src/app/media/utils/useDetectBlurhash.js index c7d3fb77c6b7..6a3421735cc7 100644 --- a/packages/story-editor/src/app/media/utils/useDetectBlurhash.js +++ b/packages/story-editor/src/app/media/utils/useDetectBlurhash.js @@ -101,7 +101,7 @@ function useDetectBlurHash({ updateMediaElement }) { blurHash, }); } - } catch (error) { + } catch { // This might happen as an author when trying to updateMedia() that // was uploaded by someone else. // Do nothing with the error for now. @@ -130,7 +130,7 @@ function useDetectBlurHash({ updateMediaElement }) { if (posterResource) { imageSrc = getSmallestUrlForWidth(300, posterResource); } - } catch (error) { + } catch { // The user might not have the permission to access the video with context=edit. // This might happen as an author when the video // was uploaded by someone else. diff --git a/packages/story-editor/src/app/media/utils/useDetectVideoHasAudio.ts b/packages/story-editor/src/app/media/utils/useDetectVideoHasAudio.ts index e9568210a919..9530a2d257d2 100644 --- a/packages/story-editor/src/app/media/utils/useDetectVideoHasAudio.ts +++ b/packages/story-editor/src/app/media/utils/useDetectVideoHasAudio.ts @@ -86,7 +86,7 @@ function useDetectVideoHasAudio({ isMuted: !hasAudio, }); } - } catch (error) { + } catch { // Do nothing for now. } }, diff --git a/packages/story-editor/src/app/media/utils/useFFmpeg.ts b/packages/story-editor/src/app/media/utils/useFFmpeg.ts index a52efbb9c766..21b00f49ddd9 100644 --- a/packages/story-editor/src/app/media/utils/useFFmpeg.ts +++ b/packages/story-editor/src/app/media/utils/useFFmpeg.ts @@ -613,7 +613,7 @@ function useFFmpeg() { try { ffmpeg?.exit(); // eslint-disable-next-line no-empty -- no-op - } catch (e) {} + } catch {} trackTiming(); } @@ -668,7 +668,7 @@ function useFFmpeg() { try { ffmpeg?.exit(); // eslint-disable-next-line no-empty -- no-op - } catch (e) {} + } catch {} trackTiming(); } diff --git a/packages/story-editor/src/app/media/utils/useProcessMedia.ts b/packages/story-editor/src/app/media/utils/useProcessMedia.ts index f8ec416a1fcf..ee4641d15640 100644 --- a/packages/story-editor/src/app/media/utils/useProcessMedia.ts +++ b/packages/story-editor/src/app/media/utils/useProcessMedia.ts @@ -236,7 +236,7 @@ function useProcessMedia({ let file = null; try { file = await fetchRemoteFile(url, mimeType); - } catch (e) { + } catch { // Ignore for now. return; } @@ -352,14 +352,14 @@ function useProcessMedia({ let posterFile = null; try { file = await fetchRemoteFile(url, mimeType); - } catch (e) { + } catch { // Ignore for now. return; } if (poster) { try { posterFile = await fetchRemoteBlob(poster); - } catch (e) { + } catch { // Ignore for now. } } @@ -451,14 +451,14 @@ function useProcessMedia({ let posterFile = null; try { file = await fetchRemoteFile(url, mimeType); - } catch (e) { + } catch { // Ignore for now. return; } if (poster) { try { posterFile = await fetchRemoteBlob(poster); - } catch (e) { + } catch { // Ignore for now. } } @@ -530,7 +530,7 @@ function useProcessMedia({ let file = null; try { file = await fetchRemoteFile(url, mimeType); - } catch (e) { + } catch { // Ignore for now. return; } diff --git a/packages/story-editor/src/app/story/effects/useHashState.ts b/packages/story-editor/src/app/story/effects/useHashState.ts index 578b047a37fe..0271227ac567 100644 --- a/packages/story-editor/src/app/story/effects/useHashState.ts +++ b/packages/story-editor/src/app/story/effects/useHashState.ts @@ -63,8 +63,7 @@ function useHashState( } _value = JSON.parse(decodeURI(paramValue)) as string; } - } catch (e) { - // @TODO Add some error handling + } catch { } return _value; }); diff --git a/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js b/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js index 23bb6e3512ef..fefaa2fae968 100644 --- a/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js +++ b/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js @@ -48,7 +48,7 @@ function CopyStoryDataToClipboard() { try { await navigator.clipboard.writeText(jsonStr); alert(__('Copied to clipboard', 'web-stories')); - } catch (err) { + } catch { alert(__('Failed to copy story data', 'web-stories')); } }, [pages, current, selection, story]); diff --git a/packages/story-editor/src/components/header/buttons/preview.js b/packages/story-editor/src/components/header/buttons/preview.js index 9c5f2750f6a4..2878a1d19fad 100644 --- a/packages/story-editor/src/components/header/buttons/preview.js +++ b/packages/story-editor/src/components/header/buttons/preview.js @@ -103,7 +103,7 @@ function PreviewButton({ forceIsSaving = false }) { ` ); } - } catch (e) { + } catch { // Ignore errors. Anything can happen with a popup. The errors // will be resolved after the story is saved. } diff --git a/packages/story-editor/src/components/library/panes/media/local/hotlink/useInsert.js b/packages/story-editor/src/components/library/panes/media/local/hotlink/useInsert.js index 7f105f2c064a..69ffa380a7b4 100644 --- a/packages/story-editor/src/components/library/panes/media/local/hotlink/useInsert.js +++ b/packages/story-editor/src/components/library/panes/media/local/hotlink/useInsert.js @@ -169,7 +169,7 @@ function useInsert() { needs_proxy: needsProxy, }); setIsOpen(false); - } catch (e) { + } catch { // Do nothing for now } }, diff --git a/packages/story-editor/src/components/library/panes/shopping/productDropdown.js b/packages/story-editor/src/components/library/panes/shopping/productDropdown.js index dbd5430b1057..1d8e13f4b5e3 100644 --- a/packages/story-editor/src/components/library/panes/shopping/productDropdown.js +++ b/packages/story-editor/src/components/library/panes/shopping/productDropdown.js @@ -84,7 +84,7 @@ function ProductDropdown({ product, setProduct, ...rest }) { setIsLoading(true); const products = await getProductsByQuery(); setInitialOptions(products); - } catch (err) { + } catch { setInitialOptions(initialProducts); } finally { setIsLoading(false); diff --git a/packages/story-editor/src/components/mediaRecording/playbackMedia.js b/packages/story-editor/src/components/mediaRecording/playbackMedia.js index dd79daac9c9b..ca0a3526c9ab 100644 --- a/packages/story-editor/src/components/mediaRecording/playbackMedia.js +++ b/packages/story-editor/src/components/mediaRecording/playbackMedia.js @@ -188,7 +188,7 @@ function PlaybackMedia() { if (streamNode && streamNode.videoWidth && canvasRef.current) { try { await selfieSegmentation.current.send({ image: streamNode }); - } catch (e) { + } catch { // We can't do much about the WASM memory issue. } } diff --git a/packages/story-editor/src/components/mediaRecording/provider.js b/packages/story-editor/src/components/mediaRecording/provider.js index 8111755aa5fd..ab329b5709ab 100644 --- a/packages/story-editor/src/components/mediaRecording/provider.js +++ b/packages/story-editor/src/components/mediaRecording/provider.js @@ -249,7 +249,7 @@ function MediaRecordingProvider({ children }) { // remove these devices from the list. .filter((device) => device.label) ); - } catch (err) { + } catch { // Do nothing for now. } }, []); diff --git a/packages/story-editor/src/components/panels/design/pageAttachment/shared.js b/packages/story-editor/src/components/panels/design/pageAttachment/shared.js index 959051b050eb..1bba4d72eb40 100644 --- a/packages/story-editor/src/components/panels/design/pageAttachment/shared.js +++ b/packages/story-editor/src/components/panels/design/pageAttachment/shared.js @@ -234,7 +234,7 @@ export function LinkUrl({ icon: iconUrl, needsProxy, }); - } catch (e) { + } catch { // We're allowing to save invalid URLs, however, remove icon in this case. onChange({ url: newValue, icon: '', needsProxy: false }); setIsInvalidUrl(true); diff --git a/packages/story-editor/src/utils/presetUtils.js b/packages/story-editor/src/utils/presetUtils.js index ddb747a4e91b..be42bbd0eb87 100644 --- a/packages/story-editor/src/utils/presetUtils.js +++ b/packages/story-editor/src/utils/presetUtils.js @@ -49,7 +49,7 @@ export function findMatchingColor(color, storyStyles, isText) { return colorsToMatch.find((value) => { try { return isPatternEqual(value, color, patternType); - } catch (e) { + } catch { // Some preset couldn't be rendered as patternType return false; } diff --git a/packages/story-editor/src/utils/useCORSProxy.ts b/packages/story-editor/src/utils/useCORSProxy.ts index 8459e90af6de..e6cbf4a5e9c1 100644 --- a/packages/story-editor/src/utils/useCORSProxy.ts +++ b/packages/story-editor/src/utils/useCORSProxy.ts @@ -50,7 +50,7 @@ function useCORSProxy() { await fetch(link, { method: 'HEAD', }); - } catch (err) { + } catch { shouldProxy = true; } diff --git a/packages/story-editor/src/utils/useRefreshPostEditURL.ts b/packages/story-editor/src/utils/useRefreshPostEditURL.ts index 95290d5c0d39..beafa4004c1d 100644 --- a/packages/story-editor/src/utils/useRefreshPostEditURL.ts +++ b/packages/story-editor/src/utils/useRefreshPostEditURL.ts @@ -37,7 +37,7 @@ function useRefreshPostEditURL(postId: number, postEditURL: string) { ), newUrl.toString() ); - } catch (error) { + } catch { // Do nothing for now. } }, [postId, postEditURL]); diff --git a/packages/url/src/safeDecodeUriComponent.ts b/packages/url/src/safeDecodeUriComponent.ts index b6f2760d512b..01030cc6e06c 100644 --- a/packages/url/src/safeDecodeUriComponent.ts +++ b/packages/url/src/safeDecodeUriComponent.ts @@ -24,7 +24,7 @@ export default function safeDecodeURIComponent(uriComponent: string) { try { return decodeURIComponent(uriComponent); - } catch (uriComponentError) { + } catch { return uriComponent; } } diff --git a/packages/url/src/url.ts b/packages/url/src/url.ts index 6ab9be1c8e09..4179c2363106 100644 --- a/packages/url/src/url.ts +++ b/packages/url/src/url.ts @@ -17,7 +17,7 @@ export function toAbsoluteUrl(base: string, path: string): string { try { return new URL(path, base).href; - } catch (error) { + } catch { return path; } } diff --git a/packages/wp-dashboard/src/api/hooks/useMediaApi.js b/packages/wp-dashboard/src/api/hooks/useMediaApi.js index 1e2b5025f51e..35845220bd7d 100644 --- a/packages/wp-dashboard/src/api/hooks/useMediaApi.js +++ b/packages/wp-dashboard/src/api/hooks/useMediaApi.js @@ -53,7 +53,7 @@ export default function useMediaApi() { newlyCreatedMediaIds: mediaResponse.map(({ id }) => id), }, }); - } catch (err) { + } catch { dispatch({ type: MEDIA_ACTION_TYPES.ADD_MEDIA_FAILURE, payload: { diff --git a/packages/wp-dashboard/src/api/hooks/usePagesApi.js b/packages/wp-dashboard/src/api/hooks/usePagesApi.js index 2815ee17d349..16846a7babce 100644 --- a/packages/wp-dashboard/src/api/hooks/usePagesApi.js +++ b/packages/wp-dashboard/src/api/hooks/usePagesApi.js @@ -43,7 +43,7 @@ export default function usePagesApi() { title: stripHTML(title.rendered), link, }; - } catch (e) { + } catch { return null; } }, @@ -59,7 +59,7 @@ export default function usePagesApi() { value: id, label: stripHTML(title.rendered), })); - } catch (e) { + } catch { return []; } }, diff --git a/packages/wp-dashboard/src/api/hooks/usePublisherLogosApi.js b/packages/wp-dashboard/src/api/hooks/usePublisherLogosApi.js index feaa0628d2d4..89ee50d9fbae 100644 --- a/packages/wp-dashboard/src/api/hooks/usePublisherLogosApi.js +++ b/packages/wp-dashboard/src/api/hooks/usePublisherLogosApi.js @@ -68,7 +68,7 @@ export default function usePublisherLogosApi() { }, }); } - } catch (err) { + } catch { dispatch({ type: ACTION_TYPES.FETCH_FAILURE, payload: { @@ -96,7 +96,7 @@ export default function usePublisherLogosApi() { id: publisherLogoId, }, }); - } catch (err) { + } catch { dispatch({ type: ACTION_TYPES.FETCH_FAILURE, payload: { @@ -130,7 +130,7 @@ export default function usePublisherLogosApi() { }, }); } - } catch (err) { + } catch { dispatch({ type: ACTION_TYPES.ADD_FAILURE, payload: { @@ -160,7 +160,7 @@ export default function usePublisherLogosApi() { publisherLogo: response, }, }); - } catch (err) { + } catch { dispatch({ type: ACTION_TYPES.FETCH_FAILURE, payload: { diff --git a/packages/wp-dashboard/src/api/hooks/useSettingsApi.js b/packages/wp-dashboard/src/api/hooks/useSettingsApi.js index 88a34835fd98..889eed260434 100644 --- a/packages/wp-dashboard/src/api/hooks/useSettingsApi.js +++ b/packages/wp-dashboard/src/api/hooks/useSettingsApi.js @@ -47,7 +47,7 @@ export default function useSettingsApi() { type: SETTINGS_ACTION_TYPES.FETCH_SETTINGS_SUCCESS, payload: response, }); - } catch (err) { + } catch { dispatch({ type: SETTINGS_ACTION_TYPES.FETCH_SETTINGS_FAILURE, payload: { @@ -71,7 +71,7 @@ export default function useSettingsApi() { payload: response, }); dispatch({ type: SETTINGS_ACTION_TYPES.SETTING_SAVED, payload: true }); - } catch (err) { + } catch { dispatch({ type: SETTINGS_ACTION_TYPES.UPDATE_SETTINGS_FAILURE, payload: { diff --git a/packages/wp-story-editor/src/components/corsCheck/corsCheck.js b/packages/wp-story-editor/src/components/corsCheck/corsCheck.js index 987258dca4f4..97a71361479e 100644 --- a/packages/wp-story-editor/src/components/corsCheck/corsCheck.js +++ b/packages/wp-story-editor/src/components/corsCheck/corsCheck.js @@ -51,7 +51,7 @@ function CorsCheck() { let mediaItems; try { mediaItems = await getMediaForCorsCheck(); - } catch (err) { + } catch { return; } if (!mediaItems?.length) { diff --git a/packages/wp-story-editor/src/components/mediaUpload/mediaPicker/useMediaPicker.js b/packages/wp-story-editor/src/components/mediaUpload/mediaPicker/useMediaPicker.js index ac02cbcffbef..2ea1d031863b 100644 --- a/packages/wp-story-editor/src/components/mediaUpload/mediaPicker/useMediaPicker.js +++ b/packages/wp-story-editor/src/components/mediaUpload/mediaPicker/useMediaPicker.js @@ -89,7 +89,7 @@ function useMediaPicker({ altText: attributes.alt || attributes.title, }); }; - } catch (e) { + } catch { // Silence. } }, [updateMedia]); From 04875588e3dae0ffe9aa91f1c7e5c718e1e2984b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Fri, 25 Oct 2024 21:36:39 +0200 Subject: [PATCH 15/32] Rename some refs --- .../library/panes/media/common/innerElement.js | 14 +++++++------- .../library/panes/media/common/mediaElement.js | 2 +- .../story-editor/src/utils/useIdleTaskQueue.ts | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/story-editor/src/components/library/panes/media/common/innerElement.js b/packages/story-editor/src/components/library/panes/media/common/innerElement.js index a58b72978924..7488a9d6cb4f 100644 --- a/packages/story-editor/src/components/library/panes/media/common/innerElement.js +++ b/packages/story-editor/src/components/library/panes/media/common/innerElement.js @@ -98,7 +98,7 @@ function InnerElement({ onClick, onLoad = noop, showVideoDetail, - mediaElement, + mediaElementRef, active, isMuted, }) { @@ -156,8 +156,8 @@ function InnerElement({ }, [resource.poster]); const makeMediaVisible = () => { - if (mediaElement.current) { - mediaElement.current.style.opacity = 1; + if (mediaElementRef.current) { + mediaElementRef.current.style.opacity = 1; } onLoad(); }; @@ -206,17 +206,17 @@ function InnerElement({ if (type === ContentType.Image || type === ContentType.Sticker) { // eslint-disable-next-line styled-components-a11y/alt-text -- False positive. - media = ; + media = ; cloneProps.src = thumbnailURL; } else if ([ContentType.Video, ContentType.Gif].includes(type)) { media = ( <> {poster && !active ? ( /* eslint-disable-next-line styled-components-a11y/alt-text -- False positive. */ - + ) : ( // eslint-disable-next-line jsx-a11y/media-has-caption,styled-components-a11y/media-has-caption -- No captions/tracks because video is muted. - )} - {!showLoadingPill && attribution} + {!showLoadingPill && } ); } From 284eebbcf68094ac70b01290f75f3797e56261f8 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 00:26:00 +0200 Subject: [PATCH 19/32] Fix checkbox `id` attribute not matching the label's `for` --- .../src/components/panels/design/pageAttachment/shared.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/story-editor/src/components/panels/design/pageAttachment/shared.js b/packages/story-editor/src/components/panels/design/pageAttachment/shared.js index 1bba4d72eb40..5af2e267fb53 100644 --- a/packages/story-editor/src/components/panels/design/pageAttachment/shared.js +++ b/packages/story-editor/src/components/panels/design/pageAttachment/shared.js @@ -22,6 +22,7 @@ import { v4 as uuidv4 } from 'uuid'; import { useCallback, useDebouncedCallback, + useMemo, useState, } from '@googleforcreators/react'; import { @@ -117,7 +118,7 @@ CallToActionText.propTypes = { }; export function Theme({ theme, onChange }) { - const checkboxId = `cb-${uuidv4()}`; + const checkboxId = useMemo(() => `cb-${uuidv4()}`, []); const handleChangeTheme = useCallback( (evt) => { From edc150539396293b938f539fa795dbf46d330365 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 00:30:47 +0200 Subject: [PATCH 20/32] Fix proptypes warning --- .../components/library/panes/pageTemplates/savedTemplates.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/components/library/panes/pageTemplates/savedTemplates.js b/packages/story-editor/src/components/library/panes/pageTemplates/savedTemplates.js index 73034a4543d2..d259c3d3f411 100644 --- a/packages/story-editor/src/components/library/panes/pageTemplates/savedTemplates.js +++ b/packages/story-editor/src/components/library/panes/pageTemplates/savedTemplates.js @@ -127,8 +127,8 @@ function SavedTemplates({ } SavedTemplates.propTypes = { - searchTerm: PropTypes.string.isRequired, - setSearchTerm: PropTypes.func.isRequired, + searchTerm: PropTypes.string, + setSearchTerm: PropTypes.func, pageSize: PropTypes.object.isRequired, loadTemplates: PropTypes.func.isRequired, isLoading: PropTypes.bool, From 4955c23806096fa7c925500ab81e872d050a010b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 00:30:56 +0200 Subject: [PATCH 21/32] Fix text sets panel missing --- .../story-editor/src/components/library/panes/text/textPane.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/components/library/panes/text/textPane.js b/packages/story-editor/src/components/library/panes/text/textPane.js index 31f7e8f23d7e..34d3ce89fb14 100644 --- a/packages/story-editor/src/components/library/panes/text/textPane.js +++ b/packages/story-editor/src/components/library/panes/text/textPane.js @@ -133,7 +133,7 @@ function TextPane(props) { - {paneRef.current && } + ); } From 24b1e78bc79ce754570fac58e73a7f318a9998a3 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 00:39:16 +0200 Subject: [PATCH 22/32] Update oxlint config --- .distignore | 1 + .oxlintrc.json | 13 +++++++++++++ package.json | 6 +++--- .../karma/integrationLayerTesting/config.karma.js | 2 +- .../karma/integrationLayerTesting/config.karma.js | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 .oxlintrc.json diff --git a/.distignore b/.distignore index 2ec079e1ee34..98a1c1aafa95 100644 --- a/.distignore +++ b/.distignore @@ -40,6 +40,7 @@ web-stories-scraper .npmpackagejsonlintrc.json .npmrc .nvmrc +.oxlintrc.json .phpstorm.config.js .phpstorm.meta.php .phpunit.result.cache diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 000000000000..a2713a8f92ec --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,13 @@ +{ + "settings": { + "jsdoc": { + "tagNamePreference": { + "returns": "return", + "yields": "yield" + } + } + }, + "rules": { + "no-unused-vars": "off" + } +} diff --git a/package.json b/package.json index 52cd8896d4e5..2cf044b972fb 100644 --- a/package.json +++ b/package.json @@ -224,9 +224,9 @@ "lint:css:js:fix": "stylelint \"**/*.js\" --fix", "lint:css:css": "stylelint \"**/*.css\"", "lint:css:css:fix": "stylelint \"**/*.css\" --fix", - "lint:js": "oxlint && eslint .", - "lint:js:fix": "oxlint --fix && eslint --fix .", - "lint:js:report": "oxlint && eslint --output-file build/lint-js-report.json --format json .", + "lint:js": "oxlint -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint .", + "lint:js:fix": "oxlint --fix -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint --fix .", + "lint:js:report": "oxlint -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint --output-file build/lint-js-report.json --format json .", "lint:package-json": "npmPkgJsonLint .", "lint:php": "composer phpcs", "lint:php:fix": "composer phpcbf", diff --git a/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js b/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js index f8d5854aac4b..94930da53c69 100644 --- a/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js +++ b/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js @@ -31,7 +31,7 @@ describe('Integration Layer tests : EditorConfig Params :', () => { MINIMUM_CONFIG[key] = undefined; } MINIMUM_CONFIG.apiCallbacks = { - fetchStories: () => new Promise.resolve({}), + fetchStories: () => Promise.resolve({}), }; }); diff --git a/packages/story-editor/src/karma/integrationLayerTesting/config.karma.js b/packages/story-editor/src/karma/integrationLayerTesting/config.karma.js index 46905c8dfe97..e846a7234e60 100644 --- a/packages/story-editor/src/karma/integrationLayerTesting/config.karma.js +++ b/packages/story-editor/src/karma/integrationLayerTesting/config.karma.js @@ -35,7 +35,7 @@ describe('Integration Layer tests : EditorConfig Params :', () => { MINIMUM_CONFIG.storyId = 1; MINIMUM_CONFIG.apiCallbacks = { - saveStoryById: () => new Promise.resolve({}), + saveStoryById: () => Promise.resolve({}), }; afterEach(() => { From 41bdc9f710a68200db7617c4af2daa9a96aa15f9 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 11:53:05 +0200 Subject: [PATCH 23/32] Use `renderHook` in hook unit test --- .../media3p/test/useContextValueProvider.js | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js b/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js index 6b04eb8829de..80e4bc728f12 100644 --- a/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js +++ b/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js @@ -14,6 +14,11 @@ * limitations under the License. */ +/** + * External dependencies + */ +import { renderHook } from '@testing-library/react-hooks'; + /** * Internal dependencies */ @@ -28,16 +33,18 @@ describe('useContextValueProvider', () => { state: { media: [] }, }); - const value = useContextValueProvider( - { - selectedProvider: 'unsplash', - searchTerm: '', - unsplash: {}, - }, - { setSelectedProvider: () => {}, setSearchTerm: () => {} } + const { result } = renderHook(() => + useContextValueProvider( + { + selectedProvider: 'unsplash', + searchTerm: '', + unsplash: {}, + }, + { setSelectedProvider: () => {}, setSearchTerm: () => {} } + ) ); - expect(value).toStrictEqual( + expect(result.current).toStrictEqual( expect.objectContaining({ state: { selectedProvider: 'unsplash', searchTerm: '' }, actions: { From 76617cfff628179c3ba76afb914c35b3fb0cca74 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 11:57:07 +0200 Subject: [PATCH 24/32] Don't use effect in `TermsDialog` --- .../components/library/panes/media/media3p/termsDialog.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/story-editor/src/components/library/panes/media/media3p/termsDialog.js b/packages/story-editor/src/components/library/panes/media/media3p/termsDialog.js index 878d0bbc5eae..7677167d95bf 100644 --- a/packages/story-editor/src/components/library/panes/media/media3p/termsDialog.js +++ b/packages/story-editor/src/components/library/panes/media/media3p/termsDialog.js @@ -16,7 +16,7 @@ /** * External dependencies */ -import { useState, useEffect, useCallback } from '@googleforcreators/react'; +import { useState, useCallback } from '@googleforcreators/react'; import { __, TranslateWithMarkup } from '@googleforcreators/i18n'; import { trackClick, trackEvent } from '@googleforcreators/tracking'; import { @@ -26,6 +26,7 @@ import { LOCAL_STORAGE_PREFIX, localStore, } from '@googleforcreators/design-system'; + /** * Internal dependencies */ @@ -44,12 +45,9 @@ function TermsDialog() { setDialogOpen(false); localStore.setItemByKey(LOCAL_STORAGE_PREFIX.TERMS_MEDIA3P, true); trackEvent('media3p_terms_acknowledged'); + setDialogOpen(false); }, []); - useEffect(() => { - setDialogOpen(!hasAcknowledgedTerms3p); - }, [hasAcknowledgedTerms3p]); - const onTermsClick = useCallback((evt) => { trackClick(evt, 'click_terms_of_service'); }, []); From cc81564fa6962e415ad08e251a614ecfa7d61b22 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 12:43:34 +0200 Subject: [PATCH 25/32] Use named import --- packages/design-system/src/components/input/useNumericInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/design-system/src/components/input/useNumericInput.tsx b/packages/design-system/src/components/input/useNumericInput.tsx index 794569dd7bfb..eb6da40d2044 100644 --- a/packages/design-system/src/components/input/useNumericInput.tsx +++ b/packages/design-system/src/components/input/useNumericInput.tsx @@ -16,7 +16,7 @@ /** * External dependencies */ -import Big from 'big.js'; +import { Big } from 'big.js'; import { useCallback, useEffect, From 88f96d8c9e683b9449f5ef06cb98eba83b5497c4 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 12:43:42 +0200 Subject: [PATCH 26/32] Use same version for all --- package-lock.json | 255 ++++++---------------------------------------- package.json | 4 +- 2 files changed, 31 insertions(+), 228 deletions(-) diff --git a/package-lock.json b/package-lock.json index f7196afe51c0..70b3452be61b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,7 +76,7 @@ "ajv-formats": "^3.0.1", "babel-jest": "^29.6.1", "babel-loader": "^9.2.1", - "babel-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", + "babel-plugin-react-compiler": "0.0.0-experimental-34d04b6-20241024", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "browserslist": "^4.24.2", @@ -101,7 +101,7 @@ "eslint-plugin-oxlint": "^0.10.1", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", + "eslint-plugin-react-compiler": "0.0.0-experimental-34d04b6-20241024", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-styled-components-a11y": "^2.1.35", @@ -5997,9 +5997,10 @@ } }, "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -11516,11 +11517,12 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -11953,191 +11955,13 @@ } }, "node_modules/babel-plugin-react-compiler": { - "version": "19.0.0-beta-8a03594-20241020", - "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", - "integrity": "sha512-Wk0748DZzQEmjkEN4SbBujM5al4q5TfRBapA32ax0AID/Yek3emS+eyCvPvb4zPddYJTAF4LaJNLt8uHYfdKAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/generator": "7.2.0", - "@babel/types": "^7.19.0", - "chalk": "4", - "invariant": "^2.2.4", - "pretty-format": "^24", - "zod": "^3.22.4", - "zod-validation-error": "^2.1.0" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/@babel/generator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.2.0.tgz", - "integrity": "sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.2.0", - "jsesc": "^2.5.1", - "lodash": "^4.17.10", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*", - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/@types/yargs": { - "version": "13.0.12", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.12.tgz", - "integrity": "sha512-qCxJE1qgz2y0hA4pIxjBR+PelCH0U5CK1XJXFwCNqfmliatKp47UCXXE9Dyk1OXBDLvsCF57TqQEJaeLfDYEOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-plugin-react-compiler/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/babel-plugin-react-compiler/node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-plugin-react-compiler/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "0.0.0-experimental-34d04b6-20241024", + "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-0.0.0-experimental-34d04b6-20241024.tgz", + "integrity": "sha512-u0PCnjIWiwZ8MtPgatHSmLf4HU4rXS2ZYf8tqL2rMKU/3U8JQQ7sWvyJdDfZsqGVYkohBbpFCxEJ8AIeKs3yOA==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@babel/types": "^7.19.0" } }, "node_modules/babel-plugin-styled-components": { @@ -16191,9 +16015,9 @@ } }, "node_modules/eslint-plugin-react-compiler": { - "version": "19.0.0-beta-8a03594-20241020", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.0.0-beta-8a03594-20241020.tgz", - "integrity": "sha512-bYg1COih1s3r14IV/AKdQs/SN7CQmNI0ZaMtPdgZ6gp1S1Q/KGP9P43w7R6dHJ4wYpuMBvekNJHQdVu+x6UM+A==", + "version": "0.0.0-experimental-34d04b6-20241024", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-0.0.0-experimental-34d04b6-20241024.tgz", + "integrity": "sha512-J3TPwkQzBeg5V5RyfuH/HcBR7MDz4vKBKCSMksXwiYk6N5AtXeeMyHCF7p9+dQXK9kypB56Lt+qdB/vOusBOeA==", "dev": true, "license": "MIT", "dependencies": { @@ -17007,9 +16831,10 @@ } }, "node_modules/expect-puppeteer": { - "version": "10.1.3", - "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-10.1.3.tgz", - "integrity": "sha512-2t1D2t0AfBDMp8rMHEws6mRx1iXeER6sOrIm/8sxM3KxkY7O8AD6j5XfTtVJI6Updc/c4IiuFSz3o/82soHUdA==", + "version": "10.1.4", + "resolved": "https://registry.npmjs.org/expect-puppeteer/-/expect-puppeteer-10.1.4.tgz", + "integrity": "sha512-zNVzk/+TkPS/CuTlGSK7SjXuUpQiakXtUJhbTRrcPHop4jCWydPx9RlvHhQELzZYgXlLhIP+hvBzUNiN8WNAow==", + "license": "MIT", "engines": { "node": ">=16" } @@ -23822,13 +23647,14 @@ } }, "node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } @@ -33455,16 +33281,6 @@ "node": ">=8" } }, - "node_modules/trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -36036,19 +35852,6 @@ "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/zod-validation-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-2.1.0.tgz", - "integrity": "sha512-VJh93e2wb4c3tWtGgTa0OF/dTt/zoPCPzXq4V11ZjxmEAFaPi/Zss1xIZdEB5RD8GD00U0/iVXgqkF77RV7pdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.18.0" - } - }, "packages/activation-notice": { "name": "@web-stories-wp/activation-notice", "license": "Apache-2.0", diff --git a/package.json b/package.json index 2cf044b972fb..2b242bf91483 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "ajv-formats": "^3.0.1", "babel-jest": "^29.6.1", "babel-loader": "^9.2.1", - "babel-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", + "babel-plugin-react-compiler": "0.0.0-experimental-34d04b6-20241024", "babel-plugin-styled-components": "^2.1.4", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", "browserslist": "^4.24.2", @@ -125,7 +125,7 @@ "eslint-plugin-oxlint": "^0.10.1", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-react": "^7.37.2", - "eslint-plugin-react-compiler": "^19.0.0-beta-8a03594-20241020", + "eslint-plugin-react-compiler": "0.0.0-experimental-34d04b6-20241024", "eslint-plugin-react-hooks": "^5.0.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-styled-components-a11y": "^2.1.35", From 66b168d40b8da0402b9345ee6bfca6e6eb02dd41 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Sat, 26 Oct 2024 12:44:02 +0200 Subject: [PATCH 27/32] Silence some warnings. --- .../story-editor/src/components/colorPicker/gradientLine.js | 1 + .../src/components/library/panes/shopping/productDropdown.js | 1 + .../src/components/mediaRecording/playbackMedia.js | 1 + .../story-editor/src/components/mediaRecording/provider.js | 3 +-- packages/wp-story-editor/src/components/corsCheck/corsCheck.js | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/components/colorPicker/gradientLine.js b/packages/story-editor/src/components/colorPicker/gradientLine.js index 6023bf60bfde..132adb14b1c9 100644 --- a/packages/story-editor/src/components/colorPicker/gradientLine.js +++ b/packages/story-editor/src/components/colorPicker/gradientLine.js @@ -109,6 +109,7 @@ function GradientLine({ {stops.map(({ position, color }, index) => ( (stopsRef[index].current = ref)} key={ // eslint-disable-next-line react/no-array-index-key -- Should be OK here. diff --git a/packages/story-editor/src/components/library/panes/shopping/productDropdown.js b/packages/story-editor/src/components/library/panes/shopping/productDropdown.js index 1d8e13f4b5e3..90479451980f 100644 --- a/packages/story-editor/src/components/library/panes/shopping/productDropdown.js +++ b/packages/story-editor/src/components/library/panes/shopping/productDropdown.js @@ -90,6 +90,7 @@ function ProductDropdown({ product, setProduct, ...rest }) { setIsLoading(false); } })(); + // eslint-disable-next-line react-compiler/react-compiler -- FIXME // eslint-disable-next-line react-hooks/exhaustive-deps -- Stop getProductsByQuery from re-render. }, [initialProducts]); diff --git a/packages/story-editor/src/components/mediaRecording/playbackMedia.js b/packages/story-editor/src/components/mediaRecording/playbackMedia.js index ca0a3526c9ab..28a761526a2f 100644 --- a/packages/story-editor/src/components/mediaRecording/playbackMedia.js +++ b/packages/story-editor/src/components/mediaRecording/playbackMedia.js @@ -204,6 +204,7 @@ function PlaybackMedia() { run(); + // eslint-disable-next-line react-compiler/react-compiler -- FIXME // eslint-disable-next-line react-hooks/exhaustive-deps -- including liveStream will cause freeze }, [videoEffect, hasVideoEffect, streamNode, setCanvasStream, setCanvasNode]); diff --git a/packages/story-editor/src/components/mediaRecording/provider.js b/packages/story-editor/src/components/mediaRecording/provider.js index ab329b5709ab..f2bc2390ca30 100644 --- a/packages/story-editor/src/components/mediaRecording/provider.js +++ b/packages/story-editor/src/components/mediaRecording/provider.js @@ -271,8 +271,7 @@ function MediaRecordingProvider({ children }) { updateMediaDevices ); }; - // eslint-disable-next-line react-hooks/exhaustive-deps -- We only want to run it once. - }, []); + }, [updateMediaDevices]); const toggleVideo = useCallback(() => { setHasVideo(!hasVideo); diff --git a/packages/wp-story-editor/src/components/corsCheck/corsCheck.js b/packages/wp-story-editor/src/components/corsCheck/corsCheck.js index 97a71361479e..868d5ff8596b 100644 --- a/packages/wp-story-editor/src/components/corsCheck/corsCheck.js +++ b/packages/wp-story-editor/src/components/corsCheck/corsCheck.js @@ -70,6 +70,7 @@ function CorsCheck() { trackError('cors_check', err.message); } })(); + // eslint-disable-next-line react-compiler/react-compiler -- FIXME // eslint-disable-next-line react-hooks/exhaustive-deps -- Only run this effect once, so do not pass dependencies. }, []); From f4a71b943d17fe1a78eeefc3ced0c457bc59226b Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 6 Jan 2025 20:45:05 +0100 Subject: [PATCH 28/32] Fix another `null` issue in `useVideoTrimMode` --- .../components/videoTrim/useVideoTrimMode.js | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js b/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js index fbeef0f6bc46..f4d7e508770d 100644 --- a/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js +++ b/packages/story-editor/src/components/videoTrim/useVideoTrimMode.js @@ -40,9 +40,18 @@ function useVideoTrimMode() { clearEditing, }) ); - const { selectedElement } = useStory(({ state: { selectedElements } }) => ({ - selectedElement: selectedElements.length === 1 ? selectedElements[0] : null, - })); + const { selectedElement, selectedId, selectedResource, isVideo } = useStory( + ({ state: { selectedElements } }) => { + const selectedElement = + selectedElements.length === 1 ? selectedElements[0] : null; + return { + selectedElement, + selectedId: selectedElement ? selectedElement?.id : null, + selectedResource: selectedElement?.resource || {}, + isVideo: selectedElement?.type === 'video', + }; + } + ); const { actions: { getMediaById }, @@ -56,12 +65,11 @@ function useVideoTrimMode() { ); const getVideoData = useCallback(() => { - const { resource } = selectedElement; - const { trimData } = resource; + const { trimData } = selectedResource; const defaultVideoData = { element: selectedElement, - resource, + resource: selectedResource, start: 0, end: null, }; @@ -87,13 +95,13 @@ function useVideoTrimMode() { } else { setVideoData(defaultVideoData); } - }, [getMediaById, selectedElement]); + }, [getMediaById, selectedElement, selectedResource]); const toggleTrimMode = useCallback(() => { if (isEditing) { clearEditing(); - } else if (selectedElement) { - setEditingElementWithState(selectedElement.id, { + } else if (selectedId) { + setEditingElementWithState(selectedId, { isTrimMode: true, hasEditMenu: true, showOverflow: false, @@ -108,23 +116,28 @@ function useVideoTrimMode() { isEditing, clearEditing, setEditingElementWithState, - selectedElement, + selectedId, getVideoData, ]); const { isTranscodingEnabled } = useFFmpeg(); const hasTrimMode = useMemo(() => { - if (selectedElement?.type !== 'video' || !selectedElement?.resource) { + if (!isVideo) { return false; } - const { id, isExternal } = selectedElement.resource; - return ( - isTranscodingEnabled && !isExternal && !isCurrentResourceUploading(id) + isTranscodingEnabled && + !selectedResource.isExternal && + !isCurrentResourceUploading(selectedResource.id) ); - }, [selectedElement, isTranscodingEnabled, isCurrentResourceUploading]); + }, [ + isVideo, + selectedResource, + isTranscodingEnabled, + isCurrentResourceUploading, + ]); return { isTrimMode: Boolean(isEditing && isTrimMode), From 05e2693cf1c6adb18070111861afd8a0f0d60002 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 7 Jan 2025 10:52:36 +0100 Subject: [PATCH 29/32] Fix a couple more issues --- .../app/views/myStories/content/storiesView/index.js | 12 +++++++----- .../components/floatingMenu/elements/textAlign.js | 8 +++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/dashboard/src/app/views/myStories/content/storiesView/index.js b/packages/dashboard/src/app/views/myStories/content/storiesView/index.js index 0c27f6868694..b5c6caea41a7 100644 --- a/packages/dashboard/src/app/views/myStories/content/storiesView/index.js +++ b/packages/dashboard/src/app/views/myStories/content/storiesView/index.js @@ -113,7 +113,7 @@ function StoriesView({ loading, storyActions, stories, view }) { const handleOnDeleteStory = useCallback(() => { trackEvent('delete_story'); storyActions.trashStory(activeStory); - setFocusedStory({ id: activeStory.id, isDeleted: true }); + setFocusedStory({ id: activeStory?.id, isDeleted: true }); setActiveDialog(''); }, [storyActions, activeStory]); @@ -162,6 +162,11 @@ function StoriesView({ loading, storyActions, stories, view }) { [showSnackbar] ); + const handleCloseConfirmDialog = useCallback(() => { + setFocusedStory({ id: activeStory?.id }); + setActiveDialog(''); + }, [activeStory]); + const menuItems = STORY_CONTEXT_MENU_ITEMS.map((item) => { switch (item?.value) { case STORY_CONTEXT_MENU_ACTIONS.COPY_STORY_LINK: @@ -257,10 +262,7 @@ function StoriesView({ loading, storyActions, stories, view }) { isOpen contentLabel={__('Dialog to confirm deleting a story', 'web-stories')} title={__('Delete Story', 'web-stories')} - onClose={() => { - setFocusedStory({ id: activeStory.id }); - setActiveDialog(''); - }} + onClose={handleCloseConfirmDialog} secondaryText={__('Cancel', 'web-stories')} secondaryRest={{ ['aria-label']: sprintf( diff --git a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js index 1a3b31ee5959..8ddd78fff58d 100644 --- a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js +++ b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js @@ -106,7 +106,13 @@ function TextAlign() { // Record left position of this button in the parent design menu useEffect( - () => setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X), + () => { + if ( buttonRef.current) { + setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X) + } else { + setOffsetLeft(OFFSET_X) + } + }, [] ); From 619f4d1ee0ab2e6c760c1625a71aa5f46664a445 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Tue, 7 Jan 2025 11:12:50 +0100 Subject: [PATCH 30/32] Lint fix --- .../floatingMenu/elements/textAlign.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js index 8ddd78fff58d..4681a33ee4e0 100644 --- a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js +++ b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js @@ -105,16 +105,13 @@ function TextAlign() { const [offsetLeft, setOffsetLeft] = useState(0); // Record left position of this button in the parent design menu - useEffect( - () => { - if ( buttonRef.current) { - setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X) - } else { - setOffsetLeft(OFFSET_X) - } - }, - [] - ); + useEffect(() => { + if (buttonRef.current) { + setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X); + } else { + setOffsetLeft(OFFSET_X); + } + }, []); // When menu has just opened, focus the current button in submenu const currentIconMounted = (node) => { From b926938ba9a4ee93bec1ac6482e43df5771dd603 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 9 Jan 2025 22:29:33 +0100 Subject: [PATCH 31/32] Increase count in tab util --- .../story-editor/src/components/floatingMenu/karma/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/components/floatingMenu/karma/utils.js b/packages/story-editor/src/components/floatingMenu/karma/utils.js index 5ccc3b5a536b..fd9562442629 100644 --- a/packages/story-editor/src/components/floatingMenu/karma/utils.js +++ b/packages/story-editor/src/components/floatingMenu/karma/utils.js @@ -21,7 +21,7 @@ export async function tabToCanvasFocusContainer(focusContainer, fixture) { // tab until focus reaches the canvas container let count = 0; - while (count < 15) { + while (count < 20) { // eslint-disable-next-line no-await-in-loop -- need to await key press await fixture.events.keyboard.press('tab'); @@ -32,7 +32,7 @@ export async function tabToCanvasFocusContainer(focusContainer, fixture) { count++; } - if (count >= 15) { + if (count >= 20) { throw new Error('Could not find focus container.'); } } From b7eae28432687ab4ec33984eb03accf3f4195621 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Thu, 9 Jan 2025 22:43:26 +0100 Subject: [PATCH 32/32] Add sleep --- .../panes/pageTemplates/karma/savedPageTemplates.karma.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/story-editor/src/components/library/panes/pageTemplates/karma/savedPageTemplates.karma.js b/packages/story-editor/src/components/library/panes/pageTemplates/karma/savedPageTemplates.karma.js index d48d93821cf1..24c76011491c 100644 --- a/packages/story-editor/src/components/library/panes/pageTemplates/karma/savedPageTemplates.karma.js +++ b/packages/story-editor/src/components/library/panes/pageTemplates/karma/savedPageTemplates.karma.js @@ -244,6 +244,9 @@ describe('CUJ: Page Templates: Custom Saved Templates', () => { const message = fixture.screen.getByRole('alert', { hidden: true }); expect(message.textContent).toBe('Page Template saved.'); + // Wait until the page templates list has rendered. + await fixture.events.sleep(800); + expect( fixture.editor.library.pageTemplatesPane.pageTemplates.length ).toBe(1);