From 763ec4cd1d252c8e0b63b8672c1190e76d44301e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 7 Nov 2022 12:52:23 -0300 Subject: [PATCH 01/99] Set up base for typing. --- packages/story-editor/package.json | 1 + .../{useAutoSave.js => useAutoSave.ts} | 0 ...seLocalAutoSave.js => useLocalAutoSave.ts} | 0 .../{useSaveStory.js => useSaveStory.ts} | 0 .../src/app/story/{context.js => context.ts} | 0 .../{useHashState.js => useHashState.ts} | 0 ...{useHistoryEntry.js => useHistoryEntry.ts} | 0 ...seHistoryReplay.js => useHistoryReplay.ts} | 0 .../{useLoadStory.js => useLoadStory.ts} | 0 .../src/app/story/{index.js => index.ts} | 0 .../{storyProvider.js => storyProvider.tsx} | 0 .../storyTriggers/{index.js => index.ts} | 0 .../storyEvents/{index.js => index.ts} | 0 ...er.js => onInitialElementAddedRegister.ts} | 0 ...ddedRegister.js => onPageAddedRegister.ts} | 0 .../storyEvents/{types.js => types.ts} | 0 ...sProvider.js => storyTriggersProvider.tsx} | 0 ...seStoryTriggers.js => useStoryTriggers.ts} | 0 .../app/story/{useStory.js => useStory.tsx} | 0 .../{actions.js => actions.ts} | 0 .../useStoryReducer/{index.js => index.ts} | 0 .../{reducer.js => reducer.ts} | 0 .../{addAnimations.js => addAnimations.ts} | 0 .../{addElements.js => addElements.ts} | 0 ...rossPages.js => addElementsAcrossPages.ts} | 0 .../reducers/{addGroup.js => addGroup.ts} | 0 .../reducers/{addPage.js => addPage.ts} | 0 .../{arrangeElement.js => arrangeElement.ts} | 0 .../{arrangeGroup.js => arrangeGroup.ts} | 0 .../{arrangePage.js => arrangePage.ts} | 0 ...{combineElements.js => combineElements.ts} | 0 ...ectedElement.js => copySelectedElement.ts} | 0 .../{deleteElements.js => deleteElements.ts} | 0 ...rceId.js => deleteElementsByResourceId.ts} | 0 .../{deleteGroup.js => deleteGroup.ts} | 0 .../reducers/{deletePage.js => deletePage.ts} | 0 ...ementsById.js => duplicateElementsById.ts} | 0 .../{duplicateGroup.js => duplicateGroup.ts} | 0 .../reducers/{index.js => index.ts} | 0 ...FromGroup.js => removeElementFromGroup.ts} | 0 .../reducers/{restore.js => restore.ts} | 0 .../{selectElement.js => selectElement.ts} | 0 ...oundElement.js => setBackgroundElement.ts} | 0 .../{setCurrentPage.js => setCurrentPage.ts} | 0 ...ctedElements.js => setSelectedElements.ts} | 0 .../{toggleElement.js => toggleElement.ts} | 0 .../{toggleLayer.js => toggleLayer.ts} | 0 ...{unselectElement.js => unselectElement.ts} | 0 ...mationState.js => updateAnimationState.ts} | 0 .../{updateElements.js => updateElements.ts} | 0 ...amily.js => updateElementsByFontFamily.ts} | 0 ...rceId.js => updateElementsByResourceId.ts} | 0 .../{updateGroup.js => updateGroup.ts} | 0 .../reducers/{updatePage.js => updatePage.ts} | 0 .../{updateStory.js => updateStory.ts} | 0 .../reducers/{utils.js => utils.ts} | 0 .../useStoryReducer/{types.js => types.ts} | 0 ...{useStoryReducer.js => useStoryReducer.ts} | 0 ...eleteNestedKeys.js => deleteNestedKeys.ts} | 0 .../{getAllProducts.js => getAllProducts.ts} | 0 ...yPropsToSave.js => getStoryPropsToSave.ts} | 0 .../{isEmptyStory.js => isEmptyStory.ts} | 0 ...tainsBlobUrl.js => pageContainsBlobUrl.ts} | 0 .../story-editor/src/types/storyProvider.ts | 0 packages/story-editor/tsconfig.json | 19 +++++++++++++++++++ tsconfig.json | 2 ++ 66 files changed, 22 insertions(+) rename packages/story-editor/src/app/story/actions/{useAutoSave.js => useAutoSave.ts} (100%) rename packages/story-editor/src/app/story/actions/{useLocalAutoSave.js => useLocalAutoSave.ts} (100%) rename packages/story-editor/src/app/story/actions/{useSaveStory.js => useSaveStory.ts} (100%) rename packages/story-editor/src/app/story/{context.js => context.ts} (100%) rename packages/story-editor/src/app/story/effects/{useHashState.js => useHashState.ts} (100%) rename packages/story-editor/src/app/story/effects/{useHistoryEntry.js => useHistoryEntry.ts} (100%) rename packages/story-editor/src/app/story/effects/{useHistoryReplay.js => useHistoryReplay.ts} (100%) rename packages/story-editor/src/app/story/effects/{useLoadStory.js => useLoadStory.ts} (100%) rename packages/story-editor/src/app/story/{index.js => index.ts} (100%) rename packages/story-editor/src/app/story/{storyProvider.js => storyProvider.tsx} (100%) rename packages/story-editor/src/app/story/storyTriggers/{index.js => index.ts} (100%) rename packages/story-editor/src/app/story/storyTriggers/storyEvents/{index.js => index.ts} (100%) rename packages/story-editor/src/app/story/storyTriggers/storyEvents/{onInitialElementAddedRegister.js => onInitialElementAddedRegister.ts} (100%) rename packages/story-editor/src/app/story/storyTriggers/storyEvents/{onPageAddedRegister.js => onPageAddedRegister.ts} (100%) rename packages/story-editor/src/app/story/storyTriggers/storyEvents/{types.js => types.ts} (100%) rename packages/story-editor/src/app/story/storyTriggers/{storyTriggersProvider.js => storyTriggersProvider.tsx} (100%) rename packages/story-editor/src/app/story/storyTriggers/{useStoryTriggers.js => useStoryTriggers.ts} (100%) rename packages/story-editor/src/app/story/{useStory.js => useStory.tsx} (100%) rename packages/story-editor/src/app/story/useStoryReducer/{actions.js => actions.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/{index.js => index.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/{reducer.js => reducer.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{addAnimations.js => addAnimations.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{addElements.js => addElements.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{addElementsAcrossPages.js => addElementsAcrossPages.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{addGroup.js => addGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{addPage.js => addPage.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{arrangeElement.js => arrangeElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{arrangeGroup.js => arrangeGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{arrangePage.js => arrangePage.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{combineElements.js => combineElements.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{copySelectedElement.js => copySelectedElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{deleteElements.js => deleteElements.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{deleteElementsByResourceId.js => deleteElementsByResourceId.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{deleteGroup.js => deleteGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{deletePage.js => deletePage.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{duplicateElementsById.js => duplicateElementsById.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{duplicateGroup.js => duplicateGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{index.js => index.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{removeElementFromGroup.js => removeElementFromGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{restore.js => restore.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{selectElement.js => selectElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{setBackgroundElement.js => setBackgroundElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{setCurrentPage.js => setCurrentPage.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{setSelectedElements.js => setSelectedElements.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{toggleElement.js => toggleElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{toggleLayer.js => toggleLayer.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{unselectElement.js => unselectElement.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateAnimationState.js => updateAnimationState.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateElements.js => updateElements.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateElementsByFontFamily.js => updateElementsByFontFamily.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateElementsByResourceId.js => updateElementsByResourceId.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateGroup.js => updateGroup.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updatePage.js => updatePage.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{updateStory.js => updateStory.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/reducers/{utils.js => utils.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/{types.js => types.ts} (100%) rename packages/story-editor/src/app/story/useStoryReducer/{useStoryReducer.js => useStoryReducer.ts} (100%) rename packages/story-editor/src/app/story/utils/{deleteNestedKeys.js => deleteNestedKeys.ts} (100%) rename packages/story-editor/src/app/story/utils/{getAllProducts.js => getAllProducts.ts} (100%) rename packages/story-editor/src/app/story/utils/{getStoryPropsToSave.js => getStoryPropsToSave.ts} (100%) rename packages/story-editor/src/app/story/utils/{isEmptyStory.js => isEmptyStory.ts} (100%) rename packages/story-editor/src/app/story/utils/{pageContainsBlobUrl.js => pageContainsBlobUrl.ts} (100%) create mode 100644 packages/story-editor/src/types/storyProvider.ts create mode 100644 packages/story-editor/tsconfig.json diff --git a/packages/story-editor/package.json b/packages/story-editor/package.json index d02972a74fbc..6fe2ba2f861c 100644 --- a/packages/story-editor/package.json +++ b/packages/story-editor/package.json @@ -31,6 +31,7 @@ }, "main": "dist/index.js", "module": "dist-module/index.js", + "types": "dist-types/index.d.ts", "source": "src/index.js", "publishConfig": { "access": "public" diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.js b/packages/story-editor/src/app/story/actions/useAutoSave.ts similarity index 100% rename from packages/story-editor/src/app/story/actions/useAutoSave.js rename to packages/story-editor/src/app/story/actions/useAutoSave.ts diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.js b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts similarity index 100% rename from packages/story-editor/src/app/story/actions/useLocalAutoSave.js rename to packages/story-editor/src/app/story/actions/useLocalAutoSave.ts diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.js b/packages/story-editor/src/app/story/actions/useSaveStory.ts similarity index 100% rename from packages/story-editor/src/app/story/actions/useSaveStory.js rename to packages/story-editor/src/app/story/actions/useSaveStory.ts diff --git a/packages/story-editor/src/app/story/context.js b/packages/story-editor/src/app/story/context.ts similarity index 100% rename from packages/story-editor/src/app/story/context.js rename to packages/story-editor/src/app/story/context.ts diff --git a/packages/story-editor/src/app/story/effects/useHashState.js b/packages/story-editor/src/app/story/effects/useHashState.ts similarity index 100% rename from packages/story-editor/src/app/story/effects/useHashState.js rename to packages/story-editor/src/app/story/effects/useHashState.ts diff --git a/packages/story-editor/src/app/story/effects/useHistoryEntry.js b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts similarity index 100% rename from packages/story-editor/src/app/story/effects/useHistoryEntry.js rename to packages/story-editor/src/app/story/effects/useHistoryEntry.ts diff --git a/packages/story-editor/src/app/story/effects/useHistoryReplay.js b/packages/story-editor/src/app/story/effects/useHistoryReplay.ts similarity index 100% rename from packages/story-editor/src/app/story/effects/useHistoryReplay.js rename to packages/story-editor/src/app/story/effects/useHistoryReplay.ts diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.js b/packages/story-editor/src/app/story/effects/useLoadStory.ts similarity index 100% rename from packages/story-editor/src/app/story/effects/useLoadStory.js rename to packages/story-editor/src/app/story/effects/useLoadStory.ts diff --git a/packages/story-editor/src/app/story/index.js b/packages/story-editor/src/app/story/index.ts similarity index 100% rename from packages/story-editor/src/app/story/index.js rename to packages/story-editor/src/app/story/index.ts diff --git a/packages/story-editor/src/app/story/storyProvider.js b/packages/story-editor/src/app/story/storyProvider.tsx similarity index 100% rename from packages/story-editor/src/app/story/storyProvider.js rename to packages/story-editor/src/app/story/storyProvider.tsx diff --git a/packages/story-editor/src/app/story/storyTriggers/index.js b/packages/story-editor/src/app/story/storyTriggers/index.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/index.js rename to packages/story-editor/src/app/story/storyTriggers/index.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/index.js b/packages/story-editor/src/app/story/storyTriggers/storyEvents/index.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/storyEvents/index.js rename to packages/story-editor/src/app/story/storyTriggers/storyEvents/index.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.js b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.js rename to packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.js b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.js rename to packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/types.js b/packages/story-editor/src/app/story/storyTriggers/storyEvents/types.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/storyEvents/types.js rename to packages/story-editor/src/app/story/storyTriggers/storyEvents/types.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.js b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.js rename to packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx diff --git a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.js b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts similarity index 100% rename from packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.js rename to packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts diff --git a/packages/story-editor/src/app/story/useStory.js b/packages/story-editor/src/app/story/useStory.tsx similarity index 100% rename from packages/story-editor/src/app/story/useStory.js rename to packages/story-editor/src/app/story/useStory.tsx diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.js b/packages/story-editor/src/app/story/useStoryReducer/actions.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/actions.js rename to packages/story-editor/src/app/story/useStoryReducer/actions.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/index.js b/packages/story-editor/src/app/story/useStoryReducer/index.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/index.js rename to packages/story-editor/src/app/story/useStoryReducer/index.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.js b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducer.js rename to packages/story-editor/src/app/story/useStoryReducer/reducer.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/index.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/index.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/restore.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/reducers/utils.js rename to packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/types.js b/packages/story-editor/src/app/story/useStoryReducer/types.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/types.js rename to packages/story-editor/src/app/story/useStoryReducer/types.ts diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.js b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts similarity index 100% rename from packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.js rename to packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.js b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts similarity index 100% rename from packages/story-editor/src/app/story/utils/deleteNestedKeys.js rename to packages/story-editor/src/app/story/utils/deleteNestedKeys.ts diff --git a/packages/story-editor/src/app/story/utils/getAllProducts.js b/packages/story-editor/src/app/story/utils/getAllProducts.ts similarity index 100% rename from packages/story-editor/src/app/story/utils/getAllProducts.js rename to packages/story-editor/src/app/story/utils/getAllProducts.ts diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.js b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts similarity index 100% rename from packages/story-editor/src/app/story/utils/getStoryPropsToSave.js rename to packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts diff --git a/packages/story-editor/src/app/story/utils/isEmptyStory.js b/packages/story-editor/src/app/story/utils/isEmptyStory.ts similarity index 100% rename from packages/story-editor/src/app/story/utils/isEmptyStory.js rename to packages/story-editor/src/app/story/utils/isEmptyStory.ts diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.js b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts similarity index 100% rename from packages/story-editor/src/app/story/utils/pageContainsBlobUrl.js rename to packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json new file mode 100644 index 000000000000..f9fcfdf7b074 --- /dev/null +++ b/packages/story-editor/tsconfig.json @@ -0,0 +1,19 @@ + +{ + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "dist-types" + }, + "references": [ + { "path": "../dom" }, + { "path": "../elements" }, + { "path": "../i18n" }, + { "path": "../masks" }, + { "path": "../migration" }, + { "path": "../patterns" }, + { "path": "../react" }, + { "path": "../tracking" } + ], + "include": ["src/app/story/**/*", "src/types/*"], +} diff --git a/tsconfig.json b/tsconfig.json index 57cadea14fb7..701b3ee7a19a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "references": [ { "path": "packages/activation-notice" }, + { "path": "packages/dom" }, { "path": "packages/elements" }, { "path": "packages/fonts" }, { "path": "packages/i18n" }, @@ -12,6 +13,7 @@ { "path": "packages/react" }, { "path": "packages/rich-text" }, { "path": "packages/stickers" }, + { "path": "packages/story-editor" }, { "path": "packages/templates" }, { "path": "packages/text-sets" }, { "path": "packages/tracking" }, From cbcb33be3cc96f0e01c3894a9a00b1f99c8fd152 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 8 Nov 2022 15:05:56 -0300 Subject: [PATCH 02/99] useHashState --- .../src/app/story/effects/useHashState.ts | 22 +++++++++++-------- .../src/app/story/storyProvider.tsx | 19 +++++++++------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/packages/story-editor/src/app/story/effects/useHashState.ts b/packages/story-editor/src/app/story/effects/useHashState.ts index 9a2db0d13dae..578b047a37fe 100644 --- a/packages/story-editor/src/app/story/effects/useHashState.ts +++ b/packages/story-editor/src/app/story/effects/useHashState.ts @@ -32,32 +32,36 @@ * External dependencies */ import { useEffect, useState } from '@googleforcreators/react'; +import type { Dispatch, SetStateAction } from 'react'; -export function hashToParams(hash) { +export function hashToParams(hash: string) { return new URLSearchParams(hash.startsWith('#') ? hash.substr(1) : hash); } /** * Functions like a normal `useState()` but reads initial value of of url * hash key and uses `fallback` if no value found. Also updates hash key on - * every state update so is persistant between mounts. + * every state update so is persistent between mounts. * * Values held in here must be serializable. * * Can be used as many times as needed, but may exceed url char limit * if over used. - * - * @param {string} key identifier for storing hash persisted value. - * @param {*} fallback value state intialized with if none found under key. - * @return {[*, Function]} value & setter tuple like `useState()` */ -function useHashState(key, fallback) { - const [value, setValue] = useState(() => { +function useHashState( + key: string, + fallback: string | null +): [string | null, Dispatch>] { + const [value, setValue] = useState(() => { const params = hashToParams(window.location.hash); let _value = fallback; try { if (params.has(key)) { - _value = JSON.parse(decodeURI(params.get(key))); + const paramValue = params.get(key); + if (null === paramValue) { + return paramValue; + } + _value = JSON.parse(decodeURI(paramValue)) as string; } } catch (e) { // @TODO Add some error handling diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 252408cacc5d..a826dcae42b0 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -17,8 +17,9 @@ /** * External dependencies */ -import PropTypes from 'prop-types'; +import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies @@ -36,7 +37,15 @@ import useAutoSave from './actions/useAutoSave'; import { StoryTriggersProvider } from './storyTriggers'; import useLocalAutoSave from './actions/useLocalAutoSave'; -function StoryProvider({ storyId, initialEdits, children }) { +interface ProviderProps { + storyId: number; + initialEdits?: { + [index: string]: unknown; + story?: Story; + }; + children: ReactNode; +} +function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { const [hashPageId, setHashPageId] = useHashState('page', null); const { state: reducerState, @@ -201,10 +210,4 @@ function StoryProvider({ storyId, initialEdits, children }) { ); } -StoryProvider.propTypes = { - children: PropTypes.node, - storyId: PropTypes.number, - initialEdits: PropTypes.object, -}; - export default StoryProvider; From 7ecb7cce92b29385c785665d0fa95a39d39e6a00 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 8 Nov 2022 17:12:04 -0300 Subject: [PATCH 03/99] Start typing some actions --- .../src/app/story/storyProvider.tsx | 3 +- .../src/app/story/useStoryReducer/actions.ts | 106 ++++++++++-------- .../src/app/story/useStoryReducer/reducer.ts | 12 +- .../story/useStoryReducer/reducers/addPage.ts | 13 +-- .../useStoryReducer/reducers/deletePage.ts | 17 ++- .../useStoryReducer/reducers/updatePage.ts | 16 +-- .../story/useStoryReducer/useStoryReducer.ts | 12 +- .../story-editor/src/types/storyProvider.ts | 57 ++++++++++ packages/types/src/story/story.ts | 5 +- 9 files changed, 163 insertions(+), 78 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index a826dcae42b0..9739fa22a488 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { ReactNode } from 'react'; +import type {ReactNode, Reducer} from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; import type { Story } from '@googleforcreators/types'; @@ -36,6 +36,7 @@ import useStoryReducer from './useStoryReducer'; import useAutoSave from './actions/useAutoSave'; import { StoryTriggersProvider } from './storyTriggers'; import useLocalAutoSave from './actions/useLocalAutoSave'; +import type {AddPageAction} from "../../types/storyProvider"; interface ProviderProps { storyId: number; diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index 5603812456f1..f2c7265e7f12 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -14,22 +14,34 @@ * limitations under the License. */ +/** + * External dependencies + */ +import type { Dispatch } from 'react'; + /** * Internal dependencies */ +import type { + AddPageProps, + DeletePageProps, + ReducerActionProps, + UpdatePageProps, +} from '../../../types/storyProvider'; import * as types from './types'; +type DispatchType = Dispatch; // Exposed actions const addPage = - (dispatch) => - ({ page, position, updateSelection }) => + (dispatch: DispatchType) => + ({ page, position, updateSelection }: AddPageProps) => dispatch({ type: types.ADD_PAGE, payload: { page, position, updateSelection }, }); const addPageAt = - (dispatch) => + (dispatch: DispatchType) => ({ page, position, updateSelection }) => dispatch({ type: types.ADD_PAGE, @@ -37,20 +49,20 @@ const addPageAt = }); const deletePage = - (dispatch) => - ({ pageId }) => + (dispatch: DispatchType) => + ({ pageId }: DeletePageProps) => dispatch({ type: types.DELETE_PAGE, payload: { pageId } }); -const deleteCurrentPage = (dispatch) => () => +const deleteCurrentPage = (dispatch: DispatchType) => () => dispatch({ type: types.DELETE_PAGE, payload: { pageId: null } }); const updatePageProperties = - (dispatch) => - ({ pageId, properties }) => + (dispatch: DispatchType) => + ({ pageId, properties }: UpdatePageProps) => dispatch({ type: types.UPDATE_PAGE, payload: { pageId, properties } }); const updateCurrentPageProperties = - (dispatch) => + (dispatch: DispatchType) => ({ properties }) => dispatch({ type: types.UPDATE_PAGE, @@ -58,17 +70,17 @@ const updateCurrentPageProperties = }); const arrangePage = - (dispatch) => + (dispatch: DispatchType) => ({ pageId, position }) => dispatch({ type: types.ARRANGE_PAGE, payload: { pageId, position } }); const setCurrentPage = - (dispatch) => + (dispatch: DispatchType) => ({ pageId }) => dispatch({ type: types.SET_CURRENT_PAGE, payload: { pageId } }); const addElements = - (dispatch) => + (dispatch: DispatchType) => ({ elements, pageId, updateSelection }) => dispatch({ type: types.ADD_ELEMENTS, @@ -76,7 +88,7 @@ const addElements = }); const addElement = - (dispatch) => + (dispatch: DispatchType) => ({ element, pageId, updateSelection }) => dispatch({ type: types.ADD_ELEMENTS, @@ -84,15 +96,15 @@ const addElement = }); const deleteElementsById = - (dispatch) => + (dispatch: DispatchType) => ({ elementIds }) => dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds } }); -const deleteSelectedElements = (dispatch) => () => +const deleteSelectedElements = (dispatch: DispatchType) => () => dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds: null } }); const deleteElementById = - (dispatch) => + (dispatch: DispatchType) => ({ elementId }) => dispatch({ type: types.DELETE_ELEMENTS, @@ -100,7 +112,7 @@ const deleteElementById = }); const updateElementsById = - (dispatch) => + (dispatch: DispatchType) => ({ elementIds, properties }) => dispatch({ type: types.UPDATE_ELEMENTS, @@ -108,7 +120,7 @@ const updateElementsById = }); const updateElementsByResourceId = - (dispatch) => + (dispatch: DispatchType) => ({ id, properties }) => dispatch({ type: types.UPDATE_ELEMENTS_BY_RESOURCE_ID, @@ -116,7 +128,7 @@ const updateElementsByResourceId = }); const deleteElementsByResourceId = - (dispatch) => + (dispatch: DispatchType) => ({ id }) => dispatch({ type: types.DELETE_ELEMENTS_BY_RESOURCE_ID, @@ -124,7 +136,7 @@ const deleteElementsByResourceId = }); const updateElementById = - (dispatch) => + (dispatch: DispatchType) => ({ elementId, properties }) => dispatch({ type: types.UPDATE_ELEMENTS, @@ -132,7 +144,7 @@ const updateElementById = }); const duplicateElementsById = - (dispatch) => + (dispatch: DispatchType) => ({ elementIds }) => dispatch({ type: types.DUPLICATE_ELEMENTS_BY_ID, @@ -140,7 +152,7 @@ const duplicateElementsById = }); const updateSelectedElements = - (dispatch) => + (dispatch: DispatchType) => ({ properties }) => dispatch({ type: types.UPDATE_ELEMENTS, @@ -148,7 +160,7 @@ const updateSelectedElements = }); const combineElements = - (dispatch) => + (dispatch: DispatchType) => ({ firstElement, secondId, shouldRetainAnimations }) => dispatch({ type: types.COMBINE_ELEMENTS, @@ -156,18 +168,18 @@ const combineElements = }); const setBackgroundElement = - (dispatch) => + (dispatch: DispatchType) => ({ elementId }) => dispatch({ type: types.SET_BACKGROUND_ELEMENT, payload: { elementId } }); -const clearBackgroundElement = (dispatch) => () => +const clearBackgroundElement = (dispatch: DispatchType) => () => dispatch({ type: types.SET_BACKGROUND_ELEMENT, payload: { elementId: null }, }); const arrangeElement = - (dispatch) => + (dispatch: DispatchType) => ({ elementId, position, groupId }) => dispatch({ type: types.ARRANGE_ELEMENT, @@ -175,12 +187,12 @@ const arrangeElement = }); const arrangeGroup = - (dispatch) => + (dispatch: DispatchType) => ({ groupId, position }) => dispatch({ type: types.ARRANGE_GROUP, payload: { groupId, position } }); const arrangeSelection = - (dispatch) => + (dispatch: DispatchType) => ({ position, groupId }) => dispatch({ type: types.ARRANGE_ELEMENT, @@ -188,28 +200,28 @@ const arrangeSelection = }); const setSelectedElementsById = - (dispatch) => + (dispatch: DispatchType) => ({ elementIds, withLinked }) => dispatch({ type: types.SET_SELECTED_ELEMENTS, payload: { elementIds, withLinked }, }); -const clearSelection = (dispatch) => () => +const clearSelection = (dispatch: DispatchType) => () => dispatch({ type: types.SET_SELECTED_ELEMENTS, payload: { elementIds: [] } }); const addElementToSelection = - (dispatch) => + (dispatch: DispatchType) => ({ elementId }) => dispatch({ type: types.SELECT_ELEMENT, payload: { elementId } }); const removeElementFromSelection = - (dispatch) => + (dispatch: DispatchType) => ({ elementId }) => dispatch({ type: types.UNSELECT_ELEMENT, payload: { elementId } }); const toggleElementInSelection = - (dispatch) => + (dispatch: DispatchType) => ({ elementId, withLinked }) => dispatch({ type: types.TOGGLE_ELEMENT_IN_SELECTION, @@ -217,12 +229,12 @@ const toggleElementInSelection = }); const updateStory = - (dispatch) => + (dispatch: DispatchType) => ({ properties }) => dispatch({ type: types.UPDATE_STORY, payload: { properties } }); const updateAnimationState = - (dispatch) => + (dispatch: DispatchType) => ({ animationState }) => dispatch({ type: types.UPDATE_ANIMATION_STATE, @@ -230,25 +242,25 @@ const updateAnimationState = }); const addAnimations = - (dispatch) => + (dispatch: DispatchType) => ({ animations }) => dispatch({ type: types.ADD_ANIMATIONS, payload: { animations } }); const toggleLayer = - (dispatch) => + (dispatch: DispatchType) => ({ metaKey, shiftKey, elementId, withLinked }) => dispatch({ type: types.TOGGLE_LAYER, payload: { metaKey, shiftKey, elementId, withLinked }, }); -const copySelectedElement = (dispatch) => () => +const copySelectedElement = (dispatch: DispatchType) => () => dispatch({ type: types.COPY_SELECTED_ELEMENT, }); const updateElementsByFontFamily = - (dispatch) => + (dispatch: DispatchType) => ({ family, properties }) => dispatch({ type: types.UPDATE_ELEMENTS_BY_FONT_FAMILY, @@ -256,12 +268,12 @@ const updateElementsByFontFamily = }); const addGroup = - (dispatch) => + (dispatch: DispatchType) => ({ groupId, name, isLocked }) => dispatch({ type: types.ADD_GROUP, payload: { groupId, name, isLocked } }); const updateGroupById = - (dispatch) => + (dispatch: DispatchType) => ({ groupId, properties }) => dispatch({ type: types.UPDATE_GROUP, @@ -269,7 +281,7 @@ const updateGroupById = }); const deleteGroupById = - (dispatch) => + (dispatch: DispatchType) => ({ groupId }) => dispatch({ type: types.DELETE_GROUP, @@ -277,7 +289,7 @@ const deleteGroupById = }); const deleteGroupAndElementsById = - (dispatch) => + (dispatch: DispatchType) => ({ groupId }) => dispatch({ type: types.DELETE_GROUP, @@ -285,7 +297,7 @@ const deleteGroupAndElementsById = }); const duplicateGroupById = - (dispatch) => + (dispatch: DispatchType) => ({ groupId, name, oldGroupId, isLocked }) => dispatch({ type: types.DUPLICATE_GROUP, @@ -293,7 +305,7 @@ const duplicateGroupById = }); const removeElementFromGroup = - (dispatch) => + (dispatch: DispatchType) => ({ elementId, groupId }) => dispatch({ type: types.REMOVE_ELEMENT_FROM_GROUP, @@ -301,7 +313,7 @@ const removeElementFromGroup = }); const addElementsAcrossPages = - (dispatch) => + (dispatch: DispatchType) => ({ elements, page, position }) => dispatch({ type: types.ADD_ELEMENTS_ACROSS_PAGES, @@ -356,7 +368,7 @@ export const exposedActions = { // Internal actions const restore = - (dispatch) => + (dispatch: DispatchType) => ({ pages, selection, current, story, capabilities }) => dispatch({ type: types.RESTORE, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index a3e3ac2c222e..c476e68ab853 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -14,14 +14,20 @@ * limitations under the License. */ +/** + * External dependencies + */ +import type { Story } from '@googleforcreators/types'; + /** * Internal dependencies */ +import type { ReducerActionProps } from '../../../types/storyProvider'; import * as types from './types'; import * as reducers from './reducers'; // eslint-disable-next-line complexity -- reducer function, negligible. -function reducer(state, { type, payload }) { +function reducer(state: Story, { type, payload }: ReducerActionProps): Story { switch (type) { case types.ADD_PAGE: { return reducers.addPage(state, payload); @@ -35,7 +41,7 @@ function reducer(state, { type, payload }) { return reducers.updatePage(state, payload); } - case types.ARRANGE_PAGE: { + /*case types.ARRANGE_PAGE: { return reducers.arrangePage(state, payload); } @@ -149,7 +155,7 @@ function reducer(state, { type, payload }) { case types.ADD_ELEMENTS_ACROSS_PAGES: { return reducers.addElementsAcrossPages(state, payload); - } + }*/ default: return state; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index 00102b45a591..595283fe5815 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -18,10 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ +import type { AddPageProps } from '../../../../types/storyProvider'; import { isInsideRange } from './utils'; /** @@ -34,14 +36,11 @@ import { isInsideRange } from './utils'; * New page must have at least one element, the default background element. * * Selection is cleared by default. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Object} payload.page Object with properties of new page - * @param {Object} payload.position Position at which to insert the new page. If null, insert after current - * @param {boolean} [payload.updateSelection=true] Whether to update page and element selection. */ -export const addPage = (draft, { page, position, updateSelection = true }) => { +export const addPage = ( + draft: Story, + { page, position, updateSelection = true }: AddPageProps +) => { // Ensure new page has at least one element if (!page.elements?.length) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index 9a06075e43f3..989f46cd5c1e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -18,6 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type { DeletePageProps } from '../../../../types/storyProvider'; /** * Delete page by id or delete current page if no id given. @@ -30,17 +36,16 @@ import { produce } from 'immer'; * If state only has one or zero pages, nothing happens. * * If a page is deleted, selection is cleared. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.pageId Page id to delete. If null, delete current page */ -export const deletePage = (draft, { pageId }) => { +export const deletePage = (draft: Story, { pageId }: DeletePageProps) => { if (draft.pages.length <= 1) { return; } - const idToDelete = pageId === null ? draft.current : pageId; + // @todo Why do we need to cast here? + const idToDelete = (pageId === null ? draft.current : pageId) as + | string + | undefined; const pageIndex = draft.pages.findIndex(({ id }) => id === idToDelete); if (pageIndex === -1) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index be1fc4ce2d0a..29430383f594 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -18,11 +18,13 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ import { PAGE_RESERVED_PROPERTIES } from '../types'; +import type { UpdatePageProps } from '../../../../types/storyProvider'; import { objectWithout } from './utils'; /** @@ -31,14 +33,14 @@ import { objectWithout } from './utils'; * If id doesn't exist, nothing happens. * * Current page and selection is unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.pageId Page index to update. If null, update current page. - * @param {number} payload.properties Object with properties to set for given page. */ -export const updatePage = (draft, { pageId, properties }) => { - const idToUpdate = pageId === null ? draft.current : pageId; +export const updatePage = ( + draft: Story, + { pageId, properties }: UpdatePageProps +) => { + const idToUpdate = (pageId === null ? draft.current : pageId) as + | string + | undefined; const page = draft.pages.find(({ id }) => id === idToUpdate); if (!page) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 834e8452a046..00f70c621924 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -19,6 +19,7 @@ */ import { useReducer, useMemo } from '@googleforcreators/react'; import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies @@ -55,18 +56,17 @@ const INITIAL_STATE = { * - Selection isn't guaranteed to refer to objects on the current page. * - New pages aren't validated for type of elements property when added. * - No validation of keys or values in the story object. - * - * @param {Object} partial A state partial to initialize with. - * @return {Object} An object with keys `state`, `internal` and `api`. */ -function useStoryReducer(partial) { +function useStoryReducer(partial: Partial) { const [state, dispatch] = useReducer(reducer, { ...INITIAL_STATE, ...partial, - }); + } as Story); const { internal, api } = useMemo(() => { - const wrapWithDispatch = (actions) => + const wrapWithDispatch = ( + actions: typeof internalActions | typeof exposedActions + ) => Object.keys(actions).reduce( (collection, action) => ({ ...collection, diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index e69de29bb2d1..9c5325b78c7c 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import type { Page } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type * as actionTypes from '../app/story/useStoryReducer/types'; + +export type AddPageProps = { + page: Page; + position: null | number; + updateSelection: boolean; +}; +export type AddPageAction = { + type: typeof actionTypes.ADD_PAGE; + payload: AddPageProps; +}; + +export type DeletePageProps = { + pageId: string | null; +}; +export type DeletePageAction = { + type: typeof actionTypes.DELETE_PAGE; + payload: DeletePageProps; +}; + +export type UpdatePageProps = { + pageId: string | null; + properties: Partial; +}; +export type UpdatePageAction = { + type: typeof actionTypes.UPDATE_PAGE; + payload: UpdatePageProps; +}; + +export type ReducerActionProps = + | AddPageAction + | DeletePageAction + | UpdatePageAction; diff --git a/packages/types/src/story/story.ts b/packages/types/src/story/story.ts index 647d421dce64..80d14b098a1e 100644 --- a/packages/types/src/story/story.ts +++ b/packages/types/src/story/story.ts @@ -20,7 +20,7 @@ import type { Page } from './page'; export interface Story { - version: number; + version?: number; pages: Page[]; backgroundAudio?: { resource: { @@ -31,4 +31,7 @@ export interface Story { }; autoAdvance?: boolean; defaultPageDuration?: number; + // @todo Should we separate the story that gets saved into DB vs not? + current?: string | null; + selection?: string[]; } From 60f0b51730c53d9372d0753bcbac0d815b8432e9 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 8 Nov 2022 17:45:41 -0300 Subject: [PATCH 04/99] Add placeholders for actions --- .../src/app/story/useStoryReducer/reducer.ts | 4 +- .../story-editor/src/types/storyProvider.ts | 205 +++++++++++++++++- 2 files changed, 206 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index c476e68ab853..4c21d3891c46 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -41,7 +41,7 @@ function reducer(state: Story, { type, payload }: ReducerActionProps): Story { return reducers.updatePage(state, payload); } - /*case types.ARRANGE_PAGE: { + case types.ARRANGE_PAGE: { return reducers.arrangePage(state, payload); } @@ -155,7 +155,7 @@ function reducer(state: Story, { type, payload }: ReducerActionProps): Story { case types.ADD_ELEMENTS_ACROSS_PAGES: { return reducers.addElementsAcrossPages(state, payload); - }*/ + } default: return state; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 9c5325b78c7c..69d8d4ad3ea2 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -51,7 +51,210 @@ export type UpdatePageAction = { payload: UpdatePageProps; }; +export type ArrangePageProps = {}; +export type ArrangePageAction = { + type: typeof actionTypes.ARRANGE_PAGE; + payload: ArrangePageProps; +}; + +export type SetCurrentPageProps = {}; +export type SetCurrentPagePageAction = { + type: typeof actionTypes.SET_CURRENT_PAGE; + payload: SetCurrentPageProps; +}; + +export type AddElementsProps = {}; +export type AddElementsAction = { + type: typeof actionTypes.ADD_ELEMENTS; + payload: AddElementsProps; +}; + +export type DeleteElementsProps = {}; +export type DeleteElementsAction = { + type: typeof actionTypes.DELETE_ELEMENTS; + payload: DeleteElementsProps; +}; + +export type UpdateElementsProps = {}; +export type UpdateElementsAction = { + type: typeof actionTypes.UPDATE_ELEMENTS; + payload: UpdateElementsProps; +}; + +export type UpdateElementsByResourceIdProps = {}; +export type UpdateElementsByResourceIdAction = { + type: typeof actionTypes.UPDATE_ELEMENTS_BY_RESOURCE_ID; + payload: UpdateElementsByResourceIdProps; +}; + +export type DeleteElementsByResourceIdProps = {}; +export type DeleteElementsByResourceIdAction = { + type: typeof actionTypes.DELETE_ELEMENTS_BY_RESOURCE_ID; + payload: DeleteElementsByResourceIdProps; +}; + +export type CombineElementsProps = {}; +export type CombineElementsAction = { + type: typeof actionTypes.COMBINE_ELEMENTS; + payload: CombineElementsProps; +}; + +export type SetBackgroundElementProps = {}; +export type SetBackgroundElementAction = { + type: typeof actionTypes.SET_BACKGROUND_ELEMENT; + payload: SetBackgroundElementProps; +}; + +export type ArrangeElementProps = {}; +export type ArrangeElementAction = { + type: typeof actionTypes.ARRANGE_ELEMENT; + payload: ArrangeElementProps; +}; + +export type ArrangeGroupProps = {}; +export type ArrangeGroupAction = { + type: typeof actionTypes.ARRANGE_GROUP; + payload: ArrangeGroupProps; +}; + +export type SetSelectedElementsProps = {}; +export type SetSelectedElementsAction = { + type: typeof actionTypes.SET_SELECTED_ELEMENTS; + payload: SetSelectedElementsProps; +}; + +export type SelectElementProps = {}; +export type SelectElementAction = { + type: typeof actionTypes.SELECT_ELEMENT; + payload: SelectElementProps; +}; + +export type UnselectElementProps = {}; +export type UnselectElementAction = { + type: typeof actionTypes.UNSELECT_ELEMENT; + payload: UnselectElementProps; +}; + +export type ToggleElementInSelectionProps = {}; +export type ToggleElementInSelectionAction = { + type: typeof actionTypes.TOGGLE_ELEMENT_IN_SELECTION; + payload: ToggleElementInSelectionProps; +}; + +export type ToggleLayerProps = {}; +export type ToggleLayerAction = { + type: typeof actionTypes.TOGGLE_LAYER; + payload: ToggleLayerProps; +}; + +export type DuplicateElementsByIdProps = {}; +export type DuplicateElementsByIdAction = { + type: typeof actionTypes.DUPLICATE_ELEMENTS_BY_ID; + payload: DuplicateElementsByIdProps; +}; + +export type UpdateStoryProps = {}; +export type UpdateStoryAction = { + type: typeof actionTypes.UPDATE_STORY; + payload: UpdateStoryProps; +}; + +export type UpdateAnimationStateProps = {}; +export type UpdateAnimationStateAction = { + type: typeof actionTypes.UPDATE_ANIMATION_STATE; + payload: ArrangePageProps; +}; + +export type AddAnimationsProps = {}; +export type AddAnimationsAction = { + type: typeof actionTypes.ADD_ANIMATIONS; + payload: AddAnimationsProps; +}; + +export type CopySelectedElementProps = {}; +export type CopySelectedElementAction = { + type: typeof actionTypes.COPY_SELECTED_ELEMENT; + payload: CopySelectedElementProps; +}; + +export type RestoreProps = {}; +export type RestoreAction = { + type: typeof actionTypes.RESTORE; + payload: RestoreProps; +}; + +export type UpdateElementsByFontFamilyProps = {}; +export type UpdateElementsByFontFamilyAction = { + type: typeof actionTypes.UPDATE_ELEMENTS_BY_FONT_FAMILY; + payload: UpdateElementsByFontFamilyProps; +}; + +export type AddGroupProps = {}; +export type AddGroupAction = { + type: typeof actionTypes.ADD_GROUP; + payload: AddGroupProps; +}; + +export type UpdateGroupProps = {}; +export type UpdateGroupAction = { + type: typeof actionTypes.UPDATE_GROUP; + payload: UpdateGroupProps; +}; + +export type DeleteGroupProps = {}; +export type DeleteGroupAction = { + type: typeof actionTypes.DELETE_GROUP; + payload: DeleteGroupProps; +}; + +export type DuplicateGroupProps = {}; +export type DuplicateGroupAction = { + type: typeof actionTypes.DUPLICATE_GROUP; + payload: DuplicateGroupProps; +}; + +export type RemoveElementFromGroupProps = {}; +export type RemoveElementFromGroupAction = { + type: typeof actionTypes.REMOVE_ELEMENT_FROM_GROUP; + payload: RemoveElementFromGroupProps; +}; + +export type AddElementsAcrossPagesProps = {}; +export type AddElementsAcrossPagesAction = { + type: typeof actionTypes.ADD_ELEMENTS_ACROSS_PAGES; + payload: AddElementsAcrossPagesProps; +}; + export type ReducerActionProps = | AddPageAction | DeletePageAction - | UpdatePageAction; + | UpdatePageAction + | ArrangePageAction + | SetCurrentPagePageAction + | AddElementsAction + | DeleteElementsAction + | UpdateElementsAction + | UpdateElementsByResourceIdAction + | DeleteElementsByResourceIdAction + | CombineElementsAction + | SetBackgroundElementAction + | ArrangeElementAction + | ArrangeGroupAction + | SetSelectedElementsAction + | SelectElementAction + | UnselectElementAction + | ToggleElementInSelectionAction + | ToggleLayerAction + | DuplicateElementsByIdAction + | UpdateStoryAction + | UpdateAnimationStateAction + | AddAnimationsAction + | CopySelectedElementAction + | RestoreAction + | UpdateElementsByFontFamilyAction + | AddGroupAction + | UpdateGroupAction + | DeleteGroupAction + | DuplicateGroupAction + | RemoveElementFromGroupAction + | AddElementsAcrossPagesAction; From 0699c3a75589a92242e4045627208c7e42706489 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 8 Nov 2022 18:01:18 -0300 Subject: [PATCH 05/99] Start typing actions --- .../useStoryReducer/reducers/addElements.ts | 18 ++++---- .../useStoryReducer/reducers/arrangePage.ts | 12 +++--- .../reducers/combineElements.ts | 16 +++---- .../reducers/deleteElements.ts | 7 ++- .../reducers/deleteElementsByResourceId.ts | 11 ++--- .../reducers/setCurrentPage.ts | 15 ++++--- .../reducers/updateElements.ts | 12 ++---- .../reducers/updateElementsByResourceId.ts | 12 ++---- .../story-editor/src/types/storyProvider.ts | 43 +++++++++++++++---- 9 files changed, 86 insertions(+), 60 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index 7af26043130b..eb3ce05dcc4c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -25,9 +25,13 @@ import { produce } from 'immer'; */ import { MAX_PRODUCTS_PER_PAGE } from '../../../../constants'; import { exclusion } from './utils'; +import type {Story} from "@googleforcreators/types"; +import type {AddElementsProps} from "../../../../types/storyProvider"; -const isProduct = ({ type }) => type === ELEMENT_TYPES.PRODUCT; -const isNotProduct = ({ type }) => type !== ELEMENT_TYPES.PRODUCT; +const isProduct = ({ type }: { type: string }) => + type === ELEMENT_TYPES.PRODUCT; +const isNotProduct = ({ type }: { type: string }) => + type !== ELEMENT_TYPES.PRODUCT; /** * Add elements to current page. @@ -41,16 +45,10 @@ const isNotProduct = ({ type }) => type !== ELEMENT_TYPES.PRODUCT; * Elements will be added to the front (end) of the list of elements on the current page. * * Selection is set to be exactly the new elements by default. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.elements Elements to insert on the given page. - * @param {string} payload.pageId optional pageId for page to insert elements into. - * @param {boolean} [payload.updateSelection=true] Whether to select the new element. */ export const addElements = ( - draft, - { elements, pageId, updateSelection = true } + draft: Story, + { elements, pageId, updateSelection = true }: AddElementsProps ) => { if (!Array.isArray(elements)) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 8f400b4dcab0..8ee805803007 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -18,10 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ +import type { ArrangePageProps } from '../../../../types/storyProvider'; import { isInsideRange, moveArrayElement } from './utils'; /** @@ -35,13 +37,11 @@ import { isInsideRange, moveArrayElement } from './utils'; * Current selection is unchanged. * * TODO: Handle multi-page re-order when UX and priority is finalized. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.pageId Id of page to move to a new position. - * @param {number} payload.position Index of where page should be moved to. */ -export const arrangePage = (draft, { pageId, position }) => { +export const arrangePage = ( + draft: Story, + { pageId, position }: ArrangePageProps +) => { // Abort if there's less than two elements (nothing to rearrange) if (draft.pages.length < 2) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 213d8c9d72c5..88d325f30b41 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -28,6 +28,8 @@ import { produce } from 'immer'; import objectPick from '../../../../utils/objectPick'; import objectWithout from '../../../../utils/objectWithout'; import { removeAnimationsWithElementIds } from './utils'; +import type {CombineElementsProps} from "../../../../types/storyProvider"; +import type {Story} from "@googleforcreators/types"; /** * Combine elements by taking properties from a first item and @@ -46,16 +48,14 @@ import { removeAnimationsWithElementIds } from './utils'; * save a copy of the old element as appropriate and remove flag. * * Updates selection to only include the second item after merge. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.firstElement Element with properties to merge - * @param {string} payload.secondId Element to add properties to - * @param {boolean} payload.shouldRetainAnimations Is called from copy and paste */ export const combineElements = ( - draft, - { firstElement, secondId, shouldRetainAnimations = true } + draft: Story, + { + firstElement, + secondId, + shouldRetainAnimations = true, + }: CombineElementsProps ) => { if (!firstElement || !secondId) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts index 6d272ad728cb..8071687eabd0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts @@ -23,6 +23,8 @@ import { produce } from 'immer'; * Internal dependencies */ import { intersect } from './utils'; +import type {DeleteElementsProps} from "../../../../types/storyProvider"; +import type {Story} from "@googleforcreators/types"; /** * Delete elements by the given list of ids. @@ -46,7 +48,10 @@ import { intersect } from './utils'; * @param {Object} payload Action payload * @param {Array.} payload.elementIds List of ids of elements to delete. */ -export const deleteElements = (draft, { elementIds }) => { +export const deleteElements = ( + draft: Story, + { elementIds }: DeleteElementsProps +) => { const idsToDelete = elementIds === null ? draft.selection : elementIds; if (idsToDelete.length === 0) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index 9ceb39013b96..96514aa15fd7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -18,6 +18,8 @@ * External dependencies */ import { produce } from 'immer'; +import type {Story} from "@googleforcreators/types"; +import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvider"; /** * Delete elements by the given resource id. @@ -27,12 +29,11 @@ import { produce } from 'immer'; * If an empty id or a no matches with id, state is unchanged. * * If no element with the given resource id is found, state is changed. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string|null} payload.id id Delete all elements with this resource id */ -export const deleteElementsByResourceId = (draft, { id }) => { +export const deleteElementsByResourceId = ( + draft: Story, + { id }: DeleteElementsByResourceIdProps +) => { if (id === null) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index 80c44553dbc9..9adf7adbb711 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -18,6 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type { SetCurrentPageProps } from '../../../../types/storyProvider'; /** * Set current page to the given id. @@ -25,12 +31,11 @@ import { produce } from 'immer'; * If id doesn't match an existing page, nothing happens. * * If page is changed, selection is cleared - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.pageId Page id to set as current page */ -export const setCurrentPage = (draft, { pageId }) => { +export const setCurrentPage = ( + draft: Story, + { pageId }: SetCurrentPageProps +) => { const pageExists = draft.pages.some(({ id }) => id === pageId); const pageIsAlreadyCurrent = draft.current === pageId; if (!pageExists || pageIsAlreadyCurrent) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index f6d19104b25b..8248258d4606 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -19,10 +19,12 @@ */ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ +import type { UpdateElementsProps } from '../../../../types/storyProvider'; import { updateElementWithUpdater, updateAnimations } from './utils'; /** @@ -38,16 +40,10 @@ import { updateElementWithUpdater, updateAnimations } from './utils'; * If given set of properties is empty, state is unchanged. * * Current selection and page is unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.elementIds List of elements to update - * @param {Object|function(Object):Object} payload.properties Properties to set on all the given elements or - * a function to calculate new values based on the current properties. */ export const updateElements = ( - draft, - { elementIds, properties: propertiesOrUpdater } + draft: Story, + { elementIds, properties: propertiesOrUpdater }: UpdateElementsProps ) => { if ( [ diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index 603ff6499e91..d61fa34f16ab 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -18,10 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ +import type { UpdateElementsByResourceIdProps } from '../../../../types/storyProvider'; import { updateElementWithUpdater } from './utils'; /** @@ -36,16 +38,10 @@ import { updateElementWithUpdater } from './utils'; * If given set of properties is empty, state is unchanged. * * Current selection and page is unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string|null} payload.id id Update all elements with this resource id - * @param {Object|function(Object):Object} payload.properties Properties to set on all the given elements or - * a function to calculate new values based on the current properties. */ export const updateElementsByResourceId = ( - draft, - { id, properties: propertiesOrUpdater } + draft: Story, + { id, properties: propertiesOrUpdater }: UpdateElementsByResourceIdProps ) => { if (!id) { return; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 69d8d4ad3ea2..39dbe5dfcc50 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { Page } from '@googleforcreators/types'; +import type {Page, Element, ResourceId} from '@googleforcreators/types'; /** * Internal dependencies @@ -51,49 +51,74 @@ export type UpdatePageAction = { payload: UpdatePageProps; }; -export type ArrangePageProps = {}; +export type ArrangePageProps = { + pageId: string; + position: number; +}; export type ArrangePageAction = { type: typeof actionTypes.ARRANGE_PAGE; payload: ArrangePageProps; }; -export type SetCurrentPageProps = {}; +export type SetCurrentPageProps = { + pageId: string; +}; export type SetCurrentPagePageAction = { type: typeof actionTypes.SET_CURRENT_PAGE; payload: SetCurrentPageProps; }; -export type AddElementsProps = {}; +export type AddElementsProps = { + elements: Element[]; + pageId: string; + updateSelection: boolean; +}; + export type AddElementsAction = { type: typeof actionTypes.ADD_ELEMENTS; payload: AddElementsProps; }; -export type DeleteElementsProps = {}; +export type DeleteElementsProps = { + elementIds: string[]; +}; export type DeleteElementsAction = { type: typeof actionTypes.DELETE_ELEMENTS; payload: DeleteElementsProps; }; -export type UpdateElementsProps = {}; +type ElementUpdater = (prevProps: Element) => Element; +export type UpdateElementsProps = { + elementIds: string[]; + properties: Partial | ElementUpdater; +}; export type UpdateElementsAction = { type: typeof actionTypes.UPDATE_ELEMENTS; payload: UpdateElementsProps; }; -export type UpdateElementsByResourceIdProps = {}; +export type UpdateElementsByResourceIdProps = { + id: ResourceId; + properties: Partial | ElementUpdater; +}; export type UpdateElementsByResourceIdAction = { type: typeof actionTypes.UPDATE_ELEMENTS_BY_RESOURCE_ID; payload: UpdateElementsByResourceIdProps; }; -export type DeleteElementsByResourceIdProps = {}; +export type DeleteElementsByResourceIdProps = { + id: ResourceId; +}; export type DeleteElementsByResourceIdAction = { type: typeof actionTypes.DELETE_ELEMENTS_BY_RESOURCE_ID; payload: DeleteElementsByResourceIdProps; }; -export type CombineElementsProps = {}; +export type CombineElementsProps = { + firstElement: Element; + secondId: string; + shouldRetainAnimations: boolean; +}; export type CombineElementsAction = { type: typeof actionTypes.COMBINE_ELEMENTS; payload: CombineElementsProps; From 6268272ad7d3bf31c9ab5033d76b42dbe4b63873 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 9 Nov 2022 11:48:31 -0300 Subject: [PATCH 06/99] More actions --- .../src/app/story/useStoryReducer/reducer.ts | 2 +- .../useStoryReducer/reducers/addAnimations.ts | 10 +- .../useStoryReducer/reducers/addElements.ts | 5 +- .../reducers/addElementsAcrossPages.ts | 15 +-- .../useStoryReducer/reducers/addGroup.ts | 16 +-- .../story/useStoryReducer/reducers/addPage.ts | 4 +- .../reducers/arrangeElement.ts | 12 +- .../useStoryReducer/reducers/arrangeGroup.ts | 12 +- .../useStoryReducer/reducers/arrangePage.ts | 4 +- .../reducers/combineElements.ts | 4 +- .../reducers/copySelectedElement.ts | 5 +- .../reducers/deleteElements.ts | 4 +- .../reducers/deleteElementsByResourceId.ts | 4 +- .../useStoryReducer/reducers/deleteGroup.ts | 10 +- .../useStoryReducer/reducers/deletePage.ts | 4 +- .../reducers/duplicateElementsById.ts | 15 ++- .../reducers/duplicateGroup.ts | 12 +- .../reducers/removeElementFromGroup.ts | 9 +- .../story/useStoryReducer/reducers/restore.ts | 22 ++-- .../useStoryReducer/reducers/selectElement.ts | 7 +- .../reducers/setBackgroundElement.ts | 11 +- .../reducers/setCurrentPage.ts | 4 +- .../reducers/setSelectedElements.ts | 11 +- .../useStoryReducer/reducers/toggleElement.ts | 7 +- .../useStoryReducer/reducers/toggleLayer.ts | 6 +- .../reducers/unselectElement.ts | 15 ++- .../reducers/updateAnimationState.ts | 17 ++- .../reducers/updateElements.ts | 4 +- .../reducers/updateElementsByFontFamily.ts | 14 +-- .../reducers/updateElementsByResourceId.ts | 4 +- .../useStoryReducer/reducers/updateGroup.ts | 15 ++- .../useStoryReducer/reducers/updatePage.ts | 4 +- .../useStoryReducer/reducers/updateStory.ts | 13 +- .../story-editor/src/types/storyProvider.ts | 118 ++++++++++++++---- packages/types/src/story/story.ts | 3 - 35 files changed, 255 insertions(+), 167 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index 4c21d3891c46..4063a864d346 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -122,7 +122,7 @@ function reducer(state: Story, { type, payload }: ReducerActionProps): Story { } case types.COPY_SELECTED_ELEMENT: { - return reducers.copySelectedElement(state, payload); + return reducers.copySelectedElement(state); } case types.RESTORE: { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index caf50522ca4b..65139db5fa73 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -23,6 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { exclusion } from './utils'; +import type {AddAnimationsProps, State} from "../../../../types/storyProvider"; /** * Add animations to current page. @@ -34,12 +35,11 @@ import { exclusion } from './utils'; * If animations aren't a list or an empty list (after duplicates have been filtered), nothing happens. * * Animations will be added to the end of the list of animations on the current page. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.animations Elements to insert on the given page. */ -export const addAnimations = (draft, { animations }) => { +export const addAnimations = ( + draft: State, + { animations }: AddAnimationsProps +) => { if (!Array.isArray(animations)) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index eb3ce05dcc4c..05b979b22cd0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -25,7 +25,7 @@ import { produce } from 'immer'; */ import { MAX_PRODUCTS_PER_PAGE } from '../../../../constants'; import { exclusion } from './utils'; -import type {Story} from "@googleforcreators/types"; +import type {State} from "@googleforcreators/types"; import type {AddElementsProps} from "../../../../types/storyProvider"; const isProduct = ({ type }: { type: string }) => @@ -47,9 +47,10 @@ const isNotProduct = ({ type }: { type: string }) => * Selection is set to be exactly the new elements by default. */ export const addElements = ( - draft: Story, + draft: State, { elements, pageId, updateSelection = true }: AddElementsProps ) => { + console.log(draft); if (!Array.isArray(elements)) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts index 7b876fd25cb6..947cc186329f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts @@ -23,6 +23,10 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { + AddElementsAcrossPagesProps, + State, +} from '../../../../types/storyProvider'; import { addPage } from './addPage'; import { addElements } from './addElements'; @@ -32,14 +36,11 @@ import { addElements } from './addElements'; * Adds N elements to N pages in the given order. * * Selection is unchanged afterwards. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Object} payload.page Object with properties of each new page - * @param {Array.} payload.elements Elements to insert across pages. - * @param {number} payload.position Position at which to insert the new page. If null, insert after current */ -const addElementsAcrossPages = (draft, { page, position, elements }) => { +const addElementsAcrossPages = ( + draft: State, + { page, position, elements }: AddElementsAcrossPagesProps +) => { elements.forEach((element, index) => { // Ensure every newly added page has a unique ID. const pageId = uuidv4(); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts index 5b1c2ed1e3e9..b436bba7328d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts @@ -19,16 +19,18 @@ */ import { produce } from 'immer'; +/** + * Internal dependencies + */ +import type { AddGroupProps, State } from '../../../../types/storyProvider'; + /** * Add a group to the current page groups list (id, name). - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.groupId Group id - * @param {string} payload.name Group name - * @param {boolean} payload.isLocked Is group locked */ -export const addGroup = (draft, { groupId, name, isLocked = false }) => { +export const addGroup = ( + draft: State, + { groupId, name, isLocked = false }: AddGroupProps +) => { if (!groupId || !name) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index 595283fe5815..836c74e4851d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -38,7 +38,7 @@ import { isInsideRange } from './utils'; * Selection is cleared by default. */ export const addPage = ( - draft: Story, + draft: State, { page, position, updateSelection = true }: AddPageProps ) => { // Ensure new page has at least one element diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 58db5feefc1d..00a49e013b02 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -23,6 +23,8 @@ import { produce } from 'immer'; * Internal dependencies */ import { getAbsolutePosition, moveArrayElement } from './utils'; +import type {State} from "@googleforcreators/types"; +import type {ArrangeElementProps} from "../../../../types/storyProvider"; /** * Move element in element order on the current page (optionally handle group id when moved in the Layers Panel). @@ -53,16 +55,10 @@ import { getAbsolutePosition, moveArrayElement } from './utils'; * Selection and current page is unchanged. * * TODO: Handle multi-element re-order when UX and priority is finalized. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.elementId Id of element to move - * @param {number|string} payload.position New position of element to move - * @param {string|boolean} payload.groupId New group id (when moving in the Layers Panel), false to skip updating. */ export const arrangeElement = ( - draft, - { elementId, position, groupId = false } + draft: State, + { elementId, position, groupId = false }: ArrangeElementProps ) => { if (elementId === null && draft.selection.length !== 1) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index ad7b8aaaf7b9..b86e22a44581 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -23,16 +23,16 @@ import { produce } from 'immer'; * Internal dependencies */ import { getAbsolutePosition } from './utils'; +import type {State} from "@googleforcreators/types"; +import type {ArrangeGroupProps} from "../../../../types/storyProvider"; /** * Move group to a new position - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.groupId Id of group to move - * @param {number|string} payload.position New position */ -export const arrangeGroup = (draft, { groupId, position }) => { +export const arrangeGroup = ( + draft: State, + { groupId, position }: ArrangeGroupProps +) => { if (!groupId) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 8ee805803007..81fb65ce286d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -39,7 +39,7 @@ import { isInsideRange, moveArrayElement } from './utils'; * TODO: Handle multi-page re-order when UX and priority is finalized. */ export const arrangePage = ( - draft: Story, + draft: State, { pageId, position }: ArrangePageProps ) => { // Abort if there's less than two elements (nothing to rearrange) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 88d325f30b41..f1223ca22401 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -29,7 +29,7 @@ import objectPick from '../../../../utils/objectPick'; import objectWithout from '../../../../utils/objectWithout'; import { removeAnimationsWithElementIds } from './utils'; import type {CombineElementsProps} from "../../../../types/storyProvider"; -import type {Story} from "@googleforcreators/types"; +import type {State} from "@googleforcreators/types"; /** * Combine elements by taking properties from a first item and @@ -50,7 +50,7 @@ import type {Story} from "@googleforcreators/types"; * Updates selection to only include the second item after merge. */ export const combineElements = ( - draft: Story, + draft: State, { firstElement, secondId, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts index 8e99221bdc03..2cb19553ffbf 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts @@ -23,6 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import objectPick from '../../../../utils/objectPick'; +import type { State } from '../../../../types/storyProvider'; export const ATTRIBUTES_TO_COPY = [ 'background', @@ -46,10 +47,8 @@ export const ATTRIBUTES_TO_COPY = [ /** * Copies the styles and animations of the selected element * on the current page. - * - * @param {Object} draft Current state */ -export const copySelectedElement = (draft) => { +export const copySelectedElement = (draft: State) => { // we can only copy one element and it has to exist if (draft.selection?.length !== 1 || !draft.selection[0]) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts index 8071687eabd0..fd052f5a8f45 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts @@ -24,7 +24,7 @@ import { produce } from 'immer'; */ import { intersect } from './utils'; import type {DeleteElementsProps} from "../../../../types/storyProvider"; -import type {Story} from "@googleforcreators/types"; +import type {State} from "@googleforcreators/types"; /** * Delete elements by the given list of ids. @@ -49,7 +49,7 @@ import type {Story} from "@googleforcreators/types"; * @param {Array.} payload.elementIds List of ids of elements to delete. */ export const deleteElements = ( - draft: Story, + draft: State, { elementIds }: DeleteElementsProps ) => { const idsToDelete = elementIds === null ? draft.selection : elementIds; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index 96514aa15fd7..2543ad4b552f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type {Story} from "@googleforcreators/types"; +import type {State} from "@googleforcreators/types"; import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvider"; /** @@ -31,7 +31,7 @@ import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvi * If no element with the given resource id is found, state is changed. */ export const deleteElementsByResourceId = ( - draft: Story, + draft: State, { id }: DeleteElementsByResourceIdProps ) => { if (id === null) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts index f71994d800c3..061c2f554e83 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts @@ -22,18 +22,14 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { DeleteGroupProps, State } from '../../../../types/storyProvider'; import { deleteElements } from './deleteElements'; /** * Delete group by id. - * - * @param {Object} state Current state - * @param {Object} payload Action payload - * @param {number} payload.groupId Group id - * @param {boolean} payload.includeElements If also delete all elements in the group - * @return {Object} New state */ -const deleteGroup = produce((draft, { groupId, includeElements = false }) => { +const deleteGroup = produce( + (draft: State, { groupId, includeElements = false }: DeleteGroupProps) => { const { elements, groups } = draft.pages.find( ({ id }) => id === draft.current ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index 989f46cd5c1e..3db02b15d897 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -37,7 +37,7 @@ import type { DeletePageProps } from '../../../../types/storyProvider'; * * If a page is deleted, selection is cleared. */ -export const deletePage = (draft: Story, { pageId }: DeletePageProps) => { +export const deletePage = (draft: State, { pageId }: DeletePageProps) => { if (draft.pages.length <= 1) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index 5cfcc85323fd..28f878a260e6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -19,18 +19,23 @@ */ import { duplicateElement, ELEMENT_TYPES } from '@googleforcreators/elements'; import { produce } from 'immer'; +import type { State } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type { DuplicateElementsByIdProps } from '../../../../types/storyProvider'; /** * Duplicate all elements specified by `elementIds` on the current page. * Set selected elements to be the newly created elements. * * If given `elementIds` are not a list, do nothing. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.elementIds Array of ids of elements to duplicate. */ -export const duplicateElementsById = (draft, { elementIds }) => { +export const duplicateElementsById = ( + draft: State, + { elementIds }: DuplicateElementsByIdProps +) => { if (!Array.isArray(elementIds)) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index 711f3c34e328..2bb076e8d0bb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -24,21 +24,15 @@ import { duplicateElement } from '@googleforcreators/elements'; * Internal dependencies */ import { addGroup } from './addGroup'; +import type {DuplicateGroupProps, State} from "../../../../types/storyProvider"; /** * Duplicate group with all elements on the current page. * Set selected elements to be the newly created group. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.oldGroupId Id of a group to duplicate. - * @param {string} payload.groupId New group id. - * @param {string} payload.name New group name. - * @param {string} payload.isLocked Is group locked. */ export const duplicateGroup = ( - draft, - { oldGroupId, groupId, name, isLocked } + draft: State, + { oldGroupId, groupId, name, isLocked }: DuplicateGroupProps ) => { if (!oldGroupId || !groupId || !name) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts index 0e35de15e880..1e13de163dcb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts @@ -22,6 +22,10 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { + RemoveElementFromGroupProps, + State, +} from '../../../../types/storyProvider'; import { arrangeElement } from './arrangeElement'; import { getLastIndexOfGroup } from './utils'; @@ -33,7 +37,10 @@ import { getLastIndexOfGroup } from './utils'; * @param {number} payload.elementId Selected element id * @param {number} payload.groupId Selected element group id */ -export const removeElementFromGroup = (draft, { elementId, groupId }) => { +export const removeElementFromGroup = ( + draft: State, + { elementId, groupId }: RemoveElementFromGroupProps +) => { const page = draft.pages.find(({ id }) => id === draft.current); const { elements } = page; const element = elements.find(({ id }) => id === elementId); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 1302d3d60c96..ec0108b377d8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -19,6 +19,11 @@ */ import { produce } from 'immer'; +/** + * Internal dependencies + */ +import type { State } from '../../../../types/storyProvider'; + /** * Restore internal state completely from given state. * @@ -28,25 +33,16 @@ import { produce } from 'immer'; * - `current` must point to a legal page, if at least one page exists. * - `selection` is an array. * - `story` is an object. - * - * @param {Object} draft Current state. - * @param {Object} payload New state to set. - * @param {Array} payload.pages List of pages. - * @param {string} payload.current Current page ID. - * @param {Array} payload.selection Selection. - * @param {Object} payload.story Story object. - * @param {Object} payload.capabilities Capabilities object. - * @return {Object} Restored state. */ export const restore = ( - draft, - { pages, current, selection, story, capabilities } + draft: State, + { pages, current, selection, story, capabilities }: Partial ) => { if (!Array.isArray(pages) || pages.length === 0) { return undefined; } - const newStory = typeof story === 'object' ? story : {}; + const newState = typeof story === 'object' ? story : {}; const newCapabilities = typeof capabilities === 'object' ? capabilities : {}; const oldCurrent = current ?? draft.current; const newCurrent = pages.some(({ id }) => id === oldCurrent) @@ -58,7 +54,7 @@ export const restore = ( pages, current: newCurrent, selection: newSelection, - story: newStory, + story: newState, animationState: draft.animationState, capabilities: newCapabilities, copiedElementState: {}, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index 93c585b21454..a0b841d8f7e8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -18,6 +18,8 @@ * External dependencies */ import { produce } from 'immer'; +import type {SelectElementProps} from "../../../../types/storyProvider"; +import type {State} from "@googleforcreators/types"; /** * Add the given id to the current selection. @@ -28,7 +30,10 @@ import { produce } from 'immer'; * @param {Object} payload Action payload * @param {string} payload.elementId Element id to add to the current selection. */ -export const selectElement = (draft, { elementId }) => { +export const selectElement = ( + draft: State, + { elementId }: SelectElementProps +) => { if (!elementId || draft.selection.includes(elementId)) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index 3ceb48fb3170..63e44a1fd04c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -23,6 +23,8 @@ import { produce } from 'immer'; * Internal dependencies */ import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; +import type {State} from "@googleforcreators/types"; +import type {SetBackgroundElementProps} from "../../../../types/storyProvider"; /** * Set background element on the current page to element matching the given id. @@ -35,12 +37,11 @@ import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; * * Default background element can never be "set to nothing" - only replaced by another * element. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.elementId Element id to set as background on the current page. */ -export const setBackgroundElement = (draft, { elementId }) => { +export const setBackgroundElement = ( + draft: State, + { elementId }: SetBackgroundElementProps +) => { const page = draft.pages.find(({ id }) => id === draft.current); const currentBackgroundElement = page.elements[0]; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index 9adf7adbb711..5a78022d4c3f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -33,7 +33,7 @@ import type { SetCurrentPageProps } from '../../../../types/storyProvider'; * If page is changed, selection is cleared */ export const setCurrentPage = ( - draft: Story, + draft: State, { pageId }: SetCurrentPageProps ) => { const pageExists = draft.pages.some(({ id }) => id === pageId); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index 413323bf4999..ac24e940660b 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -24,6 +24,8 @@ import { produce, current } from 'immer'; * Internal dependencies */ import { intersect } from './utils'; +import type {State} from "@googleforcreators/types"; +import type {SetSelectedElementsProps} from "../../../../types/storyProvider"; /** * Set selected elements to the given list of ids. @@ -38,15 +40,10 @@ import { intersect } from './utils'; * Locked elements can never be part of a multi-selection, so remove those if so. * * Current page and pages are unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.elementIds Object with properties of new page - * @param {boolean} payload.withLinked Include elements from the group? */ export const setSelectedElements = ( - draft, - { elementIds, withLinked = false } + draft: State, + { elementIds, withLinked = false }: SetSelectedElementsProps ) => { const newElementIds = typeof elementIds === 'function' diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts index d13572c8a753..e0bb95bb34bf 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts @@ -18,6 +18,8 @@ * External dependencies */ import { produce } from 'immer'; +import type {State} from "@googleforcreators/types"; +import type {ToggleElementInSelectionProps} from "../../../../types/storyProvider"; /** * Toggle element id in selection. @@ -36,7 +38,10 @@ import { produce } from 'immer'; * @param {string} payload.elementId Id to either add or remove from selection. * @param {boolean} payload.withLinked Include elements from the group? */ -export const toggleElement = (draft, { elementId, withLinked = false }) => { +export const toggleElement = ( + draft: State, + { elementId, withLinked = false }: ToggleElementInSelectionProps +) => { if (!elementId) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts index aed884729024..df946007acee 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts @@ -24,10 +24,12 @@ import { produce } from 'immer'; */ import { toggleElement } from './toggleElement'; import { setSelectedElements } from './setSelectedElements'; +import type {State} from "@googleforcreators/types"; +import type {ToggleLayerProps} from "../../../../types/storyProvider"; export const toggleLayer = ( - draft, - { elementId, metaKey, shiftKey, withLinked = false } + draft: State, + { elementId, metaKey, shiftKey, withLinked = false }: ToggleLayerProps ) => { // Meta pressed. Toggle this layer in the selection. if (metaKey) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts index ce6e45bb2dcf..ff7e5d61ddc9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts @@ -18,17 +18,22 @@ * External dependencies */ import { produce } from 'immer'; +import type { State } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type { UnselectElementProps } from '../../../../types/storyProvider'; /** * Remove the given id from the current selection. * * If no id is given or id is not in the current selection, nothing happens. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.elementId Element id to remove from the current selection. */ -export const unselectElement = (draft, { elementId }) => { +export const unselectElement = ( + draft: State, + { elementId }: UnselectElementProps +) => { const index = draft.selection.indexOf(elementId); if (index === -1) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts index bc90e444974d..7407f8fe0fca 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts @@ -19,15 +19,22 @@ */ import { produce } from 'immer'; +/** + * Internal dependencies + */ +import type { + State, + UpdateAnimationStateProps, +} from '../../../../types/storyProvider'; + /** * Update the story animation state to play, pause, scrub or reset * active pages animations. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.animationState STORY_ANIMATION_STATE state to update to. */ -export const updateAnimationState = (draft, { animationState }) => { +export const updateAnimationState = ( + draft: State, + { animationState }: UpdateAnimationStateProps +) => { draft.animationState = animationState; }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index 8248258d4606..fb92ddbcc2d0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -19,7 +19,7 @@ */ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -42,7 +42,7 @@ import { updateElementWithUpdater, updateAnimations } from './utils'; * Current selection and page is unchanged. */ export const updateElements = ( - draft: Story, + draft: State, { elementIds, properties: propertiesOrUpdater }: UpdateElementsProps ) => { if ( diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts index fec689b877ec..251258340e3c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts @@ -22,6 +22,10 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { + State, + UpdateElementsByFontFamilyProps, +} from '../../../../types/storyProvider'; import { updateElementWithUpdater } from './utils'; /** @@ -36,16 +40,10 @@ import { updateElementWithUpdater } from './utils'; * If given set of properties is empty, state is unchanged. * * Current selection and page is unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string|null} payload.family Update all elements with this font family - * @param {Object|function(Object):Object} payload.properties font / properties to set on all the given elements or - * a function to update based on the current properties. */ export const updateElementsByFontFamily = ( - draft, - { family, properties: propertiesOrUpdater } + draft: State, + { family, properties: propertiesOrUpdater }: UpdateElementsByFontFamilyProps ) => { if (!family) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index d61fa34f16ab..db2b50631046 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -40,7 +40,7 @@ import { updateElementWithUpdater } from './utils'; * Current selection and page is unchanged. */ export const updateElementsByResourceId = ( - draft: Story, + draft: State, { id, properties: propertiesOrUpdater }: UpdateElementsByResourceIdProps ) => { if (!id) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts index fe1a8dcd4b98..3163a8f6359d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts @@ -19,15 +19,18 @@ */ import { produce } from 'immer'; +/** + * Internal dependencies + */ +import type { State, UpdateGroupProps } from '../../../../types/storyProvider'; + /** * Update group by id. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.groupId Group id - * @param {number} payload.properties Object with properties to set for given group. */ -export const updateGroup = (draft, { groupId, properties }) => { +export const updateGroup = ( + draft: State, + { groupId, properties }: UpdateGroupProps +) => { if (!groupId) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index 29430383f594..b9ba36bf77f6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Story } from '@googleforcreators/types'; +import type { State } from '@googleforcreators/types'; /** * Internal dependencies @@ -35,7 +35,7 @@ import { objectWithout } from './utils'; * Current page and selection is unchanged. */ export const updatePage = ( - draft: Story, + draft: State, { pageId, properties }: UpdatePageProps ) => { const idToUpdate = (pageId === null ? draft.current : pageId) as diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index 3d18fffe8365..6b9947c596d6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -18,23 +18,24 @@ * External dependencies */ import { produce, current } from 'immer'; +import type { State } from '@googleforcreators/types'; + +/** + * Internal dependencies + */ +import type { UpdateStateProps } from '../../../../types/storyProvider'; /** * Update story properties. * * No validation is performed and existing values are overwritten. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Object | Function} payload.properties Object with story properties to set. */ -export const updateStory = (draft, { properties }) => { +export const updateStory = (draft: State, { properties }: UpdateStateProps) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { draft.story = properties(current(draft.story)); return; } - // Otherwise copy all the properties into the existing story object Object.assign(draft.story, properties); }; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 39dbe5dfcc50..5f121665ac02 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -17,7 +17,14 @@ /** * External dependencies */ -import type {Page, Element, ResourceId} from '@googleforcreators/types'; +import type { + Page, + Element, + ResourceId, + Story, + Animation, + Group, +} from '@googleforcreators/types'; /** * Internal dependencies @@ -124,127 +131,180 @@ export type CombineElementsAction = { payload: CombineElementsProps; }; -export type SetBackgroundElementProps = {}; +export type SetBackgroundElementProps = { + elementId: string | null; +}; export type SetBackgroundElementAction = { type: typeof actionTypes.SET_BACKGROUND_ELEMENT; payload: SetBackgroundElementProps; }; -export type ArrangeElementProps = {}; +export type ArrangeElementProps = { + elementId: string; + position: number | string; + groupId?: string | boolean; +}; export type ArrangeElementAction = { type: typeof actionTypes.ARRANGE_ELEMENT; payload: ArrangeElementProps; }; -export type ArrangeGroupProps = {}; +export type ArrangeGroupProps = { + groupId: string; + position: number | string; +}; export type ArrangeGroupAction = { type: typeof actionTypes.ARRANGE_GROUP; payload: ArrangeGroupProps; }; -export type SetSelectedElementsProps = {}; +export type SetSelectedElementsProps = { + elementIds: string[]; + withLinked?: boolean; +}; export type SetSelectedElementsAction = { type: typeof actionTypes.SET_SELECTED_ELEMENTS; payload: SetSelectedElementsProps; }; -export type SelectElementProps = {}; +export type SelectElementProps = { + elementId: string; +}; export type SelectElementAction = { type: typeof actionTypes.SELECT_ELEMENT; payload: SelectElementProps; }; -export type UnselectElementProps = {}; +export type UnselectElementProps = { + elementId: string; +}; export type UnselectElementAction = { type: typeof actionTypes.UNSELECT_ELEMENT; payload: UnselectElementProps; }; -export type ToggleElementInSelectionProps = {}; +export type ToggleElementInSelectionProps = { + elementId: string; + withLinked?: boolean; +}; export type ToggleElementInSelectionAction = { type: typeof actionTypes.TOGGLE_ELEMENT_IN_SELECTION; payload: ToggleElementInSelectionProps; }; -export type ToggleLayerProps = {}; +export type ToggleLayerProps = { + elementId: string; + metaKey: boolean; + shiftKey: boolean; + withLinked?: boolean; +}; export type ToggleLayerAction = { type: typeof actionTypes.TOGGLE_LAYER; payload: ToggleLayerProps; }; -export type DuplicateElementsByIdProps = {}; +export type DuplicateElementsByIdProps = { + elementIds: string[]; +}; export type DuplicateElementsByIdAction = { type: typeof actionTypes.DUPLICATE_ELEMENTS_BY_ID; payload: DuplicateElementsByIdProps; }; -export type UpdateStoryProps = {}; +type StoryUpdater = (story: Story) => Story; +export type UpdateStoryProps = { + properties: Partial | StoryUpdater; +}; export type UpdateStoryAction = { type: typeof actionTypes.UPDATE_STORY; payload: UpdateStoryProps; }; -export type UpdateAnimationStateProps = {}; +export type UpdateAnimationStateProps = { + animationState: string; +}; export type UpdateAnimationStateAction = { type: typeof actionTypes.UPDATE_ANIMATION_STATE; payload: ArrangePageProps; }; -export type AddAnimationsProps = {}; +export type AddAnimationsProps = { + animations: Animation[]; +}; export type AddAnimationsAction = { type: typeof actionTypes.ADD_ANIMATIONS; payload: AddAnimationsProps; }; -export type CopySelectedElementProps = {}; export type CopySelectedElementAction = { type: typeof actionTypes.COPY_SELECTED_ELEMENT; - payload: CopySelectedElementProps; + payload: null; }; -export type RestoreProps = {}; export type RestoreAction = { type: typeof actionTypes.RESTORE; - payload: RestoreProps; + payload: Partial; }; -export type UpdateElementsByFontFamilyProps = {}; +export type UpdateElementsByFontFamilyProps = { + family: string; + properties: Partial | ElementUpdater; +}; export type UpdateElementsByFontFamilyAction = { type: typeof actionTypes.UPDATE_ELEMENTS_BY_FONT_FAMILY; payload: UpdateElementsByFontFamilyProps; }; -export type AddGroupProps = {}; +export type AddGroupProps = { + groupId: string; + name: string; + isLocked?: boolean; +}; export type AddGroupAction = { type: typeof actionTypes.ADD_GROUP; payload: AddGroupProps; }; -export type UpdateGroupProps = {}; +export type UpdateGroupProps = { + groupId: string; + properties: Partial; +}; export type UpdateGroupAction = { type: typeof actionTypes.UPDATE_GROUP; payload: UpdateGroupProps; }; -export type DeleteGroupProps = {}; +export type DeleteGroupProps = { groupId: string; includeElements?: boolean }; export type DeleteGroupAction = { type: typeof actionTypes.DELETE_GROUP; payload: DeleteGroupProps; }; -export type DuplicateGroupProps = {}; +export type DuplicateGroupProps = { + oldGroupId: string; + groupId: string; + name: string; + isLocked: boolean; +}; export type DuplicateGroupAction = { type: typeof actionTypes.DUPLICATE_GROUP; payload: DuplicateGroupProps; }; -export type RemoveElementFromGroupProps = {}; +export type RemoveElementFromGroupProps = { + elementId: string; + groupId: string; +}; export type RemoveElementFromGroupAction = { type: typeof actionTypes.REMOVE_ELEMENT_FROM_GROUP; payload: RemoveElementFromGroupProps; }; -export type AddElementsAcrossPagesProps = {}; +export type AddElementsAcrossPagesProps = { + page: Page; + position: number; + elements: Element[]; +}; export type AddElementsAcrossPagesAction = { type: typeof actionTypes.ADD_ELEMENTS_ACROSS_PAGES; payload: AddElementsAcrossPagesProps; @@ -283,3 +343,13 @@ export type ReducerActionProps = | DuplicateGroupAction | RemoveElementFromGroupAction | AddElementsAcrossPagesAction; + +export interface State { + story: Story; + selection: string[]; + current: string; + pages: Page[]; + animationState: string; + capabilities: Record; + copiedElementState?: Element; +} diff --git a/packages/types/src/story/story.ts b/packages/types/src/story/story.ts index 80d14b098a1e..cbad3f9fb1b5 100644 --- a/packages/types/src/story/story.ts +++ b/packages/types/src/story/story.ts @@ -31,7 +31,4 @@ export interface Story { }; autoAdvance?: boolean; defaultPageDuration?: number; - // @todo Should we separate the story that gets saved into DB vs not? - current?: string | null; - selection?: string[]; } From effa891b60bc4df8c43fb2e86b695dc95a17bdda Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 9 Nov 2022 11:50:25 -0300 Subject: [PATCH 07/99] Fix type --- .../src/app/story/useStoryReducer/reducer.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index 4063a864d346..623695368955 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -14,20 +14,15 @@ * limitations under the License. */ -/** - * External dependencies - */ -import type { Story } from '@googleforcreators/types'; - /** * Internal dependencies */ -import type { ReducerActionProps } from '../../../types/storyProvider'; +import type { ReducerActionProps, State } from '../../../types/storyProvider'; import * as types from './types'; import * as reducers from './reducers'; // eslint-disable-next-line complexity -- reducer function, negligible. -function reducer(state: Story, { type, payload }: ReducerActionProps): Story { +function reducer(state: State, { type, payload }: ReducerActionProps): State { switch (type) { case types.ADD_PAGE: { return reducers.addPage(state, payload); From 05f235d343cb037f33d1e088e4c0e0a358caacd8 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 9 Nov 2022 12:54:18 -0300 Subject: [PATCH 08/99] Update actions --- .../src/app/story/useStoryReducer/actions.ts | 112 ++++++++++++------ .../story/useStoryReducer/reducers/restore.ts | 4 +- .../story-editor/src/types/storyProvider.ts | 11 +- 3 files changed, 84 insertions(+), 43 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index f2c7265e7f12..a734fd96fe89 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -18,15 +18,44 @@ * External dependencies */ import type { Dispatch } from 'react'; +import type { Element } from '@googleforcreators/types'; /** * Internal dependencies */ import type { + AddAnimationsProps, + AddElementsAcrossPagesProps, + AddElementsProps, + AddGroupProps, AddPageProps, + ArrangeElementProps, + ArrangeGroupProps, + ArrangePageProps, + CombineElementsProps, + DeleteElementsByResourceIdProps, + DeleteElementsProps, + DeleteGroupProps, DeletePageProps, + DuplicateElementsByIdProps, + DuplicateGroupProps, ReducerActionProps, + RemoveElementFromGroupProps, + RestoreProps, + SelectElementProps, + SetBackgroundElementProps, + SetCurrentPageProps, + SetSelectedElementsProps, + ToggleElementInSelectionProps, + ToggleLayerProps, + UnselectElementProps, + UpdateAnimationStateProps, + UpdateElementsByFontFamilyProps, + UpdateElementsByResourceIdProps, + UpdateElementsProps, + UpdateGroupProps, UpdatePageProps, + UpdateStoryProps, } from '../../../types/storyProvider'; import * as types from './types'; @@ -42,7 +71,7 @@ const addPage = const addPageAt = (dispatch: DispatchType) => - ({ page, position, updateSelection }) => + ({ page, position, updateSelection }): AddPageProps => dispatch({ type: types.ADD_PAGE, payload: { page, position, updateSelection }, @@ -63,7 +92,7 @@ const updatePageProperties = const updateCurrentPageProperties = (dispatch: DispatchType) => - ({ properties }) => + ({ properties }: UpdatePageProps) => dispatch({ type: types.UPDATE_PAGE, payload: { pageId: null, properties }, @@ -71,25 +100,28 @@ const updateCurrentPageProperties = const arrangePage = (dispatch: DispatchType) => - ({ pageId, position }) => + ({ pageId, position }: ArrangePageProps) => dispatch({ type: types.ARRANGE_PAGE, payload: { pageId, position } }); const setCurrentPage = (dispatch: DispatchType) => - ({ pageId }) => + ({ pageId }: SetCurrentPageProps) => dispatch({ type: types.SET_CURRENT_PAGE, payload: { pageId } }); const addElements = (dispatch: DispatchType) => - ({ elements, pageId, updateSelection }) => + ({ elements, pageId, updateSelection }: AddElementsProps) => dispatch({ type: types.ADD_ELEMENTS, payload: { elements, pageId, updateSelection }, }); +interface AddElementProps extends Omit { + element: Element; +} const addElement = (dispatch: DispatchType) => - ({ element, pageId, updateSelection }) => + ({ element, pageId, updateSelection }: AddElementProps) => dispatch({ type: types.ADD_ELEMENTS, payload: { elements: [element], pageId, updateSelection }, @@ -97,15 +129,18 @@ const addElement = const deleteElementsById = (dispatch: DispatchType) => - ({ elementIds }) => + ({ elementIds }: DeleteElementsProps) => dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds } }); const deleteSelectedElements = (dispatch: DispatchType) => () => dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds: null } }); +interface DeleteElementProps extends Omit { + elementId: string; +} const deleteElementById = (dispatch: DispatchType) => - ({ elementId }) => + ({ elementId }: DeleteElementProps) => dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds: [elementId] }, @@ -113,7 +148,7 @@ const deleteElementById = const updateElementsById = (dispatch: DispatchType) => - ({ elementIds, properties }) => + ({ elementIds, properties }: UpdateElementsProps) => dispatch({ type: types.UPDATE_ELEMENTS, payload: { elementIds, properties }, @@ -121,7 +156,7 @@ const updateElementsById = const updateElementsByResourceId = (dispatch: DispatchType) => - ({ id, properties }) => + ({ id, properties }: UpdateElementsByResourceIdProps) => dispatch({ type: types.UPDATE_ELEMENTS_BY_RESOURCE_ID, payload: { id, properties }, @@ -129,15 +164,19 @@ const updateElementsByResourceId = const deleteElementsByResourceId = (dispatch: DispatchType) => - ({ id }) => + ({ id }: DeleteElementsByResourceIdProps) => dispatch({ type: types.DELETE_ELEMENTS_BY_RESOURCE_ID, payload: { id }, }); +interface UpdateElementByIdProps + extends Omit { + elementId: string; +} const updateElementById = (dispatch: DispatchType) => - ({ elementId, properties }) => + ({ elementId, properties }: UpdateElementByIdProps) => dispatch({ type: types.UPDATE_ELEMENTS, payload: { elementIds: [elementId], properties }, @@ -145,7 +184,7 @@ const updateElementById = const duplicateElementsById = (dispatch: DispatchType) => - ({ elementIds }) => + ({ elementIds }: DuplicateElementsByIdProps) => dispatch({ type: types.DUPLICATE_ELEMENTS_BY_ID, payload: { elementIds }, @@ -153,7 +192,7 @@ const duplicateElementsById = const updateSelectedElements = (dispatch: DispatchType) => - ({ properties }) => + ({ properties }: UpdateElementsProps) => dispatch({ type: types.UPDATE_ELEMENTS, payload: { elementIds: null, properties }, @@ -161,7 +200,7 @@ const updateSelectedElements = const combineElements = (dispatch: DispatchType) => - ({ firstElement, secondId, shouldRetainAnimations }) => + ({ firstElement, secondId, shouldRetainAnimations }: CombineElementsProps) => dispatch({ type: types.COMBINE_ELEMENTS, payload: { firstElement, secondId, shouldRetainAnimations }, @@ -169,7 +208,7 @@ const combineElements = const setBackgroundElement = (dispatch: DispatchType) => - ({ elementId }) => + ({ elementId }: SetBackgroundElementProps) => dispatch({ type: types.SET_BACKGROUND_ELEMENT, payload: { elementId } }); const clearBackgroundElement = (dispatch: DispatchType) => () => @@ -180,7 +219,7 @@ const clearBackgroundElement = (dispatch: DispatchType) => () => const arrangeElement = (dispatch: DispatchType) => - ({ elementId, position, groupId }) => + ({ elementId, position, groupId }: ArrangeElementProps) => dispatch({ type: types.ARRANGE_ELEMENT, payload: { elementId, position, groupId }, @@ -188,12 +227,12 @@ const arrangeElement = const arrangeGroup = (dispatch: DispatchType) => - ({ groupId, position }) => + ({ groupId, position }: ArrangeGroupProps) => dispatch({ type: types.ARRANGE_GROUP, payload: { groupId, position } }); const arrangeSelection = (dispatch: DispatchType) => - ({ position, groupId }) => + ({ position, groupId }: ArrangeElementProps) => dispatch({ type: types.ARRANGE_ELEMENT, payload: { elementId: null, position, groupId }, @@ -201,7 +240,7 @@ const arrangeSelection = const setSelectedElementsById = (dispatch: DispatchType) => - ({ elementIds, withLinked }) => + ({ elementIds, withLinked }: SetSelectedElementsProps) => dispatch({ type: types.SET_SELECTED_ELEMENTS, payload: { elementIds, withLinked }, @@ -212,17 +251,17 @@ const clearSelection = (dispatch: DispatchType) => () => const addElementToSelection = (dispatch: DispatchType) => - ({ elementId }) => + ({ elementId }: SelectElementProps) => dispatch({ type: types.SELECT_ELEMENT, payload: { elementId } }); const removeElementFromSelection = (dispatch: DispatchType) => - ({ elementId }) => + ({ elementId }: UnselectElementProps) => dispatch({ type: types.UNSELECT_ELEMENT, payload: { elementId } }); const toggleElementInSelection = (dispatch: DispatchType) => - ({ elementId, withLinked }) => + ({ elementId, withLinked }: ToggleElementInSelectionProps) => dispatch({ type: types.TOGGLE_ELEMENT_IN_SELECTION, payload: { elementId, withLinked }, @@ -230,12 +269,12 @@ const toggleElementInSelection = const updateStory = (dispatch: DispatchType) => - ({ properties }) => + ({ properties }: UpdateStoryProps) => dispatch({ type: types.UPDATE_STORY, payload: { properties } }); const updateAnimationState = (dispatch: DispatchType) => - ({ animationState }) => + ({ animationState }: UpdateAnimationStateProps) => dispatch({ type: types.UPDATE_ANIMATION_STATE, payload: { animationState }, @@ -243,12 +282,12 @@ const updateAnimationState = const addAnimations = (dispatch: DispatchType) => - ({ animations }) => + ({ animations }: AddAnimationsProps) => dispatch({ type: types.ADD_ANIMATIONS, payload: { animations } }); const toggleLayer = (dispatch: DispatchType) => - ({ metaKey, shiftKey, elementId, withLinked }) => + ({ metaKey, shiftKey, elementId, withLinked }: ToggleLayerProps) => dispatch({ type: types.TOGGLE_LAYER, payload: { metaKey, shiftKey, elementId, withLinked }, @@ -257,11 +296,12 @@ const toggleLayer = const copySelectedElement = (dispatch: DispatchType) => () => dispatch({ type: types.COPY_SELECTED_ELEMENT, + payload: null, }); const updateElementsByFontFamily = (dispatch: DispatchType) => - ({ family, properties }) => + ({ family, properties }: UpdateElementsByFontFamilyProps) => dispatch({ type: types.UPDATE_ELEMENTS_BY_FONT_FAMILY, payload: { family, properties }, @@ -269,12 +309,12 @@ const updateElementsByFontFamily = const addGroup = (dispatch: DispatchType) => - ({ groupId, name, isLocked }) => + ({ groupId, name, isLocked }: AddGroupProps) => dispatch({ type: types.ADD_GROUP, payload: { groupId, name, isLocked } }); const updateGroupById = (dispatch: DispatchType) => - ({ groupId, properties }) => + ({ groupId, properties }: UpdateGroupProps) => dispatch({ type: types.UPDATE_GROUP, payload: { groupId, properties }, @@ -282,7 +322,7 @@ const updateGroupById = const deleteGroupById = (dispatch: DispatchType) => - ({ groupId }) => + ({ groupId }: DeleteGroupProps) => dispatch({ type: types.DELETE_GROUP, payload: { groupId }, @@ -290,7 +330,7 @@ const deleteGroupById = const deleteGroupAndElementsById = (dispatch: DispatchType) => - ({ groupId }) => + ({ groupId }: DeleteGroupProps) => dispatch({ type: types.DELETE_GROUP, payload: { groupId, includeElements: true }, @@ -298,7 +338,7 @@ const deleteGroupAndElementsById = const duplicateGroupById = (dispatch: DispatchType) => - ({ groupId, name, oldGroupId, isLocked }) => + ({ groupId, name, oldGroupId, isLocked }: DuplicateGroupProps) => dispatch({ type: types.DUPLICATE_GROUP, payload: { groupId, name, oldGroupId, isLocked }, @@ -306,7 +346,7 @@ const duplicateGroupById = const removeElementFromGroup = (dispatch: DispatchType) => - ({ elementId, groupId }) => + ({ elementId, groupId }: RemoveElementFromGroupProps) => dispatch({ type: types.REMOVE_ELEMENT_FROM_GROUP, payload: { elementId, groupId }, @@ -314,7 +354,7 @@ const removeElementFromGroup = const addElementsAcrossPages = (dispatch: DispatchType) => - ({ elements, page, position }) => + ({ elements, page, position }: AddElementsAcrossPagesProps) => dispatch({ type: types.ADD_ELEMENTS_ACROSS_PAGES, payload: { elements, page, position }, @@ -369,7 +409,7 @@ export const exposedActions = { // Internal actions const restore = (dispatch: DispatchType) => - ({ pages, selection, current, story, capabilities }) => + ({ pages, selection, current, story, capabilities }: RestoreProps) => dispatch({ type: types.RESTORE, payload: { pages, selection, current, story, capabilities }, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index ec0108b377d8..609444ddeadc 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { State } from '../../../../types/storyProvider'; +import type {RestoreProps, State} from '../../../../types/storyProvider'; /** * Restore internal state completely from given state. @@ -36,7 +36,7 @@ import type { State } from '../../../../types/storyProvider'; */ export const restore = ( draft: State, - { pages, current, selection, story, capabilities }: Partial + { pages, current, selection, story, capabilities }: RestoreProps ) => { if (!Array.isArray(pages) || pages.length === 0) { return undefined; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 5f121665ac02..8ba9ab60bb5c 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -87,7 +87,7 @@ export type AddElementsAction = { }; export type DeleteElementsProps = { - elementIds: string[]; + elementIds: string[] | null; }; export type DeleteElementsAction = { type: typeof actionTypes.DELETE_ELEMENTS; @@ -96,7 +96,7 @@ export type DeleteElementsAction = { type ElementUpdater = (prevProps: Element) => Element; export type UpdateElementsProps = { - elementIds: string[]; + elementIds: string[] | null; properties: Partial | ElementUpdater; }; export type UpdateElementsAction = { @@ -140,7 +140,7 @@ export type SetBackgroundElementAction = { }; export type ArrangeElementProps = { - elementId: string; + elementId: string | null; position: number | string; groupId?: string | boolean; }; @@ -225,7 +225,7 @@ export type UpdateAnimationStateProps = { }; export type UpdateAnimationStateAction = { type: typeof actionTypes.UPDATE_ANIMATION_STATE; - payload: ArrangePageProps; + payload: UpdateAnimationStateProps; }; export type AddAnimationsProps = { @@ -241,9 +241,10 @@ export type CopySelectedElementAction = { payload: null; }; +export type RestoreProps = Partial; export type RestoreAction = { type: typeof actionTypes.RESTORE; - payload: Partial; + payload: RestoreProps; }; export type UpdateElementsByFontFamilyProps = { From 8ba9ea67f40c9dc011f15ebd15fbed0b6ef4b0be Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 9 Nov 2022 12:54:55 -0300 Subject: [PATCH 09/99] Fix typo --- packages/story-editor/src/app/story/useStoryReducer/actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index a734fd96fe89..751fbf17d852 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -71,7 +71,7 @@ const addPage = const addPageAt = (dispatch: DispatchType) => - ({ page, position, updateSelection }): AddPageProps => + ({ page, position, updateSelection }: AddPageProps) => dispatch({ type: types.ADD_PAGE, payload: { page, position, updateSelection }, From 3f4dc2d68e1b6fca11288e05efbada7a8d5bfe13 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 9 Nov 2022 12:59:43 -0300 Subject: [PATCH 10/99] More fixes. --- .../story-editor/src/app/story/storyProvider.tsx | 13 ++++++------- .../app/story/useStoryReducer/useStoryReducer.ts | 6 +++--- packages/story-editor/src/types/storyProvider.ts | 2 +- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 9739fa22a488..26cd1f14532a 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -17,9 +17,9 @@ /** * External dependencies */ -import type {ReactNode, Reducer} from 'react'; +import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Story } from '@googleforcreators/types'; +import type {Page, Story} from '@googleforcreators/types'; /** * Internal dependencies @@ -36,7 +36,6 @@ import useStoryReducer from './useStoryReducer'; import useAutoSave from './actions/useAutoSave'; import { StoryTriggersProvider } from './storyTriggers'; import useLocalAutoSave from './actions/useLocalAutoSave'; -import type {AddPageAction} from "../../types/storyProvider"; interface ProviderProps { storyId: number; @@ -68,10 +67,10 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { useEffect(() => setHashPageId(current), [current, setHashPageId]); // Generate current page info. - let currentPageId = null; - let currentPageIndex = null; - let currentPageNumber = null; - let currentPage = null; + let currentPageId: string | null = null; + let currentPageIndex: number | null = null; + let currentPageNumber: number | null = null; + let currentPage: Page | null = null; if (current) { currentPageId = current; currentPageIndex = pages.findIndex(({ id }) => id === current); diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 00f70c621924..25524876f3a6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -19,11 +19,11 @@ */ import { useReducer, useMemo } from '@googleforcreators/react'; import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; -import type { Story } from '@googleforcreators/types'; /** * Internal dependencies */ +import type { State } from '../../../types/storyProvider'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -57,11 +57,11 @@ const INITIAL_STATE = { * - New pages aren't validated for type of elements property when added. * - No validation of keys or values in the story object. */ -function useStoryReducer(partial: Partial) { +function useStoryReducer(partial: Partial) { const [state, dispatch] = useReducer(reducer, { ...INITIAL_STATE, ...partial, - } as Story); + } as State); const { internal, api } = useMemo(() => { const wrapWithDispatch = ( diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 8ba9ab60bb5c..ee63dda8cd39 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -348,7 +348,7 @@ export type ReducerActionProps = export interface State { story: Story; selection: string[]; - current: string; + current: string | null; pages: Page[]; animationState: string; capabilities: Record; From 92103ce54ff8e07e44277b72626f13f6548f5e31 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 10 Nov 2022 14:25:51 -0300 Subject: [PATCH 11/99] Lint --- packages/story-editor/src/app/story/storyProvider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 26cd1f14532a..a5c25dcbd52d 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,7 +19,7 @@ */ import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type {Page, Story} from '@googleforcreators/types'; +import type { Page, Story } from '@googleforcreators/types'; /** * Internal dependencies From 35a3a362073fdc2315e31c91f4f91f22733b4f70 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 10 Nov 2022 15:17:29 -0300 Subject: [PATCH 12/99] Remaining types in the storyProvider.tsx file --- .../story-editor/src/app/story/storyProvider.tsx | 8 ++++---- .../app/story/useStoryReducer/reducers/deletePage.ts | 5 +---- .../src/app/story/useStoryReducer/useStoryReducer.ts | 10 +++++----- .../src/constants/{fonts.js => fonts.ts} | 0 .../src/constants/{headings.js => headings.ts} | 0 .../src/constants/{index.js => index.ts} | 0 .../src/constants/{media.js => media.ts} | 0 .../constants/{multipleValue.js => multipleValue.ts} | 0 ...rackingEvents.js => performanceTrackingEvents.ts} | 0 .../src/constants/{zIndex.js => zIndex.ts} | 0 packages/story-editor/src/types/storyProvider.ts | 12 ++++++++++++ packages/story-editor/tsconfig.json | 8 +++++++- packages/types/src/story/story.ts | 1 + 13 files changed, 30 insertions(+), 14 deletions(-) rename packages/story-editor/src/constants/{fonts.js => fonts.ts} (100%) rename packages/story-editor/src/constants/{headings.js => headings.ts} (100%) rename packages/story-editor/src/constants/{index.js => index.ts} (100%) rename packages/story-editor/src/constants/{media.js => media.ts} (100%) rename packages/story-editor/src/constants/{multipleValue.js => multipleValue.ts} (100%) rename packages/story-editor/src/constants/{performanceTrackingEvents.js => performanceTrackingEvents.ts} (100%) rename packages/story-editor/src/constants/{zIndex.js => zIndex.ts} (100%) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index a5c25dcbd52d..03fab9518012 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,7 +19,7 @@ */ import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Page, Story } from '@googleforcreators/types'; +import type { Animation, Page, Story } from '@googleforcreators/types'; /** * Internal dependencies @@ -90,8 +90,8 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { if (isCurrentPageEmpty) { return STABLE_ARRAY; } - const els = currentPageElements.filter(({ id }) => selection.includes(id)); - return els.length > 0 ? els : STABLE_ARRAY; + const els = currentPageElements?.filter(({ id }) => selection.includes(id)); + return els && els.length > 0 ? els : STABLE_ARRAY; }, [isCurrentPageEmpty, currentPageElements, selection]); const currentPageAnimations = currentPage?.animations; @@ -100,7 +100,7 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { return STABLE_ARRAY; } const animations = (currentPageAnimations || []).reduce( - (acc, { targets, ...properties }) => { + (acc: Animation[], { targets, ...properties }) => { if (targets.some((id) => selection.includes(id))) { return [...acc, { targets, ...properties }]; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index 3db02b15d897..866d30bfdfdb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -42,10 +42,7 @@ export const deletePage = (draft: State, { pageId }: DeletePageProps) => { return; } - // @todo Why do we need to cast here? - const idToDelete = (pageId === null ? draft.current : pageId) as - | string - | undefined; + const idToDelete = (pageId === null ? draft.current : pageId); const pageIndex = draft.pages.findIndex(({ id }) => id === idToDelete); if (pageIndex === -1) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 25524876f3a6..052ded54034f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -23,7 +23,7 @@ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; /** * Internal dependencies */ -import type { State } from '../../../types/storyProvider'; +import type {ExternalActions, InternalActions, ReducerState, State} from '../../../types/storyProvider'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -57,7 +57,7 @@ const INITIAL_STATE = { * - New pages aren't validated for type of elements property when added. * - No validation of keys or values in the story object. */ -function useStoryReducer(partial: Partial) { +function useStoryReducer(partial: Partial): ReducerState { const [state, dispatch] = useReducer(reducer, { ...INITIAL_STATE, ...partial, @@ -68,7 +68,7 @@ function useStoryReducer(partial: Partial) { actions: typeof internalActions | typeof exposedActions ) => Object.keys(actions).reduce( - (collection, action) => ({ + (collection: InternalActions | ExternalActions, action) => ({ ...collection, [action]: actions[action](dispatch), }), @@ -76,8 +76,8 @@ function useStoryReducer(partial: Partial) { ); return { - internal: wrapWithDispatch(internalActions), - api: wrapWithDispatch(exposedActions), + internal: wrapWithDispatch(internalActions) as InternalActions, + api: wrapWithDispatch(exposedActions) as ExternalActions, }; }, [dispatch]); diff --git a/packages/story-editor/src/constants/fonts.js b/packages/story-editor/src/constants/fonts.ts similarity index 100% rename from packages/story-editor/src/constants/fonts.js rename to packages/story-editor/src/constants/fonts.ts diff --git a/packages/story-editor/src/constants/headings.js b/packages/story-editor/src/constants/headings.ts similarity index 100% rename from packages/story-editor/src/constants/headings.js rename to packages/story-editor/src/constants/headings.ts diff --git a/packages/story-editor/src/constants/index.js b/packages/story-editor/src/constants/index.ts similarity index 100% rename from packages/story-editor/src/constants/index.js rename to packages/story-editor/src/constants/index.ts diff --git a/packages/story-editor/src/constants/media.js b/packages/story-editor/src/constants/media.ts similarity index 100% rename from packages/story-editor/src/constants/media.js rename to packages/story-editor/src/constants/media.ts diff --git a/packages/story-editor/src/constants/multipleValue.js b/packages/story-editor/src/constants/multipleValue.ts similarity index 100% rename from packages/story-editor/src/constants/multipleValue.js rename to packages/story-editor/src/constants/multipleValue.ts diff --git a/packages/story-editor/src/constants/performanceTrackingEvents.js b/packages/story-editor/src/constants/performanceTrackingEvents.ts similarity index 100% rename from packages/story-editor/src/constants/performanceTrackingEvents.js rename to packages/story-editor/src/constants/performanceTrackingEvents.ts diff --git a/packages/story-editor/src/constants/zIndex.js b/packages/story-editor/src/constants/zIndex.ts similarity index 100% rename from packages/story-editor/src/constants/zIndex.js rename to packages/story-editor/src/constants/zIndex.ts diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index ee63dda8cd39..5117095f6de0 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -354,3 +354,15 @@ export interface State { capabilities: Record; copiedElementState?: Element; } + +export type InternalActions = { + restore: (props: RestoreProps) => State; +}; +export type ExternalActions = { + [index: string]: unknown; +}; +export interface ReducerState { + state: State; + internal: InternalActions; + api: ExternalActions; +} diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index ad7b7b4e2e28..f6c2a92aa51d 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -14,5 +14,11 @@ { "path": "../react" }, { "path": "../tracking" } ], - "include": ["src/app/config/*", "src/app/story/**/*", "src/types/*"] + "include": [ + "src/app/config/*", + "src/app/story/*", + "src/app/story/**/*", + "src/types/*", + "src/constants/*" + ] } diff --git a/packages/types/src/story/story.ts b/packages/types/src/story/story.ts index cbad3f9fb1b5..a0e1b5e9e703 100644 --- a/packages/types/src/story/story.ts +++ b/packages/types/src/story/story.ts @@ -22,6 +22,7 @@ import type { Page } from './page'; export interface Story { version?: number; pages: Page[]; + status: string; backgroundAudio?: { resource: { src: string; From e86fb7122dbf1f4365e2f4daaa4c640f271ee33e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 10 Nov 2022 15:31:51 -0300 Subject: [PATCH 13/99] Partially convert useautoSave.ts --- .../src/app/story/actions/useAutoSave.ts | 14 +++++++------- packages/story-editor/src/types/configProvider.ts | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 92ab2422003b..683e3e95ca83 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -18,6 +18,7 @@ * External dependencies */ import { useCallback, useState } from '@googleforcreators/react'; +import type { Page, Story } from '@googleforcreators/types'; /** * Internal dependencies @@ -26,16 +27,15 @@ import { useAPI } from '../../api'; import { useConfig } from '../../config'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; +interface AutoSaveProps { + storyId: number; + pages: Page[]; + story: Story; +} /** * Custom hook to auto-save a story. - * - * @param {Object} properties Properties to update. - * @param {number} properties.storyId Story post id. - * @param {Array} properties.pages Array of all pages. - * @param {Object} properties.story Story-global properties - * @return {Function} Function that can be called to save a story. */ -function useAutoSave({ storyId, pages, story }) { +function useAutoSave({ storyId, pages, story }: AutoSaveProps) { const { actions: { autoSaveById }, } = useAPI(); diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index 3641fca1a9fe..c3c323574306 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -241,7 +241,7 @@ export interface ConfigState { /** Max allowed upload in bytes */ maxUpload: number; capabilities: Capabilities; - metaData: MetaData; + metadata: MetaData; canViewDefaultTemplates: boolean; /** If to show the 3rd party media in the library */ showMedia3p: boolean; From d13cb2143bf4d1f660d56dad751c9c5a24203467 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 11 Nov 2022 10:23:27 -0300 Subject: [PATCH 14/99] Post-merge fixes --- packages/story-editor/src/app/story/actions/useAutoSave.ts | 2 +- packages/story-editor/src/app/story/storyProvider.tsx | 2 +- .../story-editor/src/app/story/useStoryReducer/actions.ts | 2 +- .../src/app/story/useStoryReducer/reducers/addPage.ts | 3 +-- .../src/app/story/useStoryReducer/reducers/arrangePage.ts | 3 +-- .../src/app/story/useStoryReducer/reducers/deletePage.ts | 3 +-- .../story/useStoryReducer/reducers/duplicateElementsById.ts | 3 +-- .../app/story/useStoryReducer/reducers/setCurrentPage.ts | 3 +-- .../app/story/useStoryReducer/reducers/unselectElement.ts | 3 +-- .../app/story/useStoryReducer/reducers/updateElements.ts | 3 +-- .../useStoryReducer/reducers/updateElementsByResourceId.ts | 6 ++++-- .../src/app/story/useStoryReducer/reducers/updatePage.ts | 3 +-- .../src/app/story/useStoryReducer/reducers/updateStory.ts | 5 ++--- packages/story-editor/src/types/storyProvider.ts | 4 ++-- 14 files changed, 19 insertions(+), 26 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 683e3e95ca83..178812ed55f2 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -18,7 +18,7 @@ * External dependencies */ import { useCallback, useState } from '@googleforcreators/react'; -import type { Page, Story } from '@googleforcreators/types'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 03fab9518012..bf3b10154e69 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,7 +19,7 @@ */ import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Animation, Page, Story } from '@googleforcreators/types'; +import type { Animation, Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index 751fbf17d852..9a43d4a4ee1a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -18,7 +18,7 @@ * External dependencies */ import type { Dispatch } from 'react'; -import type { Element } from '@googleforcreators/types'; +import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index 836c74e4851d..d719bed9a608 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -18,12 +18,11 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { AddPageProps } from '../../../../types/storyProvider'; +import type { AddPageProps, State } from '../../../../types/storyProvider'; import { isInsideRange } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 81fb65ce286d..7b5987dcf4df 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -18,12 +18,11 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { ArrangePageProps } from '../../../../types/storyProvider'; +import type { ArrangePageProps, State } from '../../../../types/storyProvider'; import { isInsideRange, moveArrayElement } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index 866d30bfdfdb..f982ee9d9353 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -18,12 +18,11 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { DeletePageProps } from '../../../../types/storyProvider'; +import type { DeletePageProps, State } from '../../../../types/storyProvider'; /** * Delete page by id or delete current page if no id given. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index 28f878a260e6..99f58c96ff09 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -19,12 +19,11 @@ */ import { duplicateElement, ELEMENT_TYPES } from '@googleforcreators/elements'; import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { DuplicateElementsByIdProps } from '../../../../types/storyProvider'; +import type { DuplicateElementsByIdProps, State } from '../../../../types/storyProvider'; /** * Duplicate all elements specified by `elementIds` on the current page. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index 5a78022d4c3f..7288062c48ed 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -18,12 +18,11 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { SetCurrentPageProps } from '../../../../types/storyProvider'; +import type { SetCurrentPageProps, State } from '../../../../types/storyProvider'; /** * Set current page to the given id. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts index ff7e5d61ddc9..d5176a972045 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts @@ -18,12 +18,11 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { UnselectElementProps } from '../../../../types/storyProvider'; +import type { UnselectElementProps, State } from '../../../../types/storyProvider'; /** * Remove the given id from the current selection. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index fb92ddbcc2d0..f587d002d255 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -19,12 +19,11 @@ */ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { UpdateElementsProps } from '../../../../types/storyProvider'; +import type { UpdateElementsProps, State } from '../../../../types/storyProvider'; import { updateElementWithUpdater, updateAnimations } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index db2b50631046..0dbfe0567910 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -18,12 +18,14 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { UpdateElementsByResourceIdProps } from '../../../../types/storyProvider'; +import type { + UpdateElementsByResourceIdProps, + State, +} from '../../../../types/storyProvider'; import { updateElementWithUpdater } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index b9ba36bf77f6..64b51cd21c6c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -18,13 +18,12 @@ * External dependencies */ import { produce } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ import { PAGE_RESERVED_PROPERTIES } from '../types'; -import type { UpdatePageProps } from '../../../../types/storyProvider'; +import type { UpdatePageProps, State } from '../../../../types/storyProvider'; import { objectWithout } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index 6b9947c596d6..c443884315e5 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -18,19 +18,18 @@ * External dependencies */ import { produce, current } from 'immer'; -import type { State } from '@googleforcreators/types'; /** * Internal dependencies */ -import type { UpdateStateProps } from '../../../../types/storyProvider'; +import type { UpdatePageProps, State } from '../../../../types/storyProvider'; /** * Update story properties. * * No validation is performed and existing values are overwritten. */ -export const updateStory = (draft: State, { properties }: UpdateStateProps) => { +export const updateStory = (draft: State, { properties }: UpdatePageProps) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { draft.story = properties(current(draft.story)); diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 5117095f6de0..c5235e49b2a7 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -20,11 +20,11 @@ import type { Page, Element, - ResourceId, Story, Animation, Group, -} from '@googleforcreators/types'; +} from '@googleforcreators/elements'; +import type { ResourceId } from '@googleforcreators/media'; /** * Internal dependencies From 661b9d817564ce428bfd24ce785bb853e215a2ae Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 14 Nov 2022 18:10:56 -0300 Subject: [PATCH 15/99] Continue with story provider --- packages/elements/src/types/data.ts | 71 +++++++++++++++++++ packages/elements/src/types/story.ts | 47 ++++++++++++ packages/migration/src/migrate.ts | 5 +- .../src/app/story/effects/useLoadStory.ts | 27 +++++-- 4 files changed, 145 insertions(+), 5 deletions(-) diff --git a/packages/elements/src/types/data.ts b/packages/elements/src/types/data.ts index 743200b31cc1..c30a804d8afb 100644 --- a/packages/elements/src/types/data.ts +++ b/packages/elements/src/types/data.ts @@ -14,6 +14,16 @@ * limitations under the License. */ +/** + * External dependencies + */ +import type { Pattern } from '@googleforcreators/patterns'; + +/** + * Internal dependencies + */ +import type { Page } from './page'; + export type FontStyle = 'normal' | 'italic' | 'regular'; export enum FontVariantStyle { Normal = 0, @@ -67,3 +77,64 @@ export interface ProductData { productTitle: string; productUrl: string; } + +export interface StoryData { + id: number; + date: string; + modified: string; + password: string; + slug: string; + status: string; + link: string; + title: { + raw?: string; + rendered?: string; + }; + excerpt: { + raw?: string; + rendered?: string; + protected?: boolean; + }; + permalinkTemplate: string; + storyData: { + version: number; + pages: Page[]; + autoAdvance: boolean; + defaultPageDuration: number; + currentStoryStyles: { + colors: Pattern[]; + }; + }; + stylePresets: { + colors?: Pattern[]; + textStyles?: Partial[]; + }; + previewLink: string; + editLink: string; + embedPostLink: string; + author: { + id: number; + name: string; + }; + capabilities: Record; + extras: Record; + featuredMedia: { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; + }; + publisherLogo: { + id: number; + height: number; + width: number; + url: string; + }; + taxonomies: string[]; + revisions: { + count: number; + }; + terms: string[]; +} diff --git a/packages/elements/src/types/story.ts b/packages/elements/src/types/story.ts index 368d7c577306..18063edaf6bd 100644 --- a/packages/elements/src/types/story.ts +++ b/packages/elements/src/types/story.ts @@ -22,10 +22,57 @@ import type { AudioResource } from '@googleforcreators/media'; /** * Internal dependencies */ +import type { Pattern } from '@googleforcreators/patterns'; import type { Page } from './page'; export interface Story { + storyId: number; version?: number; + title: string; + author: { + id: number; + name: string; + }; + date: null | string; + modified: string; + excerpt: string; + slug: string; + link: string; + extras: Record; + featuredMedia: { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; + }; + permalinkConfig: null | { + prefix: string; + suffix: string; + }; + publisherLogo: { + id: number; + height: number; + width: number; + url: string; + }; + previewLink: string; + editLink: string; + password: string; + embedPostLink: string; + revisions: { + count: number; + }; + currentStoryStyles: { + colors: Pattern[]; + }; + globalStoryStyles: { + colors: Pattern[]; + textStyles: Partial; + }; + taxonomies: string[]; + terms: string[]; pages: Page[]; status: string; backgroundAudio?: { diff --git a/packages/migration/src/migrate.ts b/packages/migration/src/migrate.ts index 38d0e26db7fd..cca38666d5ac 100644 --- a/packages/migration/src/migrate.ts +++ b/packages/migration/src/migrate.ts @@ -128,7 +128,10 @@ export const DATA_VERSION = Math.max.apply( Object.keys(MIGRATIONS).map(Number) ); -export function migrate(storyData: Story, version: number): Story { +export function migrate( + storyData: Partial, + version: number +): Partial { let result = storyData; for (let v = version; v < DATA_VERSION; v++) { const migrations = MIGRATIONS[v + 1]; diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 713aa363a3b8..79ca500704bc 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -19,7 +19,7 @@ */ import { useEffect } from '@googleforcreators/react'; import { migrate } from '@googleforcreators/migration'; -import { createPage } from '@googleforcreators/elements'; +import { createPage, Story, StoryData } from '@googleforcreators/elements'; /** * Internal dependencies @@ -28,8 +28,18 @@ import { useAPI } from '../../api'; import { useHistory } from '../../history'; import getUniquePresets from '../../../utils/getUniquePresets'; import { useConfig } from '../../config'; +import type { RestoreProps, State } from '../../../types/storyProvider'; -function loadStory(storyId, post, restore, clearHistory, globalConfig) { +function loadStory( + storyId: number, + post: StoryData, + restore: (props: RestoreProps) => State, + clearHistory: () => void, + globalConfig: { + globalAutoAdvance?: boolean; + globalPageDuration?: number; + } +) { const { title: { raw: title = '' } = {}, status, @@ -82,7 +92,10 @@ function loadStory(storyId, post, restore, clearHistory, globalConfig) { // If there are no pages, create empty page. const storyData = storyDataRaw && migrate(storyDataRaw, storyDataRaw.version || 0); - const pages = storyData?.pages?.length > 0 ? storyData.pages : [createPage()]; + const pages = + storyData?.pages && storyData.pages.length > 0 + ? storyData.pages + : [createPage()]; // Initialize color/style presets, if missing. // Otherwise ensure the saved presets are unique. @@ -144,8 +157,14 @@ function loadStory(storyId, post, restore, clearHistory, globalConfig) { }); } +interface LoadStoryProps { + storyId: number; + story: Story; + shouldLoad: boolean; + restore: (props: RestoreProps) => State; +} // When ID is set, load story from API. -function useLoadStory({ storyId, story, shouldLoad, restore }) { +function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { const { actions: { getStoryById }, } = useAPI(); From 4451ecc2086a329d4396f9f955fe4574029c1e2a Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 10:35:03 -0300 Subject: [PATCH 16/99] Create different story types. --- packages/elements/src/types/data.ts | 65 ++------ packages/elements/src/types/index.ts | 1 - packages/elements/src/types/story.ts | 83 ---------- packages/migration/src/migrate.ts | 6 +- .../src/app/story/effects/useLoadStory.ts | 13 +- .../story-editor/src/types/configProvider.ts | 7 +- .../story-editor/src/types/storyProvider.ts | 145 ++++++++++++++++-- 7 files changed, 159 insertions(+), 161 deletions(-) delete mode 100644 packages/elements/src/types/story.ts diff --git a/packages/elements/src/types/data.ts b/packages/elements/src/types/data.ts index c30a804d8afb..b8bf9c22f097 100644 --- a/packages/elements/src/types/data.ts +++ b/packages/elements/src/types/data.ts @@ -18,6 +18,7 @@ * External dependencies */ import type { Pattern } from '@googleforcreators/patterns'; +import type { AudioResource } from '@googleforcreators/media'; /** * Internal dependencies @@ -79,62 +80,14 @@ export interface ProductData { } export interface StoryData { - id: number; - date: string; - modified: string; - password: string; - slug: string; - status: string; - link: string; - title: { - raw?: string; - rendered?: string; + version: number; + pages: Page[]; + autoAdvance: boolean; + defaultPageDuration: number; + currentStoryStyles: { + colors: Pattern[]; }; - excerpt: { - raw?: string; - rendered?: string; - protected?: boolean; + backgroundAudio?: { + resource: AudioResource; }; - permalinkTemplate: string; - storyData: { - version: number; - pages: Page[]; - autoAdvance: boolean; - defaultPageDuration: number; - currentStoryStyles: { - colors: Pattern[]; - }; - }; - stylePresets: { - colors?: Pattern[]; - textStyles?: Partial[]; - }; - previewLink: string; - editLink: string; - embedPostLink: string; - author: { - id: number; - name: string; - }; - capabilities: Record; - extras: Record; - featuredMedia: { - id: number; - height: number; - width: number; - url: string; - needsProxy: boolean; - isExternal: boolean; - }; - publisherLogo: { - id: number; - height: number; - width: number; - url: string; - }; - taxonomies: string[]; - revisions: { - count: number; - }; - terms: string[]; } diff --git a/packages/elements/src/types/index.ts b/packages/elements/src/types/index.ts index 0b2ec096e988..fc528b15aef2 100644 --- a/packages/elements/src/types/index.ts +++ b/packages/elements/src/types/index.ts @@ -20,4 +20,3 @@ export * from './elementType'; export * from './elementDefinition'; export * from './propTypes'; export * from './page'; -export * from './story'; diff --git a/packages/elements/src/types/story.ts b/packages/elements/src/types/story.ts deleted file mode 100644 index 18063edaf6bd..000000000000 --- a/packages/elements/src/types/story.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * External dependencies - */ -import type { AudioResource } from '@googleforcreators/media'; - -/** - * Internal dependencies - */ -import type { Pattern } from '@googleforcreators/patterns'; -import type { Page } from './page'; - -export interface Story { - storyId: number; - version?: number; - title: string; - author: { - id: number; - name: string; - }; - date: null | string; - modified: string; - excerpt: string; - slug: string; - link: string; - extras: Record; - featuredMedia: { - id: number; - height: number; - width: number; - url: string; - needsProxy: boolean; - isExternal: boolean; - }; - permalinkConfig: null | { - prefix: string; - suffix: string; - }; - publisherLogo: { - id: number; - height: number; - width: number; - url: string; - }; - previewLink: string; - editLink: string; - password: string; - embedPostLink: string; - revisions: { - count: number; - }; - currentStoryStyles: { - colors: Pattern[]; - }; - globalStoryStyles: { - colors: Pattern[]; - textStyles: Partial; - }; - taxonomies: string[]; - terms: string[]; - pages: Page[]; - status: string; - backgroundAudio?: { - resource: AudioResource; - }; - autoAdvance?: boolean; - defaultPageDuration?: number; -} diff --git a/packages/migration/src/migrate.ts b/packages/migration/src/migrate.ts index 01d50059fbca..f0e7100714f1 100644 --- a/packages/migration/src/migrate.ts +++ b/packages/migration/src/migrate.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { Story } from '@googleforcreators/elements'; +import type { StoryData } from '@googleforcreators/elements'; /** * Internal dependencies @@ -129,9 +129,9 @@ export const DATA_VERSION = Math.max.apply( ); export function migrate( - storyData: Partial, + storyData: Partial, version: number -): Partial { +): Partial { let result = storyData; for (let v = version; v < DATA_VERSION; v++) { const migrations = MIGRATIONS[v + 1]; diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 79ca500704bc..6a527d49cc47 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -19,7 +19,7 @@ */ import { useEffect } from '@googleforcreators/react'; import { migrate } from '@googleforcreators/migration'; -import { createPage, Story, StoryData } from '@googleforcreators/elements'; +import { createPage } from '@googleforcreators/elements'; /** * Internal dependencies @@ -28,11 +28,15 @@ import { useAPI } from '../../api'; import { useHistory } from '../../history'; import getUniquePresets from '../../../utils/getUniquePresets'; import { useConfig } from '../../config'; -import type { RestoreProps, State } from '../../../types/storyProvider'; +import type { + RawStory, + RestoreProps, + State, Story, +} from '../../../types/storyProvider'; function loadStory( storyId: number, - post: StoryData, + post: RawStory, restore: (props: RestoreProps) => State, clearHistory: () => void, globalConfig: { @@ -177,9 +181,10 @@ function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { const globalConfig = { globalAutoAdvance, globalPageDuration }; if (storyId && shouldLoad) { if (story) { + console.log('story', story); loadStory(storyId, story, restore, clearHistory, globalConfig); } else { - getStoryById(storyId).then((post) => { + getStoryById(storyId).then((post: RawStory) => { loadStory(storyId, post, restore, clearHistory, globalConfig); }); } diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index a3ff72dd8c87..b48923e37127 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -31,6 +31,11 @@ import type { VideoResource, } from '@googleforcreators/media'; +/** + * Internal dependencies + */ +import type { RawStory } from './storyProvider'; + export interface Capabilities { /** If the user has permissions to upload files. */ hasUploadMediaAction?: boolean; @@ -206,7 +211,7 @@ export interface APICallbacks { getPosterMediaById?: (id: number) => Promise; getProducts?: () => Promise; getProxyUrl?: (src: string) => string; - getStoryById?: (id: number) => Promise; + getStoryById?: (id: number) => Promise; getTaxonomies?: () => Promise; getTaxonomyTerm?: (props: { search?: string; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index c5235e49b2a7..26b2d31c4271 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -20,12 +20,12 @@ import type { Page, Element, - Story, Animation, Group, + StoryData, } from '@googleforcreators/elements'; -import type { ResourceId } from '@googleforcreators/media'; - +import type { AudioResource, ResourceId } from '@googleforcreators/media'; +import type { Pattern } from '@googleforcreators/patterns'; /** * Internal dependencies */ @@ -345,16 +345,6 @@ export type ReducerActionProps = | RemoveElementFromGroupAction | AddElementsAcrossPagesAction; -export interface State { - story: Story; - selection: string[]; - current: string | null; - pages: Page[]; - animationState: string; - capabilities: Record; - copiedElementState?: Element; -} - export type InternalActions = { restore: (props: RestoreProps) => State; }; @@ -366,3 +356,132 @@ export interface ReducerState { internal: InternalActions; api: ExternalActions; } + +export interface Story { + storyId: number; + title: string; + author: { + id: number; + name: string; + }; + date: null | string; + modified: string; + excerpt: string; + slug: string; + link: string; + extras: Record; + featuredMedia: { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; + }; + permalinkConfig: null | { + prefix: string; + suffix: string; + }; + publisherLogo: { + id: number; + height: number; + width: number; + url: string; + }; + previewLink: string; + editLink: string; + password: string; + embedPostLink: string; + revisions: { + count: number; + }; + currentStoryStyles: { + colors: Pattern[]; + }; + globalStoryStyles: { + colors: Pattern[]; + textStyles: Partial; + }; + taxonomies: string[]; + terms: string[]; + status: string; + backgroundAudio?: { + resource: AudioResource; + }; + autoAdvance?: boolean; + defaultPageDuration?: number; +} + +// Raw story that comes to the provider from API callback. +export interface RawStory { + id: number; + date: string; + modified: string; + password: string; + slug: string; + status: string; + link: string; + title: { + raw?: string; + rendered?: string; + }; + excerpt: { + raw?: string; + rendered?: string; + protected?: boolean; + }; + permalinkTemplate: string; + storyData: StoryData; + stylePresets: { + colors?: Pattern[]; + textStyles?: Partial[]; + }; + previewLink: string; + editLink: string; + embedPostLink: string; + author: { + id: number; + name: string; + }; + capabilities: Record; + extras: Record; + featuredMedia: { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; + }; + publisherLogo: { + id: number; + height: number; + width: number; + url: string; + }; + taxonomies: string[]; + revisions: { + count: number; + }; + terms: string[]; +} + +export interface State { + story: Story | undefined; + selection: string[]; + current: string | null; + pages: Page[]; + animationState: string; + capabilities: Record; + copiedElementState?: Element; +} + +export interface StoryProviderState { + state: State; + // @todo + actions: {}; + internal: { + reducerState: ReducerState; + restore: (props: RestoreProps) => State; + }; +} From 480bbd716106d19342388026965005755c9d360b Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 10:36:27 -0300 Subject: [PATCH 17/99] Adjust --- packages/story-editor/src/app/story/effects/useLoadStory.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 6a527d49cc47..cd9e9172f862 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -31,7 +31,7 @@ import { useConfig } from '../../config'; import type { RawStory, RestoreProps, - State, Story, + State, } from '../../../types/storyProvider'; function loadStory( @@ -163,7 +163,7 @@ function loadStory( interface LoadStoryProps { storyId: number; - story: Story; + story: RawStory; shouldLoad: boolean; restore: (props: RestoreProps) => State; } @@ -181,7 +181,6 @@ function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { const globalConfig = { globalAutoAdvance, globalPageDuration }; if (storyId && shouldLoad) { if (story) { - console.log('story', story); loadStory(storyId, story, restore, clearHistory, globalConfig); } else { getStoryById(storyId).then((post: RawStory) => { From 48e802bff1beacae47d74914ff0e4414ab646259 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 11:00:22 -0300 Subject: [PATCH 18/99] Fix import --- packages/story-editor/src/app/story/storyProvider.tsx | 4 ++-- packages/story-editor/src/types/storyProvider.ts | 2 +- packages/text-sets/src/types.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index bf3b10154e69..26f948028951 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,7 +19,7 @@ */ import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Animation, Page, Story } from '@googleforcreators/elements'; +import type { Animation, Page, StoryData } from '@googleforcreators/elements'; /** * Internal dependencies @@ -41,7 +41,7 @@ interface ProviderProps { storyId: number; initialEdits?: { [index: string]: unknown; - story?: Story; + story?: StoryData; }; children: ReactNode; } diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 26b2d31c4271..9eb4ed9d91df 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -467,7 +467,7 @@ export interface RawStory { } export interface State { - story: Story | undefined; + story: Story; selection: string[]; current: string | null; pages: Page[]; diff --git a/packages/text-sets/src/types.ts b/packages/text-sets/src/types.ts index 1437607c6b38..d02331a36386 100644 --- a/packages/text-sets/src/types.ts +++ b/packages/text-sets/src/types.ts @@ -16,9 +16,9 @@ /** * External dependencies */ -import type { Page, Story, Element } from '@googleforcreators/elements'; +import type { Page, StoryData, Element } from '@googleforcreators/elements'; -export interface TextSetData extends Omit { +export interface TextSetData extends Omit { current: null; selection: never[]; story: Record; From c4ad37cdee3d556725cdb67ebf4afdde14335b92 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 11:10:04 -0300 Subject: [PATCH 19/99] useLoadStory --- .../src/app/story/effects/useLoadStory.ts | 11 +++++++---- .../src/app/story/useStoryReducer/useStoryReducer.ts | 9 +++++++-- .../{getUniquePresets.js => getUniquePresets.ts} | 11 +++++++++-- packages/story-editor/tsconfig.json | 3 ++- 4 files changed, 25 insertions(+), 9 deletions(-) rename packages/story-editor/src/utils/{getUniquePresets.js => getUniquePresets.ts} (72%) diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index cd9e9172f862..6d5c9b0b5796 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -20,6 +20,7 @@ import { useEffect } from '@googleforcreators/react'; import { migrate } from '@googleforcreators/migration'; import { createPage } from '@googleforcreators/elements'; +import type { Pattern } from '@googleforcreators/patterns'; /** * Internal dependencies @@ -70,7 +71,7 @@ function loadStory( taxonomies, terms, revisions, - } = post; + }: RawStory = post; const date = ['draft', 'auto-draft', 'pending'].includes(status) && @@ -105,10 +106,10 @@ function loadStory( // Otherwise ensure the saved presets are unique. const newGlobalStoryStyles = { colors: globalStoryStyles.colors - ? getUniquePresets(globalStoryStyles.colors) + ? (getUniquePresets(globalStoryStyles.colors) as Pattern[]) : [], textStyles: globalStoryStyles.textStyles - ? getUniquePresets(globalStoryStyles.textStyles) + ? (getUniquePresets(globalStoryStyles.textStyles) as Partial[]) : [], }; @@ -134,7 +135,9 @@ function loadStory( revisions, currentStoryStyles: { colors: storyData?.currentStoryStyles?.colors - ? getUniquePresets(storyData.currentStoryStyles.colors) + ? (getUniquePresets( + storyData.currentStoryStyles.colors as Pattern + ) as Pattern[]) : [], }, globalStoryStyles: newGlobalStoryStyles, diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 052ded54034f..92f5553089c7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -23,7 +23,12 @@ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; /** * Internal dependencies */ -import type {ExternalActions, InternalActions, ReducerState, State} from '../../../types/storyProvider'; +import type { + ExternalActions, + InternalActions, + ReducerState, + State, +} from '../../../types/storyProvider'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -33,7 +38,7 @@ const INITIAL_STATE = { current: null, selection: [], story: {}, - animationState: STORY_ANIMATION_STATE.RESET, + animationState: STORY_ANIMATION_STATE.RESET as string, copiedElementState: {}, }; diff --git a/packages/story-editor/src/utils/getUniquePresets.js b/packages/story-editor/src/utils/getUniquePresets.ts similarity index 72% rename from packages/story-editor/src/utils/getUniquePresets.js rename to packages/story-editor/src/utils/getUniquePresets.ts index 6d5e86df14aa..94e5e3694e5a 100644 --- a/packages/story-editor/src/utils/getUniquePresets.js +++ b/packages/story-editor/src/utils/getUniquePresets.ts @@ -13,9 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -function getUniquePresets(presets) { +/** + * External dependencies + */ +import type { Pattern } from '@googleforcreators/patterns'; + +function getUniquePresets(presets: Pattern[] | Partial[]) { const list = presets.map((preset) => JSON.stringify(preset)); - return Array.from(new Set(list)).map((preset) => JSON.parse(preset)); + return Array.from(new Set(list)).map( + (preset) => JSON.parse(preset) as Pattern | Partial + ); } export default getUniquePresets; diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index f6c2a92aa51d..f41d921b4166 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -19,6 +19,7 @@ "src/app/story/*", "src/app/story/**/*", "src/types/*", - "src/constants/*" + "src/constants/*", + "src/utils/*.ts" ] } From 9dd0a1402969ad20af2c9978be7ff9bac675d85e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 11:37:50 -0300 Subject: [PATCH 20/99] useSaveStory --- .../src/app/story/actions/useSaveStory.ts | 37 ++++++++++++------- .../useStoryReducer/reducers/updateStory.ts | 4 +- .../story-editor/src/types/storyEditor.ts | 21 +++++++++++ ...ostEditURL.js => useRefreshPostEditURL.ts} | 8 +--- 4 files changed, 48 insertions(+), 22 deletions(-) create mode 100644 packages/story-editor/src/types/storyEditor.ts rename packages/story-editor/src/utils/{useRefreshPostEditURL.js => useRefreshPostEditURL.ts} (83%) diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index 9f84bef39a75..d3aeafa18ee7 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -22,6 +22,7 @@ import { useCallback, useState } from '@googleforcreators/react'; import { getTimeTracker, trackError } from '@googleforcreators/tracking'; import { useSnackbar } from '@googleforcreators/design-system'; import { stripHTML } from '@googleforcreators/dom'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies @@ -31,6 +32,8 @@ import { useConfig } from '../../config'; import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; +import type { Story } from '../../../types/storyProvider'; +import type { RESTError } from '../../../types/storyEditor'; const HTTP_STATUS_DESCRIPTIONS = { 400: _x('Bad Request', 'HTTP status description', 'web-stories'), @@ -39,17 +42,22 @@ const HTTP_STATUS_DESCRIPTIONS = { 500: _x('Internal Server Error', 'HTTP status description', 'web-stories'), }; +interface UseSaveStoryProps { + storyId: number; + pages: Page[]; + story: Story; + updateStory: (data: { properties: Partial }) => Story; +} + /** * Custom hook to save story. - * - * @param {Object} properties Properties to update. - * @param {number} properties.storyId Story post id. - * @param {Array} properties.pages Array of all pages. - * @param {Object} properties.story Story-global properties. - * @param {Function} properties.updateStory Function to update a story. - * @return {Function} Function that can be called to save a story. */ -function useSaveStory({ storyId, pages, story, updateStory }) { +function useSaveStory({ + storyId, + pages, + story, + updateStory, +}: UseSaveStoryProps) { const { actions: { saveStoryById }, } = useAPI(); @@ -92,7 +100,7 @@ function useSaveStory({ storyId, pages, story, updateStory }) { ...props, }) ) - .then((data) => { + .then((data: Story) => { const { status, slug, @@ -104,7 +112,7 @@ function useSaveStory({ storyId, pages, story, updateStory }) { featuredMedia, } = data; - const properties = { + const properties: Partial = { status, slug, link, @@ -125,7 +133,7 @@ function useSaveStory({ storyId, pages, story, updateStory }) { setIsFreshlyPublished(!isStoryAlreadyPublished && isStoryPublished); setIsFreshlyPending(!isStoryAlreadyPending && isStoryPending); }) - .catch((err) => { + .catch((err: RESTError) => { const description = err.message ? stripHTML(err.message) : null; let message = __('Failed to save the story', 'web-stories'); @@ -138,6 +146,7 @@ function useSaveStory({ storyId, pages, story, updateStory }) { } if ( + err?.data?.status && Object.prototype.hasOwnProperty.call( HTTP_STATUS_DESCRIPTIONS, err?.data?.status @@ -148,20 +157,20 @@ function useSaveStory({ storyId, pages, story, updateStory }) { /* translators: 1: error message. 2: status code */ __('Failed to save the story: %1$s (%2$s)', 'web-stories'), description, - HTTP_STATUS_DESCRIPTIONS[err?.data?.status] + HTTP_STATUS_DESCRIPTIONS[err.data.status] ); } else { message = sprintf( /* translators: %s: error message */ __('Failed to save the story: %s', 'web-stories'), - HTTP_STATUS_DESCRIPTIONS[err?.data?.status] + HTTP_STATUS_DESCRIPTIONS[err.data.status] ); } } // eslint-disable-next-line no-console -- We want to surface this error. console.log(__('Failed to save the story', 'web-stories'), err); - trackError('save_story', description); + void trackError('save_story', description || ''); showSnackbar({ message, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index c443884315e5..b2e690efc6fe 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -22,14 +22,14 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ -import type { UpdatePageProps, State } from '../../../../types/storyProvider'; +import type { UpdateStoryProps, State } from '../../../../types/storyProvider'; /** * Update story properties. * * No validation is performed and existing values are overwritten. */ -export const updateStory = (draft: State, { properties }: UpdatePageProps) => { +export const updateStory = (draft: State, { properties }: UpdateStoryProps) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { draft.story = properties(current(draft.story)); diff --git a/packages/story-editor/src/types/storyEditor.ts b/packages/story-editor/src/types/storyEditor.ts new file mode 100644 index 000000000000..a434ccb1f247 --- /dev/null +++ b/packages/story-editor/src/types/storyEditor.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface RESTError { + message?: string; + data?: { + status: 400 | 401 | 403 | 500; + }; +} diff --git a/packages/story-editor/src/utils/useRefreshPostEditURL.js b/packages/story-editor/src/utils/useRefreshPostEditURL.ts similarity index 83% rename from packages/story-editor/src/utils/useRefreshPostEditURL.js rename to packages/story-editor/src/utils/useRefreshPostEditURL.ts index 2c8a15efa4f2..95290d5c0d39 100644 --- a/packages/story-editor/src/utils/useRefreshPostEditURL.js +++ b/packages/story-editor/src/utils/useRefreshPostEditURL.ts @@ -22,12 +22,8 @@ import { __, sprintf } from '@googleforcreators/i18n'; /** * Update page URL in browser. - * - * @param {number} postId Current story id. - * @param {string} postEditURL Current story's edit link. - * @return {Function} Function to refresh the post edit URL. */ -function useRefreshPostEditURL(postId, postEditURL) { +function useRefreshPostEditURL(postId: number, postEditURL: string) { return useCallback(() => { try { const newUrl = new URL(postEditURL); @@ -37,7 +33,7 @@ function useRefreshPostEditURL(postId, postEditURL) { sprintf( /* translators: %d: current story id. */ __('Post %d', 'web-stories'), - postId + postId.toString() ), newUrl.toString() ); From 498b8510fb8e8322f2237793c0da9282e00bf220 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 11:42:00 -0300 Subject: [PATCH 21/99] Remove import exts --- .../story-editor/src/components/canvas/test/useCanvasKeys.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/components/canvas/test/useCanvasKeys.js b/packages/story-editor/src/components/canvas/test/useCanvasKeys.js index 4c4b56b64fd6..6ccffc6db81e 100644 --- a/packages/story-editor/src/components/canvas/test/useCanvasKeys.js +++ b/packages/story-editor/src/components/canvas/test/useCanvasKeys.js @@ -27,8 +27,8 @@ import { elementTypes } from '@googleforcreators/element-library'; */ import useHighlights from '../../../app/highlights/useHighlights'; import useCanvasKeys from '../../../app/canvas/useCanvasKeys'; -import StoryContext from '../../../app/story/context.js'; -import CanvasContext from '../../../app/canvas/context.js'; +import StoryContext from '../../../app/story/context'; +import CanvasContext from '../../../app/canvas/context'; jest.mock('../../../app/highlights/useHighlights', () => ({ ...jest.requireActual('../../../app/highlights/useHighlights'), From 6a263fb946d65bab08b7084e6d80c4d1579cacef Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 12:27:38 -0300 Subject: [PATCH 22/99] More types --- .../src/app/story/actions/useLocalAutoSave.ts | 18 +++++++++++++- .../src/app/story/effects/useLoadStory.ts | 2 +- .../src/app/story/storyProvider.tsx | 13 ++++++---- .../storyTriggers/storyTriggersProvider.tsx | 24 +++++++++---------- .../story/useStoryReducer/useStoryReducer.ts | 2 +- .../story-editor/src/types/storyProvider.ts | 19 +++++++++++++-- ...nStorageKey.js => getSessionStorageKey.ts} | 2 +- 7 files changed, 57 insertions(+), 23 deletions(-) rename packages/story-editor/src/utils/{getSessionStorageKey.js => getSessionStorageKey.ts} (93%) diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index 6788dc83153f..8769eeb4c8d9 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -18,13 +18,29 @@ */ import { useCallback } from '@googleforcreators/react'; import { sessionStore } from '@googleforcreators/design-system'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ import getSessionStorageKey from '../../../utils/getSessionStorageKey'; +import type { RestoreProps, State } from '../../../types/storyProvider'; +import type { Capabilities } from '../../../types/configProvider'; -function useLocalAutoSave({ restore, storyId, pages, capabilities, isNew }) { +interface UseLocalAutoSaveProps { + restore: (props: RestoreProps) => State; + storyId: number; + pages: Page[]; + capabilities: Capabilities; + isNew: boolean; +} +function useLocalAutoSave({ + restore, + storyId, + pages, + capabilities, + isNew, +}: UseLocalAutoSaveProps) { const restoreLocalAutoSave = useCallback(() => { const existingAutoSave = sessionStore.getItemByKey( getSessionStorageKey(storyId, isNew) diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 6d5c9b0b5796..af1529e30321 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -166,7 +166,7 @@ function loadStory( interface LoadStoryProps { storyId: number; - story: RawStory; + story: RawStory | undefined; shouldLoad: boolean; restore: (props: RestoreProps) => State; } diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 26f948028951..aa7daa569f2e 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,12 +19,13 @@ */ import type { ReactNode } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Animation, Page, StoryData } from '@googleforcreators/elements'; +import type { Animation, Page } from '@googleforcreators/elements'; /** * Internal dependencies */ import { STABLE_ARRAY } from '../../constants'; +import type { RawStory } from '../../types/storyProvider'; import Context from './context'; import useLoadStory from './effects/useLoadStory'; @@ -41,7 +42,7 @@ interface ProviderProps { storyId: number; initialEdits?: { [index: string]: unknown; - story?: StoryData; + story?: RawStory; }; children: ReactNode; } @@ -80,7 +81,7 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { // Generate selection info const selectedElementIds = useMemo( - () => (selection.length > 0 ? selection : STABLE_ARRAY), + () => (selection && selection.length > 0 ? selection : STABLE_ARRAY), [selection] ); const isCurrentPageEmpty = !currentPage; @@ -90,7 +91,9 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { if (isCurrentPageEmpty) { return STABLE_ARRAY; } - const els = currentPageElements?.filter(({ id }) => selection.includes(id)); + const els = currentPageElements?.filter( + ({ id }) => selection && selection.includes(id) + ); return els && els.length > 0 ? els : STABLE_ARRAY; }, [isCurrentPageEmpty, currentPageElements, selection]); @@ -101,7 +104,7 @@ function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { } const animations = (currentPageAnimations || []).reduce( (acc: Animation[], { targets, ...properties }) => { - if (targets.some((id) => selection.includes(id))) { + if (targets.some((id) => selection && selection.includes(id))) { return [...acc, { targets, ...properties }]; } return acc; diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index fedadf84a9cc..dbd55db2a7b3 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -23,11 +23,12 @@ import { useCallback, createContext, } from '@googleforcreators/react'; -import PropTypes from 'prop-types'; +import type { ReactNode } from 'react'; /** * Internal dependencies */ +import type { State } from '../../../types/storyProvider'; import { STORY_EVENTS, StoryEventRegisters } from './storyEvents'; export const Context = createContext({ state: {}, actions: {} }); @@ -42,19 +43,23 @@ function createSubscriptionMap() { ); } -function reducer([currentStory], updatedStory) { +function reducer([currentStory]: [State], updatedStory: State | null) { return [updatedStory, currentStory]; } -export function StoryTriggersProvider({ children, story }) { +interface StoryTriggersProviderProps { + children: ReactNode; + story: State; +} +export function StoryTriggersProvider({ + children, + story, +}: StoryTriggersProviderProps) { // store prev & next versions of story to help compute internally fired events. // Not sure if this is necessarily needed but was used a lot in FTUE. Lets keep // an eye on this as we create more internal event registers, and we can always // remove if we end up not using it. - const [[currentStory, previousStory], updateStory] = useReducer(reducer, [ - story, - null, - ]); + const [[currentStory, previousStory], updateStory] = useReducer(reducer, [story, null]); const subscriptionMap = useMemo(createSubscriptionMap, []); // Update story to derive events @@ -111,8 +116,3 @@ export function StoryTriggersProvider({ children, story }) { ); } - -StoryTriggersProvider.propTypes = { - story: PropTypes.object, - children: PropTypes.node, -}; diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 92f5553089c7..fa204d68379f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -67,7 +67,7 @@ function useStoryReducer(partial: Partial): ReducerState { ...INITIAL_STATE, ...partial, } as State); - +console.log(state); const { internal, api } = useMemo(() => { const wrapWithDispatch = ( actions: typeof internalActions | typeof exposedActions diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 9eb4ed9d91df..4b3f709da6bf 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -468,12 +468,27 @@ export interface RawStory { export interface State { story: Story; - selection: string[]; - current: string | null; + selection?: string[]; + current?: string | null; pages: Page[]; animationState: string; capabilities: Record; copiedElementState?: Element; + currentPage: Page | null; + currentPageId: string | null; + currentPageIndex: number | null; + currentPageNumber: number | null; + selectedElementIds: string[]; + selectedElements: Element[]; + selectedElementAnimations: Animation[]; + hasSelection: boolean; + meta: { + isSaving: boolean; + isSavingStory: boolean; + isAutoSavingStory: boolean; + isFreshlyPublished: boolean; + isFreshlyPending: boolean; + }, } export interface StoryProviderState { diff --git a/packages/story-editor/src/utils/getSessionStorageKey.js b/packages/story-editor/src/utils/getSessionStorageKey.ts similarity index 93% rename from packages/story-editor/src/utils/getSessionStorageKey.js rename to packages/story-editor/src/utils/getSessionStorageKey.ts index f1e4f07b1494..b233d7e9f8cb 100644 --- a/packages/story-editor/src/utils/getSessionStorageKey.js +++ b/packages/story-editor/src/utils/getSessionStorageKey.ts @@ -21,7 +21,7 @@ import { SESSION_STORAGE_PREFIX } from '@googleforcreators/design-system'; // Note: this key format is also used in the `dashboard` package which should be updated in case of changes. // See https://github.com/GoogleForCreators/web-stories-wp/pull/12416/files#diff-a314e9df4ccf61e1a84cd3ca5b318a729c086e49e92da545b5a6272da3666b98R43 -export default function getSessionStorageKey(storyId, isNew) { +export default function getSessionStorageKey(storyId: number, isNew: boolean) { return `${SESSION_STORAGE_PREFIX.LOCAL_AUTOSAVE_PREFIX}_${ isNew ? 'auto-draft' : storyId }`; From fbb14155fdd5ca05641f86b9ef96c564c7eb8273 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 16 Nov 2022 12:31:06 -0300 Subject: [PATCH 23/99] Remove debug data --- .../src/app/story/useStoryReducer/useStoryReducer.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index fa204d68379f..fb9dbe41db38 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -67,7 +67,6 @@ function useStoryReducer(partial: Partial): ReducerState { ...INITIAL_STATE, ...partial, } as State); -console.log(state); const { internal, api } = useMemo(() => { const wrapWithDispatch = ( actions: typeof internalActions | typeof exposedActions From aed73f91eb12d2d23af94b20372a9a5806821a4b Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 14:23:23 -0300 Subject: [PATCH 24/99] Temp test --- .../story/useStoryReducer/useStoryReducer.ts | 21 ++++++++++++------- .../story-editor/src/types/storyProvider.ts | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index fb9dbe41db38..ec4ddd43b706 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -68,20 +68,27 @@ function useStoryReducer(partial: Partial): ReducerState { ...partial, } as State); const { internal, api } = useMemo(() => { - const wrapWithDispatch = ( - actions: typeof internalActions | typeof exposedActions - ) => + const wrapWithDispatch = (actions: typeof internalActions) => Object.keys(actions).reduce( - (collection: InternalActions | ExternalActions, action) => ({ + (collection: InternalActions, action) => ({ ...collection, - [action]: actions[action](dispatch), + [action]: actions[action as keyof typeof actions](dispatch), }), - {} + {} as InternalActions + ); + + const wrapWithDispatch2 = (actions: typeof exposedActions) => + Object.keys(actions).reduce( + (collection: ExternalActions, action) => ({ + ...collection, + [action]: actions[action as keyof typeof actions](dispatch), + }), + {} as ExternalActions ); return { internal: wrapWithDispatch(internalActions) as InternalActions, - api: wrapWithDispatch(exposedActions) as ExternalActions, + api: wrapWithDispatch2(exposedActions) as ExternalActions, }; }, [dispatch]); diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 4b3f709da6bf..ff4ae24e5b2c 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -349,7 +349,7 @@ export type InternalActions = { restore: (props: RestoreProps) => State; }; export type ExternalActions = { - [index: string]: unknown; + addAnimations: (props: AddAnimationsProps) => State; }; export interface ReducerState { state: State; From 966c27ccaea78b2ec84b000e257c24028f0071af Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 14:39:29 -0300 Subject: [PATCH 25/99] Adjust --- .../story/useStoryReducer/useStoryReducer.ts | 20 +++++++------------ .../story-editor/src/types/storyProvider.ts | 2 +- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index ec4ddd43b706..ac384c97d30f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -62,33 +62,27 @@ const INITIAL_STATE = { * - New pages aren't validated for type of elements property when added. * - No validation of keys or values in the story object. */ +type Actions = InternalActions | ExternalActions; function useStoryReducer(partial: Partial): ReducerState { const [state, dispatch] = useReducer(reducer, { ...INITIAL_STATE, ...partial, } as State); const { internal, api } = useMemo(() => { - const wrapWithDispatch = (actions: typeof internalActions) => + const wrapWithDispatch = ( + actions: typeof internalActions | typeof exposedActions + ) => Object.keys(actions).reduce( - (collection: InternalActions, action) => ({ + (collection: Actions, action) => ({ ...collection, [action]: actions[action as keyof typeof actions](dispatch), }), - {} as InternalActions - ); - - const wrapWithDispatch2 = (actions: typeof exposedActions) => - Object.keys(actions).reduce( - (collection: ExternalActions, action) => ({ - ...collection, - [action]: actions[action as keyof typeof actions](dispatch), - }), - {} as ExternalActions + {} as Actions ); return { internal: wrapWithDispatch(internalActions) as InternalActions, - api: wrapWithDispatch2(exposedActions) as ExternalActions, + api: wrapWithDispatch(exposedActions) as ExternalActions, }; }, [dispatch]); diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index ff4ae24e5b2c..8230990a8fd9 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -488,7 +488,7 @@ export interface State { isAutoSavingStory: boolean; isFreshlyPublished: boolean; isFreshlyPending: boolean; - }, + }; } export interface StoryProviderState { From a109b287cf9df08ea541ea04b4003e04f5319d9d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 14:42:47 -0300 Subject: [PATCH 26/99] Fix import --- packages/story-editor/src/app/story/actions/useAutoSave.ts | 3 ++- .../src/app/story/useStoryReducer/reducers/restore.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 178812ed55f2..87940b820029 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -18,7 +18,7 @@ * External dependencies */ import { useCallback, useState } from '@googleforcreators/react'; -import type { Page, Story } from '@googleforcreators/elements'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies @@ -26,6 +26,7 @@ import type { Page, Story } from '@googleforcreators/elements'; import { useAPI } from '../../api'; import { useConfig } from '../../config'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; +import type { Story } from '../../../types/storyProvider'; interface AutoSaveProps { storyId: number; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 609444ddeadc..f1f17da505e4 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type {RestoreProps, State} from '../../../../types/storyProvider'; +import type { RestoreProps, State } from '../../../../types/storyProvider'; /** * Restore internal state completely from given state. From c3f0fe3421dc9739bbb3d11524c87aa6b7fde465 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 15:39:52 -0300 Subject: [PATCH 27/99] design-system snackbar --- packages/design-system/package.json | 2 +- packages/design-system/src/contexts/index.js | 5 +-- .../src/contexts/snackbar/context.ts | 33 +++++++++++++++++++ .../snackbar/{context.js => index.ts} | 12 +++---- ...ackbarProvider.js => snackbarProvider.tsx} | 25 +++++++------- .../{useSnackbar.js => useSnackbar.ts} | 6 +++- .../design-system/src/{index.ts => index.js} | 0 .../src/theme/{index.ts => index.js} | 7 +--- packages/design-system/src/types.ts | 23 +++++++++++++ packages/design-system/src/types/snackbar.ts | 30 +++++++++++++++++ packages/design-system/tsconfig.json | 7 +++- .../story-editor/src/types/configProvider.ts | 3 +- packages/story-editor/tsconfig.json | 1 + tsconfig.json | 1 + 14 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 packages/design-system/src/contexts/snackbar/context.ts rename packages/design-system/src/contexts/snackbar/{context.js => index.ts} (74%) rename packages/design-system/src/contexts/snackbar/{snackbarProvider.js => snackbarProvider.tsx} (78%) rename packages/design-system/src/contexts/snackbar/{useSnackbar.js => useSnackbar.ts} (80%) rename packages/design-system/src/{index.ts => index.js} (100%) rename packages/design-system/src/theme/{index.ts => index.js} (90%) create mode 100644 packages/design-system/src/types.ts create mode 100644 packages/design-system/src/types/snackbar.ts diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 53e80f6d22a8..dbf61c72ac96 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -31,7 +31,7 @@ }, "main": "dist/index.js", "module": "dist-module/index.js", - "types": "dist-types/index.d.ts", + "types": "dist-types/types.d.ts", "source": "src/index.ts", "publishConfig": { "access": "public" diff --git a/packages/design-system/src/contexts/index.js b/packages/design-system/src/contexts/index.js index a4c41d64bead..5fa5bf00908c 100644 --- a/packages/design-system/src/contexts/index.js +++ b/packages/design-system/src/contexts/index.js @@ -13,10 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export { default as SnackbarContext } from './snackbar/context'; -export { default as SnackbarProvider } from './snackbar/snackbarProvider'; -export { useSnackbar } from './snackbar/useSnackbar'; +export * from './snackbar'; export { default as PopupContext } from './popup/context'; export { default as PopupProvider } from './popup/popupProvider'; export { usePopup } from './popup/usePopup'; diff --git a/packages/design-system/src/contexts/snackbar/context.ts b/packages/design-system/src/contexts/snackbar/context.ts new file mode 100644 index 000000000000..cb60ea7815ac --- /dev/null +++ b/packages/design-system/src/contexts/snackbar/context.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import { createContext } from '@googleforcreators/react'; + +/** + * Internal dependencies + */ +import type { SnackbarState } from '../../types/snackbar'; + +export default createContext({ + showSnackbar: () => false, + clearSnackbar: () => false, + removeSnack: () => false, + currentSnacks: [], + placement: '', +}); diff --git a/packages/design-system/src/contexts/snackbar/context.js b/packages/design-system/src/contexts/snackbar/index.ts similarity index 74% rename from packages/design-system/src/contexts/snackbar/context.js rename to packages/design-system/src/contexts/snackbar/index.ts index 6b679ad2156e..317ffe7d5356 100644 --- a/packages/design-system/src/contexts/snackbar/context.js +++ b/packages/design-system/src/contexts/snackbar/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 Google LLC + * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * External dependencies - */ -import { createContext } from '@googleforcreators/react'; - -export default createContext({}); +export { default as SnackbarContext } from './context'; +export { default as SnackbarProvider } from './snackbarProvider'; +export { useSnackbar } from './useSnackbar'; diff --git a/packages/design-system/src/contexts/snackbar/snackbarProvider.js b/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx similarity index 78% rename from packages/design-system/src/contexts/snackbar/snackbarProvider.js rename to packages/design-system/src/contexts/snackbar/snackbarProvider.tsx index 66d76735fbed..aa6555f68abe 100644 --- a/packages/design-system/src/contexts/snackbar/snackbarProvider.js +++ b/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx @@ -17,19 +17,27 @@ /** * External dependencies */ -import PropTypes from 'prop-types'; import { useCallback, useMemo, useState } from '@googleforcreators/react'; import { v4 as uuidv4 } from 'uuid'; +import type { ReactNode } from 'react'; + /** * Internal dependencies */ -import { Placement } from '../../components/snackbar/constants'; +import type { Notification } from '../../types/snackbar'; import Context from './context'; -function SnackbarProvider({ children, placement = 'bottom' }) { - const [notifications, setNotifications] = useState([]); +interface SnackbarProviderProps { + children: ReactNode; + placement?: string; +} +function SnackbarProvider({ + children, + placement = 'bottom', +}: SnackbarProviderProps) { + const [notifications, setNotifications] = useState([]); - const remove = useCallback((toRemove) => { + const remove = useCallback((toRemove: Notification | Notification[]) => { setNotifications((currentNotifications) => currentNotifications.filter((item) => { if (Array.isArray(toRemove)) { @@ -40,7 +48,7 @@ function SnackbarProvider({ children, placement = 'bottom' }) { ); }, []); - const create = useCallback((notification) => { + const create = useCallback((notification: Omit) => { const newNotification = { id: uuidv4(), ...notification, @@ -71,9 +79,4 @@ function SnackbarProvider({ children, placement = 'bottom' }) { return {children}; } -SnackbarProvider.propTypes = { - placement: Placement, - children: PropTypes.node, -}; - export default SnackbarProvider; diff --git a/packages/design-system/src/contexts/snackbar/useSnackbar.js b/packages/design-system/src/contexts/snackbar/useSnackbar.ts similarity index 80% rename from packages/design-system/src/contexts/snackbar/useSnackbar.js rename to packages/design-system/src/contexts/snackbar/useSnackbar.ts index 5a6b3b939065..d7df97ecca1a 100644 --- a/packages/design-system/src/contexts/snackbar/useSnackbar.js +++ b/packages/design-system/src/contexts/snackbar/useSnackbar.ts @@ -22,8 +22,12 @@ import { identity, useContextSelector } from '@googleforcreators/react'; /** * Internal dependencies */ +import type { SnackbarState } from '../../types/snackbar'; import Context from './context'; -export function useSnackbar(selector) { +export function useSnackbar(): SnackbarState; +export function useSnackbar( + selector: (state: SnackbarState) => T | SnackbarState = identity +) { return useContextSelector(Context, selector ?? identity); } diff --git a/packages/design-system/src/index.ts b/packages/design-system/src/index.js similarity index 100% rename from packages/design-system/src/index.ts rename to packages/design-system/src/index.js diff --git a/packages/design-system/src/theme/index.ts b/packages/design-system/src/theme/index.js similarity index 90% rename from packages/design-system/src/theme/index.ts rename to packages/design-system/src/theme/index.js index 53ce897a429d..7618d25107d5 100644 --- a/packages/design-system/src/theme/index.ts +++ b/packages/design-system/src/theme/index.js @@ -14,11 +14,6 @@ * limitations under the License. */ -/** - * External dependencies - */ -import type { DefaultTheme } from 'styled-components'; - /** * Internal dependencies */ @@ -30,7 +25,7 @@ import { typography } from './typography'; import { borders } from './borders'; import { breakpoint, raw } from './breakpoint'; -export const theme: DefaultTheme = { +export const theme = { borders, typography, colors: { ...darkMode }, diff --git a/packages/design-system/src/types.ts b/packages/design-system/src/types.ts new file mode 100644 index 000000000000..74413df3ca5b --- /dev/null +++ b/packages/design-system/src/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Temporary workaround while this package is not fully converted yet. +// Adjust tsconfig.json and "types" field in package.json and then +// delete this file once complete. + +export * from './contexts/snackbar'; + +export {}; diff --git a/packages/design-system/src/types/snackbar.ts b/packages/design-system/src/types/snackbar.ts new file mode 100644 index 000000000000..d18d0e99292e --- /dev/null +++ b/packages/design-system/src/types/snackbar.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export interface Notification { + id: string; + key: string; + 'aria-label': string; + message: string; + onDismiss: () => void; +} +export interface SnackbarState { + showSnackbar: (snackbar: Omit) => void; + clearSnackbar: () => void; + removeSnack: (toRemove: Notification | Notification[]) => void; + currentSnacks: Notification[]; + placement: string; +} diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json index c9d87fc4143c..290c4afc6094 100644 --- a/packages/design-system/tsconfig.json +++ b/packages/design-system/tsconfig.json @@ -4,5 +4,10 @@ "rootDir": "src", "declarationDir": "dist-types" }, - "include": ["src/**/*"] + "include": [ + "src/contexts/snackbar/*", + "src/types.ts", + "src/types/*", + "src/components/snackbar/constants.ts" + ] } diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index b48923e37127..44be4adedfb5 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -20,7 +20,6 @@ import type { MediaElement, Page, - Story, FontData, ProductData, } from '@googleforcreators/elements'; @@ -34,7 +33,7 @@ import type { /** * Internal dependencies */ -import type { RawStory } from './storyProvider'; +import type { RawStory, Story } from './storyProvider'; export interface Capabilities { /** If the user has permissions to upload files. */ diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index f41d921b4166..0c69474bc7b0 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -6,6 +6,7 @@ }, "references": [ { "path": "../dom" }, + { "path": "../design-system" }, { "path": "../elements" }, { "path": "../i18n" }, { "path": "../masks" }, diff --git a/tsconfig.json b/tsconfig.json index d91eef38e98c..90cf9808f2b7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,6 +3,7 @@ { "path": "packages/activation-notice" }, { "path": "packages/element-library" }, { "path": "packages/dashboard" }, + { "path": "packages/design-system" }, { "path": "packages/dom" }, { "path": "packages/elements" }, { "path": "packages/fonts" }, From 795917d498a2180ed5016bb4b46b0ac3a68437b5 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 16:19:07 -0300 Subject: [PATCH 28/99] Start typing utils --- packages/design-system/package.json | 4 ++-- packages/elements/src/types/page.ts | 5 +++++ packages/media/src/blob.ts | 4 ++-- packages/media/src/types/resource.ts | 2 ++ .../src/app/story/utils/deleteNestedKeys.ts | 7 ++---- .../src/app/story/utils/getAllProducts.ts | 8 +++---- .../app/story/utils/getStoryPropsToSave.ts | 16 +++++++++++++- .../src/app/story/utils/isEmptyStory.ts | 22 +++++++++++++------ .../app/story/utils/pageContainsBlobUrl.ts | 7 +++--- 9 files changed, 51 insertions(+), 24 deletions(-) diff --git a/packages/design-system/package.json b/packages/design-system/package.json index dbf61c72ac96..ec48b319740f 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -26,13 +26,13 @@ }, "customExports": { ".": { - "default": "./src/index.ts" + "default": "./src/index.js" } }, "main": "dist/index.js", "module": "dist-module/index.js", "types": "dist-types/types.d.ts", - "source": "src/index.ts", + "source": "src/index.js", "publishConfig": { "access": "public" }, diff --git a/packages/elements/src/types/page.ts b/packages/elements/src/types/page.ts index 0784c71c34be..80d3d29a11f1 100644 --- a/packages/elements/src/types/page.ts +++ b/packages/elements/src/types/page.ts @@ -61,4 +61,9 @@ export interface Page { }; autoAdvance?: boolean; defaultPageDuration?: number; + pageAttachment?: { + url: string; + ctaText: string; + theme: string; + }; } diff --git a/packages/media/src/blob.ts b/packages/media/src/blob.ts index 2eed2ce08467..2ac73ee95bcc 100644 --- a/packages/media/src/blob.ts +++ b/packages/media/src/blob.ts @@ -61,6 +61,6 @@ export function revokeBlob(url: string): void { * @param url The URL. * @return Is the url a blob url? */ -export function isBlobURL(url: string): boolean { - return url?.startsWith('blob:'); +export function isBlobURL(url?: string): boolean { + return url ? url.startsWith('blob:') : false; } diff --git a/packages/media/src/types/resource.ts b/packages/media/src/types/resource.ts index af2ba65a566b..284569df104b 100644 --- a/packages/media/src/types/resource.ts +++ b/packages/media/src/types/resource.ts @@ -87,6 +87,8 @@ export interface Resource { /** Resource author attribution */ attribution?: Attribution; + poster?: string; + // TODO: Figure out why sometimes _images_ end up having these properties. posterId?: ResourceId; isOptimized?: boolean; diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index 1c34ba34657c..d30cded3a2cc 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -19,12 +19,9 @@ * Each path has to be in the format of nested keys separated by a dot, e.g. `foo.bar.a` * * Note that this function mutates the original object. - * - * @param {Array} paths Array of paths of keys. - * @return {Object} Changed object. */ -function deleteNestedKeys(paths) { - return (object) => { +function deleteNestedKeys(paths: string[]) { + return (object: Record) => { if (!Array.isArray(paths)) { return; } diff --git a/packages/story-editor/src/app/story/utils/getAllProducts.ts b/packages/story-editor/src/app/story/utils/getAllProducts.ts index 024edad0ca93..74ea4b12c1ee 100644 --- a/packages/story-editor/src/app/story/utils/getAllProducts.ts +++ b/packages/story-editor/src/app/story/utils/getAllProducts.ts @@ -17,11 +17,11 @@ /** * External dependencies */ -import { ELEMENT_TYPES } from '@googleforcreators/elements'; +import { ELEMENT_TYPES, Page, ProductData } from '@googleforcreators/elements'; -function getAllProducts(pages) { - const products = []; - const productIds = []; +function getAllProducts(pages: Page[]) { + const products: Element[] = []; + const productIds: string[] = []; pages.forEach(({ elements }) => elements.forEach(({ product, type }) => { if ( diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts index 617949883d4a..16e21f0dd64f 100644 --- a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts +++ b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts @@ -17,14 +17,28 @@ * External dependencies */ import { getStoryMarkup } from '@googleforcreators/output'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ import objectPick from '../../../utils/objectPick'; +import type { Story } from '../../../types/storyProvider'; +import type { MetaData } from '../../../types/configProvider'; import getAllProducts from './getAllProducts'; -function getStoryPropsToSave({ story, pages, metadata, flags }) { +interface StoryPropsToSave { + story: Story; + pages: Page[]; + metadata: MetaData; + flags: Record; +} +function getStoryPropsToSave({ + story, + pages, + metadata, + flags, +}: StoryPropsToSave) { const { terms, ...propsFromStory } = objectPick(story, [ 'title', 'status', diff --git a/packages/story-editor/src/app/story/utils/isEmptyStory.ts b/packages/story-editor/src/app/story/utils/isEmptyStory.ts index 432269572bca..24f495e9f78c 100644 --- a/packages/story-editor/src/app/story/utils/isEmptyStory.ts +++ b/packages/story-editor/src/app/story/utils/isEmptyStory.ts @@ -18,9 +18,13 @@ * External dependencies */ import { shallowEqual } from '@googleforcreators/react'; -import { DEFAULT_PAGE_BACKGROUND_COLOR } from '@googleforcreators/elements'; +import { + DEFAULT_PAGE_BACKGROUND_COLOR, + DefaultBackgroundElement, + Page, +} from '@googleforcreators/elements'; -const isEmptyStory = (pages) => { +const isEmptyStory = (pages: Page[]) => { const hasOnlyOnePage = pages.length === 1; if (!hasOnlyOnePage) { return false; @@ -31,7 +35,9 @@ const isEmptyStory = (pages) => { return false; } - const hasNoBackgroundMedia = pages[0].elements[0].isDefaultBackground; + const hasNoBackgroundMedia = ( + pages[0].elements[0] as DefaultBackgroundElement + ).isDefaultBackground; if (!hasNoBackgroundMedia) { return false; } @@ -41,10 +47,12 @@ const isEmptyStory = (pages) => { return false; } - const hasDefaultBackgroundColor = shallowEqual( - DEFAULT_PAGE_BACKGROUND_COLOR.color, - pages[0].backgroundColor.color - ); + const hasDefaultBackgroundColor = + 'color' in pages[0].backgroundColor && + shallowEqual( + DEFAULT_PAGE_BACKGROUND_COLOR.color, + pages[0].backgroundColor.color + ); if (!hasDefaultBackgroundColor) { return false; } diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts index 19ef0d3b9266..619b456c29b1 100644 --- a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts +++ b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts @@ -17,15 +17,16 @@ * External dependencies */ import { isBlobURL } from '@googleforcreators/media'; +import type { MediaElement, Page } from '@googleforcreators/elements'; -function pageContainsBlobUrl(pages) { +function pageContainsBlobUrl(pages: Page[]) { // skip entries that have a blob url // https://github.com/GoogleForCreators/web-stories-wp/issues/10289 return pages.some((page) => page.elements.some( (element) => - isBlobURL(element?.resource?.src) || - isBlobURL(element?.resource?.poster) + isBlobURL((element as MediaElement)?.resource?.src) || + isBlobURL((element as MediaElement)?.resource?.poster) ) ); } From 8e8e273c52c178642d1ba47629ac634088d052c8 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 16:57:34 -0300 Subject: [PATCH 29/99] More types. --- packages/elements/src/types/element.ts | 6 ++++ .../story-editor/src/app/story/context.ts | 31 ++++++++++++++++++- .../story-editor/src/app/story/useStory.tsx | 6 +++- .../src/app/story/utils/getAllProducts.ts | 25 +++++++++++---- .../story-editor/src/types/storyProvider.ts | 4 +-- packages/templates/src/types.ts | 4 +-- 6 files changed, 64 insertions(+), 12 deletions(-) diff --git a/packages/elements/src/types/element.ts b/packages/elements/src/types/element.ts index d92fa5b52e43..ac7573e115f1 100644 --- a/packages/elements/src/types/element.ts +++ b/packages/elements/src/types/element.ts @@ -25,6 +25,7 @@ import type { ElementBox } from '@googleforcreators/units'; * Internal dependencies */ import type { ElementType } from './elementType'; +import type { ProductData } from './data'; export interface Link { url: string; @@ -106,3 +107,8 @@ export interface MediaElement extends BackgroundableElement { export interface SequenceMediaElement extends MediaElement { resource: SequenceResource; } + +export interface ProductElement extends Element { + type: ElementType.Product; + product: ProductData; +} diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index 4afad84092f1..f94c0d8ec52c 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -18,5 +18,34 @@ * External dependencies */ import { createContext } from '@googleforcreators/react'; +import type { Animation, Element, Page } from '@googleforcreators/elements'; -export default createContext({ state: {}, actions: {} }); +/** + * Internal dependencies + */ +import type { StoryProviderState } from '../../types/storyProvider'; + +export default createContext({ + state: { + story: null, + pages: [] as Page[], + animationState: '', + capabilities: {}, + currentPage: null, + currentPageId: null, + currentPageIndex: null, + currentPageNumber: null, + selectedElementIds: [], + selectedElements: [] as Element[], + selectedElementAnimations: [] as Animation[], + hasSelection: false, + meta: { + isSaving: false, + isSavingStory: false, + isAutoSavingStory: false, + isFreshlyPublished: false, + isFreshlyPending: false, + }, + }, + actions: {}, +}); diff --git a/packages/story-editor/src/app/story/useStory.tsx b/packages/story-editor/src/app/story/useStory.tsx index 4abf7e18a7dd..32e0a8ae5b93 100644 --- a/packages/story-editor/src/app/story/useStory.tsx +++ b/packages/story-editor/src/app/story/useStory.tsx @@ -21,9 +21,13 @@ import { identity, useContextSelector } from '@googleforcreators/react'; /** * Internal dependencies */ +import type { StoryProviderState } from '../../types/storyProvider'; import Context from './context'; -function useStory(selector) { +export function useStory(): StoryProviderState; +export function useStory( + selector: (state: StoryProviderState) => T | StoryProviderState = identity +) { return useContextSelector(Context, selector ?? identity); } diff --git a/packages/story-editor/src/app/story/utils/getAllProducts.ts b/packages/story-editor/src/app/story/utils/getAllProducts.ts index 74ea4b12c1ee..efc42b3f18dc 100644 --- a/packages/story-editor/src/app/story/utils/getAllProducts.ts +++ b/packages/story-editor/src/app/story/utils/getAllProducts.ts @@ -17,20 +17,33 @@ /** * External dependencies */ -import { ELEMENT_TYPES, Page, ProductData } from '@googleforcreators/elements'; +import { + Element, + ELEMENT_TYPES, + Page, + ProductElement, + ProductData, +} from '@googleforcreators/elements'; -function getAllProducts(pages: Page[]) { - const products: Element[] = []; +function isProduct(e: Element): e is ProductElement { + return 'product' in e; +} +function getAllProducts(pages: Page[]): ProductData[] { + const products: ProductData[] = []; const productIds: string[] = []; pages.forEach(({ elements }) => - elements.forEach(({ product, type }) => { + elements.forEach((element) => { + if (!isProduct(element)) { + return; + } + const { product, type } = element; if ( type === ELEMENT_TYPES.PRODUCT && product && - !productIds.includes(product?.productId) + !productIds.includes(product.productId) ) { products.push(product); - productIds.push(product?.productId); + productIds.push(product.productId); } }) ); diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 8230990a8fd9..80ec064ddbbf 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -467,7 +467,7 @@ export interface RawStory { } export interface State { - story: Story; + story: Story | null; selection?: string[]; current?: string | null; pages: Page[]; @@ -495,7 +495,7 @@ export interface StoryProviderState { state: State; // @todo actions: {}; - internal: { + internal?: { reducerState: ReducerState; restore: (props: RestoreProps) => State; }; diff --git a/packages/templates/src/types.ts b/packages/templates/src/types.ts index b97f7354baa9..704de80b07c0 100644 --- a/packages/templates/src/types.ts +++ b/packages/templates/src/types.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { Story, Page, Element } from '@googleforcreators/elements'; +import type { StoryData, Page, Element } from '@googleforcreators/elements'; export interface Color { label: string; @@ -37,7 +37,7 @@ export interface MetaData { modified?: string; } -export interface TemplateData extends Omit { +export interface TemplateData extends Omit { current: null; selection: never[]; story: Record; From b8ea880387611ea57cca33c4545cde64c3b2cbea Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 17:18:14 -0300 Subject: [PATCH 30/99] More types --- .../src/app/story/useStoryReducer/reducer.ts | 10 ++++++++-- .../useStoryReducer/reducers/addAnimations.ts | 4 ++-- .../story/useStoryReducer/reducers/addElements.ts | 4 ++-- .../reducers/addElementsAcrossPages.ts | 4 ++-- .../app/story/useStoryReducer/reducers/addGroup.ts | 4 ++-- .../app/story/useStoryReducer/reducers/addPage.ts | 4 ++-- .../useStoryReducer/reducers/arrangeElement.ts | 4 ++-- .../story/useStoryReducer/reducers/arrangeGroup.ts | 4 ++-- .../story/useStoryReducer/reducers/arrangePage.ts | 4 ++-- .../useStoryReducer/reducers/combineElements.ts | 4 ++-- .../reducers/copySelectedElement.ts | 6 +++--- .../useStoryReducer/reducers/deleteElements.ts | 4 ++-- .../reducers/deleteElementsByResourceId.ts | 4 ++-- .../story/useStoryReducer/reducers/deleteGroup.ts | 4 ++-- .../story/useStoryReducer/reducers/deletePage.ts | 4 ++-- .../reducers/duplicateElementsById.ts | 4 ++-- .../useStoryReducer/reducers/duplicateGroup.ts | 4 ++-- .../app/story/useStoryReducer/reducers/index.ts | 2 +- .../reducers/removeElementFromGroup.ts | 4 ++-- .../app/story/useStoryReducer/reducers/restore.ts | 12 ++++++------ .../useStoryReducer/reducers/selectElement.ts | 4 ++-- .../reducers/setBackgroundElement.ts | 4 ++-- .../useStoryReducer/reducers/setCurrentPage.ts | 4 ++-- .../reducers/setSelectedElements.ts | 6 +++--- .../useStoryReducer/reducers/toggleElement.ts | 4 ++-- .../story/useStoryReducer/reducers/toggleLayer.ts | 4 ++-- .../useStoryReducer/reducers/unselectElement.ts | 4 ++-- .../reducers/updateAnimationState.ts | 14 +++++++------- .../useStoryReducer/reducers/updateElements.ts | 6 +++--- .../reducers/updateElementsByFontFamily.ts | 4 ++-- .../reducers/updateElementsByResourceId.ts | 4 ++-- .../story/useStoryReducer/reducers/updateGroup.ts | 4 ++-- .../story/useStoryReducer/reducers/updatePage.ts | 4 ++-- .../story/useStoryReducer/reducers/updateStory.ts | 4 ++-- .../app/story/useStoryReducer/useStoryReducer.ts | 6 +++--- packages/story-editor/src/types/storyProvider.ts | 11 +++++++---- 36 files changed, 95 insertions(+), 86 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index 623695368955..d19506fea67b 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -17,12 +17,18 @@ /** * Internal dependencies */ -import type { ReducerActionProps, State } from '../../../types/storyProvider'; +import type { + ReducerActionProps, + ReducerState, +} from '../../../types/storyProvider'; import * as types from './types'; import * as reducers from './reducers'; // eslint-disable-next-line complexity -- reducer function, negligible. -function reducer(state: State, { type, payload }: ReducerActionProps): State { +function reducer( + state: ReducerState, + { type, payload }: ReducerActionProps +): ReducerState { switch (type) { case types.ADD_PAGE: { return reducers.addPage(state, payload); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index 65139db5fa73..f71b08252d06 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { exclusion } from './utils'; -import type {AddAnimationsProps, State} from "../../../../types/storyProvider"; +import type {AddAnimationsProps, ReducerState} from "../../../../types/storyProvider"; /** * Add animations to current page. @@ -37,7 +37,7 @@ import type {AddAnimationsProps, State} from "../../../../types/storyProvider"; * Animations will be added to the end of the list of animations on the current page. */ export const addAnimations = ( - draft: State, + draft: ReducerState, { animations }: AddAnimationsProps ) => { if (!Array.isArray(animations)) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index 05b979b22cd0..2503b90a73ce 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -25,7 +25,7 @@ import { produce } from 'immer'; */ import { MAX_PRODUCTS_PER_PAGE } from '../../../../constants'; import { exclusion } from './utils'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {AddElementsProps} from "../../../../types/storyProvider"; const isProduct = ({ type }: { type: string }) => @@ -47,7 +47,7 @@ const isNotProduct = ({ type }: { type: string }) => * Selection is set to be exactly the new elements by default. */ export const addElements = ( - draft: State, + draft: ReducerState, { elements, pageId, updateSelection = true }: AddElementsProps ) => { console.log(draft); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts index 947cc186329f..ba5ab5452819 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts @@ -25,7 +25,7 @@ import { produce } from 'immer'; */ import type { AddElementsAcrossPagesProps, - State, + ReducerState, } from '../../../../types/storyProvider'; import { addPage } from './addPage'; import { addElements } from './addElements'; @@ -38,7 +38,7 @@ import { addElements } from './addElements'; * Selection is unchanged afterwards. */ const addElementsAcrossPages = ( - draft: State, + draft: ReducerState, { page, position, elements }: AddElementsAcrossPagesProps ) => { elements.forEach((element, index) => { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts index b436bba7328d..fb29c954cf0a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts @@ -22,13 +22,13 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddGroupProps, State } from '../../../../types/storyProvider'; +import type { AddGroupProps, ReducerState } from '../../../../types/storyProvider'; /** * Add a group to the current page groups list (id, name). */ export const addGroup = ( - draft: State, + draft: ReducerState, { groupId, name, isLocked = false }: AddGroupProps ) => { if (!groupId || !name) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index d719bed9a608..9423ee433d38 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddPageProps, State } from '../../../../types/storyProvider'; +import type { AddPageProps, ReducerState } from '../../../../types/storyProvider'; import { isInsideRange } from './utils'; /** @@ -37,7 +37,7 @@ import { isInsideRange } from './utils'; * Selection is cleared by default. */ export const addPage = ( - draft: State, + draft: ReducerState, { page, position, updateSelection = true }: AddPageProps ) => { // Ensure new page has at least one element diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 00a49e013b02..521a2d0b1374 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { getAbsolutePosition, moveArrayElement } from './utils'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {ArrangeElementProps} from "../../../../types/storyProvider"; /** @@ -57,7 +57,7 @@ import type {ArrangeElementProps} from "../../../../types/storyProvider"; * TODO: Handle multi-element re-order when UX and priority is finalized. */ export const arrangeElement = ( - draft: State, + draft: ReducerState, { elementId, position, groupId = false }: ArrangeElementProps ) => { if (elementId === null && draft.selection.length !== 1) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index b86e22a44581..702a038b5d15 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -23,14 +23,14 @@ import { produce } from 'immer'; * Internal dependencies */ import { getAbsolutePosition } from './utils'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {ArrangeGroupProps} from "../../../../types/storyProvider"; /** * Move group to a new position */ export const arrangeGroup = ( - draft: State, + draft: ReducerState, { groupId, position }: ArrangeGroupProps ) => { if (!groupId) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 7b5987dcf4df..b8635722dfa8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { ArrangePageProps, State } from '../../../../types/storyProvider'; +import type { ArrangePageProps, ReducerState } from '../../../../types/storyProvider'; import { isInsideRange, moveArrayElement } from './utils'; /** @@ -38,7 +38,7 @@ import { isInsideRange, moveArrayElement } from './utils'; * TODO: Handle multi-page re-order when UX and priority is finalized. */ export const arrangePage = ( - draft: State, + draft: ReducerState, { pageId, position }: ArrangePageProps ) => { // Abort if there's less than two elements (nothing to rearrange) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index f1223ca22401..255bf72525f3 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -29,7 +29,7 @@ import objectPick from '../../../../utils/objectPick'; import objectWithout from '../../../../utils/objectWithout'; import { removeAnimationsWithElementIds } from './utils'; import type {CombineElementsProps} from "../../../../types/storyProvider"; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; /** * Combine elements by taking properties from a first item and @@ -50,7 +50,7 @@ import type {State} from "@googleforcreators/types"; * Updates selection to only include the second item after merge. */ export const combineElements = ( - draft: State, + draft: ReducerState, { firstElement, secondId, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts index 2cb19553ffbf..b83a090d2f1a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import objectPick from '../../../../utils/objectPick'; -import type { State } from '../../../../types/storyProvider'; +import type { ReducerState } from '../../../../types/storyProvider'; export const ATTRIBUTES_TO_COPY = [ 'background', @@ -48,7 +48,7 @@ export const ATTRIBUTES_TO_COPY = [ * Copies the styles and animations of the selected element * on the current page. */ -export const copySelectedElement = (draft: State) => { +export const copySelectedElement = (draft: ReducerState) => { // we can only copy one element and it has to exist if (draft.selection?.length !== 1 || !draft.selection[0]) { return; @@ -65,7 +65,7 @@ export const copySelectedElement = (draft: State) => { // omit properties that must not be copied const copiedStyles = objectPick(element, ATTRIBUTES_TO_COPY); - draft.copiedElementState = { + draft.copiedElementReducerState = { animations: elementAnimations, styles: copiedStyles, type: element.type, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts index fd052f5a8f45..4381debe740b 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts @@ -24,7 +24,7 @@ import { produce } from 'immer'; */ import { intersect } from './utils'; import type {DeleteElementsProps} from "../../../../types/storyProvider"; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; /** * Delete elements by the given list of ids. @@ -49,7 +49,7 @@ import type {State} from "@googleforcreators/types"; * @param {Array.} payload.elementIds List of ids of elements to delete. */ export const deleteElements = ( - draft: State, + draft: ReducerState, { elementIds }: DeleteElementsProps ) => { const idsToDelete = elementIds === null ? draft.selection : elementIds; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index 2543ad4b552f..613fba19b56d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvider"; /** @@ -31,7 +31,7 @@ import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvi * If no element with the given resource id is found, state is changed. */ export const deleteElementsByResourceId = ( - draft: State, + draft: ReducerState, { id }: DeleteElementsByResourceIdProps ) => { if (id === null) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts index 061c2f554e83..91a5754f7e27 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts @@ -22,14 +22,14 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeleteGroupProps, State } from '../../../../types/storyProvider'; +import type { DeleteGroupProps, ReducerState } from '../../../../types/storyProvider'; import { deleteElements } from './deleteElements'; /** * Delete group by id. */ const deleteGroup = produce( - (draft: State, { groupId, includeElements = false }: DeleteGroupProps) => { + (draft: ReducerState, { groupId, includeElements = false }: DeleteGroupProps) => { const { elements, groups } = draft.pages.find( ({ id }) => id === draft.current ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index f982ee9d9353..fdd8dda3494d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeletePageProps, State } from '../../../../types/storyProvider'; +import type { DeletePageProps, ReducerState } from '../../../../types/storyProvider'; /** * Delete page by id or delete current page if no id given. @@ -36,7 +36,7 @@ import type { DeletePageProps, State } from '../../../../types/storyProvider'; * * If a page is deleted, selection is cleared. */ -export const deletePage = (draft: State, { pageId }: DeletePageProps) => { +export const deletePage = (draft: ReducerState, { pageId }: DeletePageProps) => { if (draft.pages.length <= 1) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index 99f58c96ff09..30452f706783 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DuplicateElementsByIdProps, State } from '../../../../types/storyProvider'; +import type { DuplicateElementsByIdProps, ReducerState } from '../../../../types/storyProvider'; /** * Duplicate all elements specified by `elementIds` on the current page. @@ -32,7 +32,7 @@ import type { DuplicateElementsByIdProps, State } from '../../../../types/storyP * If given `elementIds` are not a list, do nothing. */ export const duplicateElementsById = ( - draft: State, + draft: ReducerState, { elementIds }: DuplicateElementsByIdProps ) => { if (!Array.isArray(elementIds)) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index 2bb076e8d0bb..744fb6d61daa 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -24,14 +24,14 @@ import { duplicateElement } from '@googleforcreators/elements'; * Internal dependencies */ import { addGroup } from './addGroup'; -import type {DuplicateGroupProps, State} from "../../../../types/storyProvider"; +import type {DuplicateGroupProps, ReducerState} from "../../../../types/storyProvider"; /** * Duplicate group with all elements on the current page. * Set selected elements to be the newly created group. */ export const duplicateGroup = ( - draft: State, + draft: ReducerState, { oldGroupId, groupId, name, isLocked }: DuplicateGroupProps ) => { if (!oldGroupId || !groupId || !name) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts index 59cb521a240f..574ce141d69f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts @@ -45,7 +45,7 @@ export { default as toggleElement } from './toggleElement'; export { default as toggleLayer } from './toggleLayer'; // Manipulate animation state -export { default as updateAnimationState } from './updateAnimationState'; +export { default as updateAnimationReducerState } from './updateAnimationReducerState'; export { default as addAnimations } from './addAnimations'; // Manipulate entire internal state. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts index 1e13de163dcb..ed93510c4abb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts @@ -24,7 +24,7 @@ import { produce } from 'immer'; */ import type { RemoveElementFromGroupProps, - State, + ReducerState, } from '../../../../types/storyProvider'; import { arrangeElement } from './arrangeElement'; import { getLastIndexOfGroup } from './utils'; @@ -38,7 +38,7 @@ import { getLastIndexOfGroup } from './utils'; * @param {number} payload.groupId Selected element group id */ export const removeElementFromGroup = ( - draft: State, + draft: ReducerState, { elementId, groupId }: RemoveElementFromGroupProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index f1f17da505e4..fa8fe66a25c1 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { RestoreProps, State } from '../../../../types/storyProvider'; +import type { RestoreProps, ReducerState } from '../../../../types/storyProvider'; /** * Restore internal state completely from given state. @@ -35,14 +35,14 @@ import type { RestoreProps, State } from '../../../../types/storyProvider'; * - `story` is an object. */ export const restore = ( - draft: State, + draft: ReducerState, { pages, current, selection, story, capabilities }: RestoreProps ) => { if (!Array.isArray(pages) || pages.length === 0) { return undefined; } - const newState = typeof story === 'object' ? story : {}; + const newReducerState = typeof story === 'object' ? story : {}; const newCapabilities = typeof capabilities === 'object' ? capabilities : {}; const oldCurrent = current ?? draft.current; const newCurrent = pages.some(({ id }) => id === oldCurrent) @@ -54,10 +54,10 @@ export const restore = ( pages, current: newCurrent, selection: newSelection, - story: newState, - animationState: draft.animationState, + story: newReducerState, + animationReducerState: draft.animationReducerState, capabilities: newCapabilities, - copiedElementState: {}, + copiedElementReducerState: {}, }; }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index a0b841d8f7e8..4e4023bf2a1d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -19,7 +19,7 @@ */ import { produce } from 'immer'; import type {SelectElementProps} from "../../../../types/storyProvider"; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; /** * Add the given id to the current selection. @@ -31,7 +31,7 @@ import type {State} from "@googleforcreators/types"; * @param {string} payload.elementId Element id to add to the current selection. */ export const selectElement = ( - draft: State, + draft: ReducerState, { elementId }: SelectElementProps ) => { if (!elementId || draft.selection.includes(elementId)) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index 63e44a1fd04c..50c40df0b243 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {SetBackgroundElementProps} from "../../../../types/storyProvider"; /** @@ -39,7 +39,7 @@ import type {SetBackgroundElementProps} from "../../../../types/storyProvider"; * element. */ export const setBackgroundElement = ( - draft: State, + draft: ReducerState, { elementId }: SetBackgroundElementProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index 7288062c48ed..0908ac27cb7d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { SetCurrentPageProps, State } from '../../../../types/storyProvider'; +import type { SetCurrentPageProps, ReducerState } from '../../../../types/storyProvider'; /** * Set current page to the given id. @@ -32,7 +32,7 @@ import type { SetCurrentPageProps, State } from '../../../../types/storyProvider * If page is changed, selection is cleared */ export const setCurrentPage = ( - draft: State, + draft: ReducerState, { pageId }: SetCurrentPageProps ) => { const pageExists = draft.pages.some(({ id }) => id === pageId); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index ac24e940660b..974af06bcff1 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -24,7 +24,7 @@ import { produce, current } from 'immer'; * Internal dependencies */ import { intersect } from './utils'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {SetSelectedElementsProps} from "../../../../types/storyProvider"; /** @@ -42,7 +42,7 @@ import type {SetSelectedElementsProps} from "../../../../types/storyProvider"; * Current page and pages are unchanged. */ export const setSelectedElements = ( - draft: State, + draft: ReducerState, { elementIds, withLinked = false }: SetSelectedElementsProps ) => { const newElementIds = @@ -100,7 +100,7 @@ export const setSelectedElements = ( ) : uniqueElementIds; - draft.animationState = STORY_ANIMATION_STATE.RESET; + draft.animationReducerState = STORY_ANIMATION_STATE.RESET; draft.selection = newSelection; }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts index e0bb95bb34bf..ecbb8631253a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {ToggleElementInSelectionProps} from "../../../../types/storyProvider"; /** @@ -39,7 +39,7 @@ import type {ToggleElementInSelectionProps} from "../../../../types/storyProvide * @param {boolean} payload.withLinked Include elements from the group? */ export const toggleElement = ( - draft: State, + draft: ReducerState, { elementId, withLinked = false }: ToggleElementInSelectionProps ) => { if (!elementId) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts index df946007acee..84da4d0af1ba 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts @@ -24,11 +24,11 @@ import { produce } from 'immer'; */ import { toggleElement } from './toggleElement'; import { setSelectedElements } from './setSelectedElements'; -import type {State} from "@googleforcreators/types"; +import type {ReducerState} from "@googleforcreators/types"; import type {ToggleLayerProps} from "../../../../types/storyProvider"; export const toggleLayer = ( - draft: State, + draft: ReducerState, { elementId, metaKey, shiftKey, withLinked = false }: ToggleLayerProps ) => { // Meta pressed. Toggle this layer in the selection. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts index d5176a972045..a356d9725f68 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UnselectElementProps, State } from '../../../../types/storyProvider'; +import type { UnselectElementProps, ReducerState } from '../../../../types/storyProvider'; /** * Remove the given id from the current selection. @@ -30,7 +30,7 @@ import type { UnselectElementProps, State } from '../../../../types/storyProvide * If no id is given or id is not in the current selection, nothing happens. */ export const unselectElement = ( - draft: State, + draft: ReducerState, { elementId }: UnselectElementProps ) => { const index = draft.selection.indexOf(elementId); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts index 7407f8fe0fca..9b00ca9c0c56 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts @@ -23,19 +23,19 @@ import { produce } from 'immer'; * Internal dependencies */ import type { - State, - UpdateAnimationStateProps, + ReducerState, + UpdateAnimationReducerStateProps, } from '../../../../types/storyProvider'; /** * Update the story animation state to play, pause, scrub or reset * active pages animations. */ -export const updateAnimationState = ( - draft: State, - { animationState }: UpdateAnimationStateProps +export const updateAnimationReducerState = ( + draft: ReducerState, + { animationReducerState }: UpdateAnimationReducerStateProps ) => { - draft.animationState = animationState; + draft.animationReducerState = animationReducerState; }; -export default produce(updateAnimationState); +export default produce(updateAnimationReducerState); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index f587d002d255..73ba9c631660 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UpdateElementsProps, State } from '../../../../types/storyProvider'; +import type { UpdateElementsProps, ReducerState } from '../../../../types/storyProvider'; import { updateElementWithUpdater, updateAnimations } from './utils'; /** @@ -41,7 +41,7 @@ import { updateElementWithUpdater, updateAnimations } from './utils'; * Current selection and page is unchanged. */ export const updateElements = ( - draft: State, + draft: ReducerState, { elementIds, properties: propertiesOrUpdater }: UpdateElementsProps ) => { if ( @@ -49,7 +49,7 @@ export const updateElements = ( STORY_ANIMATION_STATE.PLAYING, STORY_ANIMATION_STATE.PLAYING_SELECTED, STORY_ANIMATION_STATE.SCRUBBING, - ].includes(draft.animationState) + ].includes(draft.animationReducerState) ) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts index 251258340e3c..477b05946f42 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import type { - State, + ReducerState, UpdateElementsByFontFamilyProps, } from '../../../../types/storyProvider'; import { updateElementWithUpdater } from './utils'; @@ -42,7 +42,7 @@ import { updateElementWithUpdater } from './utils'; * Current selection and page is unchanged. */ export const updateElementsByFontFamily = ( - draft: State, + draft: ReducerState, { family, properties: propertiesOrUpdater }: UpdateElementsByFontFamilyProps ) => { if (!family) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index 0dbfe0567910..d4126831a708 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -24,7 +24,7 @@ import { produce } from 'immer'; */ import type { UpdateElementsByResourceIdProps, - State, + ReducerState, } from '../../../../types/storyProvider'; import { updateElementWithUpdater } from './utils'; @@ -42,7 +42,7 @@ import { updateElementWithUpdater } from './utils'; * Current selection and page is unchanged. */ export const updateElementsByResourceId = ( - draft: State, + draft: ReducerState, { id, properties: propertiesOrUpdater }: UpdateElementsByResourceIdProps ) => { if (!id) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts index 3163a8f6359d..a106ee543bbb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts @@ -22,13 +22,13 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { State, UpdateGroupProps } from '../../../../types/storyProvider'; +import type { ReducerState, UpdateGroupProps } from '../../../../types/storyProvider'; /** * Update group by id. */ export const updateGroup = ( - draft: State, + draft: ReducerState, { groupId, properties }: UpdateGroupProps ) => { if (!groupId) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index 64b51cd21c6c..8087edb4971c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { PAGE_RESERVED_PROPERTIES } from '../types'; -import type { UpdatePageProps, State } from '../../../../types/storyProvider'; +import type { UpdatePageProps, ReducerState } from '../../../../types/storyProvider'; import { objectWithout } from './utils'; /** @@ -34,7 +34,7 @@ import { objectWithout } from './utils'; * Current page and selection is unchanged. */ export const updatePage = ( - draft: State, + draft: ReducerState, { pageId, properties }: UpdatePageProps ) => { const idToUpdate = (pageId === null ? draft.current : pageId) as diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index b2e690efc6fe..a26294be51c7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -22,14 +22,14 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ -import type { UpdateStoryProps, State } from '../../../../types/storyProvider'; +import type { UpdateStoryProps, ReducerState } from '../../../../types/storyProvider'; /** * Update story properties. * * No validation is performed and existing values are overwritten. */ -export const updateStory = (draft: State, { properties }: UpdateStoryProps) => { +export const updateStory = (draft: ReducerState, { properties }: UpdateStoryProps) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { draft.story = properties(current(draft.story)); diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index ac384c97d30f..8be0c238b70e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -27,7 +27,7 @@ import type { ExternalActions, InternalActions, ReducerState, - State, + ReducerProviderState, } from '../../../types/storyProvider'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -63,11 +63,11 @@ const INITIAL_STATE = { * - No validation of keys or values in the story object. */ type Actions = InternalActions | ExternalActions; -function useStoryReducer(partial: Partial): ReducerState { +function useStoryReducer(partial: Partial): ReducerProviderState { const [state, dispatch] = useReducer(reducer, { ...INITIAL_STATE, ...partial, - } as State); + } as ReducerState); const { internal, api } = useMemo(() => { const wrapWithDispatch = ( actions: typeof internalActions | typeof exposedActions diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 80ec064ddbbf..93ac97235e50 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -351,8 +351,8 @@ export type InternalActions = { export type ExternalActions = { addAnimations: (props: AddAnimationsProps) => State; }; -export interface ReducerState { - state: State; +export interface ReducerProviderState { + state: ReducerState; internal: InternalActions; api: ExternalActions; } @@ -466,7 +466,7 @@ export interface RawStory { terms: string[]; } -export interface State { +export interface ReducerState { story: Story | null; selection?: string[]; current?: string | null; @@ -474,6 +474,9 @@ export interface State { animationState: string; capabilities: Record; copiedElementState?: Element; +} + +export interface State extends ReducerState { currentPage: Page | null; currentPageId: string | null; currentPageIndex: number | null; @@ -495,7 +498,7 @@ export interface StoryProviderState { state: State; // @todo actions: {}; - internal?: { + internal: { reducerState: ReducerState; restore: (props: RestoreProps) => State; }; From 774740a33a01f4be6147ee9b7284bdb36883d53a Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 17 Nov 2022 17:45:55 -0300 Subject: [PATCH 31/99] Type utils --- packages/elements/src/types/animation.ts | 1 + .../useStoryReducer/reducers/addAnimations.ts | 9 +- .../story/useStoryReducer/reducers/index.ts | 2 +- .../reducers/updateAnimationState.ts | 10 +- .../story/useStoryReducer/reducers/utils.ts | 122 ++++++++++++------ .../story-editor/src/types/storyProvider.ts | 2 +- .../{objectWithout.js => objectWithout.ts} | 5 +- 7 files changed, 101 insertions(+), 50 deletions(-) rename packages/story-editor/src/utils/{objectWithout.js => objectWithout.ts} (87%) diff --git a/packages/elements/src/types/animation.ts b/packages/elements/src/types/animation.ts index 07117e0ec91d..3dc58287aaa4 100644 --- a/packages/elements/src/types/animation.ts +++ b/packages/elements/src/types/animation.ts @@ -65,4 +65,5 @@ export interface Animation { whooshInDir?: AnimationDirection; scaleDirection?: ZoomDirection; flyInDir?: AnimationDirection; + delete?: boolean; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index f71b08252d06..01004d15c9ae 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -22,8 +22,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { + AddAnimationsProps, + ReducerState, +} from '../../../../types/storyProvider'; import { exclusion } from './utils'; -import type {AddAnimationsProps, ReducerState} from "../../../../types/storyProvider"; /** * Add animations to current page. @@ -46,6 +49,10 @@ export const addAnimations = ( const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } + if (!page.animations) { page.animations = []; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts index 574ce141d69f..59cb521a240f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/index.ts @@ -45,7 +45,7 @@ export { default as toggleElement } from './toggleElement'; export { default as toggleLayer } from './toggleLayer'; // Manipulate animation state -export { default as updateAnimationReducerState } from './updateAnimationReducerState'; +export { default as updateAnimationState } from './updateAnimationState'; export { default as addAnimations } from './addAnimations'; // Manipulate entire internal state. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts index 9b00ca9c0c56..29da0ca9e56f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts @@ -24,18 +24,18 @@ import { produce } from 'immer'; */ import type { ReducerState, - UpdateAnimationReducerStateProps, + UpdateAnimationStateProps, } from '../../../../types/storyProvider'; /** * Update the story animation state to play, pause, scrub or reset * active pages animations. */ -export const updateAnimationReducerState = ( +export const updateAnimationState = ( draft: ReducerState, - { animationReducerState }: UpdateAnimationReducerStateProps + { animationState }: UpdateAnimationStateProps ) => { - draft.animationReducerState = animationReducerState; + draft.animationState = animationState; }; -export default produce(updateAnimationReducerState); +export default produce(updateAnimationState); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 6f4ba6bc4ae0..b636c9c54cc6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -14,15 +14,21 @@ * limitations under the License. */ +/** + * External dependencies + */ +import type { Animation, Element } from '@googleforcreators/elements'; + /** * Internal dependencies */ import { LAYER_DIRECTIONS } from '../../../../constants'; import { ELEMENT_RESERVED_PROPERTIES } from '../types'; import objectWithout from '../../../../utils/objectWithout'; +import type { ElementUpdater } from '../../../../types/storyProvider'; export { objectWithout }; -export function intersect(first, ...rest) { +export function intersect(first: string[], ...rest: string[][]) { if (!first || !rest?.length) { return first; } @@ -34,11 +40,15 @@ export function intersect(first, ...rest) { ); } -export function isInsideRange(index, start, end) { +export function isInsideRange(index: number, start: number, end: number) { return index >= start && index <= end; } -export function moveArrayElement(array, oldPosition, newPosition) { +export function moveArrayElement( + array: Element[], + oldPosition: number, + newPosition: number +) { // First remove from list. const element = array[oldPosition]; const arrayWithoutElement = [ @@ -54,12 +64,18 @@ export function moveArrayElement(array, oldPosition, newPosition) { ]; } +interface PositionProps { + currentPosition: number; + minPosition: number; + maxPosition: number; + desiredPosition: string | number; +} export function getAbsolutePosition({ currentPosition, minPosition, maxPosition, desiredPosition, -}) { +}: PositionProps) { if (typeof desiredPosition === 'number') { return Math.min(maxPosition, Math.max(minPosition, desiredPosition)); } @@ -82,47 +98,62 @@ export function getAbsolutePosition({ } } -export function updateElementWithUpdater(element, properties) { +export function updateElementWithUpdater( + element: Element, + properties: Partial | ElementUpdater +) { const updater = typeof properties === 'function' ? properties(element) : properties; - const allowedProperties = objectWithout(updater, ELEMENT_RESERVED_PROPERTIES); + const allowedProperties: Partial | Element = objectWithout( + updater, + ELEMENT_RESERVED_PROPERTIES + ); if (Object.keys(allowedProperties).length === 0) { return null; } - if (allowedProperties.animation) { + if ('animation' in allowedProperties) { return allowedProperties.animation; } Object.assign(element, allowedProperties); return null; } -export function removeAnimationsWithElementIds(animations = [], ids = []) { - return animations.reduce((accum, animation) => { +export function removeAnimationsWithElementIds( + animations: Animation[] = [], + ids: string[] = [] +) { + return animations.reduce((accum: Animation[], animation) => { if (ids.some((id) => animation.targets?.includes(id))) { return accum; } return [...accum, animation]; - }, []); + }, [] as Animation[]); } -export function updateAnimations(oldAnimations, animationUpdates) { - const newAnimations = oldAnimations.reduce((animations, animation) => { - const updatedAnimation = animationUpdates[animation.id]; - - // remove animation from lookup - delete animationUpdates[animation.id]; - - if (updatedAnimation?.delete) { - // delete animation - return animations; - } else if (updatedAnimation) { - // update animation - return [...animations, updatedAnimation]; - } else { - // No updates - return [...animations, animation]; - } - }, []); +export function updateAnimations( + oldAnimations: Animation[], + animationUpdates: Animation[] +) { + const newAnimations = oldAnimations.reduce( + (animations: Animation[], animation) => { + const updatedAnimation = animationUpdates[animation.id] as Animation; + + // remove animation from lookup + delete animationUpdates[animation.id]; + + if (updatedAnimation?.delete) { + // delete animation + return animations; + } else if (updatedAnimation) { + // update animation + return [...animations, updatedAnimation]; + } else { + // No updates + return [...animations, animation]; + } + }, + [] + ); // add animations Object.values(animationUpdates).forEach((a) => newAnimations.push(a)); @@ -137,14 +168,17 @@ export function updateAnimations(oldAnimations, animationUpdates) { * @typedef {Object.} Entry */ +interface Entry { + id: string; +} /** * Remove duplicate entries. Uses last instance if * multiple entries share the same id. * - * @param {Array} entries - set of entries with possible duplicate Ids - * @return {Array} New set of entries with only unique Ids + * @param entries - set of entries with possible duplicate Ids + * @return New set of entries with only unique Ids */ -export function removeDuplicates(entries = []) { +export function removeDuplicates(entries: Entry[] = []) { // Use only last of multiple elements with same id by turning into an object and getting the values. return Object.values( Object.fromEntries(entries.map((entry) => [entry.id, entry])) @@ -155,11 +189,11 @@ export function removeDuplicates(entries = []) { * Takes to sets of entries and returns unique entries * (keying on id) of right set not present in left set. * - * @param {Array} left - base set of entries - * @param {Array} right - new entries - * @return {Array} - right exclusion of sets set + * @param left - base set of entries + * @param right - new entries + * @return - right exclusion of sets set */ -export function exclusion(left = [], right = []) { +export function exclusion(left: Entry[] = [], right: Entry[] = []) { const rightSet = removeDuplicates(right); const leftJoinKeys = left.map(({ id }) => id); return rightSet.filter(({ id }) => !leftJoinKeys.includes(id)); @@ -168,13 +202,19 @@ export function exclusion(left = [], right = []) { /** * Calculate the last index of a group. * - * @param {Object} props Props - * @param {Array} props.elements Elements array - * @param {string} props.groupId Group id - * @return {number} Last index of group + * @param props Props + * @param props.elements Elements array + * @param props.groupId Group id + * @return Last index of group */ -export function getLastIndexOfGroup({ elements, groupId }) { - const isMember = (e) => e.groupId === groupId; +export function getLastIndexOfGroup({ + elements, + groupId, +}: { + elements: Element[]; + groupId: string; +}) { + const isMember = (e: Element) => e.groupId === groupId; const firstGroupElemenIndex = elements.findIndex(isMember); const groupSize = elements.filter(isMember).length; return firstGroupElemenIndex + groupSize - 1; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 93ac97235e50..f0cce98386d6 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -94,7 +94,7 @@ export type DeleteElementsAction = { payload: DeleteElementsProps; }; -type ElementUpdater = (prevProps: Element) => Element; +export type ElementUpdater = (prevProps: Element) => Element; export type UpdateElementsProps = { elementIds: string[] | null; properties: Partial | ElementUpdater; diff --git a/packages/story-editor/src/utils/objectWithout.js b/packages/story-editor/src/utils/objectWithout.ts similarity index 87% rename from packages/story-editor/src/utils/objectWithout.js rename to packages/story-editor/src/utils/objectWithout.ts index ac9ca0adf4d4..51f0da8879f8 100644 --- a/packages/story-editor/src/utils/objectWithout.js +++ b/packages/story-editor/src/utils/objectWithout.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -export default function objectWithout(obj, propertiesToRemove) { +export default function objectWithout( + obj: Record, + propertiesToRemove: string[] +) { return Object.keys(obj) .filter((key) => !propertiesToRemove.includes(key)) .reduce((newObj, key) => ({ ...newObj, [key]: obj[key] }), {}); From 17f543f142450b0c25706da29e9f6c2af637789a Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 21 Nov 2022 10:58:13 -0300 Subject: [PATCH 32/99] Refactor --- .../src/app/story/actions/useAutoSave.ts | 2 +- .../src/app/story/actions/useSaveStory.ts | 7 +- .../app/story/utils/getStoryPropsToSave.ts | 9 +- .../story-editor/src/types/configProvider.ts | 4 +- packages/story-editor/src/types/index.ts | 20 ++ packages/story-editor/src/types/story.ts | 179 ++++++++++++++++++ .../story-editor/src/types/storyProvider.ts | 114 +---------- 7 files changed, 211 insertions(+), 124 deletions(-) create mode 100644 packages/story-editor/src/types/index.ts create mode 100644 packages/story-editor/src/types/story.ts diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 87940b820029..01fad0d92049 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -26,7 +26,7 @@ import type { Page } from '@googleforcreators/elements'; import { useAPI } from '../../api'; import { useConfig } from '../../config'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; -import type { Story } from '../../../types/storyProvider'; +import type { Story } from '../../../types/story'; interface AutoSaveProps { storyId: number; diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index d3aeafa18ee7..c0005f5c4fb5 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -32,8 +32,7 @@ import { useConfig } from '../../config'; import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; -import type { Story } from '../../../types/storyProvider'; -import type { RESTError } from '../../../types/storyEditor'; +import type {Story, RESTError, StorySaveData} from '../../../types'; const HTTP_STATUS_DESCRIPTIONS = { 400: _x('Bad Request', 'HTTP status description', 'web-stories'), @@ -98,9 +97,9 @@ function useSaveStory({ // Saving an auto-draft should create a draft by default. status: 'auto-draft' === story.status ? 'draft' : story.status, ...props, - }) + } as StorySaveData) ) - .then((data: Story) => { + .then((data) => { const { status, slug, diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts index 16e21f0dd64f..cec0cd6cfa31 100644 --- a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts +++ b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts @@ -23,8 +23,7 @@ import type { Page } from '@googleforcreators/elements'; * Internal dependencies */ import objectPick from '../../../utils/objectPick'; -import type { Story } from '../../../types/storyProvider'; -import type { MetaData } from '../../../types/configProvider'; +import type { Story, StorySaveData, MetaData } from '../../../types'; import getAllProducts from './getAllProducts'; interface StoryPropsToSave { @@ -38,7 +37,7 @@ function getStoryPropsToSave({ pages, metadata, flags, -}: StoryPropsToSave) { +}: StoryPropsToSave): StorySaveData { const { terms, ...propsFromStory } = objectPick(story, [ 'title', 'status', @@ -58,14 +57,14 @@ function getStoryPropsToSave({ 'terms', ]); const products = getAllProducts(pages); - const content = getStoryMarkup(story, pages, metadata, flags); + const content = getStoryMarkup(story, pages, metadata, flags) as string; return { content, pages, ...propsFromStory, ...terms, products, - }; + } as StorySaveData; } export default getStoryPropsToSave; diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index 8f7994bc2f78..1f837093c004 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -34,7 +34,7 @@ import type { Template } from '@googleforcreators/templates'; /** * Internal dependencies */ -import type { RawStory, Story } from './storyProvider'; +import type {RawStory, Story, StoryReturnData, StorySaveData} from './story'; export interface Capabilities { /** If the user has permissions to upload files. */ @@ -217,7 +217,7 @@ export interface APICallbacks { search?: string; per_page?: number; }) => Promise; - saveStoryById?: (data: Story) => Promise; + saveStoryById: (data: StorySaveData) => Promise; updateCurrentUser?: (data: { mediaOptimization?: boolean; onboarding?: Record; diff --git a/packages/story-editor/src/types/index.ts b/packages/story-editor/src/types/index.ts new file mode 100644 index 000000000000..6c0195efec00 --- /dev/null +++ b/packages/story-editor/src/types/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './story'; +export * from './storyProvider'; +export * from './configProvider'; +export * from './apiProvider'; +export * from './storyEditor'; diff --git a/packages/story-editor/src/types/story.ts b/packages/story-editor/src/types/story.ts new file mode 100644 index 000000000000..e8a53604e643 --- /dev/null +++ b/packages/story-editor/src/types/story.ts @@ -0,0 +1,179 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import type { Page, ProductData, StoryData } from '@googleforcreators/elements'; +import type { Pattern } from '@googleforcreators/patterns'; +import type { AudioResource } from '@googleforcreators/media'; + +interface FeaturedMedia { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; +} +interface PublisherLogo { + id: number; + height: number; + width: number; + url: string; +} + +interface Author { + id: number; + name: string; +} +interface CurrentStyles { + colors: Pattern[]; +} +interface GlobalStyles { + colors: Pattern[]; + textStyles: Partial; +} +export interface Story { + storyId: number; + title: string; + author: Author; + date: null | string; + modified: string; + excerpt: string; + slug: string; + link: string; + extras: Record; + featuredMedia: FeaturedMedia; + permalinkConfig: null | { + prefix: string; + suffix: string; + }; + publisherLogo: PublisherLogo; + previewLink: string; + editLink: string; + password: string; + embedPostLink: string; + revisions: { + count: number; + }; + currentStoryStyles: CurrentStyles; + globalStoryStyles: GlobalStyles; + taxonomies: string[]; + terms: string[]; + status: string; + backgroundAudio?: { + resource: AudioResource; + }; + autoAdvance?: boolean; + defaultPageDuration?: number; +} + +// Data required by API callbacks for saving a story. +export interface StorySaveData + extends Pick< + Story, + | 'title' + | 'status' + | 'author' + | 'date' + | 'modified' + | 'slug' + | 'excerpt' + | 'featuredMedia' + | 'publisherLogo' + | 'password' + | 'currentStoryStyles' + | 'globalStoryStyles' + | 'autoAdvance' + | 'defaultPageDuration' + | 'backgroundAudio' + | 'terms' + > { + storyId?: number; + content: string; + products: ProductData[]; + pages: Page[]; +} + +// Data that's returned from API after saving. +export interface StoryReturnData { + slug: string; + status: string; + link: string; + previewLink: string; + editLink: string; + embedPostLink: string; + featuredMedia: FeaturedMedia; + revisions: { + count: number; + id: number; + }; +} + +// Raw story that comes to the provider from API callback. +export interface RawStory { + id: number; + date: string; + modified: string; + password: string; + slug: string; + status: string; + link: string; + title: { + raw?: string; + rendered?: string; + }; + excerpt: { + raw?: string; + rendered?: string; + protected?: boolean; + }; + permalinkTemplate: string; + storyData: StoryData; + stylePresets: { + colors?: Pattern[]; + textStyles?: Partial[]; + }; + previewLink: string; + editLink: string; + embedPostLink: string; + author: { + id: number; + name: string; + }; + capabilities: Record; + extras: Record; + featuredMedia: { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; + }; + publisherLogo: { + id: number; + height: number; + width: number; + url: string; + }; + taxonomies: string[]; + revisions: { + count: number; + }; + terms: string[]; +} diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index f0cce98386d6..889df64f26f7 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -22,14 +22,13 @@ import type { Element, Animation, Group, - StoryData, } from '@googleforcreators/elements'; -import type { AudioResource, ResourceId } from '@googleforcreators/media'; -import type { Pattern } from '@googleforcreators/patterns'; +import type { ResourceId } from '@googleforcreators/media'; /** * Internal dependencies */ import type * as actionTypes from '../app/story/useStoryReducer/types'; +import type { Story } from './story'; export type AddPageProps = { page: Page; @@ -357,115 +356,6 @@ export interface ReducerProviderState { api: ExternalActions; } -export interface Story { - storyId: number; - title: string; - author: { - id: number; - name: string; - }; - date: null | string; - modified: string; - excerpt: string; - slug: string; - link: string; - extras: Record; - featuredMedia: { - id: number; - height: number; - width: number; - url: string; - needsProxy: boolean; - isExternal: boolean; - }; - permalinkConfig: null | { - prefix: string; - suffix: string; - }; - publisherLogo: { - id: number; - height: number; - width: number; - url: string; - }; - previewLink: string; - editLink: string; - password: string; - embedPostLink: string; - revisions: { - count: number; - }; - currentStoryStyles: { - colors: Pattern[]; - }; - globalStoryStyles: { - colors: Pattern[]; - textStyles: Partial; - }; - taxonomies: string[]; - terms: string[]; - status: string; - backgroundAudio?: { - resource: AudioResource; - }; - autoAdvance?: boolean; - defaultPageDuration?: number; -} - -// Raw story that comes to the provider from API callback. -export interface RawStory { - id: number; - date: string; - modified: string; - password: string; - slug: string; - status: string; - link: string; - title: { - raw?: string; - rendered?: string; - }; - excerpt: { - raw?: string; - rendered?: string; - protected?: boolean; - }; - permalinkTemplate: string; - storyData: StoryData; - stylePresets: { - colors?: Pattern[]; - textStyles?: Partial[]; - }; - previewLink: string; - editLink: string; - embedPostLink: string; - author: { - id: number; - name: string; - }; - capabilities: Record; - extras: Record; - featuredMedia: { - id: number; - height: number; - width: number; - url: string; - needsProxy: boolean; - isExternal: boolean; - }; - publisherLogo: { - id: number; - height: number; - width: number; - url: string; - }; - taxonomies: string[]; - revisions: { - count: number; - }; - terms: string[]; -} - export interface ReducerState { story: Story | null; selection?: string[]; From abcaf477b71866d034d78b4f00fcc56227b9cab1 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 21 Nov 2022 11:17:35 -0300 Subject: [PATCH 33/99] Update --- packages/story-editor/src/app/api/context.ts | 2 +- .../story-editor/src/app/story/actions/useAutoSave.ts | 4 ++-- .../story-editor/src/app/story/actions/useSaveStory.ts | 2 +- .../story-editor/src/app/story/effects/useLoadStory.ts | 10 +++------- packages/story-editor/src/app/story/storyProvider.tsx | 2 +- packages/story-editor/src/types/configProvider.ts | 4 ++-- packages/story-editor/src/types/storyProvider.ts | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/story-editor/src/app/api/context.ts b/packages/story-editor/src/app/api/context.ts index 5b441b906e50..3023906fc245 100644 --- a/packages/story-editor/src/app/api/context.ts +++ b/packages/story-editor/src/app/api/context.ts @@ -22,6 +22,6 @@ import { createContext } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { APIState } from '../../types/apiProvider'; +import type { APIState } from '../../types'; export default createContext({ actions: {} }); diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 01fad0d92049..c0e62c2b5055 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -26,7 +26,7 @@ import type { Page } from '@googleforcreators/elements'; import { useAPI } from '../../api'; import { useConfig } from '../../config'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; -import type { Story } from '../../../types/story'; +import type { Story, StorySaveData } from '../../../types'; interface AutoSaveProps { storyId: number; @@ -55,7 +55,7 @@ function useAutoSave({ storyId, pages, story }: AutoSaveProps) { flags, }), ...props, - }).finally(() => setIsAutoSaving(false)); + } as StorySaveData).finally(() => setIsAutoSaving(false)); }, [story, pages, metadata, autoSaveById, storyId, flags] ); diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index c0005f5c4fb5..a3c8e1368839 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -32,7 +32,7 @@ import { useConfig } from '../../config'; import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; -import type {Story, RESTError, StorySaveData} from '../../../types'; +import type { Story, RESTError, StorySaveData } from '../../../types'; const HTTP_STATUS_DESCRIPTIONS = { 400: _x('Bad Request', 'HTTP status description', 'web-stories'), diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index af1529e30321..58065503aabf 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -29,11 +29,7 @@ import { useAPI } from '../../api'; import { useHistory } from '../../history'; import getUniquePresets from '../../../utils/getUniquePresets'; import { useConfig } from '../../config'; -import type { - RawStory, - RestoreProps, - State, -} from '../../../types/storyProvider'; +import type { RawStory, RestoreProps, State } from '../../../types'; function loadStory( storyId: number, @@ -136,7 +132,7 @@ function loadStory( currentStoryStyles: { colors: storyData?.currentStoryStyles?.colors ? (getUniquePresets( - storyData.currentStoryStyles.colors as Pattern + storyData.currentStoryStyles.colors as Pattern[] ) as Pattern[]) : [], }, @@ -186,7 +182,7 @@ function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { if (story) { loadStory(storyId, story, restore, clearHistory, globalConfig); } else { - getStoryById(storyId).then((post: RawStory) => { + void getStoryById(storyId).then((post: RawStory) => { loadStory(storyId, post, restore, clearHistory, globalConfig); }); } diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index aa7daa569f2e..5f27f90cc122 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -25,7 +25,7 @@ import type { Animation, Page } from '@googleforcreators/elements'; * Internal dependencies */ import { STABLE_ARRAY } from '../../constants'; -import type { RawStory } from '../../types/storyProvider'; +import type { RawStory } from '../../types'; import Context from './context'; import useLoadStory from './effects/useLoadStory'; diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index 1f837093c004..3a20911e78d6 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -175,7 +175,7 @@ export type Taxonomy = { export interface APICallbacks { addPageTemplate?: (data: TemplateData) => Promise; - autoSaveById?: (story: Story) => Promise; + autoSaveById?: (story: StorySaveData) => Promise; createTaxonomyTerm?: ( endpoint: string, term: { @@ -217,7 +217,7 @@ export interface APICallbacks { search?: string; per_page?: number; }) => Promise; - saveStoryById: (data: StorySaveData) => Promise; + saveStoryById?: (data: StorySaveData) => Promise; updateCurrentUser?: (data: { mediaOptimization?: boolean; onboarding?: Record; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 889df64f26f7..7f3501e21d2a 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -359,7 +359,7 @@ export interface ReducerProviderState { export interface ReducerState { story: Story | null; selection?: string[]; - current?: string | null; + current: string | null; pages: Page[]; animationState: string; capabilities: Record; From e5c2f8d0c972b9e53e2623b6abbf687a39a20fda Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 21 Nov 2022 11:19:58 -0300 Subject: [PATCH 34/99] Move types. --- .../story-editor/src/types/apiProvider.ts | 154 +++++++++++++++++- .../story-editor/src/types/configProvider.ts | 150 +---------------- 2 files changed, 155 insertions(+), 149 deletions(-) diff --git a/packages/story-editor/src/types/apiProvider.ts b/packages/story-editor/src/types/apiProvider.ts index 45daf98768fa..5ef87db7c6c5 100644 --- a/packages/story-editor/src/types/apiProvider.ts +++ b/packages/story-editor/src/types/apiProvider.ts @@ -13,10 +13,162 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +/** + * External dependencies + */ +import type { + FontData, + MediaElement, + ProductData, +} from '@googleforcreators/elements'; +import type { + Resource, + ResourceId, + TrimData, + VideoResource, +} from '@googleforcreators/media'; +import type { Template } from '@googleforcreators/templates'; + /** * Internal dependencies */ -import type { APICallbacks } from './configProvider'; +import type { RawStory, StoryReturnData, StorySaveData } from './story'; +import type { PageTemplate, Taxonomy } from './configProvider'; + +interface TemplateData { + story_data: PageTemplate; + featured_media: number; + title?: string; +} + +type Term = { + id: number; + name: string; + slug: string; + taxonomy: string; +}; + +type Author = { + id: number; + name: string; + url?: string; + description?: string; + slug: string; + link: string; + avatarUrls?: Record; +}; + +type User = { + id: number; + mediaOptimization: boolean; + onboarding: Record; + trackingOptin: boolean; +}; + +type GetFontProps = { + service?: string; + include?: string; + search?: string; +}; + +type HotlinkInfo = { + ext?: string; + fileName?: string; + fileSize?: number; + mimeType?: string; + type?: string; + width?: number; + height?: number; +}; + +type LinkMetaData = { + title: string; + image: string; +}; + +type UploadMediaProps = { + onUploadSuccess?: (media: MediaElement) => void; + onUploadProgress?: (media: MediaElement) => void; + onUploadError?: (media: MediaElement) => void; + cropVideo?: boolean; + additionalData: { + originalId?: number; + mediaId?: number; + storyId?: number; + templateId?: number; + optimizedId?: number; + cropOriginId?: number; + mutedId?: number; + posterId?: number; + isMuted?: boolean; + mediaSource?: string; + trimData?: TrimData; + baseColor?: string; + blurHash?: string; + isGif?: boolean; + altText?: string; + }; + originalResourceId: ResourceId; + resource: Resource; +}; +export interface APICallbacks { + addPageTemplate?: (data: TemplateData) => Promise; + autoSaveById?: (story: StorySaveData) => Promise; + createTaxonomyTerm?: ( + endpoint: string, + term: { + name: string; + parent?: number; + slug?: string; + } + ) => Promise; + deleteMedia?: (id: number) => Promise; + deletePageTemplate?: (id: number) => Promise; + getAuthors?: () => Promise; + getCurrentUser?: () => Promise; + getCustomPageTemplates?: (page: number | boolean) => Promise<{ + hasMore: boolean; + templates: PageTemplate[]; + }>; + getFonts?: (props: GetFontProps) => Promise; + getHotlinkInfo?: (link: string) => Promise; + getLinkMetadata?: (link: string) => Promise; + getMedia?: (props: { + mediaType: string; + searchTerm: string; + pagingNum: number; + }) => Promise<{ + data: Resource[]; + headers: Record; + }>; + getMediaById?: (id: number) => Promise; + getMediaForCorsCheck?: () => Promise; + getMutedMediaById?: (id: number) => Promise; + getOptimizedMediaById?: (id: number) => Promise; + getPageTemplates?: () => Promise; + getPosterMediaById?: (id: number) => Promise; + getProducts?: () => Promise; + getProxyUrl?: (src: string) => string; + getStoryById?: (id: number) => Promise; + getTaxonomies?: () => Promise; + getTaxonomyTerm?: (props: { + search?: string; + per_page?: number; + }) => Promise; + saveStoryById?: (data: StorySaveData) => Promise; + updateCurrentUser?: (data: { + mediaOptimization?: boolean; + onboarding?: Record; + trackingOptin?: boolean; + }) => Promise; + updateMedia?: (id: number, data: Partial) => Promise; + updatePageTemplate?: ( + id: number, + data: Partial + ) => Promise; + uploadMedia?: (files: string[], props: UploadMediaProps) => Promise; +} export interface APIState { actions: APICallbacks; diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index 3a20911e78d6..09b277537619 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -17,24 +17,12 @@ /** * External dependencies */ -import type { - MediaElement, - Page, - FontData, - ProductData, -} from '@googleforcreators/elements'; -import type { - Resource, - ResourceId, - TrimData, - VideoResource, -} from '@googleforcreators/media'; -import type { Template } from '@googleforcreators/templates'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type {RawStory, Story, StoryReturnData, StorySaveData} from './story'; +import type { APICallbacks } from './apiProvider'; export interface Capabilities { /** If the user has permissions to upload files. */ @@ -81,82 +69,6 @@ export interface Tip { export interface PageTemplate extends Page { version: string; } -interface TemplateData { - story_data: PageTemplate; - featured_media: number; - title?: string; -} - -type Term = { - id: number; - name: string; - slug: string; - taxonomy: string; -}; - -type Author = { - id: number; - name: string; - url?: string; - description?: string; - slug: string; - link: string; - avatarUrls?: Record; -}; - -type User = { - id: number; - mediaOptimization: boolean; - onboarding: Record; - trackingOptin: boolean; -}; - -type GetFontProps = { - service?: string; - include?: string; - search?: string; -}; - -type HotlinkInfo = { - ext?: string; - fileName?: string; - fileSize?: number; - mimeType?: string; - type?: string; - width?: number; - height?: number; -}; - -type LinkMetaData = { - title: string; - image: string; -}; - -type UploadMediaProps = { - onUploadSuccess?: (media: MediaElement) => void; - onUploadProgress?: (media: MediaElement) => void; - onUploadError?: (media: MediaElement) => void; - cropVideo?: boolean; - additionalData: { - originalId?: number; - mediaId?: number; - storyId?: number; - templateId?: number; - optimizedId?: number; - cropOriginId?: number; - mutedId?: number; - posterId?: number; - isMuted?: boolean; - mediaSource?: string; - trimData?: TrimData; - baseColor?: string; - blurHash?: string; - isGif?: boolean; - altText?: string; - }; - originalResourceId: ResourceId; - resource: Resource; -}; export type Taxonomy = { name: string; @@ -173,64 +85,6 @@ export type Taxonomy = { restPath: string; }; -export interface APICallbacks { - addPageTemplate?: (data: TemplateData) => Promise; - autoSaveById?: (story: StorySaveData) => Promise; - createTaxonomyTerm?: ( - endpoint: string, - term: { - name: string; - parent?: number; - slug?: string; - } - ) => Promise; - deleteMedia?: (id: number) => Promise; - deletePageTemplate?: (id: number) => Promise; - getAuthors?: () => Promise; - getCurrentUser?: () => Promise; - getCustomPageTemplates?: (page: number | boolean) => Promise<{ - hasMore: boolean; - templates: PageTemplate[]; - }>; - getFonts?: (props: GetFontProps) => Promise; - getHotlinkInfo?: (link: string) => Promise; - getLinkMetadata?: (link: string) => Promise; - getMedia?: (props: { - mediaType: string; - searchTerm: string; - pagingNum: number; - }) => Promise<{ - data: Resource[]; - headers: Record; - }>; - getMediaById?: (id: number) => Promise; - getMediaForCorsCheck?: () => Promise; - getMutedMediaById?: (id: number) => Promise; - getOptimizedMediaById?: (id: number) => Promise; - getPageTemplates?: () => Promise; - getPosterMediaById?: (id: number) => Promise; - getProducts?: () => Promise; - getProxyUrl?: (src: string) => string; - getStoryById?: (id: number) => Promise; - getTaxonomies?: () => Promise; - getTaxonomyTerm?: (props: { - search?: string; - per_page?: number; - }) => Promise; - saveStoryById?: (data: StorySaveData) => Promise; - updateCurrentUser?: (data: { - mediaOptimization?: boolean; - onboarding?: Record; - trackingOptin?: boolean; - }) => Promise; - updateMedia?: (id: number, data: Partial) => Promise; - updatePageTemplate?: ( - id: number, - data: Partial - ) => Promise; - uploadMedia?: (files: string[], props: UploadMediaProps) => Promise; -} - export interface ConfigState { /** Interval in seconds. */ autoSaveInterval: number | null; From 0b565be8b477ac371664d15ff22f87d34d4de21d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 21 Nov 2022 12:56:45 -0300 Subject: [PATCH 35/99] Update actions --- packages/elements/src/types/element.ts | 9 +++ packages/elements/src/utils/elementIs.ts | 56 +++++++++++++++++++ packages/elements/src/utils/index.ts | 1 + .../src/app/story/actions/useSaveStory.ts | 4 +- .../useStoryReducer/reducers/addAnimations.ts | 8 +-- .../useStoryReducer/reducers/addElements.ts | 21 ++++--- .../reducers/addElementsAcrossPages.ts | 2 +- .../useStoryReducer/reducers/addGroup.ts | 5 +- .../story/useStoryReducer/reducers/addPage.ts | 2 +- .../reducers/arrangeElement.ts | 14 ++--- .../useStoryReducer/reducers/arrangeGroup.ts | 14 +++-- .../useStoryReducer/reducers/arrangePage.ts | 5 +- .../reducers/combineElements.ts | 24 +++++--- .../reducers/copySelectedElement.ts | 15 ++++- .../reducers/deleteElements.ts | 21 ++++--- .../reducers/deleteElementsByResourceId.ts | 27 ++++++--- .../useStoryReducer/reducers/deleteGroup.ts | 47 +++++++++------- .../useStoryReducer/reducers/deletePage.ts | 7 ++- .../reducers/duplicateElementsById.ts | 16 +++++- .../reducers/duplicateGroup.ts | 15 +++-- .../reducers/removeElementFromGroup.ts | 12 ++-- .../story/useStoryReducer/reducers/restore.ts | 2 +- .../useStoryReducer/reducers/selectElement.ts | 20 ++++--- .../reducers/setBackgroundElement.ts | 33 ++++++++--- .../reducers/setCurrentPage.ts | 2 +- .../reducers/setSelectedElements.ts | 24 +++++--- .../useStoryReducer/reducers/toggleElement.ts | 26 +++++---- .../useStoryReducer/reducers/toggleLayer.ts | 6 +- .../reducers/unselectElement.ts | 2 +- .../reducers/updateElements.ts | 5 +- .../reducers/updateElementsByFontFamily.ts | 7 ++- .../reducers/updateElementsByResourceId.ts | 7 ++- .../useStoryReducer/reducers/updateGroup.ts | 8 ++- .../useStoryReducer/reducers/updatePage.ts | 2 +- .../useStoryReducer/reducers/updateStory.ts | 7 ++- .../story/useStoryReducer/reducers/utils.ts | 6 +- .../story-editor/src/types/storyProvider.ts | 8 ++- 37 files changed, 332 insertions(+), 158 deletions(-) create mode 100644 packages/elements/src/utils/elementIs.ts diff --git a/packages/elements/src/types/element.ts b/packages/elements/src/types/element.ts index ac7573e115f1..3e6affc44228 100644 --- a/packages/elements/src/types/element.ts +++ b/packages/elements/src/types/element.ts @@ -112,3 +112,12 @@ export interface ProductElement extends Element { type: ElementType.Product; product: ProductData; } + +export interface TextElement extends Element { + content: string; + font: { + service: string; + family: string; + fallbacks: string[]; + }; +} diff --git a/packages/elements/src/utils/elementIs.ts b/packages/elements/src/utils/elementIs.ts new file mode 100644 index 000000000000..10921a2f75f7 --- /dev/null +++ b/packages/elements/src/utils/elementIs.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Internal dependencies + */ +import type { + BackgroundableElement, + DefaultBackgroundElement, + Element, + MediaElement, + TextElement, + ProductElement, +} from '../types'; + +function isMediaElement(e: Element): e is MediaElement { + return 'resource' in e; +} + +function isTextElement(e: Element): e is TextElement { + return 'font' in e; +} + +function isDefaultBackgroundElement(e: Element): e is DefaultBackgroundElement { + return 'isDefaultBackground' in e; +} + +function isBackgroundable(e: Element): e is BackgroundableElement { + return 'isBackground' in e; +} + +function isProduct(e: Element): e is ProductElement { + return 'product' in e; +} + +const elementIs = { + media: isMediaElement, + text: isTextElement, + defaultBackground: isDefaultBackgroundElement, + backgroundable: isBackgroundable, + product: isProduct, +}; + +export default elementIs; diff --git a/packages/elements/src/utils/index.ts b/packages/elements/src/utils/index.ts index 613c655c325d..a426f6b72b65 100644 --- a/packages/elements/src/utils/index.ts +++ b/packages/elements/src/utils/index.ts @@ -23,3 +23,4 @@ export { default as getLayerName } from './getLayerName'; export { default as duplicateElement } from './duplicateElement'; export * from './getElementOffsets'; export { default as getElementOrigin } from './getElementOrigin'; +export { default as elementIs } from './elementIs'; diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index a3c8e1368839..6e497e1b7d17 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -32,7 +32,7 @@ import { useConfig } from '../../config'; import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; -import type { Story, RESTError, StorySaveData } from '../../../types'; +import type {Story, RESTError, StorySaveData, UpdateStoryProps, State} from '../../../types'; const HTTP_STATUS_DESCRIPTIONS = { 400: _x('Bad Request', 'HTTP status description', 'web-stories'), @@ -45,7 +45,7 @@ interface UseSaveStoryProps { storyId: number; pages: Page[]; story: Story; - updateStory: (data: { properties: Partial }) => Story; + updateStory: (props: UpdateStoryProps) => State; } /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index 01004d15c9ae..32fb881d13f3 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -18,14 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Animation } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { - AddAnimationsProps, - ReducerState, -} from '../../../../types/storyProvider'; +import type { AddAnimationsProps, ReducerState } from '../../../../types'; import { exclusion } from './utils'; /** @@ -57,7 +55,7 @@ export const addAnimations = ( page.animations = []; } page.animations = page.animations.concat( - exclusion(page.animations, animations) + exclusion(page.animations, animations) as Animation[] ); }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index 2503b90a73ce..e75b5b7829c9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -17,21 +17,18 @@ /** * External dependencies */ -import { ELEMENT_TYPES } from '@googleforcreators/elements'; +import { Element, elementIs, ElementType } from '@googleforcreators/elements'; import { produce } from 'immer'; /** * Internal dependencies */ import { MAX_PRODUCTS_PER_PAGE } from '../../../../constants'; +import type { AddElementsProps, ReducerState } from '../../../../types'; import { exclusion } from './utils'; -import type {ReducerState} from "@googleforcreators/types"; -import type {AddElementsProps} from "../../../../types/storyProvider"; -const isProduct = ({ type }: { type: string }) => - type === ELEMENT_TYPES.PRODUCT; -const isNotProduct = ({ type }: { type: string }) => - type !== ELEMENT_TYPES.PRODUCT; +const isProduct = ({ type }: Element) => type === ElementType.Product; +const isNotProduct = ({ type }: Element) => type !== ElementType.Product; /** * Add elements to current page. @@ -50,7 +47,6 @@ export const addElements = ( draft: ReducerState, { elements, pageId, updateSelection = true }: AddElementsProps ) => { - console.log(draft); if (!Array.isArray(elements)) { return; } @@ -58,8 +54,11 @@ export const addElements = ( const page = draft.pages.find(({ id }) => pageId ? id === pageId : id === draft.current ); + if (!page) { + return; + } - const newElements = exclusion(page.elements, elements); + const newElements = exclusion(page.elements, elements) as Element[]; if (newElements.length === 0) { return; @@ -80,10 +79,10 @@ export const addElements = ( if (newProducts.length) { const currentProducts = page.elements .filter(isProduct) - .map(({ product }) => product?.productId); + .map((e) => elementIs.product(e) && e.product?.productId); const uniqueProducts = newProducts.filter( - ({ product }) => !currentProducts.includes(product?.productId) + (e) => elementIs.product(e) && !currentProducts.includes(e.product?.productId) ); // Then, if the number of products after adding these would still be within diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts index ba5ab5452819..b2dcbe248f21 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts @@ -26,7 +26,7 @@ import { produce } from 'immer'; import type { AddElementsAcrossPagesProps, ReducerState, -} from '../../../../types/storyProvider'; +} from '../../../../types'; import { addPage } from './addPage'; import { addElements } from './addElements'; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts index fb29c954cf0a..6c7767024efa 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddGroupProps, ReducerState } from '../../../../types/storyProvider'; +import type { AddGroupProps, ReducerState } from '../../../../types'; /** * Add a group to the current page groups list (id, name). @@ -36,6 +36,9 @@ export const addGroup = ( } const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } if (!page.groups) { page.groups = {}; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index 9423ee433d38..553fd3f3d54c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddPageProps, ReducerState } from '../../../../types/storyProvider'; +import type { AddPageProps, ReducerState } from '../../../../types'; import { isInsideRange } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 521a2d0b1374..9c59620b34e9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -18,13 +18,13 @@ * External dependencies */ import { produce } from 'immer'; +import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { ArrangeElementProps, ReducerState } from '../../../../types'; import { getAbsolutePosition, moveArrayElement } from './utils'; -import type {ReducerState} from "@googleforcreators/types"; -import type {ArrangeElementProps} from "../../../../types/storyProvider"; /** * Move element in element order on the current page (optionally handle group id when moved in the Layers Panel). @@ -69,7 +69,7 @@ export const arrangeElement = ( const page = draft.pages.find(({ id }) => id === draft.current); // Abort if there's less than three elements (nothing to rearrange as first is bg) - if (page.elements.length < 3) { + if (!page || page.elements.length < 3) { return; } @@ -100,10 +100,10 @@ export const arrangeElement = ( // Update group id on current element if (groupId) { // Can only change groups to a group that exists - if (!page.groups[groupId]) { + if (!page.groups?.[groupId as string]) { return; } - page.elements[currentPosition].groupId = groupId; + page.elements[currentPosition].groupId = groupId as string; } else if (groupId === undefined || groupId === null) { delete page.elements[currentPosition].groupId; } @@ -113,13 +113,13 @@ export const arrangeElement = ( const groupHasElements = page.elements.some( (e) => e.groupId === currentGroupId ); - if (!groupHasElements) { + if (!groupHasElements && page.groups) { delete page.groups[currentGroupId]; } } // Then reorder if relevant - page.elements = moveArrayElement(page.elements, currentPosition, newPosition); + page.elements = moveArrayElement(page.elements, currentPosition, newPosition) as Element[]; }; export default produce(arrangeElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index 702a038b5d15..ca971576ccff 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -18,13 +18,13 @@ * External dependencies */ import { produce } from 'immer'; +import { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { ArrangeGroupProps, ReducerState } from '../../../../types'; import { getAbsolutePosition } from './utils'; -import type {ReducerState} from "@googleforcreators/types"; -import type {ArrangeGroupProps} from "../../../../types/storyProvider"; /** * Move group to a new position @@ -37,10 +37,12 @@ export const arrangeGroup = ( return; } - const { elements, groups } = draft.pages.find( - ({ id }) => id === draft.current - ); - const isInGroup = (el) => el.groupId === groupId; + const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } + const { elements, groups } = page; + const isInGroup = (el: Element) => el.groupId === groupId; // If group doesn't exist or doesn't have any elements, abort if (!groups?.[groupId] || !elements.some(isInGroup)) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index b8635722dfa8..6028aa37ccb3 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -18,11 +18,12 @@ * External dependencies */ import { produce } from 'immer'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { ArrangePageProps, ReducerState } from '../../../../types/storyProvider'; +import type { ArrangePageProps, ReducerState } from '../../../../types'; import { isInsideRange, moveArrayElement } from './utils'; /** @@ -57,7 +58,7 @@ export const arrangePage = ( return; } - draft.pages = moveArrayElement(draft.pages, pageIndex, position); + draft.pages = moveArrayElement(draft.pages, pageIndex, position) as Page[]; }; export default produce(arrangePage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 255bf72525f3..2e5abc456df8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -21,15 +21,16 @@ import { v4 as uuidv4 } from 'uuid'; import { canSupportMultiBorder } from '@googleforcreators/masks'; import { DEFAULT_ATTRIBUTES_FOR_MEDIA } from '@googleforcreators/element-library'; import { produce } from 'immer'; +import type { Element } from '@googleforcreators/elements'; +import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies */ import objectPick from '../../../../utils/objectPick'; import objectWithout from '../../../../utils/objectWithout'; +import type { CombineElementsProps, ReducerState } from '../../../../types'; import { removeAnimationsWithElementIds } from './utils'; -import type {CombineElementsProps} from "../../../../types/storyProvider"; -import type {ReducerState} from "@googleforcreators/types"; /** * Combine elements by taking properties from a first item and @@ -64,17 +65,23 @@ export const combineElements = ( const element = firstElement; const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } const secondElementPosition = page.elements.findIndex( ({ id }) => id === secondId ); const secondElement = page.elements[secondElementPosition]; - if (!element || !element.resource || !secondElement) { + if (!elementIs.media(element) || !secondElement) { return; } - if (secondElement.isDefaultBackground) { + if ( + elementIs.defaultBackground(secondElement) && + secondElement.isDefaultBackground + ) { page.defaultBackgroundElement = { ...secondElement, // But generate a new ID for this temp background element @@ -94,7 +101,10 @@ export const combineElements = ( ]; // If the element we're dropping into is not background, maintain link and border. - if (!secondElement.isBackground) { + if ( + !('isBackground' in secondElement) || + (elementIs.backgroundable(secondElement) && !secondElement.isBackground) + ) { propsFromFirst.push('link'); propsFromFirst.push('border'); if (canSupportMultiBorder(secondElement)) { @@ -107,14 +117,14 @@ export const combineElements = ( propsFromFirst.push('flip', 'overlay', 'width', 'height', 'x', 'y'); } - const newElement = { + const newElement: Element = { // First copy everything from existing element except if it was default background ...objectWithout(secondElement, ['isDefaultBackground']), // Then set sensible default attributes ...DEFAULT_ATTRIBUTES_FOR_MEDIA, // Then copy all relevant attributes from new element ...objectPick(element, propsFromFirst), - }; + } as Element; // Elements are now page.elements = page.elements diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts index b83a090d2f1a..b7b2ff036396 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import objectPick from '../../../../utils/objectPick'; -import type { ReducerState } from '../../../../types/storyProvider'; +import type { ReducerState } from '../../../../types'; export const ATTRIBUTES_TO_COPY = [ 'background', @@ -55,7 +55,13 @@ export const copySelectedElement = (draft: ReducerState) => { } const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } const element = page.elements.find(({ id }) => id === draft.selection[0]); + if (!element) { + return; + } // find related animations const elementAnimations = (page.animations || []).filter(({ targets }) => @@ -63,9 +69,12 @@ export const copySelectedElement = (draft: ReducerState) => { ); // omit properties that must not be copied - const copiedStyles = objectPick(element, ATTRIBUTES_TO_COPY); + const copiedStyles = objectPick( + element, + ATTRIBUTES_TO_COPY + ) as Partial; - draft.copiedElementReducerState = { + draft.copiedElementState = { animations: elementAnimations, styles: copiedStyles, type: element.type, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts index 4381debe740b..5cef86a2ff28 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts @@ -18,13 +18,13 @@ * External dependencies */ import { produce } from 'immer'; +import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { DeleteElementsProps, ReducerState } from '../../../../types'; import { intersect } from './utils'; -import type {DeleteElementsProps} from "../../../../types/storyProvider"; -import type {ReducerState} from "@googleforcreators/types"; /** * Delete elements by the given list of ids. @@ -43,10 +43,6 @@ import type {ReducerState} from "@googleforcreators/types"; * Otherwise selection is unchanged. * * Current page is unchanged. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {Array.} payload.elementIds List of ids of elements to delete. */ export const deleteElements = ( draft: ReducerState, @@ -59,13 +55,18 @@ export const deleteElements = ( } const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } const pageElementIds = page.elements.map(({ id }) => id); const backgroundElement = page.elements[0]; const isDeletingBackground = idsToDelete.some( (id) => id === backgroundElement.id ); - const backgroundIsDefault = backgroundElement.isDefaultBackground; + const backgroundIsDefault = + elementIs.defaultBackground(backgroundElement) && + backgroundElement.isDefaultBackground; const validDeletionIds = isDeletingBackground && backgroundIsDefault @@ -84,7 +85,11 @@ export const deleteElements = ( ); // Restore default background if non-default bg has been deleted. - if (isDeletingBackground && !backgroundIsDefault) { + if ( + isDeletingBackground && + !backgroundIsDefault && + page.defaultBackgroundElement + ) { page.elements.unshift(page.defaultBackgroundElement); } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index 613fba19b56d..808ea1065293 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -18,8 +18,15 @@ * External dependencies */ import { produce } from 'immer'; -import type {ReducerState} from "@googleforcreators/types"; -import type {DeleteElementsByResourceIdProps} from "../../../../types/storyProvider"; +import { elementIs } from '@googleforcreators/elements'; + +/** + * Internal dependencies + */ +import type { + DeleteElementsByResourceIdProps, + ReducerState, +} from '../../../../types'; /** * Delete elements by the given resource id. @@ -39,30 +46,32 @@ export const deleteElementsByResourceId = ( } const hasElementWithResourceId = draft.pages.some((page) => - page.elements.some((element) => element.resource?.id === id) + page.elements.some( + (element) => elementIs.media(element) && element.resource?.id === id + ) ); if (!hasElementWithResourceId) { return; } - const idsToDelete = []; + const idsToDelete: string[] = []; draft.pages.forEach((page) => { const { elements, animations } = page; - const isDeletingBackground = elements[0].resource?.id === id; + const isDeletingBackground = + elementIs.media(elements[0]) && elements[0].resource?.id === id; page.elements = elements.filter((element) => { - const { id: elementId, resource } = element; - if (resource?.id === id) { - idsToDelete.push(elementId); + if (elementIs.media(element) && element.resource?.id === id) { + idsToDelete.push(element.id); return false; } return true; }); - if (isDeletingBackground) { + if (isDeletingBackground && page.defaultBackgroundElement) { page.elements.unshift(page.defaultBackgroundElement); } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts index 91a5754f7e27..d9a65c5c8e42 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts @@ -22,35 +22,40 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeleteGroupProps, ReducerState } from '../../../../types/storyProvider'; +import type { DeleteGroupProps, ReducerState } from '../../../../types'; import { deleteElements } from './deleteElements'; /** * Delete group by id. */ const deleteGroup = produce( - (draft: ReducerState, { groupId, includeElements = false }: DeleteGroupProps) => { - const { elements, groups } = draft.pages.find( - ({ id }) => id === draft.current - ); - if (!groupId || !groups?.[groupId]) { - return; - } + ( + draft: ReducerState, + { groupId, includeElements = false }: DeleteGroupProps + ) => { + const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } + const { elements, groups } = page; + if (!groupId || !groups?.[groupId]) { + return; + } - // Delete the group object completely - delete groups[groupId]; + // Delete the group object completely + delete groups[groupId]; - // If includeElements is true, remove elements as well - // Otherwise just unset groupId on elements - const groupElements = elements.filter((el) => el.groupId === groupId); - if (includeElements) { - const elementIds = groupElements.map(({ id }) => id); - deleteElements(draft, { elementIds }); - } else { - groupElements.forEach((el) => { - delete el.groupId; - }); - } + // If includeElements is true, remove elements as well + // Otherwise just unset groupId on elements + const groupElements = elements.filter((el) => el.groupId === groupId); + if (includeElements) { + const elementIds = groupElements.map(({ id }) => id); + deleteElements(draft, { elementIds }); + } else { + groupElements.forEach((el) => { + delete el.groupId; + }); + } }); export default deleteGroup; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index fdd8dda3494d..f4cd9d5ecc20 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeletePageProps, ReducerState } from '../../../../types/storyProvider'; +import type { DeletePageProps, ReducerState } from '../../../../types'; /** * Delete page by id or delete current page if no id given. @@ -36,7 +36,10 @@ import type { DeletePageProps, ReducerState } from '../../../../types/storyProvi * * If a page is deleted, selection is cleared. */ -export const deletePage = (draft: ReducerState, { pageId }: DeletePageProps) => { +export const deletePage = ( + draft: ReducerState, + { pageId }: DeletePageProps +) => { if (draft.pages.length <= 1) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index 30452f706783..efb9acfeca72 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -17,13 +17,17 @@ /** * External dependencies */ -import { duplicateElement, ELEMENT_TYPES } from '@googleforcreators/elements'; +import { + duplicateElement, + ELEMENT_TYPES, + elementIs, +} from '@googleforcreators/elements'; import { produce } from 'immer'; /** * Internal dependencies */ -import type { DuplicateElementsByIdProps, ReducerState } from '../../../../types/storyProvider'; +import type { DuplicateElementsByIdProps, ReducerState } from '../../../../types'; /** * Duplicate all elements specified by `elementIds` on the current page. @@ -40,6 +44,9 @@ export const duplicateElementsById = ( } const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } let hasDeletedSomething = false; elementIds.forEach((elementId) => { @@ -51,7 +58,10 @@ export const duplicateElementsById = ( const elementToDuplicate = page.elements[elementIndex]; - if (elementToDuplicate.isBackground) { + if ( + elementIs.backgroundable(elementToDuplicate) && + elementToDuplicate.isBackground + ) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index 744fb6d61daa..cef04bb9d4b7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -18,13 +18,14 @@ * External dependencies */ import { produce } from 'immer'; -import { duplicateElement } from '@googleforcreators/elements'; +import { duplicateElement, elementIs } from '@googleforcreators/elements'; +import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { DuplicateGroupProps, ReducerState } from '../../../../types'; import { addGroup } from './addGroup'; -import type {DuplicateGroupProps, ReducerState} from "../../../../types/storyProvider"; /** * Duplicate group with all elements on the current page. @@ -40,19 +41,23 @@ export const duplicateGroup = ( // Check that old group exists const page = draft.pages.find(({ id }) => id === draft.current); - if (!page.groups?.[oldGroupId]) { + if (!page?.groups?.[oldGroupId]) { return; } // Check that old group has members - const isInGroup = (el) => el.groupId === oldGroupId; + const isInGroup = (el: Element) => el.groupId === oldGroupId; const members = page.elements.filter(isInGroup); if (!members.length) { return; } // Check that old group doesn't include background - if (members.some(({ isBackground }) => isBackground)) { + if ( + members.some( + (element) => elementIs.backgroundable(element) && element.isBackground + ) + ) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts index ed93510c4abb..676157f62e64 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts @@ -25,26 +25,24 @@ import { produce } from 'immer'; import type { RemoveElementFromGroupProps, ReducerState, -} from '../../../../types/storyProvider'; +} from '../../../../types'; import { arrangeElement } from './arrangeElement'; import { getLastIndexOfGroup } from './utils'; /** * Remove element from group. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {number} payload.elementId Selected element id - * @param {number} payload.groupId Selected element group id */ export const removeElementFromGroup = ( draft: ReducerState, { elementId, groupId }: RemoveElementFromGroupProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } const { elements } = page; const element = elements.find(({ id }) => id === elementId); - if (element.groupId !== groupId) { + if (!element || element.groupId !== groupId) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index fa8fe66a25c1..dd527b683782 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { RestoreProps, ReducerState } from '../../../../types/storyProvider'; +import type { RestoreProps, ReducerState } from '../../../../types'; /** * Restore internal state completely from given state. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index 4e4023bf2a1d..ceaeff6e2b65 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -18,17 +18,17 @@ * External dependencies */ import { produce } from 'immer'; -import type {SelectElementProps} from "../../../../types/storyProvider"; -import type {ReducerState} from "@googleforcreators/types"; +import { elementIs } from '@googleforcreators/elements'; + +/** + * Internal dependencies + */ +import type { SelectElementProps, ReducerState } from '../../../../types'; /** * Add the given id to the current selection. * * If no id is given or id is already in the current selection, nothing happens. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.elementId Element id to add to the current selection. */ export const selectElement = ( draft: ReducerState, @@ -39,10 +39,14 @@ export const selectElement = ( } const currentPage = draft.pages.find(({ id }) => id === draft.current); - const byId = (i) => currentPage.elements.find(({ id }) => id === i); + if (!currentPage) { + return; + } + const byId = (i: string) => currentPage.elements.find(({ id }) => id === i); const isBackgroundElement = currentPage.elements[0].id === elementId; const element = byId(elementId); - const isVideoPlaceholder = element?.resource?.isPlaceholder; + const isVideoPlaceholder = + element && elementIs.media(element) && element.resource?.isPlaceholder; const hasExistingSelection = draft.selection.length > 0; // The bg element can't be added to non-empty selection. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index 50c40df0b243..614c5f78590e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -18,13 +18,16 @@ * External dependencies */ import { produce } from 'immer'; +import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { + SetBackgroundElementProps, + ReducerState, +} from '../../../../types'; import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; -import type {ReducerState} from "@googleforcreators/types"; -import type {SetBackgroundElementProps} from "../../../../types/storyProvider"; /** * Set background element on the current page to element matching the given id. @@ -43,21 +46,31 @@ export const setBackgroundElement = ( { elementId }: SetBackgroundElementProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } const currentBackgroundElement = page.elements[0]; // If new id is null, clear background attribute and proceed if (elementId === null) { - if (currentBackgroundElement.isDefaultBackground) { + if ( + elementIs.defaultBackground(currentBackgroundElement) && + currentBackgroundElement.isDefaultBackground + ) { // Nothing to do here, we can't unset default background return; } // Unset isBackground for the element, too. page.elements.forEach((element) => { - delete element.isBackground; + if (elementIs.backgroundable(element)) { + delete element.isBackground; + } }); - page.elements.unshift(page.defaultBackgroundElement); - draft.selection = [page.defaultBackgroundElement.id]; + if (page.defaultBackgroundElement) { + page.elements.unshift(page.defaultBackgroundElement); + draft.selection = [page.defaultBackgroundElement.id]; + } } else { // Does the element even exist or is it already background const elementPosition = page.elements.findIndex( @@ -70,7 +83,9 @@ export const setBackgroundElement = ( } // If current bg is default, save it as such - const wasDefault = currentBackgroundElement.isDefaultBackground; + const wasDefault = + elementIs.defaultBackground(currentBackgroundElement) && + currentBackgroundElement.isDefaultBackground; if (wasDefault) { page.defaultBackgroundElement = currentBackgroundElement; } @@ -91,7 +106,7 @@ export const setBackgroundElement = ( page.elements = moveArrayElement(page.elements, currentPosition, 0); page.elements.forEach((element) => { // Set isBackground for the element. - if (element.id === elementId) { + if (element.id === elementId && elementIs.backgroundable(element)) { element.isBackground = true; if (Object.prototype.hasOwnProperty.call(element, 'opacity')) { element.opacity = 100; @@ -108,7 +123,7 @@ export const setBackgroundElement = ( // Remove any applied background animations // or exising element animations. const backgroundElementId = page.elements.find( - (element) => element.isBackground + (element) => elementIs.backgroundable(element) && element.isBackground ); page.animations = removeAnimationsWithElementIds(page.animations, [ elementId, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index 0908ac27cb7d..b0753160d8b4 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { SetCurrentPageProps, ReducerState } from '../../../../types/storyProvider'; +import type { SetCurrentPageProps, ReducerState } from '../../../../types'; /** * Set current page to the given id. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index 974af06bcff1..d6cbc84be5ba 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -23,9 +23,9 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ +import type { SetSelectedElementsProps, ReducerState } from '../../../../types'; import { intersect } from './utils'; -import type {ReducerState} from "@googleforcreators/types"; -import type {SetSelectedElementsProps} from "../../../../types/storyProvider"; +import {elementIs} from "@googleforcreators/elements"; /** * Set selected elements to the given list of ids. @@ -55,6 +55,9 @@ export const setSelectedElements = ( } const currentPage = draft.pages.find(({ id }) => id === draft.current); + if (!currentPage) { + return; + } let allIds = newElementIds; if (withLinked) { @@ -84,19 +87,24 @@ export const setSelectedElements = ( // If it's a non-group multi-selection, filter out the background element, // locked elements, and video placeholders. - const byId = (id) => currentPage.elements.find(({ id: i }) => i === id); + const byId = (id: string) => + currentPage.elements.find(({ id: i }) => i === id); const isMultiSelection = uniqueElementIds.length > 1; const isGroupSelection = withLinked; - const isNotBackgroundElement = (id) => currentPage.elements[0].id !== id; - const isNotLockedElement = (id) => !byId(id).isLocked; - const isNotVideoPlaceholder = (id) => !byId(id).resource?.isPlaceholder; + const isNotBackgroundElement = (id: string) => + currentPage.elements[0].id !== id; + const isLockedElement = (id: string) => byId(id)?.isLocked; + const isVideoPlaceholder = (id: string) => { + const e = byId(id); + return e && elementIs.media(e) && e.resource?.isPlaceholder; + }; const newSelection = isMultiSelection && !isGroupSelection ? uniqueElementIds.filter( (id) => isNotBackgroundElement(id) && - isNotVideoPlaceholder(id) && - isNotLockedElement(id) + !isVideoPlaceholder(id) && + !isLockedElement(id) ) : uniqueElementIds; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts index ecbb8631253a..c88836187bda 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts @@ -18,8 +18,14 @@ * External dependencies */ import { produce } from 'immer'; -import type {ReducerState} from "@googleforcreators/types"; -import type {ToggleElementInSelectionProps} from "../../../../types/storyProvider"; + +/** + * Internal dependencies + */ +import type { + ToggleElementInSelectionProps, + ReducerState, +} from '../../../../types'; /** * Toggle element id in selection. @@ -32,11 +38,6 @@ import type {ToggleElementInSelectionProps} from "../../../../types/storyProvide * element is locked, create new selection of only the new element. * * If no id is given, do nothing. - * - * @param {Object} draft Current state - * @param {Object} payload Action payload - * @param {string} payload.elementId Id to either add or remove from selection. - * @param {boolean} payload.withLinked Include elements from the group? */ export const toggleElement = ( draft: ReducerState, @@ -46,8 +47,10 @@ export const toggleElement = ( return; } - const wasSelected = draft.selection.includes(elementId); const currentPage = draft.pages.find(({ id }) => id === draft.current); + if (!currentPage) { + return; + } const backgroundElementId = currentPage.elements[0].id; const isBackgroundElement = backgroundElementId === elementId; const hasExistingSelection = draft.selection.length > 0; @@ -67,6 +70,7 @@ export const toggleElement = ( } // If it wasn't selected, we're adding the element(s) to the selection. + const wasSelected = draft.selection.includes(elementId); if (!wasSelected) { // The bg element can't be added to non-empty selection if (isBackgroundElement && hasExistingSelection) { @@ -79,15 +83,15 @@ export const toggleElement = ( // * if new selection is a locked element const selectionWasOnlyBackground = draft.selection.includes(backgroundElementId); - const getElementById = (byId) => + const getElementById = (byId: string) => currentPage.elements.find(({ id }) => id === byId); const oldElementIsLocked = draft.selection.length > 0 - ? getElementById(draft.selection[0]).isLocked + ? getElementById(draft.selection[0])?.isLocked : false; const newElement = getElementById(elementId); const resultIsOnlyNewElement = - selectionWasOnlyBackground || oldElementIsLocked || newElement.isLocked; + selectionWasOnlyBackground || oldElementIsLocked || newElement?.isLocked; // If either of those, return a selection with only the new element(s) if (resultIsOnlyNewElement) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts index 84da4d0af1ba..d7458497bb9d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts @@ -22,10 +22,9 @@ import { produce } from 'immer'; /** * Internal dependencies */ +import type { ToggleLayerProps, ReducerState } from '../../../../types'; import { toggleElement } from './toggleElement'; import { setSelectedElements } from './setSelectedElements'; -import type {ReducerState} from "@googleforcreators/types"; -import type {ToggleLayerProps} from "../../../../types/storyProvider"; export const toggleLayer = ( draft: ReducerState, @@ -50,6 +49,9 @@ export const toggleLayer = ( // select everything between this layer and the first selected layer const firstId = draft.selection[0]; const currentPage = draft.pages.find(({ id }) => id === draft.current); + if (!currentPage) { + return; + } const pageElementIds = currentPage.elements.map((el) => el.id); const firstIndex = pageElementIds.findIndex((id) => id === firstId); const clickedIndex = pageElementIds.findIndex((id) => id === elementId); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts index a356d9725f68..3b6439fefa13 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UnselectElementProps, ReducerState } from '../../../../types/storyProvider'; +import type { UnselectElementProps, ReducerState } from '../../../../types'; /** * Remove the given id from the current selection. diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index 73ba9c631660..03bea129d3af 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UpdateElementsProps, ReducerState } from '../../../../types/storyProvider'; +import type { UpdateElementsProps, ReducerState } from '../../../../types'; import { updateElementWithUpdater, updateAnimations } from './utils'; /** @@ -56,6 +56,9 @@ export const updateElements = ( const idsToUpdate = elementIds === null ? draft.selection : elementIds; const page = draft.pages.find(({ id }) => id === draft.current); + if (!page || !idsToUpdate) { + return; + } const animationLookup = {}; page.elements .filter(({ id }) => idsToUpdate.includes(id)) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts index 477b05946f42..9deef72a3aff 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts @@ -18,6 +18,7 @@ * External dependencies */ import { produce } from 'immer'; +import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies @@ -25,7 +26,7 @@ import { produce } from 'immer'; import type { ReducerState, UpdateElementsByFontFamilyProps, -} from '../../../../types/storyProvider'; +} from '../../../../types'; import { updateElementWithUpdater } from './utils'; /** @@ -51,7 +52,9 @@ export const updateElementsByFontFamily = ( draft.pages.forEach((page) => { page.elements - .filter(({ font }) => font?.family === family) + .filter( + (element) => elementIs.text(element) && element.font?.family === family + ) .forEach((element) => updateElementWithUpdater(element, propertiesOrUpdater) ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index d4126831a708..389a14aebde9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -18,6 +18,7 @@ * External dependencies */ import { produce } from 'immer'; +import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies @@ -25,7 +26,7 @@ import { produce } from 'immer'; import type { UpdateElementsByResourceIdProps, ReducerState, -} from '../../../../types/storyProvider'; +} from '../../../../types'; import { updateElementWithUpdater } from './utils'; /** @@ -51,7 +52,9 @@ export const updateElementsByResourceId = ( draft.pages.forEach((page) => { page.elements - .filter(({ resource }) => resource?.id === id) + .filter( + (element) => elementIs.media(element) && element.resource?.id === id + ) .forEach((element) => updateElementWithUpdater(element, propertiesOrUpdater) ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts index a106ee543bbb..c3bc6f644007 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts @@ -22,7 +22,7 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { ReducerState, UpdateGroupProps } from '../../../../types/storyProvider'; +import type { ReducerState, UpdateGroupProps } from '../../../../types'; /** * Update group by id. @@ -35,7 +35,11 @@ export const updateGroup = ( return; } - const { groups } = draft.pages.find(({ id }) => id === draft.current); + const page = draft.pages.find(({ id }) => id === draft.current); + if (!page) { + return; + } + const { groups } = page; // Should only update existing groups if (!groups?.[groupId]) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index 8087edb4971c..d4442033df87 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import { PAGE_RESERVED_PROPERTIES } from '../types'; -import type { UpdatePageProps, ReducerState } from '../../../../types/storyProvider'; +import type { UpdatePageProps, ReducerState } from '../../../../types'; import { objectWithout } from './utils'; /** diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index a26294be51c7..40e8c3d8e963 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -22,14 +22,17 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ -import type { UpdateStoryProps, ReducerState } from '../../../../types/storyProvider'; +import type { UpdateStoryProps, ReducerState } from '../../../../types'; /** * Update story properties. * * No validation is performed and existing values are overwritten. */ -export const updateStory = (draft: ReducerState, { properties }: UpdateStoryProps) => { +export const updateStory = ( + draft: ReducerState, + { properties }: UpdateStoryProps +) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { draft.story = properties(current(draft.story)); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index b636c9c54cc6..0d01f27f32e7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { Animation, Element } from '@googleforcreators/elements'; +import type {Animation, Element, Page} from '@googleforcreators/elements'; /** * Internal dependencies @@ -45,7 +45,7 @@ export function isInsideRange(index: number, start: number, end: number) { } export function moveArrayElement( - array: Element[], + array: Page[] | Element[], oldPosition: number, newPosition: number ) { @@ -101,7 +101,7 @@ export function getAbsolutePosition({ export function updateElementWithUpdater( element: Element, properties: Partial | ElementUpdater -) { +): null | void { const updater = typeof properties === 'function' ? properties(element) : properties; const allowedProperties: Partial | Element = objectWithout( diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 7f3501e21d2a..c192242fa70d 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -157,8 +157,9 @@ export type ArrangeGroupAction = { payload: ArrangeGroupProps; }; +type ElementIdsFunc = (props: string[]) => string[]; export type SetSelectedElementsProps = { - elementIds: string[]; + elementIds: string[] | ElementIdsFunc; withLinked?: boolean; }; export type SetSelectedElementsAction = { @@ -349,6 +350,7 @@ export type InternalActions = { }; export type ExternalActions = { addAnimations: (props: AddAnimationsProps) => State; + updateStory: (props: UpdateStoryProps) => State; }; export interface ReducerProviderState { state: ReducerState; @@ -357,8 +359,8 @@ export interface ReducerProviderState { } export interface ReducerState { - story: Story | null; - selection?: string[]; + story: Story; + selection: string[]; current: string | null; pages: Page[]; animationState: string; From d6eec2ed0ba6ac6ae749025251b9efe9760122e1 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 14:12:21 -0300 Subject: [PATCH 36/99] Add actions --- .../src/app/story/actions/useAutoSave.ts | 2 +- .../src/app/story/actions/useSaveStory.ts | 2 +- .../story-editor/src/app/story/context.ts | 2 +- .../src/app/story/useStoryReducer/reducer.ts | 5 +- .../story/useStoryReducer/reducers/restore.ts | 2 +- .../reducers/setSelectedElements.ts | 2 +- .../reducers/updateElements.ts | 2 +- .../story/useStoryReducer/reducers/utils.ts | 4 +- .../story/useStoryReducer/useStoryReducer.ts | 2 +- .../story-editor/src/types/storyProvider.ts | 71 +++++++++++++++++-- 10 files changed, 76 insertions(+), 18 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index c0e62c2b5055..1cd30eb955c3 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -44,7 +44,7 @@ function useAutoSave({ storyId, pages, story }: AutoSaveProps) { const [isAutoSaving, setIsAutoSaving] = useState(false); const autoSave = useCallback( - (props) => { + (props: Partial) => { setIsAutoSaving(true); return autoSaveById({ storyId, diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index 6e497e1b7d17..b6734786d6f2 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -73,7 +73,7 @@ function useSaveStory({ const refreshPostEditURL = useRefreshPostEditURL(storyId, editLink); const saveStory = useCallback( - (props) => { + (props: Partial) => { setIsSaving(true); const isStoryAlreadyPublished = ['publish', 'future', 'private'].includes( diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index f94c0d8ec52c..a9c28a3c9014 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -23,7 +23,7 @@ import type { Animation, Element, Page } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { StoryProviderState } from '../../types/storyProvider'; +import type { StoryProviderState } from '../../types'; export default createContext({ state: { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index d19506fea67b..91cebeab3223 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -17,10 +17,7 @@ /** * Internal dependencies */ -import type { - ReducerActionProps, - ReducerState, -} from '../../../types/storyProvider'; +import type { ReducerActionProps, ReducerState } from '../../../types'; import * as types from './types'; import * as reducers from './reducers'; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index dd527b683782..26292c1b38a0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -55,7 +55,7 @@ export const restore = ( current: newCurrent, selection: newSelection, story: newReducerState, - animationReducerState: draft.animationReducerState, + animationState: draft.animationState, capabilities: newCapabilities, copiedElementReducerState: {}, }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index d6cbc84be5ba..0184c2f38733 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -108,7 +108,7 @@ export const setSelectedElements = ( ) : uniqueElementIds; - draft.animationReducerState = STORY_ANIMATION_STATE.RESET; + draft.animationState = STORY_ANIMATION_STATE.RESET; draft.selection = newSelection; }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index 03bea129d3af..ccce9d3793f8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -49,7 +49,7 @@ export const updateElements = ( STORY_ANIMATION_STATE.PLAYING, STORY_ANIMATION_STATE.PLAYING_SELECTED, STORY_ANIMATION_STATE.SCRUBBING, - ].includes(draft.animationReducerState) + ].includes(draft.animationState) ) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 0d01f27f32e7..f7a67967a695 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type {Animation, Element, Page} from '@googleforcreators/elements'; +import type { Animation, Element, Page } from '@googleforcreators/elements'; /** * Internal dependencies @@ -25,7 +25,7 @@ import type {Animation, Element, Page} from '@googleforcreators/elements'; import { LAYER_DIRECTIONS } from '../../../../constants'; import { ELEMENT_RESERVED_PROPERTIES } from '../types'; import objectWithout from '../../../../utils/objectWithout'; -import type { ElementUpdater } from '../../../../types/storyProvider'; +import type { ElementUpdater } from '../../../../types'; export { objectWithout }; export function intersect(first: string[], ...rest: string[][]) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 8be0c238b70e..818e741c705a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -28,7 +28,7 @@ import type { InternalActions, ReducerState, ReducerProviderState, -} from '../../../types/storyProvider'; +} from '../../../types'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index c192242fa70d..058fed64d450 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -28,7 +28,7 @@ import type { ResourceId } from '@googleforcreators/media'; * Internal dependencies */ import type * as actionTypes from '../app/story/useStoryReducer/types'; -import type { Story } from './story'; +import type { Story, StorySaveData } from './story'; export type AddPageProps = { page: Page; @@ -348,9 +348,66 @@ export type ReducerActionProps = export type InternalActions = { restore: (props: RestoreProps) => State; }; + +interface DeleteElementProps { + elementId: string; +} +interface UpdateElementProps { + elementId: string; + properties: Partial | ElementUpdater; +} export type ExternalActions = { - addAnimations: (props: AddAnimationsProps) => State; - updateStory: (props: UpdateStoryProps) => State; + addAnimations: (props: AddAnimationsProps) => ReducerState; + updateStory: (props: UpdateStoryProps) => ReducerState; + addPage: (props: AddPageProps) => ReducerState; + addPageAt: (props: AddPageProps) => ReducerState; + copySelectedElement: () => ReducerState; + deletePage: (props: DeletePageProps) => ReducerState; + deleteCurrentPage: () => ReducerState; + updatePageProperties: (props: UpdatePageProps) => ReducerState; + updateCurrentPageProperties: (props: UpdatePageProps) => ReducerState; + arrangePage: (props: ArrangePageProps) => ReducerState; + setCurrentPage: (props: SetCurrentPageProps) => ReducerState; + addElements: (props: AddElementsProps) => ReducerState; + addElement: (props: AddElementsProps) => ReducerState; + deleteElementsById: (props: DeleteElementsProps) => ReducerState; + deleteElementById: (props: DeleteElementProps) => ReducerState; + deleteSelectedElements: () => ReducerState; + updateElementsById: (props: UpdateElementsProps) => ReducerState; + updateElementsByResourceId: ( + props: UpdateElementsByResourceIdProps + ) => ReducerState; + deleteElementsByResourceId: ( + props: DeleteElementsByResourceIdProps + ) => ReducerState; + updateElementById: (props: UpdateElementProps) => ReducerState; + duplicateElementsById: (props: DuplicateElementsByIdAction) => ReducerState; + updateSelectedElements: (props: UpdateElementsProps) => ReducerState; + combineElements: (props: CombineElementsProps) => ReducerState; + setBackgroundElement: (props: SetBackgroundElementProps) => ReducerState; + clearBackgroundElement: () => ReducerState; + arrangeElement: (props: ArrangeElementProps) => ReducerState; + arrangeGroup: (props: ArrangeGroupProps) => ReducerState; + arrangeSelection: (props: ArrangeElementProps) => ReducerState; + setSelectedElementsById: (props: SetSelectedElementsProps) => ReducerState; + clearSelection: () => ReducerState; + addElementToSelection: (props: SelectElementProps) => ReducerState; + removeElementFromSelection: (props: UnselectElementProps) => ReducerState; + toggleElementInSelection: ( + props: ToggleElementInSelectionProps + ) => ReducerState; + updateAnimationState: (props: UpdateAnimationStateProps) => ReducerState; + toggleLayer: (props: ToggleLayerProps) => ReducerState; + updateElementsByFontFamily: ( + props: UpdateElementsByFontFamilyProps + ) => ReducerState; + addGroup: (props: AddGroupProps) => ReducerState; + updateGroupById: (props: UpdateGroupProps) => ReducerState; + deleteGroupById: (props: DeleteGroupProps) => ReducerState; + deleteGroupAndElementsById: (props: DeleteGroupProps) => ReducerState; + duplicateGroupById: (props: DuplicateGroupProps) => ReducerState; + removeElementFromGroup: (props: RemoveElementFromGroupProps) => ReducerState; + addElementsAcrossPages: (props: AddElementsAcrossPagesProps) => ReducerState; }; export interface ReducerProviderState { state: ReducerState; @@ -386,10 +443,14 @@ export interface State extends ReducerState { }; } +interface SaveActions { + autoSave: (props: Partial) => void; + saveStory: (props: Partial) => void; + restoreLocalAutoSave: () => void; +} export interface StoryProviderState { state: State; - // @todo - actions: {}; + actions: InternalActions & ExternalActions & SaveActions; internal: { reducerState: ReducerState; restore: (props: RestoreProps) => State; From 4228444955e0c3a0012c6b31a6ce267d6919d9d1 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 14:32:03 -0300 Subject: [PATCH 37/99] Updates --- .../src/app/story/actions/useLocalAutoSave.ts | 7 +++---- .../story-editor/src/app/story/actions/useSaveStory.ts | 10 ++++++++-- .../story-editor/src/app/story/effects/useLoadStory.ts | 10 ++++------ packages/story-editor/src/types/storyProvider.ts | 10 +++++----- 4 files changed, 20 insertions(+), 17 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index 8769eeb4c8d9..9e3820090eb6 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -24,11 +24,10 @@ import type { Page } from '@googleforcreators/elements'; * Internal dependencies */ import getSessionStorageKey from '../../../utils/getSessionStorageKey'; -import type { RestoreProps, State } from '../../../types/storyProvider'; -import type { Capabilities } from '../../../types/configProvider'; +import type { ReducerState, RestoreProps, Capabilities } from '../../../types'; interface UseLocalAutoSaveProps { - restore: (props: RestoreProps) => State; + restore: (props: RestoreProps) => ReducerState; storyId: number; pages: Page[]; capabilities: Capabilities; @@ -55,7 +54,7 @@ function useLocalAutoSave({ selection: [], capabilities, ...existingAutoSave, - }); + } as Partial); }, [restore, storyId, pages, capabilities, isNew]); return { diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index b6734786d6f2..6b508fa0c066 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -32,7 +32,13 @@ import { useConfig } from '../../config'; import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; -import type {Story, RESTError, StorySaveData, UpdateStoryProps, State} from '../../../types'; +import type { + Story, + RESTError, + StorySaveData, + UpdateStoryProps, + ReducerState, +} from '../../../types'; const HTTP_STATUS_DESCRIPTIONS = { 400: _x('Bad Request', 'HTTP status description', 'web-stories'), @@ -45,7 +51,7 @@ interface UseSaveStoryProps { storyId: number; pages: Page[]; story: Story; - updateStory: (props: UpdateStoryProps) => State; + updateStory: (props: UpdateStoryProps) => ReducerState; } /** diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 58065503aabf..d364678d9e28 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -29,12 +29,12 @@ import { useAPI } from '../../api'; import { useHistory } from '../../history'; import getUniquePresets from '../../../utils/getUniquePresets'; import { useConfig } from '../../config'; -import type { RawStory, RestoreProps, State } from '../../../types'; +import type { RawStory, ReducerState, RestoreProps } from '../../../types'; function loadStory( storyId: number, post: RawStory, - restore: (props: RestoreProps) => State, + restore: (props: RestoreProps) => ReducerState, clearHistory: () => void, globalConfig: { globalAutoAdvance?: boolean; @@ -131,9 +131,7 @@ function loadStory( revisions, currentStoryStyles: { colors: storyData?.currentStoryStyles?.colors - ? (getUniquePresets( - storyData.currentStoryStyles.colors as Pattern[] - ) as Pattern[]) + ? (getUniquePresets(storyData.currentStoryStyles.colors) as Pattern[]) : [], }, globalStoryStyles: newGlobalStoryStyles, @@ -164,7 +162,7 @@ interface LoadStoryProps { storyId: number; story: RawStory | undefined; shouldLoad: boolean; - restore: (props: RestoreProps) => State; + restore: (props: RestoreProps) => ReducerState; } // When ID is set, load story from API. function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 058fed64d450..32be42473729 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -241,7 +241,7 @@ export type CopySelectedElementAction = { payload: null; }; -export type RestoreProps = Partial; +export type RestoreProps = Partial; export type RestoreAction = { type: typeof actionTypes.RESTORE; payload: RestoreProps; @@ -346,7 +346,7 @@ export type ReducerActionProps = | AddElementsAcrossPagesAction; export type InternalActions = { - restore: (props: RestoreProps) => State; + restore: (props: RestoreProps) => ReducerState; }; interface DeleteElementProps { @@ -425,7 +425,7 @@ export interface ReducerState { copiedElementState?: Element; } -export interface State extends ReducerState { +export interface State extends Omit { currentPage: Page | null; currentPageId: string | null; currentPageIndex: number | null; @@ -450,9 +450,9 @@ interface SaveActions { } export interface StoryProviderState { state: State; - actions: InternalActions & ExternalActions & SaveActions; + actions: ExternalActions & SaveActions; internal: { reducerState: ReducerState; - restore: (props: RestoreProps) => State; + restore: (props: RestoreProps) => ReducerState; }; } From ec8dd34b86b41d2a7a930a2903fc616ce242125d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 14:37:26 -0300 Subject: [PATCH 38/99] Fix typos --- .../story-editor/src/app/story/actions/useLocalAutoSave.ts | 4 ++-- packages/story-editor/src/app/story/effects/useLoadStory.ts | 6 +++--- packages/story-editor/src/types/storyProvider.ts | 5 +++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index 9e3820090eb6..b9e002de486c 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -24,10 +24,10 @@ import type { Page } from '@googleforcreators/elements'; * Internal dependencies */ import getSessionStorageKey from '../../../utils/getSessionStorageKey'; -import type { ReducerState, RestoreProps, Capabilities } from '../../../types'; +import type { ReducerState, Capabilities, Restore } from '../../../types'; interface UseLocalAutoSaveProps { - restore: (props: RestoreProps) => ReducerState; + restore: Restore; storyId: number; pages: Page[]; capabilities: Capabilities; diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index d364678d9e28..c6bd933e2245 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -29,12 +29,12 @@ import { useAPI } from '../../api'; import { useHistory } from '../../history'; import getUniquePresets from '../../../utils/getUniquePresets'; import { useConfig } from '../../config'; -import type { RawStory, ReducerState, RestoreProps } from '../../../types'; +import type { RawStory, Restore } from '../../../types'; function loadStory( storyId: number, post: RawStory, - restore: (props: RestoreProps) => ReducerState, + restore: Restore, clearHistory: () => void, globalConfig: { globalAutoAdvance?: boolean; @@ -162,7 +162,7 @@ interface LoadStoryProps { storyId: number; story: RawStory | undefined; shouldLoad: boolean; - restore: (props: RestoreProps) => ReducerState; + restore: Restore; } // When ID is set, load story from API. function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 32be42473729..3bd42e0f456e 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -345,8 +345,9 @@ export type ReducerActionProps = | RemoveElementFromGroupAction | AddElementsAcrossPagesAction; +export type Restore = (props: RestoreProps) => ReducerState; export type InternalActions = { - restore: (props: RestoreProps) => ReducerState; + restore: Restore; }; interface DeleteElementProps { @@ -453,6 +454,6 @@ export interface StoryProviderState { actions: ExternalActions & SaveActions; internal: { reducerState: ReducerState; - restore: (props: RestoreProps) => ReducerState; + restore: Restore; }; } From b90f716d47fdc13870fe738c9b1d65f33a209f7d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 14:58:13 -0300 Subject: [PATCH 39/99] Type context --- .../story-editor/src/app/story/context.ts | 58 ++++++++++++++++++- .../story/useStoryReducer/useStoryReducer.ts | 8 ++- .../utils/{objectPick.js => objectPick.ts} | 4 +- 3 files changed, 62 insertions(+), 8 deletions(-) rename packages/story-editor/src/utils/{objectPick.js => objectPick.ts} (87%) diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index a9c28a3c9014..fb137e9566ff 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -23,11 +23,12 @@ import type { Animation, Element, Page } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { StoryProviderState } from '../../types'; +import type { Story, StoryProviderState } from '../../types'; +import { INITIAL_STATE } from './useStoryReducer/useStoryReducer'; export default createContext({ state: { - story: null, + story: {} as Story, pages: [] as Page[], animationState: '', capabilities: {}, @@ -47,5 +48,56 @@ export default createContext({ isFreshlyPending: false, }, }, - actions: {}, + actions: { + addPage: () => INITIAL_STATE, + addPageAt: () => INITIAL_STATE, + copySelectedElement: () => INITIAL_STATE, + deletePage: () => INITIAL_STATE, + deleteCurrentPage: () => INITIAL_STATE, + updatePageProperties: () => INITIAL_STATE, + updateCurrentPageProperties: () => INITIAL_STATE, + arrangePage: () => INITIAL_STATE, + setCurrentPage: () => INITIAL_STATE, + addElements: () => INITIAL_STATE, + addElement: () => INITIAL_STATE, + deleteElementsById: () => INITIAL_STATE, + deleteElementById: () => INITIAL_STATE, + deleteSelectedElements: () => INITIAL_STATE, + updateElementsById: () => INITIAL_STATE, + updateElementsByResourceId: () => INITIAL_STATE, + deleteElementsByResourceId: () => INITIAL_STATE, + updateElementById: () => INITIAL_STATE, + duplicateElementsById: () => INITIAL_STATE, + updateSelectedElements: () => INITIAL_STATE, + combineElements: () => INITIAL_STATE, + setBackgroundElement: () => INITIAL_STATE, + clearBackgroundElement: () => INITIAL_STATE, + arrangeElement: () => INITIAL_STATE, + arrangeGroup: () => INITIAL_STATE, + arrangeSelection: () => INITIAL_STATE, + setSelectedElementsById: () => INITIAL_STATE, + clearSelection: () => INITIAL_STATE, + addElementToSelection: () => INITIAL_STATE, + removeElementFromSelection: () => INITIAL_STATE, + toggleElementInSelection: () => INITIAL_STATE, + updateAnimationState: () => INITIAL_STATE, + addAnimations: () => INITIAL_STATE, + updateStory: () => INITIAL_STATE, + toggleLayer: () => INITIAL_STATE, + updateElementsByFontFamily: () => INITIAL_STATE, + addGroup: () => INITIAL_STATE, + updateGroupById: () => INITIAL_STATE, + deleteGroupById: () => INITIAL_STATE, + deleteGroupAndElementsById: () => INITIAL_STATE, + duplicateGroupById: () => INITIAL_STATE, + removeElementFromGroup: () => INITIAL_STATE, + addElementsAcrossPages: () => INITIAL_STATE, + autoSave: () => null, + saveStory: () => null, + restoreLocalAutoSave: () => null, + }, + internal: { + reducerState: INITIAL_STATE, + restore: () => INITIAL_STATE, + }, }); diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 818e741c705a..e583b082b82c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -19,6 +19,7 @@ */ import { useReducer, useMemo } from '@googleforcreators/react'; import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; +import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies @@ -28,18 +29,19 @@ import type { InternalActions, ReducerState, ReducerProviderState, + Story, } from '../../../types'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; -const INITIAL_STATE = { +export const INITIAL_STATE = { pages: [], capabilities: {}, current: null, selection: [], - story: {}, + story: null as unknown as Story, animationState: STORY_ANIMATION_STATE.RESET as string, - copiedElementState: {}, + copiedElementState: {} as Element, }; /** diff --git a/packages/story-editor/src/utils/objectPick.js b/packages/story-editor/src/utils/objectPick.ts similarity index 87% rename from packages/story-editor/src/utils/objectPick.js rename to packages/story-editor/src/utils/objectPick.ts index 25fc3a96b012..f18f0d46c20b 100644 --- a/packages/story-editor/src/utils/objectPick.js +++ b/packages/story-editor/src/utils/objectPick.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -export default function pick(o, fields = []) { +export default function pick(o: Record, fields: string[] = []) { if (!o || typeof o !== 'object') { return {}; } return Object.assign( {}, ...fields.map((prop) => (o && prop in o ? { [prop]: o && o[prop] } : {})) - ); + ) as Record; } From 0e440fffd29f3b3beebb1919aa98ae3303a7c922 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 15:07:18 -0300 Subject: [PATCH 40/99] type session storage utils --- .../{sessionStore.js => sessionStore.ts} | 22 +++++++++++++------ packages/design-system/tsconfig.json | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) rename packages/design-system/src/utils/{sessionStore.js => sessionStore.ts} (67%) diff --git a/packages/design-system/src/utils/sessionStore.js b/packages/design-system/src/utils/sessionStore.ts similarity index 67% rename from packages/design-system/src/utils/sessionStore.js rename to packages/design-system/src/utils/sessionStore.ts index 887a8697463b..1b333fb17992 100644 --- a/packages/design-system/src/utils/sessionStore.js +++ b/packages/design-system/src/utils/sessionStore.ts @@ -23,31 +23,39 @@ export const SESSION_STORAGE_PREFIX = { LOCAL_AUTOSAVE_PREFIX: 'wp_stories_autosave_story', }; -export function getItemByKey(key) { +export function getItemByKey(key: string) { let parsed; try { const stored = window.sessionStorage.getItem(key); - parsed = JSON.parse(stored); + if (stored) { + parsed = JSON.parse(stored) as Record; + } } catch (err) { - trackError('session_storage_read', err.message); + if (err instanceof Error) { + void trackError('session_storage_read', err.message); + } } return parsed; } -export function setItemByKey(key, data) { +export function setItemByKey(key: string, data: Record) { try { window.sessionStorage.setItem(key, JSON.stringify(data)); } catch (err) { - trackError('session_storage_write', err.message); + if (err instanceof Error) { + void trackError('session_storage_write', err.message); + } } } -export function deleteItemByKey(key) { +export function deleteItemByKey(key: string) { try { window.sessionStorage.removeItem(key); } catch (err) { - trackError('session_storage_delete', err.message); + if (err instanceof Error) { + void trackError('session_storage_delete', err.message); + } } } diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json index 290c4afc6094..33047518ccaf 100644 --- a/packages/design-system/tsconfig.json +++ b/packages/design-system/tsconfig.json @@ -8,6 +8,7 @@ "src/contexts/snackbar/*", "src/types.ts", "src/types/*", - "src/components/snackbar/constants.ts" + "src/components/snackbar/constants.ts", + "src/utils/*.ts", ] } From b7d90363bc11eceea9db503ef66d2268e77e22bc Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 15:13:03 -0300 Subject: [PATCH 41/99] Temp workaround --- packages/design-system/src/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/design-system/src/types.ts b/packages/design-system/src/types.ts index 74413df3ca5b..809ef5ca601b 100644 --- a/packages/design-system/src/types.ts +++ b/packages/design-system/src/types.ts @@ -19,5 +19,6 @@ // delete this file once complete. export * from './contexts/snackbar'; +export * from './utils/sessionStore'; export {}; From c9c2e67aaba20704a7bb4fba174333e2fccbd431 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 15:23:24 -0300 Subject: [PATCH 42/99] Fix using restore --- .../story-editor/src/app/story/actions/useLocalAutoSave.ts | 2 +- .../src/app/story/useStoryReducer/useStoryReducer.ts | 2 +- packages/story-editor/src/types/storyProvider.ts | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index b9e002de486c..ca117a292713 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -50,7 +50,7 @@ function useLocalAutoSave({ } restore({ - current: pages[0], + current: pages[0].id, selection: [], capabilities, ...existingAutoSave, diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index e583b082b82c..286a23f5744b 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -39,7 +39,7 @@ export const INITIAL_STATE = { capabilities: {}, current: null, selection: [], - story: null as unknown as Story, + story: {} as Story, animationState: STORY_ANIMATION_STATE.RESET as string, copiedElementState: {} as Element, }; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 3bd42e0f456e..9baa4d4b50f6 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -29,6 +29,7 @@ import type { ResourceId } from '@googleforcreators/media'; */ import type * as actionTypes from '../app/story/useStoryReducer/types'; import type { Story, StorySaveData } from './story'; +import type { Capabilities } from './configProvider'; export type AddPageProps = { page: Page; @@ -422,7 +423,7 @@ export interface ReducerState { current: string | null; pages: Page[]; animationState: string; - capabilities: Record; + capabilities: Capabilities; copiedElementState?: Element; } From f1783c8b2813cd7e7079e44ada84a05d98cbd6cc Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 15:48:56 -0300 Subject: [PATCH 43/99] More triggers --- .../onInitialElementAddedRegister.ts | 32 ++++--------------- .../storyEvents/onPageAddedRegister.ts | 17 +++------- .../story/storyTriggers/useStoryTriggers.ts | 27 ++++++++++------ .../reducers/setBackgroundElement.ts | 18 +++++++---- packages/story-editor/src/types/index.ts | 1 + .../story-editor/src/types/storyTriggers.ts | 26 +++++++++++++++ 6 files changed, 67 insertions(+), 54 deletions(-) create mode 100644 packages/story-editor/src/types/storyTriggers.ts diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts index 3b75e9c4b56a..48ff5a738904 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts +++ b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts @@ -17,22 +17,24 @@ * External dependencies */ import { useRef, useEffect } from '@googleforcreators/react'; -import PropTypes from 'prop-types'; -import { StoryPropTypes } from '@googleforcreators/elements'; /** * Internal dependencies */ +import type { OnActionProps, State } from '../../../../types'; import { STORY_EVENTS } from './types'; -export function isNewStory(story) { +export function isNewStory(story: State) { return ( story?.pages?.length === 0 || (story?.pages?.length === 1 && story?.pages[0]?.elements?.length <= 1) ); } -function OnInitialElementAddedRegister({ currentStory, dispatchStoryEvent }) { +function OnInitialElementAddedRegister({ + currentStory, + dispatchStoryEvent, +}: OnActionProps) { const hasFiredOnceRef = useRef(false); // Dispatch `onInitialElementAdded` story event once, the first time @@ -47,26 +49,4 @@ function OnInitialElementAddedRegister({ currentStory, dispatchStoryEvent }) { return null; } -OnInitialElementAddedRegister.propTypes = { - currentStory: PropTypes.shape({ - story: PropTypes.shape({ - pages: PropTypes.arrayOf( - PropTypes.shape({ - elements: PropTypes.arrayOf(PropTypes.shape(StoryPropTypes.element)), - }) - ), - }), - }), - prevStory: PropTypes.shape({ - story: PropTypes.shape({ - pages: PropTypes.arrayOf( - PropTypes.shape({ - elements: PropTypes.arrayOf(PropTypes.shape(StoryPropTypes.element)), - }) - ), - }), - }), - dispatchStoryEvent: PropTypes.func.isRequired, -}; - export { OnInitialElementAddedRegister }; diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts index 7101c5972dfb..6b37ddc54677 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts +++ b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onPageAddedRegister.ts @@ -17,14 +17,17 @@ * External dependencies */ import { useRef, useEffect } from '@googleforcreators/react'; -import PropTypes from 'prop-types'; /** * Internal dependencies */ +import type { OnActionProps } from '../../../../types'; import { STORY_EVENTS } from './types'; -function OnPageAddedRegister({ currentStory, dispatchStoryEvent }) { +function OnPageAddedRegister({ + currentStory, + dispatchStoryEvent, +}: OnActionProps) { const hasFiredOnceRef = useRef({ [STORY_EVENTS.onSecondPageAdded]: false, [STORY_EVENTS.onFifthPageAdded]: false, @@ -57,14 +60,4 @@ function OnPageAddedRegister({ currentStory, dispatchStoryEvent }) { return null; } -OnPageAddedRegister.propTypes = { - currentStory: PropTypes.shape({ - pages: PropTypes.array, - }), - prevStory: PropTypes.shape({ - pages: PropTypes.array, - }), - dispatchStoryEvent: PropTypes.func.isRequired, -}; - export { OnPageAddedRegister }; diff --git a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts index 95cdbc63cbd7..ad8f55c06534 100644 --- a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts +++ b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts @@ -25,20 +25,29 @@ import { /** * Internal dependencies */ +import type { StoryTriggersState } from '../../../types'; import { Context } from './storyTriggersProvider'; -export function useStoryTriggers(selector) { - return useContextSelector(Context, selector ?? identity); +export function useStoryTriggers(): StoryTriggersState; +export function useStoryTriggers( + selector: (state: StoryTriggersState) => T | StoryTriggersState = identity +) { + return useContextSelector(Context, selector); } -function getAddEventListener(v) { +interface Value { + 0: (eventType: string, listener: Listener) => void; + 1: (eventType: string) => void; +} +function getAddEventListener(v: Value) { return v[0]; } -function getDispatch(v) { +function getDispatch(v: Value) { return v[1]; } +type Listener = (props: T) => void; /** * Example usage: * ```js @@ -49,13 +58,11 @@ function getDispatch(v) { // on this event }, []) ) - * ``` - * - * @param {string} eventType a `STORY_EVENT` - * @param {Function} listener preferably memoized. - * @return {void} */ -export function useStoryTriggerListener(eventType, listener) { +export function useStoryTriggerListener( + eventType: string, + listener: Listener +) { const addEventListener = useContextSelector(Context, getAddEventListener); useEffect( () => addEventListener(eventType, listener), diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index 614c5f78590e..fbd1e7ac1de2 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import { elementIs } from '@googleforcreators/elements'; +import { elementIs, Element } from '@googleforcreators/elements'; /** * Internal dependencies @@ -103,7 +103,11 @@ export const setBackgroundElement = ( // Reorder elements and set element opacity to 100% because backgrounds // cannot be transparent. - page.elements = moveArrayElement(page.elements, currentPosition, 0); + page.elements = moveArrayElement( + page.elements, + currentPosition, + 0 + ) as unknown as Element[]; page.elements.forEach((element) => { // Set isBackground for the element. if (element.id === elementId && elementIs.backgroundable(element)) { @@ -125,10 +129,12 @@ export const setBackgroundElement = ( const backgroundElementId = page.elements.find( (element) => elementIs.backgroundable(element) && element.isBackground ); - page.animations = removeAnimationsWithElementIds(page.animations, [ - elementId, - backgroundElementId.id, - ]); + if (backgroundElementId) { + page.animations = removeAnimationsWithElementIds(page.animations, [ + elementId as string, + backgroundElementId.id, + ]); + } }; export default produce(setBackgroundElement); diff --git a/packages/story-editor/src/types/index.ts b/packages/story-editor/src/types/index.ts index 6c0195efec00..d6d3caacc37a 100644 --- a/packages/story-editor/src/types/index.ts +++ b/packages/story-editor/src/types/index.ts @@ -18,3 +18,4 @@ export * from './storyProvider'; export * from './configProvider'; export * from './apiProvider'; export * from './storyEditor'; +export * from './storyTriggers'; diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts new file mode 100644 index 000000000000..258ea2bb21bc --- /dev/null +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * Internal dependencies + */ +import type { State } from './storyProvider'; + +export interface StoryTriggersState {} + +export interface OnActionProps { + currentStory: State; + dispatchStoryEvent: (eventType: string) => void; +} From de87b406771972039ca1441462c518a3a72026cb Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 16:07:48 -0300 Subject: [PATCH 44/99] More triggers types. --- .../story/storyTriggers/storyTriggersProvider.tsx | 14 ++++++++++---- .../app/story/storyTriggers/useStoryTriggers.ts | 10 ++-------- packages/story-editor/src/types/storyTriggers.ts | 5 ++++- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index dbd55db2a7b3..2350fdc465d7 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -28,10 +28,10 @@ import type { ReactNode } from 'react'; /** * Internal dependencies */ -import type { State } from '../../../types/storyProvider'; +import type { State, StoryTriggersState } from '../../../types'; import { STORY_EVENTS, StoryEventRegisters } from './storyEvents'; -export const Context = createContext({ state: {}, actions: {} }); +export const Context = createContext([]); function createSubscriptionMap() { return Object.values(STORY_EVENTS).reduce( @@ -43,7 +43,7 @@ function createSubscriptionMap() { ); } -function reducer([currentStory]: [State], updatedStory: State | null) { +function reducer([currentStory]: [State], updatedStory: State) { return [updatedStory, currentStory]; } @@ -59,7 +59,10 @@ export function StoryTriggersProvider({ // Not sure if this is necessarily needed but was used a lot in FTUE. Lets keep // an eye on this as we create more internal event registers, and we can always // remove if we end up not using it. - const [[currentStory, previousStory], updateStory] = useReducer(reducer, [story, null]); + const [[currentStory, previousStory], updateStory] = useReducer(reducer, [ + story, + null, + ]); const subscriptionMap = useMemo(createSubscriptionMap, []); // Update story to derive events @@ -116,3 +119,6 @@ export function StoryTriggersProvider({ ); } + +export class TriggersContextValue { +} diff --git a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts index ad8f55c06534..aaa08c677d5a 100644 --- a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts +++ b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts @@ -35,15 +35,11 @@ export function useStoryTriggers( return useContextSelector(Context, selector); } -interface Value { - 0: (eventType: string, listener: Listener) => void; - 1: (eventType: string) => void; -} -function getAddEventListener(v: Value) { +function getAddEventListener(v: StoryTriggersState) { return v[0]; } -function getDispatch(v: Value) { +function getDispatch(v: StoryTriggersState) { return v[1]; } @@ -77,8 +73,6 @@ export function useStoryTriggerListener( * // later in some effect or action * dispatchStoryEvent(STORY_EVENTS.onInitialElementAdded); * ``` - * - * @return {Function} takes and dispatches a `STORY_EVENT` */ export function useStoryTriggersDispatch() { return useContextSelector(Context, getDispatch); diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts index 258ea2bb21bc..3d94bb63d8fe 100644 --- a/packages/story-editor/src/types/storyTriggers.ts +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -18,7 +18,10 @@ */ import type { State } from './storyProvider'; -export interface StoryTriggersState {} +export type StoryTriggersState = ( + | ((eventType: string, listener: any) => () => void) + | ((eventType: string) => void) +)[]; export interface OnActionProps { currentStory: State; From a35b1cb0835f6b9ae1a74ec04003897842349eb1 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 16:18:07 -0300 Subject: [PATCH 45/99] More triggers --- .../storyTriggers/storyTriggersProvider.tsx | 27 ++++++++----------- .../story-editor/src/types/storyTriggers.ts | 1 + 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index 2350fdc465d7..955bc1a361ed 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -23,7 +23,7 @@ import { useCallback, createContext, } from '@googleforcreators/react'; -import type { ReactNode } from 'react'; +import type { PropsWithChildren } from 'react'; /** * Internal dependencies @@ -33,7 +33,8 @@ import { STORY_EVENTS, StoryEventRegisters } from './storyEvents'; export const Context = createContext([]); -function createSubscriptionMap() { +type Listener = (story?: State) => void; +function createSubscriptionMap(): Record> { return Object.values(STORY_EVENTS).reduce( (accum, evenType) => ({ ...accum, @@ -47,22 +48,17 @@ function reducer([currentStory]: [State], updatedStory: State) { return [updatedStory, currentStory]; } -interface StoryTriggersProviderProps { - children: ReactNode; - story: State; -} +type StoryTuple = [State, State]; export function StoryTriggersProvider({ children, story, -}: StoryTriggersProviderProps) { +}: PropsWithChildren<{ story: State }>) { // store prev & next versions of story to help compute internally fired events. // Not sure if this is necessarily needed but was used a lot in FTUE. Lets keep // an eye on this as we create more internal event registers, and we can always // remove if we end up not using it. - const [[currentStory, previousStory], updateStory] = useReducer(reducer, [ - story, - null, - ]); + const [[currentStory, previousStory], updateStory]: [StoryTuple, () => void] = + useReducer(reducer, [story, null]); const subscriptionMap = useMemo(createSubscriptionMap, []); // Update story to derive events @@ -71,7 +67,7 @@ export function StoryTriggersProvider({ // Method provided to listen to story events // return self cleanup method const addEventListener = useCallback( - (eventType, listener) => { + (eventType: string, listener: Listener) => { const key = Symbol(); subscriptionMap[eventType].set(key, listener); return () => subscriptionMap[eventType].delete(key); @@ -82,7 +78,9 @@ export function StoryTriggersProvider({ // Method to push events into the queue const dispatchStoryEvent = useCallback( (eventType) => { - subscriptionMap[eventType]?.forEach((listener) => listener(currentStory)); + subscriptionMap[eventType as keyof typeof subscriptionMap]?.forEach( + (listener) => listener(currentStory) + ); }, [subscriptionMap, currentStory] ); @@ -119,6 +117,3 @@ export function StoryTriggersProvider({ ); } - -export class TriggersContextValue { -} diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts index 3d94bb63d8fe..d33004c34b71 100644 --- a/packages/story-editor/src/types/storyTriggers.ts +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -26,4 +26,5 @@ export type StoryTriggersState = ( export interface OnActionProps { currentStory: State; dispatchStoryEvent: (eventType: string) => void; + previousStory?: State; } From a1c2a22bd7f2aeb6b149776fd0f3228011d9e769 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 16:23:31 -0300 Subject: [PATCH 46/99] More fixes --- .../src/app/story/useStoryReducer/useStoryReducer.ts | 3 ++- packages/story-editor/src/types/storyProvider.ts | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 286a23f5744b..1439d3d60ad8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -30,6 +30,7 @@ import type { ReducerState, ReducerProviderState, Story, + CopiedElementState, } from '../../../types'; import { exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -41,7 +42,7 @@ export const INITIAL_STATE = { selection: [], story: {} as Story, animationState: STORY_ANIMATION_STATE.RESET as string, - copiedElementState: {} as Element, + copiedElementState: {} as CopiedElementState, }; /** diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 9baa4d4b50f6..1f43a2a8054a 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -417,6 +417,11 @@ export interface ReducerProviderState { api: ExternalActions; } +export interface CopiedElementState { + animations?: Animation[]; + styles: Record; + type: string; +} export interface ReducerState { story: Story; selection: string[]; @@ -424,7 +429,7 @@ export interface ReducerState { pages: Page[]; animationState: string; capabilities: Capabilities; - copiedElementState?: Element; + copiedElementState?: CopiedElementState; } export interface State extends Omit { From 9c7866d2f959e10f02002dbdc38734eab9797f4f Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 20:19:49 -0300 Subject: [PATCH 47/99] Fix triggers reducer --- .../storyEvents/onInitialElementAddedRegister.ts | 2 +- .../app/story/storyTriggers/storyTriggersProvider.tsx | 10 ++++++---- packages/story-editor/src/types/storyTriggers.ts | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts index 48ff5a738904..4bfb2e92ebe5 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts +++ b/packages/story-editor/src/app/story/storyTriggers/storyEvents/onInitialElementAddedRegister.ts @@ -24,7 +24,7 @@ import { useRef, useEffect } from '@googleforcreators/react'; import type { OnActionProps, State } from '../../../../types'; import { STORY_EVENTS } from './types'; -export function isNewStory(story: State) { +export function isNewStory(story: State | null) { return ( story?.pages?.length === 0 || (story?.pages?.length === 1 && story?.pages[0]?.elements?.length <= 1) diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index 955bc1a361ed..74c29723147f 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -44,11 +44,11 @@ function createSubscriptionMap(): Record> { ); } -function reducer([currentStory]: [State], updatedStory: State) { +function reducer([currentStory]: StoryTuple, updatedStory: State): StoryTuple { return [updatedStory, currentStory]; } -type StoryTuple = [State, State]; +type StoryTuple = [State, State | null]; export function StoryTriggersProvider({ children, story, @@ -57,8 +57,10 @@ export function StoryTriggersProvider({ // Not sure if this is necessarily needed but was used a lot in FTUE. Lets keep // an eye on this as we create more internal event registers, and we can always // remove if we end up not using it. - const [[currentStory, previousStory], updateStory]: [StoryTuple, () => void] = - useReducer(reducer, [story, null]); + const [[currentStory, previousStory], updateStory] = useReducer(reducer, [ + story, + null, + ] as StoryTuple); const subscriptionMap = useMemo(createSubscriptionMap, []); // Update story to derive events diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts index d33004c34b71..d97f1d19584c 100644 --- a/packages/story-editor/src/types/storyTriggers.ts +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -24,7 +24,7 @@ export type StoryTriggersState = ( )[]; export interface OnActionProps { - currentStory: State; + currentStory: State | null; dispatchStoryEvent: (eventType: string) => void; - previousStory?: State; + previousStory: State | null; } From ee7fe7c19b7d16badce0441b7eda545fd869ea8f Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 22 Nov 2022 20:21:06 -0300 Subject: [PATCH 48/99] Another fix --- .../src/app/story/useStoryReducer/useStoryReducer.ts | 1 - packages/story-editor/src/types/storyTriggers.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index 1439d3d60ad8..cbd42a86183d 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -19,7 +19,6 @@ */ import { useReducer, useMemo } from '@googleforcreators/react'; import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; -import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts index d97f1d19584c..53193ead55c6 100644 --- a/packages/story-editor/src/types/storyTriggers.ts +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -24,7 +24,7 @@ export type StoryTriggersState = ( )[]; export interface OnActionProps { - currentStory: State | null; + currentStory: State; dispatchStoryEvent: (eventType: string) => void; previousStory: State | null; } From c64142a1689cc54a8fead3d7b67c75bf77628f3d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 23 Nov 2022 11:52:07 -0300 Subject: [PATCH 49/99] Fix some merging issues. --- packages/design-system/src/types/snackbar.ts | 1 + packages/story-editor/src/app/api/useAPI.ts | 2 +- .../src/app/story/useStoryReducer/reducers/arrangeGroup.ts | 2 +- packages/story-editor/src/types/historyProvider.ts | 3 ++- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/design-system/src/types/snackbar.ts b/packages/design-system/src/types/snackbar.ts index d18d0e99292e..877761d8e505 100644 --- a/packages/design-system/src/types/snackbar.ts +++ b/packages/design-system/src/types/snackbar.ts @@ -20,6 +20,7 @@ export interface Notification { 'aria-label': string; message: string; onDismiss: () => void; + dismissible?: boolean; } export interface SnackbarState { showSnackbar: (snackbar: Omit) => void; diff --git a/packages/story-editor/src/app/api/useAPI.ts b/packages/story-editor/src/app/api/useAPI.ts index c594564a659a..a32edbc94f7c 100644 --- a/packages/story-editor/src/app/api/useAPI.ts +++ b/packages/story-editor/src/app/api/useAPI.ts @@ -22,7 +22,7 @@ import { identity, useContextSelector } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { APIState } from '../../types/apiProvider'; +import type { APIState } from '../../types'; import Context from './context'; function useAPI(): APIState; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index ca971576ccff..64c68346a314 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import { Element } from '@googleforcreators/elements'; +import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies diff --git a/packages/story-editor/src/types/historyProvider.ts b/packages/story-editor/src/types/historyProvider.ts index ecf5ace17da5..ed4b358f92da 100644 --- a/packages/story-editor/src/types/historyProvider.ts +++ b/packages/story-editor/src/types/historyProvider.ts @@ -17,12 +17,13 @@ /** * External dependencies */ -import type { Page, Story } from '@googleforcreators/elements'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ import type { ActionType } from '../app/history/reducer'; +import type { Story } from './story'; export interface HistoryEntry { story: Story; From e8de27b98aecefa167a211d11eb9567e3c27bda6 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 23 Nov 2022 12:18:00 -0300 Subject: [PATCH 50/99] History effects fixes --- .../story-editor/src/app/history/context.ts | 4 +-- .../story-editor/src/app/history/reducer.ts | 6 ++-- .../src/app/history/useHistory.ts | 6 ++-- .../src/app/story/effects/useHistoryEntry.ts | 28 +++++++++++++------ .../src/app/story/effects/useHistoryReplay.ts | 3 +- .../story-editor/src/types/historyProvider.ts | 11 ++++---- packages/story-editor/src/types/index.ts | 1 + 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/packages/story-editor/src/app/history/context.ts b/packages/story-editor/src/app/history/context.ts index 96dabc85b525..2c2faa4eec5d 100644 --- a/packages/story-editor/src/app/history/context.ts +++ b/packages/story-editor/src/app/history/context.ts @@ -22,9 +22,9 @@ import { createContext } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { HistoryState } from '../../types/historyProvider'; +import type { HistoryProviderState } from '../../types'; -export default createContext({ +export default createContext({ state: { currentEntry: { selection: [], diff --git a/packages/story-editor/src/app/history/reducer.ts b/packages/story-editor/src/app/history/reducer.ts index 78199e1a7522..fe0a4a53fb6d 100644 --- a/packages/story-editor/src/app/history/reducer.ts +++ b/packages/story-editor/src/app/history/reducer.ts @@ -18,7 +18,7 @@ * Internal dependencies */ import type { - ReducerState, + HistoryReducerState, ReducerProps, HistoryEntry, } from '../../types/historyProvider'; @@ -39,9 +39,9 @@ export const EMPTY_STATE = { const reducer = (size: number) => ( - state: ReducerState, + state: HistoryReducerState, { type, payload }: ReducerProps - ): ReducerState | never => { + ): HistoryReducerState | never => { const currentEntry = state.entries[state.offset]; switch (type) { case ActionType.SetCurrentState: diff --git a/packages/story-editor/src/app/history/useHistory.ts b/packages/story-editor/src/app/history/useHistory.ts index c59db229fa31..e0d23560da09 100644 --- a/packages/story-editor/src/app/history/useHistory.ts +++ b/packages/story-editor/src/app/history/useHistory.ts @@ -21,12 +21,12 @@ import { identity, useContextSelector } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { HistoryState } from '../../types/historyProvider'; +import type { HistoryProviderState } from '../../types'; import Context from './context'; -function useHistory(): HistoryState; +function useHistory(): HistoryProviderState; function useHistory( - selector: (state: HistoryState) => T | HistoryState = identity + selector: (state: HistoryProviderState) => T | HistoryProviderState = identity ) { return useContextSelector(Context, selector); } diff --git a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts index cc70c148728d..8ec604db32fa 100644 --- a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts +++ b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts @@ -18,6 +18,7 @@ * External dependencies */ import { useEffect, useRef } from '@googleforcreators/react'; +import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies @@ -25,6 +26,7 @@ import { useEffect, useRef } from '@googleforcreators/react'; import { useHistory } from '../../history'; import deleteNestedKeys from '../utils/deleteNestedKeys'; import pageContainsBlobUrl from '../utils/pageContainsBlobUrl'; +import type { HistoryEntry } from '../../../types'; // Changes to these properties of elements do not create a new history entry // if only one (or multiple) of these properties change but nothing else changes. @@ -51,27 +53,33 @@ const ELEMENT_PROPS_TO_IGNORE = [ ]; // Record any change to core variables in history (history will know if it's a replay) -function useHistoryEntry({ story, current, pages, selection, capabilities }) { +function useHistoryEntry({ + story, + current, + pages, + selection, + capabilities, +}: HistoryEntry) { const { state: { currentEntry }, actions: { stateToHistory }, } = useHistory(); - const currentHistoryEntryRef = useRef(); + const currentHistoryEntryRef = useRef(); useEffect(() => { if (currentEntry) { currentHistoryEntryRef.current = structuredClone(currentEntry); } }, [currentEntry]); - const currentPageIndexRef = useRef(); - const selectedElementIdsRef = useRef(); + const currentPageIdRef = useRef(null); + const selectedElementIdsRef = useRef([]); useEffect(() => { - currentPageIndexRef.current = current; + currentPageIdRef.current = current; selectedElementIdsRef.current = selection; }, [current, selection]); - const deleteKeysFromPages = (list) => { + const deleteKeysFromPages = (list: Page[]) => { // Create a copy of the list not to influence the original. return structuredClone(list).map((page) => { page.elements.forEach(deleteNestedKeys(ELEMENT_PROPS_TO_IGNORE)); @@ -96,8 +104,10 @@ function useHistoryEntry({ story, current, pages, selection, capabilities }) { }; const onlyPagesChanged = Object.keys(withoutPages).every( (key) => - JSON.stringify(withoutPages[key]) === - JSON.stringify(currentHistoryEntryRef.current[key]) + JSON.stringify(withoutPages[key as keyof typeof withoutPages]) === + JSON.stringify( + currentHistoryEntryRef.current?.[key as keyof HistoryEntry] + ) ); // If only pages have changed, check if relevant properties have changed. if (onlyPagesChanged) { @@ -119,7 +129,7 @@ function useHistoryEntry({ story, current, pages, selection, capabilities }) { if (!skipAddingEntry) { stateToHistory({ story, - current: currentPageIndexRef.current, + current: currentPageIdRef.current, selection: selectedElementIdsRef.current, pages, capabilities, diff --git a/packages/story-editor/src/app/story/effects/useHistoryReplay.ts b/packages/story-editor/src/app/story/effects/useHistoryReplay.ts index 52189b95a322..22058aa8ccc3 100644 --- a/packages/story-editor/src/app/story/effects/useHistoryReplay.ts +++ b/packages/story-editor/src/app/story/effects/useHistoryReplay.ts @@ -23,8 +23,9 @@ import { useEffect } from '@googleforcreators/react'; * Internal dependencies */ import { useHistory } from '../../history'; +import type { Restore } from '../../../types'; -function useHistoryReplay({ restore }) { +function useHistoryReplay({ restore }: { restore: Restore }) { const { state: { requestedState }, } = useHistory(); diff --git a/packages/story-editor/src/types/historyProvider.ts b/packages/story-editor/src/types/historyProvider.ts index ed4b358f92da..e303c076a45b 100644 --- a/packages/story-editor/src/types/historyProvider.ts +++ b/packages/story-editor/src/types/historyProvider.ts @@ -24,13 +24,14 @@ import type { Page } from '@googleforcreators/elements'; */ import type { ActionType } from '../app/history/reducer'; import type { Story } from './story'; +import type { Capabilities } from './configProvider'; export interface HistoryEntry { story: Story; selection: string[]; current: string | null; pages: Page[]; - capabilities: Record; + capabilities: Capabilities; } interface SetCurrentStateProps { @@ -52,7 +53,7 @@ export type ReducerProps = | ClearHistoryProps | ReplayProps; -export interface ReducerState { +export interface HistoryReducerState { entries: HistoryEntry[]; offset: number; requestedState: null | HistoryEntry; @@ -66,7 +67,7 @@ export interface Actions { undo: (offset: number) => boolean; redo: (offset: number) => boolean; } -export interface State { +export interface HistoryState { currentEntry: HistoryEntry; hasNewChanges: boolean; requestedState: HistoryEntry | null; @@ -74,7 +75,7 @@ export interface State { canRedo: boolean; versionNumber: number; } -export interface HistoryState { - state: State; +export interface HistoryProviderState { + state: HistoryState; actions: Actions; } diff --git a/packages/story-editor/src/types/index.ts b/packages/story-editor/src/types/index.ts index d6d3caacc37a..971a3f6f231f 100644 --- a/packages/story-editor/src/types/index.ts +++ b/packages/story-editor/src/types/index.ts @@ -19,3 +19,4 @@ export * from './configProvider'; export * from './apiProvider'; export * from './storyEditor'; export * from './storyTriggers'; +export * from './historyProvider'; From b3f82e5d47ff8bd3525d313b8ca9e74baf54d577 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 23 Nov 2022 12:21:43 -0300 Subject: [PATCH 51/99] More fixes. --- packages/story-editor/src/app/history/context.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/story-editor/src/app/history/context.ts b/packages/story-editor/src/app/history/context.ts index 2c2faa4eec5d..70ae9a5f44f1 100644 --- a/packages/story-editor/src/app/history/context.ts +++ b/packages/story-editor/src/app/history/context.ts @@ -22,17 +22,14 @@ import { createContext } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { HistoryProviderState } from '../../types'; +import type { HistoryProviderState, Story } from '../../types'; export default createContext({ state: { currentEntry: { selection: [], capabilities: {}, - story: { - version: 0, - pages: [], - }, + story: {} as Story, pages: [], current: null, }, From dfffe70fd0dfc0e35f40684203c5d1ba89e8421e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 16:26:06 -0300 Subject: [PATCH 52/99] Fix typo --- .../src/app/story/useStoryReducer/reducers/restore.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 26292c1b38a0..03a6d58b85fd 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -57,7 +57,7 @@ export const restore = ( story: newReducerState, animationState: draft.animationState, capabilities: newCapabilities, - copiedElementReducerState: {}, + copiedElementState: {}, }; }; From 713f1ef0424dafa4fe3f557aaea3cdc22dad791f Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 16:31:22 -0300 Subject: [PATCH 53/99] Adjust reducer --- .../src/app/story/useStoryReducer/actions.ts | 2 +- .../app/story/useStoryReducer/useStoryReducer.ts | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index 9a43d4a4ee1a..fe17ea50b9ae 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -59,7 +59,7 @@ import type { } from '../../../types/storyProvider'; import * as types from './types'; -type DispatchType = Dispatch; +export type DispatchType = Dispatch; // Exposed actions const addPage = (dispatch: DispatchType) => diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index cbd42a86183d..cf78f85e5512 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -31,8 +31,10 @@ import type { Story, CopiedElementState, } from '../../../types'; -import { exposedActions, internalActions } from './actions'; +import {DispatchType, exposedActions, internalActions} from './actions'; import reducer from './reducer'; +import {Dispatch} from "react"; +import {ReducerActionProps} from "../../../types"; export const INITIAL_STATE = { pages: [], @@ -71,8 +73,10 @@ function useStoryReducer(partial: Partial): ReducerProviderState { ...partial, } as ReducerState); const { internal, api } = useMemo(() => { - const wrapWithDispatch = ( - actions: typeof internalActions | typeof exposedActions + const wrapWithDispatch = < + T extends Record unknown> + >( + actions: T ) => Object.keys(actions).reduce( (collection: Actions, action) => ({ @@ -83,7 +87,9 @@ function useStoryReducer(partial: Partial): ReducerProviderState { ); return { - internal: wrapWithDispatch(internalActions) as InternalActions, + internal: wrapWithDispatch( + internalActions + ) as InternalActions, api: wrapWithDispatch(exposedActions) as ExternalActions, }; }, [dispatch]); From 4067a8e282820d1b71e83adcccdddc7a59da57e7 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 16:52:02 -0300 Subject: [PATCH 54/99] Start typing utils --- .../story-editor/src/app/history/useHistoryReducer.ts | 2 +- .../src/app/story/useStoryReducer/useStoryReducer.ts | 4 +--- .../src/app/story/utils/deleteNestedKeys.ts | 10 +++++++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/story-editor/src/app/history/useHistoryReducer.ts b/packages/story-editor/src/app/history/useHistoryReducer.ts index b9dbcbcab7c5..06089a32f987 100644 --- a/packages/story-editor/src/app/history/useHistoryReducer.ts +++ b/packages/story-editor/src/app/history/useHistoryReducer.ts @@ -22,7 +22,7 @@ import { useReducer, useCallback } from '@googleforcreators/react'; /** * Internal dependencies */ -import type { HistoryEntry } from '../../types/historyProvider'; +import type { HistoryEntry } from '../../types'; import reducer, { ActionType, EMPTY_STATE } from './reducer'; function useHistoryReducer(size: number) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index cf78f85e5512..c1a36facad70 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -31,10 +31,8 @@ import type { Story, CopiedElementState, } from '../../../types'; -import {DispatchType, exposedActions, internalActions} from './actions'; +import { DispatchType, exposedActions, internalActions } from './actions'; import reducer from './reducer'; -import {Dispatch} from "react"; -import {ReducerActionProps} from "../../../types"; export const INITIAL_STATE = { pages: [], diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index d30cded3a2cc..a2174fc7ca6d 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -20,8 +20,8 @@ * * Note that this function mutates the original object. */ -function deleteNestedKeys(paths: string[]) { - return (object: Record) => { +function deleteNestedKeys>(paths: string[]) { + return (object: T) => { if (!Array.isArray(paths)) { return; } @@ -36,7 +36,11 @@ function deleteNestedKeys(paths: string[]) { } const lastKey = keys.pop(); const nextLastKey = keys.pop(); - const nextLastObj = keys.reduce((a, key) => a?.[key] || a, object); + const nextLastObj: T = keys.reduce((a, key) => a?.[key] || a, object); + + if (!nextLastObj || !nextLastKey || !lastKey) { + return; + } // Make sure we're not trying to get a property out of `undefined` or `null`. if ( Object.prototype.hasOwnProperty.call(nextLastObj, nextLastKey) && From 818c24cf71f1e25cbc277a68aa96217081855ea7 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 17:03:15 -0300 Subject: [PATCH 55/99] More fixes --- packages/design-system/src/types/snackbar.ts | 8 ++++---- .../app/story/useStoryReducer/reducers/arrangeGroup.ts | 8 ++++++-- .../app/story/useStoryReducer/reducers/combineElements.ts | 2 +- packages/story-editor/src/utils/objectWithout.ts | 6 +++--- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/design-system/src/types/snackbar.ts b/packages/design-system/src/types/snackbar.ts index 877761d8e505..1d843371b57c 100644 --- a/packages/design-system/src/types/snackbar.ts +++ b/packages/design-system/src/types/snackbar.ts @@ -15,11 +15,11 @@ */ export interface Notification { - id: string; - key: string; - 'aria-label': string; + id?: string; + key?: string; + 'aria-label'?: string; message: string; - onDismiss: () => void; + onDismiss?: () => void; dismissible?: boolean; } export interface SnackbarState { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index 64c68346a314..198c8693cbf2 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -55,7 +55,11 @@ export const arrangeGroup = ( const groupSize = groupEndIndex - groupStartIndex + 1; // Splice out the entire group and replace with dummy entry - const groupSlice = elements.splice(groupStartIndex, groupSize, 'dummy'); + const groupSlice = elements.splice( + groupStartIndex, + groupSize, + 'dummy' as unknown as Element + ); // Dummy entry is needed to calculate the new position as if the group is one entry const minPosition = 1; @@ -68,7 +72,7 @@ export const arrangeGroup = ( }); // remove the dummy entry - elements.splice(elements.indexOf('dummy'), 1); + elements.splice(elements.indexOf('dummy' as unknown as Element), 1); // Insert the new elements at position elements.splice(newPosition, 0, ...groupSlice); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 2e5abc456df8..da6fbe1c0c5a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -119,7 +119,7 @@ export const combineElements = ( const newElement: Element = { // First copy everything from existing element except if it was default background - ...objectWithout(secondElement, ['isDefaultBackground']), + ...objectWithout(secondElement, ['isDefaultBackground']), // Then set sensible default attributes ...DEFAULT_ATTRIBUTES_FOR_MEDIA, // Then copy all relevant attributes from new element diff --git a/packages/story-editor/src/utils/objectWithout.ts b/packages/story-editor/src/utils/objectWithout.ts index 51f0da8879f8..36e6d9f508e8 100644 --- a/packages/story-editor/src/utils/objectWithout.ts +++ b/packages/story-editor/src/utils/objectWithout.ts @@ -14,11 +14,11 @@ * limitations under the License. */ -export default function objectWithout( - obj: Record, +export default function objectWithout( + obj: T, propertiesToRemove: string[] ) { return Object.keys(obj) .filter((key) => !propertiesToRemove.includes(key)) - .reduce((newObj, key) => ({ ...newObj, [key]: obj[key] }), {}); + .reduce((newObj, key) => ({ ...newObj, [key]: obj[key as keyof T] }), {}); } From accf9e0e7e3dec70ea6c3f240beb5430807b0898 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 17:07:14 -0300 Subject: [PATCH 56/99] More fixes --- packages/story-editor/src/app/story/actions/useAutoSave.ts | 2 +- packages/story-editor/src/app/story/actions/useSaveStory.ts | 5 ++++- .../src/app/story/useStoryReducer/reducers/selectElement.ts | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index 1cd30eb955c3..ba7de2f31672 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -46,7 +46,7 @@ function useAutoSave({ storyId, pages, story }: AutoSaveProps) { const autoSave = useCallback( (props: Partial) => { setIsAutoSaving(true); - return autoSaveById({ + return autoSaveById?.({ storyId, ...getStoryPropsToSave({ story, diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index 6b508fa0c066..95261fb70ace 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -92,7 +92,7 @@ function useSaveStory({ // errors caused by getStoryPropsToSave() / getStoryMarkup(). return Promise.resolve() .then(() => - saveStoryById({ + saveStoryById?.({ storyId, ...getStoryPropsToSave({ story, @@ -106,6 +106,9 @@ function useSaveStory({ } as StorySaveData) ) .then((data) => { + if (!data) { + return; + } const { status, slug, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index ceaeff6e2b65..8747be5802ae 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -59,7 +59,7 @@ export const selectElement = ( // or the new element is locked, set selection to new element only const isLockedElement = element?.isLocked; const wasBackground = draft.selection.includes(currentPage.elements[0].id); - const wasLockedElement = draft.selection.some((id) => byId(id).isLocked); + const wasLockedElement = draft.selection.some((id) => byId(id)?.isLocked); if (wasBackground || isLockedElement || wasLockedElement) { draft.selection = [elementId]; } else { From 7df11257cfa891914f1f3b6caf97b83c86769404 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 17:32:20 -0300 Subject: [PATCH 57/99] More types --- packages/story-editor/src/app/story/effects/useLoadStory.ts | 2 +- .../story-editor/src/app/story/utils/deleteNestedKeys.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index c6bd933e2245..0c9d9a1dc317 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -180,7 +180,7 @@ function useLoadStory({ storyId, story, shouldLoad, restore }: LoadStoryProps) { if (story) { loadStory(storyId, story, restore, clearHistory, globalConfig); } else { - void getStoryById(storyId).then((post: RawStory) => { + void getStoryById?.(storyId).then((post: RawStory) => { loadStory(storyId, post, restore, clearHistory, globalConfig); }); } diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index a2174fc7ca6d..917288eeaaca 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -36,7 +36,10 @@ function deleteNestedKeys>(paths: string[]) { } const lastKey = keys.pop(); const nextLastKey = keys.pop(); - const nextLastObj: T = keys.reduce((a, key) => a?.[key] || a, object); + const nextLastObj = keys.reduce>( + (a, key) => a?.[key] || a, + object + ); if (!nextLastObj || !nextLastKey || !lastKey) { return; From 34cd25fe6836266694c1ef790aa1a5d454607e9c Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 24 Nov 2022 17:53:12 -0300 Subject: [PATCH 58/99] Use enum for action types. --- .../src/app/story/useStoryReducer/actions.ts | 104 ++++++++++-------- .../src/app/story/useStoryReducer/reducer.ts | 66 +++++------ .../src/app/story/useStoryReducer/types.ts | 88 +++++++-------- .../story-editor/src/types/storyProvider.ts | 66 +++++------ 4 files changed, 169 insertions(+), 155 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/actions.ts b/packages/story-editor/src/app/story/useStoryReducer/actions.ts index fe17ea50b9ae..badc9a55ba54 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/actions.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/actions.ts @@ -56,8 +56,8 @@ import type { UpdateGroupProps, UpdatePageProps, UpdateStoryProps, -} from '../../../types/storyProvider'; -import * as types from './types'; +} from '../../../types'; +import { ActionTypes } from './types'; export type DispatchType = Dispatch; // Exposed actions @@ -65,7 +65,7 @@ const addPage = (dispatch: DispatchType) => ({ page, position, updateSelection }: AddPageProps) => dispatch({ - type: types.ADD_PAGE, + type: ActionTypes.AddPage, payload: { page, position, updateSelection }, }); @@ -73,46 +73,46 @@ const addPageAt = (dispatch: DispatchType) => ({ page, position, updateSelection }: AddPageProps) => dispatch({ - type: types.ADD_PAGE, + type: ActionTypes.AddPage, payload: { page, position, updateSelection }, }); const deletePage = (dispatch: DispatchType) => ({ pageId }: DeletePageProps) => - dispatch({ type: types.DELETE_PAGE, payload: { pageId } }); + dispatch({ type: ActionTypes.DeletePage, payload: { pageId } }); const deleteCurrentPage = (dispatch: DispatchType) => () => - dispatch({ type: types.DELETE_PAGE, payload: { pageId: null } }); + dispatch({ type: ActionTypes.DeletePage, payload: { pageId: null } }); const updatePageProperties = (dispatch: DispatchType) => ({ pageId, properties }: UpdatePageProps) => - dispatch({ type: types.UPDATE_PAGE, payload: { pageId, properties } }); + dispatch({ type: ActionTypes.UpdatePage, payload: { pageId, properties } }); const updateCurrentPageProperties = (dispatch: DispatchType) => ({ properties }: UpdatePageProps) => dispatch({ - type: types.UPDATE_PAGE, + type: ActionTypes.UpdatePage, payload: { pageId: null, properties }, }); const arrangePage = (dispatch: DispatchType) => ({ pageId, position }: ArrangePageProps) => - dispatch({ type: types.ARRANGE_PAGE, payload: { pageId, position } }); + dispatch({ type: ActionTypes.ArrangePage, payload: { pageId, position } }); const setCurrentPage = (dispatch: DispatchType) => ({ pageId }: SetCurrentPageProps) => - dispatch({ type: types.SET_CURRENT_PAGE, payload: { pageId } }); + dispatch({ type: ActionTypes.SetCurrentPage, payload: { pageId } }); const addElements = (dispatch: DispatchType) => ({ elements, pageId, updateSelection }: AddElementsProps) => dispatch({ - type: types.ADD_ELEMENTS, + type: ActionTypes.AddElements, payload: { elements, pageId, updateSelection }, }); @@ -123,17 +123,17 @@ const addElement = (dispatch: DispatchType) => ({ element, pageId, updateSelection }: AddElementProps) => dispatch({ - type: types.ADD_ELEMENTS, + type: ActionTypes.AddElements, payload: { elements: [element], pageId, updateSelection }, }); const deleteElementsById = (dispatch: DispatchType) => ({ elementIds }: DeleteElementsProps) => - dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds } }); + dispatch({ type: ActionTypes.DeleteElements, payload: { elementIds } }); const deleteSelectedElements = (dispatch: DispatchType) => () => - dispatch({ type: types.DELETE_ELEMENTS, payload: { elementIds: null } }); + dispatch({ type: ActionTypes.DeleteElements, payload: { elementIds: null } }); interface DeleteElementProps extends Omit { elementId: string; @@ -142,7 +142,7 @@ const deleteElementById = (dispatch: DispatchType) => ({ elementId }: DeleteElementProps) => dispatch({ - type: types.DELETE_ELEMENTS, + type: ActionTypes.DeleteElements, payload: { elementIds: [elementId] }, }); @@ -150,7 +150,7 @@ const updateElementsById = (dispatch: DispatchType) => ({ elementIds, properties }: UpdateElementsProps) => dispatch({ - type: types.UPDATE_ELEMENTS, + type: ActionTypes.UpdateElements, payload: { elementIds, properties }, }); @@ -158,7 +158,7 @@ const updateElementsByResourceId = (dispatch: DispatchType) => ({ id, properties }: UpdateElementsByResourceIdProps) => dispatch({ - type: types.UPDATE_ELEMENTS_BY_RESOURCE_ID, + type: ActionTypes.UpdateElementsByResourceId, payload: { id, properties }, }); @@ -166,7 +166,7 @@ const deleteElementsByResourceId = (dispatch: DispatchType) => ({ id }: DeleteElementsByResourceIdProps) => dispatch({ - type: types.DELETE_ELEMENTS_BY_RESOURCE_ID, + type: ActionTypes.DeleteElementsByResourceId, payload: { id }, }); @@ -178,7 +178,7 @@ const updateElementById = (dispatch: DispatchType) => ({ elementId, properties }: UpdateElementByIdProps) => dispatch({ - type: types.UPDATE_ELEMENTS, + type: ActionTypes.UpdateElements, payload: { elementIds: [elementId], properties }, }); @@ -186,7 +186,7 @@ const duplicateElementsById = (dispatch: DispatchType) => ({ elementIds }: DuplicateElementsByIdProps) => dispatch({ - type: types.DUPLICATE_ELEMENTS_BY_ID, + type: ActionTypes.DuplicateElementsById, payload: { elementIds }, }); @@ -194,7 +194,7 @@ const updateSelectedElements = (dispatch: DispatchType) => ({ properties }: UpdateElementsProps) => dispatch({ - type: types.UPDATE_ELEMENTS, + type: ActionTypes.UpdateElements, payload: { elementIds: null, properties }, }); @@ -202,18 +202,21 @@ const combineElements = (dispatch: DispatchType) => ({ firstElement, secondId, shouldRetainAnimations }: CombineElementsProps) => dispatch({ - type: types.COMBINE_ELEMENTS, + type: ActionTypes.CombineElements, payload: { firstElement, secondId, shouldRetainAnimations }, }); const setBackgroundElement = (dispatch: DispatchType) => ({ elementId }: SetBackgroundElementProps) => - dispatch({ type: types.SET_BACKGROUND_ELEMENT, payload: { elementId } }); + dispatch({ + type: ActionTypes.SetBackgroundElement, + payload: { elementId }, + }); const clearBackgroundElement = (dispatch: DispatchType) => () => dispatch({ - type: types.SET_BACKGROUND_ELEMENT, + type: ActionTypes.SetBackgroundElement, payload: { elementId: null }, }); @@ -221,20 +224,23 @@ const arrangeElement = (dispatch: DispatchType) => ({ elementId, position, groupId }: ArrangeElementProps) => dispatch({ - type: types.ARRANGE_ELEMENT, + type: ActionTypes.ArrangeElement, payload: { elementId, position, groupId }, }); const arrangeGroup = (dispatch: DispatchType) => ({ groupId, position }: ArrangeGroupProps) => - dispatch({ type: types.ARRANGE_GROUP, payload: { groupId, position } }); + dispatch({ + type: ActionTypes.ArrangeGroup, + payload: { groupId, position }, + }); const arrangeSelection = (dispatch: DispatchType) => ({ position, groupId }: ArrangeElementProps) => dispatch({ - type: types.ARRANGE_ELEMENT, + type: ActionTypes.ArrangeElement, payload: { elementId: null, position, groupId }, }); @@ -242,60 +248,63 @@ const setSelectedElementsById = (dispatch: DispatchType) => ({ elementIds, withLinked }: SetSelectedElementsProps) => dispatch({ - type: types.SET_SELECTED_ELEMENTS, + type: ActionTypes.SetSelectedElements, payload: { elementIds, withLinked }, }); const clearSelection = (dispatch: DispatchType) => () => - dispatch({ type: types.SET_SELECTED_ELEMENTS, payload: { elementIds: [] } }); + dispatch({ + type: ActionTypes.SetSelectedElements, + payload: { elementIds: [] }, + }); const addElementToSelection = (dispatch: DispatchType) => ({ elementId }: SelectElementProps) => - dispatch({ type: types.SELECT_ELEMENT, payload: { elementId } }); + dispatch({ type: ActionTypes.SelectElement, payload: { elementId } }); const removeElementFromSelection = (dispatch: DispatchType) => ({ elementId }: UnselectElementProps) => - dispatch({ type: types.UNSELECT_ELEMENT, payload: { elementId } }); + dispatch({ type: ActionTypes.UnselectElement, payload: { elementId } }); const toggleElementInSelection = (dispatch: DispatchType) => ({ elementId, withLinked }: ToggleElementInSelectionProps) => dispatch({ - type: types.TOGGLE_ELEMENT_IN_SELECTION, + type: ActionTypes.ToggleElementInSelection, payload: { elementId, withLinked }, }); const updateStory = (dispatch: DispatchType) => ({ properties }: UpdateStoryProps) => - dispatch({ type: types.UPDATE_STORY, payload: { properties } }); + dispatch({ type: ActionTypes.UpdateStory, payload: { properties } }); const updateAnimationState = (dispatch: DispatchType) => ({ animationState }: UpdateAnimationStateProps) => dispatch({ - type: types.UPDATE_ANIMATION_STATE, + type: ActionTypes.UpdateAnimationState, payload: { animationState }, }); const addAnimations = (dispatch: DispatchType) => ({ animations }: AddAnimationsProps) => - dispatch({ type: types.ADD_ANIMATIONS, payload: { animations } }); + dispatch({ type: ActionTypes.AddAnimations, payload: { animations } }); const toggleLayer = (dispatch: DispatchType) => ({ metaKey, shiftKey, elementId, withLinked }: ToggleLayerProps) => dispatch({ - type: types.TOGGLE_LAYER, + type: ActionTypes.ToggleLayer, payload: { metaKey, shiftKey, elementId, withLinked }, }); const copySelectedElement = (dispatch: DispatchType) => () => dispatch({ - type: types.COPY_SELECTED_ELEMENT, + type: ActionTypes.CopySelectedElement, payload: null, }); @@ -303,20 +312,23 @@ const updateElementsByFontFamily = (dispatch: DispatchType) => ({ family, properties }: UpdateElementsByFontFamilyProps) => dispatch({ - type: types.UPDATE_ELEMENTS_BY_FONT_FAMILY, + type: ActionTypes.UpdateElementsByFontFamily, payload: { family, properties }, }); const addGroup = (dispatch: DispatchType) => ({ groupId, name, isLocked }: AddGroupProps) => - dispatch({ type: types.ADD_GROUP, payload: { groupId, name, isLocked } }); + dispatch({ + type: ActionTypes.AddGroup, + payload: { groupId, name, isLocked }, + }); const updateGroupById = (dispatch: DispatchType) => ({ groupId, properties }: UpdateGroupProps) => dispatch({ - type: types.UPDATE_GROUP, + type: ActionTypes.UpdateGroup, payload: { groupId, properties }, }); @@ -324,7 +336,7 @@ const deleteGroupById = (dispatch: DispatchType) => ({ groupId }: DeleteGroupProps) => dispatch({ - type: types.DELETE_GROUP, + type: ActionTypes.DeleteGroup, payload: { groupId }, }); @@ -332,7 +344,7 @@ const deleteGroupAndElementsById = (dispatch: DispatchType) => ({ groupId }: DeleteGroupProps) => dispatch({ - type: types.DELETE_GROUP, + type: ActionTypes.DeleteGroup, payload: { groupId, includeElements: true }, }); @@ -340,7 +352,7 @@ const duplicateGroupById = (dispatch: DispatchType) => ({ groupId, name, oldGroupId, isLocked }: DuplicateGroupProps) => dispatch({ - type: types.DUPLICATE_GROUP, + type: ActionTypes.DuplicateGroup, payload: { groupId, name, oldGroupId, isLocked }, }); @@ -348,7 +360,7 @@ const removeElementFromGroup = (dispatch: DispatchType) => ({ elementId, groupId }: RemoveElementFromGroupProps) => dispatch({ - type: types.REMOVE_ELEMENT_FROM_GROUP, + type: ActionTypes.RemoveElementFromGroup, payload: { elementId, groupId }, }); @@ -356,7 +368,7 @@ const addElementsAcrossPages = (dispatch: DispatchType) => ({ elements, page, position }: AddElementsAcrossPagesProps) => dispatch({ - type: types.ADD_ELEMENTS_ACROSS_PAGES, + type: ActionTypes.AddElementsAcrossPages, payload: { elements, page, position }, }); @@ -411,7 +423,7 @@ const restore = (dispatch: DispatchType) => ({ pages, selection, current, story, capabilities }: RestoreProps) => dispatch({ - type: types.RESTORE, + type: ActionTypes.Restore, payload: { pages, selection, current, story, capabilities }, }); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts index 91cebeab3223..8195023b82bd 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducer.ts @@ -18,7 +18,7 @@ * Internal dependencies */ import type { ReducerActionProps, ReducerState } from '../../../types'; -import * as types from './types'; +import { ActionTypes } from './types'; import * as reducers from './reducers'; // eslint-disable-next-line complexity -- reducer function, negligible. @@ -27,131 +27,131 @@ function reducer( { type, payload }: ReducerActionProps ): ReducerState { switch (type) { - case types.ADD_PAGE: { + case ActionTypes.AddPage: { return reducers.addPage(state, payload); } - case types.DELETE_PAGE: { + case ActionTypes.DeletePage: { return reducers.deletePage(state, payload); } - case types.UPDATE_PAGE: { + case ActionTypes.UpdatePage: { return reducers.updatePage(state, payload); } - case types.ARRANGE_PAGE: { + case ActionTypes.ArrangePage: { return reducers.arrangePage(state, payload); } - case types.SET_CURRENT_PAGE: { + case ActionTypes.SetCurrentPage: { return reducers.setCurrentPage(state, payload); } - case types.ADD_ELEMENTS: { + case ActionTypes.AddElements: { return reducers.addElements(state, payload); } - case types.DELETE_ELEMENTS: { + case ActionTypes.DeleteElements: { return reducers.deleteElements(state, payload); } - case types.UPDATE_ELEMENTS: { + case ActionTypes.UpdateElements: { return reducers.updateElements(state, payload); } - case types.UPDATE_ELEMENTS_BY_RESOURCE_ID: { + case ActionTypes.UpdateElementsByResourceId: { return reducers.updateElementsByResourceId(state, payload); } - case types.DELETE_ELEMENTS_BY_RESOURCE_ID: { + case ActionTypes.DeleteElementsByResourceId: { return reducers.deleteElementsByResourceId(state, payload); } - case types.COMBINE_ELEMENTS: { + case ActionTypes.CombineElements: { return reducers.combineElements(state, payload); } - case types.SET_BACKGROUND_ELEMENT: { + case ActionTypes.SetBackgroundElement: { return reducers.setBackgroundElement(state, payload); } - case types.ARRANGE_ELEMENT: { + case ActionTypes.ArrangeElement: { return reducers.arrangeElement(state, payload); } - case types.ARRANGE_GROUP: { + case ActionTypes.ArrangeGroup: { return reducers.arrangeGroup(state, payload); } - case types.SET_SELECTED_ELEMENTS: { + case ActionTypes.SetSelectedElements: { return reducers.setSelectedElements(state, payload); } - case types.SELECT_ELEMENT: { + case ActionTypes.SelectElement: { return reducers.selectElement(state, payload); } - case types.UNSELECT_ELEMENT: { + case ActionTypes.UnselectElement: { return reducers.unselectElement(state, payload); } - case types.TOGGLE_ELEMENT_IN_SELECTION: { + case ActionTypes.ToggleElementInSelection: { return reducers.toggleElement(state, payload); } - case types.TOGGLE_LAYER: { + case ActionTypes.ToggleLayer: { return reducers.toggleLayer(state, payload); } - case types.DUPLICATE_ELEMENTS_BY_ID: { + case ActionTypes.DuplicateElementsById: { return reducers.duplicateElementsById(state, payload); } - case types.UPDATE_STORY: { + case ActionTypes.UpdateStory: { return reducers.updateStory(state, payload); } - case types.UPDATE_ANIMATION_STATE: { + case ActionTypes.UpdateAnimationState: { return reducers.updateAnimationState(state, payload); } - case types.ADD_ANIMATIONS: { + case ActionTypes.AddAnimations: { return reducers.addAnimations(state, payload); } - case types.COPY_SELECTED_ELEMENT: { + case ActionTypes.CopySelectedElement: { return reducers.copySelectedElement(state); } - case types.RESTORE: { + case ActionTypes.Restore: { return reducers.restore(state, payload); } - case types.UPDATE_ELEMENTS_BY_FONT_FAMILY: { + case ActionTypes.UpdateElementsByFontFamily: { return reducers.updateElementsByFontFamily(state, payload); } - case types.ADD_GROUP: { + case ActionTypes.AddGroup: { return reducers.addGroup(state, payload); } - case types.UPDATE_GROUP: { + case ActionTypes.UpdateGroup: { return reducers.updateGroup(state, payload); } - case types.DELETE_GROUP: { + case ActionTypes.DeleteGroup: { return reducers.deleteGroup(state, payload); } - case types.DUPLICATE_GROUP: { + case ActionTypes.DuplicateGroup: { return reducers.duplicateGroup(state, payload); } - case types.REMOVE_ELEMENT_FROM_GROUP: { + case ActionTypes.RemoveElementFromGroup: { return reducers.removeElementFromGroup(state, payload); } - case types.ADD_ELEMENTS_ACROSS_PAGES: { + case ActionTypes.AddElementsAcrossPages: { return reducers.addElementsAcrossPages(state, payload); } diff --git a/packages/story-editor/src/app/story/useStoryReducer/types.ts b/packages/story-editor/src/app/story/useStoryReducer/types.ts index ed3eee90af27..ea1bc14b9cd6 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/types.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/types.ts @@ -14,45 +14,57 @@ * limitations under the License. */ -// Manipulate pages. -export const ADD_PAGE = 'ADD_PAGE'; -export const UPDATE_PAGE = 'UPDATE_PAGE'; -export const DELETE_PAGE = 'DELETE_PAGE'; -export const ARRANGE_PAGE = 'ARRANGE_PAGE'; +export enum ActionTypes { + // Manipulate pages. + AddPage = 'ADD_PAGE', + UpdatePage = 'UPDATE_PAGE', + DeletePage = 'DELETE_PAGE', + ArrangePage = 'ARRANGE_PAGE', -// Manipulate elements on a page. -export const DELETE_ELEMENTS = 'DELETE_ELEMENTS'; -export const ADD_ELEMENTS = 'ADD_ELEMENTS'; -export const UPDATE_ELEMENTS = 'UPDATE_ELEMENTS'; -export const UPDATE_ELEMENTS_BY_RESOURCE_ID = 'UPDATE_ELEMENTS_BY_RESOURCE_ID'; -export const DELETE_ELEMENTS_BY_RESOURCE_ID = 'DELETE_ELEMENTS_BY_RESOURCE_ID'; -export const SET_BACKGROUND_ELEMENT = 'SET_BACKGROUND_ELEMENT'; -export const ARRANGE_ELEMENT = 'ARRANGE_ELEMENT'; -export const ARRANGE_GROUP = 'ARRANGE_GROUP'; -export const COMBINE_ELEMENTS = 'COMBINE_ELEMENTS'; -export const DUPLICATE_ELEMENTS_BY_ID = 'DUPLICATE_ELEMENTS_BY_ID'; -export const COPY_SELECTED_ELEMENT = 'COPY_SELECTED_ELEMENT'; -export const UPDATE_ELEMENTS_BY_FONT_FAMILY = 'UPDATE_ELEMENTS_BY_FONT_FAMILY'; + // Manipulate elements on a page. + DeleteElements = 'DELETE_ELEMENTS', + AddElements = 'ADD_ELEMENTS', + UpdateElements = 'UPDATE_ELEMENTS', + UpdateElementsByResourceId = 'UPDATE_ELEMENTS_BY_RESOURCE_ID', + DeleteElementsByResourceId = 'DELETE_ELEMENTS_BY_RESOURCE_ID', + SetBackgroundElement = 'SET_BACKGROUND_ELEMENT', + ArrangeElement = 'ARRANGE_ELEMENT', + ArrangeGroup = 'ARRANGE_GROUP', + CombineElements = 'COMBINE_ELEMENTS', + DuplicateElementsById = 'DUPLICATE_ELEMENTS_BY_ID', + CopySelectedElement = 'COPY_SELECTED_ELEMENT', + UpdateElementsByFontFamily = 'UPDATE_ELEMENTS_BY_FONT_FAMILY', -// Manipulate current page. -export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE'; + // Manipulate current page. + SetCurrentPage = 'SET_CURRENT_PAGE', -// Manipulate list of selected elements. -export const SET_SELECTED_ELEMENTS = 'SET_SELECTED_ELEMENTS'; -export const SELECT_ELEMENT = 'SELECT_ELEMENT'; -export const UNSELECT_ELEMENT = 'UNSELECT_ELEMENT'; -export const TOGGLE_ELEMENT_IN_SELECTION = 'TOGGLE_ELEMENT_IN_SELECTION'; -export const TOGGLE_LAYER = 'TOGGLE_LAYER'; + // Manipulate list of selected elements. + SetSelectedElements = 'SET_SELECTED_ELEMENTS', + SelectElement = 'SELECT_ELEMENT', + UnselectElement = 'UNSELECT_ELEMENT', + ToggleElementInSelection = 'TOGGLE_ELEMENT_IN_SELECTION', + ToggleLayer = 'TOGGLE_LAYER', -// Manipulate story-global state. -export const UPDATE_STORY = 'UPDATE_STORY'; + // Manipulate story-global state. + UpdateStory = 'UPDATE_STORY', -// Manipulate animation state. -export const UPDATE_ANIMATION_STATE = 'UPDATE_ANIMATION_STATE'; -export const ADD_ANIMATIONS = 'ADD_ANIMATIONS'; + // Manipulate animation state. + UpdateAnimationState = 'UPDATE_ANIMATION_STATE', + AddAnimations = 'ADD_ANIMATIONS', -// Manipulate entire internal state. -export const RESTORE = 'RESTORE'; + // Manipulate entire internal state. + Restore = 'RESTORE', + + // Layer groups + AddGroup = 'ADD_GROUP', + UpdateGroup = 'UPDATE_GROUP', + DeleteGroup = 'DELETE_GROUP', + DuplicateGroup = 'DUPLICATE_GROUP', + RemoveElementFromGroup = 'REMOVE_ELEMENT_FROM_GROUP', + + // Video segmentation. + AddElementsAcrossPages = 'ADD_ELEMENTS_ACROSS_PAGES', +} // Reserved property names for pages, elements and groups. export const PAGE_RESERVED_PROPERTIES = ['id', 'elements', 'groups']; @@ -61,13 +73,3 @@ export const ELEMENT_RESERVED_PROPERTIES = [ 'isBackground', 'isDefaultBackground', ]; - -// Layer groups -export const ADD_GROUP = 'ADD_GROUP'; -export const UPDATE_GROUP = 'UPDATE_GROUP'; -export const DELETE_GROUP = 'DELETE_GROUP'; -export const DUPLICATE_GROUP = 'DUPLICATE_GROUP'; -export const REMOVE_ELEMENT_FROM_GROUP = 'REMOVE_ELEMENT_FROM_GROUP'; - -// Video segmentation. -export const ADD_ELEMENTS_ACROSS_PAGES = 'ADD_ELEMENTS_ACROSS_PAGES'; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 1f43a2a8054a..cfae4f9b8f9f 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -27,7 +27,7 @@ import type { ResourceId } from '@googleforcreators/media'; /** * Internal dependencies */ -import type * as actionTypes from '../app/story/useStoryReducer/types'; +import type { ActionTypes } from '../app/story/useStoryReducer/types'; import type { Story, StorySaveData } from './story'; import type { Capabilities } from './configProvider'; @@ -37,7 +37,7 @@ export type AddPageProps = { updateSelection: boolean; }; export type AddPageAction = { - type: typeof actionTypes.ADD_PAGE; + type: typeof ActionTypes.AddPage; payload: AddPageProps; }; @@ -45,7 +45,7 @@ export type DeletePageProps = { pageId: string | null; }; export type DeletePageAction = { - type: typeof actionTypes.DELETE_PAGE; + type: typeof ActionTypes.DeletePage; payload: DeletePageProps; }; @@ -54,7 +54,7 @@ export type UpdatePageProps = { properties: Partial; }; export type UpdatePageAction = { - type: typeof actionTypes.UPDATE_PAGE; + type: typeof ActionTypes.UpdatePage; payload: UpdatePageProps; }; @@ -63,7 +63,7 @@ export type ArrangePageProps = { position: number; }; export type ArrangePageAction = { - type: typeof actionTypes.ARRANGE_PAGE; + type: typeof ActionTypes.ArrangePage; payload: ArrangePageProps; }; @@ -71,7 +71,7 @@ export type SetCurrentPageProps = { pageId: string; }; export type SetCurrentPagePageAction = { - type: typeof actionTypes.SET_CURRENT_PAGE; + type: typeof ActionTypes.SetCurrentPage; payload: SetCurrentPageProps; }; @@ -82,7 +82,7 @@ export type AddElementsProps = { }; export type AddElementsAction = { - type: typeof actionTypes.ADD_ELEMENTS; + type: typeof ActionTypes.AddElements; payload: AddElementsProps; }; @@ -90,7 +90,7 @@ export type DeleteElementsProps = { elementIds: string[] | null; }; export type DeleteElementsAction = { - type: typeof actionTypes.DELETE_ELEMENTS; + type: typeof ActionTypes.DeleteElements; payload: DeleteElementsProps; }; @@ -100,7 +100,7 @@ export type UpdateElementsProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsAction = { - type: typeof actionTypes.UPDATE_ELEMENTS; + type: typeof ActionTypes.UpdateElements; payload: UpdateElementsProps; }; @@ -109,7 +109,7 @@ export type UpdateElementsByResourceIdProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsByResourceIdAction = { - type: typeof actionTypes.UPDATE_ELEMENTS_BY_RESOURCE_ID; + type: typeof ActionTypes.UpdateElementsByResourceId; payload: UpdateElementsByResourceIdProps; }; @@ -117,7 +117,7 @@ export type DeleteElementsByResourceIdProps = { id: ResourceId; }; export type DeleteElementsByResourceIdAction = { - type: typeof actionTypes.DELETE_ELEMENTS_BY_RESOURCE_ID; + type: typeof ActionTypes.DeleteElementsByResourceId; payload: DeleteElementsByResourceIdProps; }; @@ -127,7 +127,7 @@ export type CombineElementsProps = { shouldRetainAnimations: boolean; }; export type CombineElementsAction = { - type: typeof actionTypes.COMBINE_ELEMENTS; + type: typeof ActionTypes.CombineElements; payload: CombineElementsProps; }; @@ -135,7 +135,7 @@ export type SetBackgroundElementProps = { elementId: string | null; }; export type SetBackgroundElementAction = { - type: typeof actionTypes.SET_BACKGROUND_ELEMENT; + type: typeof ActionTypes.SetBackgroundElement; payload: SetBackgroundElementProps; }; @@ -145,7 +145,7 @@ export type ArrangeElementProps = { groupId?: string | boolean; }; export type ArrangeElementAction = { - type: typeof actionTypes.ARRANGE_ELEMENT; + type: typeof ActionTypes.ArrangeElement; payload: ArrangeElementProps; }; @@ -154,7 +154,7 @@ export type ArrangeGroupProps = { position: number | string; }; export type ArrangeGroupAction = { - type: typeof actionTypes.ARRANGE_GROUP; + type: typeof ActionTypes.ArrangeGroup; payload: ArrangeGroupProps; }; @@ -164,7 +164,7 @@ export type SetSelectedElementsProps = { withLinked?: boolean; }; export type SetSelectedElementsAction = { - type: typeof actionTypes.SET_SELECTED_ELEMENTS; + type: typeof ActionTypes.SetSelectedElements; payload: SetSelectedElementsProps; }; @@ -172,7 +172,7 @@ export type SelectElementProps = { elementId: string; }; export type SelectElementAction = { - type: typeof actionTypes.SELECT_ELEMENT; + type: typeof ActionTypes.SelectElement; payload: SelectElementProps; }; @@ -180,7 +180,7 @@ export type UnselectElementProps = { elementId: string; }; export type UnselectElementAction = { - type: typeof actionTypes.UNSELECT_ELEMENT; + type: typeof ActionTypes.UnselectElement; payload: UnselectElementProps; }; @@ -189,7 +189,7 @@ export type ToggleElementInSelectionProps = { withLinked?: boolean; }; export type ToggleElementInSelectionAction = { - type: typeof actionTypes.TOGGLE_ELEMENT_IN_SELECTION; + type: typeof ActionTypes.ToggleElementInSelection; payload: ToggleElementInSelectionProps; }; @@ -200,7 +200,7 @@ export type ToggleLayerProps = { withLinked?: boolean; }; export type ToggleLayerAction = { - type: typeof actionTypes.TOGGLE_LAYER; + type: typeof ActionTypes.ToggleLayer; payload: ToggleLayerProps; }; @@ -208,7 +208,7 @@ export type DuplicateElementsByIdProps = { elementIds: string[]; }; export type DuplicateElementsByIdAction = { - type: typeof actionTypes.DUPLICATE_ELEMENTS_BY_ID; + type: typeof ActionTypes.DuplicateElementsById; payload: DuplicateElementsByIdProps; }; @@ -217,7 +217,7 @@ export type UpdateStoryProps = { properties: Partial | StoryUpdater; }; export type UpdateStoryAction = { - type: typeof actionTypes.UPDATE_STORY; + type: typeof ActionTypes.UpdateStory; payload: UpdateStoryProps; }; @@ -225,7 +225,7 @@ export type UpdateAnimationStateProps = { animationState: string; }; export type UpdateAnimationStateAction = { - type: typeof actionTypes.UPDATE_ANIMATION_STATE; + type: typeof ActionTypes.UpdateAnimationState; payload: UpdateAnimationStateProps; }; @@ -233,18 +233,18 @@ export type AddAnimationsProps = { animations: Animation[]; }; export type AddAnimationsAction = { - type: typeof actionTypes.ADD_ANIMATIONS; + type: typeof ActionTypes.AddAnimations; payload: AddAnimationsProps; }; export type CopySelectedElementAction = { - type: typeof actionTypes.COPY_SELECTED_ELEMENT; + type: typeof ActionTypes.CopySelectedElement; payload: null; }; export type RestoreProps = Partial; export type RestoreAction = { - type: typeof actionTypes.RESTORE; + type: typeof ActionTypes.Restore; payload: RestoreProps; }; @@ -253,7 +253,7 @@ export type UpdateElementsByFontFamilyProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsByFontFamilyAction = { - type: typeof actionTypes.UPDATE_ELEMENTS_BY_FONT_FAMILY; + type: typeof ActionTypes.UpdateElementsByFontFamily; payload: UpdateElementsByFontFamilyProps; }; @@ -263,7 +263,7 @@ export type AddGroupProps = { isLocked?: boolean; }; export type AddGroupAction = { - type: typeof actionTypes.ADD_GROUP; + type: typeof ActionTypes.AddGroup; payload: AddGroupProps; }; @@ -272,13 +272,13 @@ export type UpdateGroupProps = { properties: Partial; }; export type UpdateGroupAction = { - type: typeof actionTypes.UPDATE_GROUP; + type: typeof ActionTypes.UpdateGroup; payload: UpdateGroupProps; }; export type DeleteGroupProps = { groupId: string; includeElements?: boolean }; export type DeleteGroupAction = { - type: typeof actionTypes.DELETE_GROUP; + type: typeof ActionTypes.DeleteGroup; payload: DeleteGroupProps; }; @@ -289,7 +289,7 @@ export type DuplicateGroupProps = { isLocked: boolean; }; export type DuplicateGroupAction = { - type: typeof actionTypes.DUPLICATE_GROUP; + type: typeof ActionTypes.DuplicateGroup; payload: DuplicateGroupProps; }; @@ -298,7 +298,7 @@ export type RemoveElementFromGroupProps = { groupId: string; }; export type RemoveElementFromGroupAction = { - type: typeof actionTypes.REMOVE_ELEMENT_FROM_GROUP; + type: typeof ActionTypes.RemoveElementFromGroup; payload: RemoveElementFromGroupProps; }; @@ -308,7 +308,7 @@ export type AddElementsAcrossPagesProps = { elements: Element[]; }; export type AddElementsAcrossPagesAction = { - type: typeof actionTypes.ADD_ELEMENTS_ACROSS_PAGES; + type: typeof ActionTypes.AddElementsAcrossPages; payload: AddElementsAcrossPagesProps; }; From cf5f5332b5728e9a9421ffaf0fcac6e707524879 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 14:34:28 -0300 Subject: [PATCH 59/99] Try adding mod --- .../story-editor/src/app/story/output.d.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 packages/story-editor/src/app/story/output.d.ts diff --git a/packages/story-editor/src/app/story/output.d.ts b/packages/story-editor/src/app/story/output.d.ts new file mode 100644 index 000000000000..2e321d0c6571 --- /dev/null +++ b/packages/story-editor/src/app/story/output.d.ts @@ -0,0 +1,27 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import '@googleforcreators/output'; + +declare module '@googleforcreators/output' { + function getStoryMarkup( + story: '', + pages: [], + metadata: [], + flags: Record + ): string; + export = getStoryMarkup; +} From 39c1b0d1b749eddf710eef211fdb3f09fdcebeb1 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 15:41:50 -0300 Subject: [PATCH 60/99] Fix --- packages/story-editor/src/{app/story => typings}/output.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename packages/story-editor/src/{app/story => typings}/output.d.ts (96%) diff --git a/packages/story-editor/src/app/story/output.d.ts b/packages/story-editor/src/typings/output.d.ts similarity index 96% rename from packages/story-editor/src/app/story/output.d.ts rename to packages/story-editor/src/typings/output.d.ts index 2e321d0c6571..17a96d4219fb 100644 --- a/packages/story-editor/src/app/story/output.d.ts +++ b/packages/story-editor/src/typings/output.d.ts @@ -23,5 +23,5 @@ declare module '@googleforcreators/output' { metadata: [], flags: Record ): string; - export = getStoryMarkup; + export { getStoryMarkup }; } From 5f50244b4b0da38ed4e20ec361f3e5bbc4feed4f Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 15:47:03 -0300 Subject: [PATCH 61/99] Add module for findLastIndex --- packages/story-editor/src/typings/global.d.ts | 25 +++++++++++++++++++ packages/story-editor/tsconfig.json | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packages/story-editor/src/typings/global.d.ts diff --git a/packages/story-editor/src/typings/global.d.ts b/packages/story-editor/src/typings/global.d.ts new file mode 100644 index 000000000000..5269636d8886 --- /dev/null +++ b/packages/story-editor/src/typings/global.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export {}; + +declare global { + interface Array { + findLastIndex( + predicate: (value: T, index: number, obj: T[]) => unknown, + thisArg?: any + ): number; + } +} diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index 398237afd5d0..f21dbf26ecf9 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -23,6 +23,7 @@ "src/app/story/**/*", "src/types/*", "src/constants/*", - "src/utils/*.ts" + "src/utils/*.ts", + "src/typings/*", ] } From a4d4e3ef6883f8fb6937cf954968077eea46c54e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 16:02:10 -0300 Subject: [PATCH 62/99] Remove unknown --- packages/story-editor/src/app/story/storyProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 5f27f90cc122..da3e82e22a59 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -41,7 +41,6 @@ import useLocalAutoSave from './actions/useLocalAutoSave'; interface ProviderProps { storyId: number; initialEdits?: { - [index: string]: unknown; story?: RawStory; }; children: ReactNode; From 9348d4229f72307833f4d5a3768aba87aaaf6dfc Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 17:08:56 -0300 Subject: [PATCH 63/99] Don+t export internal types --- packages/story-editor/src/types/configProvider.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index 09b277537619..fd61bf287c11 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -31,7 +31,7 @@ export interface Capabilities { canManageSettings?: boolean; } -export interface MimeTypes { +interface MimeTypes { audio?: string[]; image?: string[]; caption?: string[]; @@ -39,7 +39,7 @@ export interface MimeTypes { video?: string[]; } -export interface Locale { +interface Locale { locale?: string; dateFormat?: string; timeFormat?: string; @@ -58,7 +58,7 @@ export interface MetaData { publisher?: string; } -export interface Tip { +interface Tip { title: string; figureSrcImg: string; figureAlt: string; From 6109ee204f80d74cef675550ee0524aa3bb0385d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 17:10:57 -0300 Subject: [PATCH 64/99] Use propswithchildren --- packages/story-editor/src/app/story/storyProvider.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index da3e82e22a59..7737f8598a72 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { ReactNode } from 'react'; +import type { PropsWithChildren } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; import type { Animation, Page } from '@googleforcreators/elements'; @@ -43,9 +43,12 @@ interface ProviderProps { initialEdits?: { story?: RawStory; }; - children: ReactNode; } -function StoryProvider({ storyId, initialEdits, children }: ProviderProps) { +function StoryProvider({ + storyId, + initialEdits, + children, +}: PropsWithChildren) { const [hashPageId, setHashPageId] = useHashState('page', null); const { state: reducerState, From d342c32f37fd0fe434865a943d1ef7fa51de4935 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 25 Nov 2022 17:18:13 -0300 Subject: [PATCH 65/99] Add todo --- packages/story-editor/src/app/story/actions/useAutoSave.ts | 2 +- packages/story-editor/src/app/story/actions/useSaveStory.ts | 2 +- .../story-editor/src/app/story/utils/getStoryPropsToSave.ts | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index ba7de2f31672..fabaeab7e70c 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -55,7 +55,7 @@ function useAutoSave({ storyId, pages, story }: AutoSaveProps) { flags, }), ...props, - } as StorySaveData).finally(() => setIsAutoSaving(false)); + }).finally(() => setIsAutoSaving(false)); }, [story, pages, metadata, autoSaveById, storyId, flags] ); diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index 95261fb70ace..a5b0804efcc2 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -103,7 +103,7 @@ function useSaveStory({ // Saving an auto-draft should create a draft by default. status: 'auto-draft' === story.status ? 'draft' : story.status, ...props, - } as StorySaveData) + }) ) .then((data) => { if (!data) { diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts index cec0cd6cfa31..0320b04b4a8b 100644 --- a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts +++ b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts @@ -57,6 +57,7 @@ function getStoryPropsToSave({ 'terms', ]); const products = getAllProducts(pages); + // @todo Remove casting once we have the module. const content = getStoryMarkup(story, pages, metadata, flags) as string; return { content, From 4ca1c9f2ecf9047368113b03f609ce0ecfc4fba1 Mon Sep 17 00:00:00 2001 From: Pascal Birchler Date: Mon, 28 Nov 2022 10:20:29 +0100 Subject: [PATCH 66/99] Try declaring output module in another way --- packages/output/package.json | 1 + .../output.d.ts => output/src/types.ts} | 19 ++++++++------- packages/output/tsconfig.json | 23 +++++++++++++++++++ .../reducers/setSelectedElements.ts | 2 +- packages/story-editor/tsconfig.json | 1 + tsconfig.json | 1 + 6 files changed, 36 insertions(+), 11 deletions(-) rename packages/{story-editor/src/typings/output.d.ts => output/src/types.ts} (66%) create mode 100644 packages/output/tsconfig.json diff --git a/packages/output/package.json b/packages/output/package.json index d0d7bf4904e1..40759529897f 100644 --- a/packages/output/package.json +++ b/packages/output/package.json @@ -31,6 +31,7 @@ }, "main": "dist/index.js", "module": "dist-module/index.js", + "types": "dist-types/types.d.ts", "source": "src/index.js", "publishConfig": { "access": "public" diff --git a/packages/story-editor/src/typings/output.d.ts b/packages/output/src/types.ts similarity index 66% rename from packages/story-editor/src/typings/output.d.ts rename to packages/output/src/types.ts index 17a96d4219fb..01fd4e363c33 100644 --- a/packages/story-editor/src/typings/output.d.ts +++ b/packages/output/src/types.ts @@ -14,14 +14,13 @@ * limitations under the License. */ -import '@googleforcreators/output'; +// Temporary workaround while this package is not fully converted yet. +// Adjust tsconfig.json and "types" field in package.json and then +// delete this file once complete. -declare module '@googleforcreators/output' { - function getStoryMarkup( - story: '', - pages: [], - metadata: [], - flags: Record - ): string; - export { getStoryMarkup }; -} +export declare function getStoryMarkup( + story: '', + pages: [], + metadata: [], + flags: Record +): string; diff --git a/packages/output/tsconfig.json b/packages/output/tsconfig.json new file mode 100644 index 000000000000..eb3533355d7c --- /dev/null +++ b/packages/output/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "rootDir": "src", + "declarationDir": "dist-types" + }, + "references": [ + { "path": "../design-system" }, + { "path": "../elements" }, + { "path": "../fonts" }, + { "path": "../i18n" }, + { "path": "../masks" }, + { "path": "../media" }, + { "path": "../patterns" }, + { "path": "../react" }, + { "path": "../rich-text" }, + { "path": "../units" }, + { "path": "../url" } + ], + "include": [ + "src/types.ts", + ] +} diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index 0184c2f38733..d7685b563143 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -18,6 +18,7 @@ * External dependencies */ import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; +import { elementIs } from '@googleforcreators/elements'; import { produce, current } from 'immer'; /** @@ -25,7 +26,6 @@ import { produce, current } from 'immer'; */ import type { SetSelectedElementsProps, ReducerState } from '../../../../types'; import { intersect } from './utils'; -import {elementIs} from "@googleforcreators/elements"; /** * Set selected elements to the given list of ids. diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index f21dbf26ecf9..c6cc49c2898b 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -11,6 +11,7 @@ { "path": "../i18n" }, { "path": "../masks" }, { "path": "../migration" }, + { "path": "../output" }, { "path": "../patterns" }, { "path": "../react" }, { "path": "../tracking" } diff --git a/tsconfig.json b/tsconfig.json index 90cf9808f2b7..085d3fbf3782 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ { "path": "packages/media" }, { "path": "packages/migration" }, { "path": "packages/moveable" }, + { "path": "packages/output" }, { "path": "packages/patterns" }, { "path": "packages/react" }, { "path": "packages/rich-text" }, From cd45c60c35c9a4cbf1dbaf0b66d0cb9524d4e849 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 28 Nov 2022 14:38:49 -0300 Subject: [PATCH 67/99] Adjust tests --- packages/elements/src/utils/elementIs.ts | 3 ++- .../test/setBackgroundElement.js | 17 ++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/elements/src/utils/elementIs.ts b/packages/elements/src/utils/elementIs.ts index 10921a2f75f7..2904a9d3d362 100644 --- a/packages/elements/src/utils/elementIs.ts +++ b/packages/elements/src/utils/elementIs.ts @@ -38,7 +38,8 @@ function isDefaultBackgroundElement(e: Element): e is DefaultBackgroundElement { } function isBackgroundable(e: Element): e is BackgroundableElement { - return 'isBackground' in e; + // All media is backgroundable. + return 'isBackground' in e || 'resource' in e; } function isProduct(e: Element): e is ProductElement { diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/setBackgroundElement.js b/packages/story-editor/src/app/story/useStoryReducer/test/setBackgroundElement.js index bcc758286e2b..e109ac411169 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/setBackgroundElement.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/setBackgroundElement.js @@ -29,7 +29,7 @@ describe('setBackgroundElement', () => { id: '111', elements: [ { id: '000', isBackground: true }, - { id: '123', opacity: 20 }, + { id: '123', opacity: 20, isBackground: false }, ], }, ], @@ -43,14 +43,17 @@ describe('setBackgroundElement', () => { { id: '123', isBackground: true, opacity: 100 }, ]); }); - it('should not set opacity for new backgroud elements if none was present', () => { + it('should not set opacity for new background elements if none was present', () => { const { restore, setBackgroundElement } = setupReducer(); restore({ pages: [ { id: '111', - elements: [{ id: '000', isBackground: true }, { id: '123' }], + elements: [ + { id: '000', isBackground: true }, + { id: '123', isBackground: false }, + ], }, ], current: '111', @@ -74,7 +77,7 @@ describe('setBackgroundElement', () => { id: '111', elements: [ { id: '123', isBackground: true }, - { id: '456' }, + { id: '456', isBackground: false }, { id: '789' }, ], }, @@ -178,7 +181,7 @@ describe('setBackgroundElement', () => { elements: [ { id: '123', isBackground: true, isDefaultBackground: true }, { id: '456' }, - { id: '789' }, + { id: '789', isBackground: false }, ], }, ], @@ -212,7 +215,7 @@ describe('setBackgroundElement', () => { elements: [ { id: '123', isBackground: true }, { id: '456' }, - { id: '789' }, + { id: '789', isBackground: false }, ], }, ], @@ -240,7 +243,7 @@ describe('setBackgroundElement', () => { elements: [ { id: '123', isBackground: true }, { id: '456' }, - { id: '789' }, + { id: '789', isBackground: false }, ], }, ], From cd1f06b5061ed239ffa688758d23b389a394847a Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 28 Nov 2022 15:05:30 -0300 Subject: [PATCH 68/99] Move story type --- packages/elements/src/types/index.ts | 1 + packages/elements/src/types/story.ts | 82 +++++++++++++++++++ packages/output/src/types.ts | 15 +++- .../app/currentUser/currentUserProvider.tsx | 2 +- .../story-editor/src/app/history/context.ts | 3 +- .../src/app/story/actions/useAutoSave.ts | 4 +- .../src/app/story/actions/useSaveStory.ts | 3 +- .../story-editor/src/app/story/context.ts | 9 +- .../story/useStoryReducer/useStoryReducer.ts | 2 +- .../app/story/utils/getStoryPropsToSave.ts | 7 +- .../story-editor/src/types/apiProvider.ts | 2 +- .../src/types/currentUserProvider.ts | 2 +- .../story-editor/src/types/historyProvider.ts | 3 +- packages/story-editor/src/types/story.ts | 60 ++------------ .../story-editor/src/types/storyProvider.ts | 3 +- 15 files changed, 123 insertions(+), 75 deletions(-) create mode 100644 packages/elements/src/types/story.ts diff --git a/packages/elements/src/types/index.ts b/packages/elements/src/types/index.ts index fc528b15aef2..0b2ec096e988 100644 --- a/packages/elements/src/types/index.ts +++ b/packages/elements/src/types/index.ts @@ -20,3 +20,4 @@ export * from './elementType'; export * from './elementDefinition'; export * from './propTypes'; export * from './page'; +export * from './story'; diff --git a/packages/elements/src/types/story.ts b/packages/elements/src/types/story.ts new file mode 100644 index 000000000000..1715ee09cf16 --- /dev/null +++ b/packages/elements/src/types/story.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * External dependencies + */ +import type { Pattern } from '@googleforcreators/patterns'; +import type { AudioResource } from '@googleforcreators/media'; + +interface FeaturedMedia { + id: number; + height: number; + width: number; + url: string; + needsProxy: boolean; + isExternal: boolean; +} +interface PublisherLogo { + id: number; + height: number; + width: number; + url: string; +} + +interface Author { + id: number; + name: string; +} +interface CurrentStyles { + colors: Pattern[]; +} +interface GlobalStyles { + colors: Pattern[]; + textStyles: Partial; +} +export interface Story { + storyId: number; + title: string; + author: Author; + date: null | string; + modified: string; + excerpt: string; + slug: string; + link: string; + extras: Record; + featuredMedia: FeaturedMedia; + permalinkConfig: null | { + prefix: string; + suffix: string; + }; + publisherLogo: PublisherLogo; + previewLink: string; + editLink: string; + password: string; + embedPostLink: string; + revisions: { + count: number; + }; + currentStoryStyles: CurrentStyles; + globalStoryStyles: GlobalStyles; + taxonomies: string[]; + terms: string[]; + status: string; + backgroundAudio?: { + resource: AudioResource; + }; + autoAdvance?: boolean; + defaultPageDuration?: number; +} diff --git a/packages/output/src/types.ts b/packages/output/src/types.ts index 01fd4e363c33..2b2fefe837e5 100644 --- a/packages/output/src/types.ts +++ b/packages/output/src/types.ts @@ -18,9 +18,18 @@ // Adjust tsconfig.json and "types" field in package.json and then // delete this file once complete. +/** + * External dependencies + */ +import type { Page, Story } from '@googleforcreators/elements'; + +interface MetaData { + publisher?: string; +} + export declare function getStoryMarkup( - story: '', - pages: [], - metadata: [], + story: Story, + pages: Page[], + metadata: MetaData, flags: Record ): string; diff --git a/packages/story-editor/src/app/currentUser/currentUserProvider.tsx b/packages/story-editor/src/app/currentUser/currentUserProvider.tsx index 1a242d81ebba..236191519572 100644 --- a/packages/story-editor/src/app/currentUser/currentUserProvider.tsx +++ b/packages/story-editor/src/app/currentUser/currentUserProvider.tsx @@ -23,7 +23,7 @@ import type { PropsWithChildren } from 'react'; * Internal dependencies */ import { useAPI } from '../api'; -import type { User } from '../../types/configProvider'; +import type { User } from '../../types'; import type { CurrentUserState, UpdateCurrentUserProps, diff --git a/packages/story-editor/src/app/history/context.ts b/packages/story-editor/src/app/history/context.ts index 70ae9a5f44f1..331857835daf 100644 --- a/packages/story-editor/src/app/history/context.ts +++ b/packages/story-editor/src/app/history/context.ts @@ -18,11 +18,12 @@ * External dependencies */ import { createContext } from '@googleforcreators/react'; +import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { HistoryProviderState, Story } from '../../types'; +import type { HistoryProviderState } from '../../types'; export default createContext({ state: { diff --git a/packages/story-editor/src/app/story/actions/useAutoSave.ts b/packages/story-editor/src/app/story/actions/useAutoSave.ts index fabaeab7e70c..e0e316b7748b 100644 --- a/packages/story-editor/src/app/story/actions/useAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useAutoSave.ts @@ -18,7 +18,7 @@ * External dependencies */ import { useCallback, useState } from '@googleforcreators/react'; -import type { Page } from '@googleforcreators/elements'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -26,7 +26,7 @@ import type { Page } from '@googleforcreators/elements'; import { useAPI } from '../../api'; import { useConfig } from '../../config'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; -import type { Story, StorySaveData } from '../../../types'; +import type { StorySaveData } from '../../../types'; interface AutoSaveProps { storyId: number; diff --git a/packages/story-editor/src/app/story/actions/useSaveStory.ts b/packages/story-editor/src/app/story/actions/useSaveStory.ts index a5b0804efcc2..20db4bd5eb3a 100644 --- a/packages/story-editor/src/app/story/actions/useSaveStory.ts +++ b/packages/story-editor/src/app/story/actions/useSaveStory.ts @@ -22,7 +22,7 @@ import { useCallback, useState } from '@googleforcreators/react'; import { getTimeTracker, trackError } from '@googleforcreators/tracking'; import { useSnackbar } from '@googleforcreators/design-system'; import { stripHTML } from '@googleforcreators/dom'; -import type { Page } from '@googleforcreators/elements'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -33,7 +33,6 @@ import useRefreshPostEditURL from '../../../utils/useRefreshPostEditURL'; import getStoryPropsToSave from '../utils/getStoryPropsToSave'; import { useHistory } from '../../history'; import type { - Story, RESTError, StorySaveData, UpdateStoryProps, diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index fb137e9566ff..02f63056416f 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -18,12 +18,17 @@ * External dependencies */ import { createContext } from '@googleforcreators/react'; -import type { Animation, Element, Page } from '@googleforcreators/elements'; +import type { + Animation, + Element, + Page, + Story, +} from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { Story, StoryProviderState } from '../../types'; +import type { StoryProviderState } from '../../types'; import { INITIAL_STATE } from './useStoryReducer/useStoryReducer'; export default createContext({ diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index c1a36facad70..bae6984e8103 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -19,6 +19,7 @@ */ import { useReducer, useMemo } from '@googleforcreators/react'; import { STORY_ANIMATION_STATE } from '@googleforcreators/animation'; +import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -28,7 +29,6 @@ import type { InternalActions, ReducerState, ReducerProviderState, - Story, CopiedElementState, } from '../../../types'; import { DispatchType, exposedActions, internalActions } from './actions'; diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts index 0320b04b4a8b..2ac433e5f861 100644 --- a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts +++ b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts @@ -17,13 +17,13 @@ * External dependencies */ import { getStoryMarkup } from '@googleforcreators/output'; -import type { Page } from '@googleforcreators/elements'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies */ import objectPick from '../../../utils/objectPick'; -import type { Story, StorySaveData, MetaData } from '../../../types'; +import type { StorySaveData, MetaData } from '../../../types'; import getAllProducts from './getAllProducts'; interface StoryPropsToSave { @@ -57,8 +57,7 @@ function getStoryPropsToSave({ 'terms', ]); const products = getAllProducts(pages); - // @todo Remove casting once we have the module. - const content = getStoryMarkup(story, pages, metadata, flags) as string; + const content = getStoryMarkup(story, pages, metadata, flags); return { content, pages, diff --git a/packages/story-editor/src/types/apiProvider.ts b/packages/story-editor/src/types/apiProvider.ts index 42a1a19f763b..3857e1357de2 100644 --- a/packages/story-editor/src/types/apiProvider.ts +++ b/packages/story-editor/src/types/apiProvider.ts @@ -35,7 +35,7 @@ import type { Template } from '@googleforcreators/templates'; */ import type { RawStory, StoryReturnData, StorySaveData } from './story'; import type { PageTemplate, Taxonomy } from './configProvider'; -import type {User} from "./storyEditor"; +import type { User } from './storyEditor'; interface TemplateData { story_data: PageTemplate; diff --git a/packages/story-editor/src/types/currentUserProvider.ts b/packages/story-editor/src/types/currentUserProvider.ts index f95e1bac6034..9c62ca629fbb 100644 --- a/packages/story-editor/src/types/currentUserProvider.ts +++ b/packages/story-editor/src/types/currentUserProvider.ts @@ -16,7 +16,7 @@ /** * Internal dependencies */ -import type { User } from './configProvider'; +import type { User } from './storyEditor'; export interface UpdateCurrentUserProps { mediaOptimization: boolean; diff --git a/packages/story-editor/src/types/historyProvider.ts b/packages/story-editor/src/types/historyProvider.ts index e303c076a45b..5366c499dd2d 100644 --- a/packages/story-editor/src/types/historyProvider.ts +++ b/packages/story-editor/src/types/historyProvider.ts @@ -17,13 +17,12 @@ /** * External dependencies */ -import type { Page } from '@googleforcreators/elements'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies */ import type { ActionType } from '../app/history/reducer'; -import type { Story } from './story'; import type { Capabilities } from './configProvider'; export interface HistoryEntry { diff --git a/packages/story-editor/src/types/story.ts b/packages/story-editor/src/types/story.ts index e8a53604e643..d900ec8c0217 100644 --- a/packages/story-editor/src/types/story.ts +++ b/packages/story-editor/src/types/story.ts @@ -17,9 +17,13 @@ /** * External dependencies */ -import type { Page, ProductData, StoryData } from '@googleforcreators/elements'; +import type { + Page, + ProductData, + StoryData, + Story, +} from '@googleforcreators/elements'; import type { Pattern } from '@googleforcreators/patterns'; -import type { AudioResource } from '@googleforcreators/media'; interface FeaturedMedia { id: number; @@ -29,58 +33,6 @@ interface FeaturedMedia { needsProxy: boolean; isExternal: boolean; } -interface PublisherLogo { - id: number; - height: number; - width: number; - url: string; -} - -interface Author { - id: number; - name: string; -} -interface CurrentStyles { - colors: Pattern[]; -} -interface GlobalStyles { - colors: Pattern[]; - textStyles: Partial; -} -export interface Story { - storyId: number; - title: string; - author: Author; - date: null | string; - modified: string; - excerpt: string; - slug: string; - link: string; - extras: Record; - featuredMedia: FeaturedMedia; - permalinkConfig: null | { - prefix: string; - suffix: string; - }; - publisherLogo: PublisherLogo; - previewLink: string; - editLink: string; - password: string; - embedPostLink: string; - revisions: { - count: number; - }; - currentStoryStyles: CurrentStyles; - globalStoryStyles: GlobalStyles; - taxonomies: string[]; - terms: string[]; - status: string; - backgroundAudio?: { - resource: AudioResource; - }; - autoAdvance?: boolean; - defaultPageDuration?: number; -} // Data required by API callbacks for saving a story. export interface StorySaveData diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index cfae4f9b8f9f..9f933f9b3b75 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -22,13 +22,14 @@ import type { Element, Animation, Group, + Story, } from '@googleforcreators/elements'; import type { ResourceId } from '@googleforcreators/media'; /** * Internal dependencies */ import type { ActionTypes } from '../app/story/useStoryReducer/types'; -import type { Story, StorySaveData } from './story'; +import type { StorySaveData } from './story'; import type { Capabilities } from './configProvider'; export type AddPageProps = { From 3d40af1b333cd11af9998c9eb8d2e537b553e637 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 28 Nov 2022 15:31:29 -0300 Subject: [PATCH 69/99] element-library deps --- packages/element-library/package.json | 2 +- .../src/{constants.js => constants.ts} | 0 packages/element-library/src/types.ts | 23 +++++++++++++++++++ packages/element-library/tsconfig.json | 2 +- .../reducers/combineElements.ts | 4 ++-- packages/story-editor/src/utils/objectPick.ts | 8 ++++--- .../story-editor/src/utils/objectWithout.ts | 2 +- packages/story-editor/tsconfig.json | 1 + tsconfig.json | 1 + 9 files changed, 35 insertions(+), 8 deletions(-) rename packages/element-library/src/{constants.js => constants.ts} (100%) create mode 100644 packages/element-library/src/types.ts diff --git a/packages/element-library/package.json b/packages/element-library/package.json index 1e2568658092..4f1dc2d78bcd 100644 --- a/packages/element-library/package.json +++ b/packages/element-library/package.json @@ -31,7 +31,7 @@ }, "main": "dist/index.js", "module": "dist-module/index.js", - "types": "dist-types/index.d.ts", + "types": "dist-types/types.d.ts", "source": "src/index.js", "publishConfig": { "access": "public" diff --git a/packages/element-library/src/constants.js b/packages/element-library/src/constants.ts similarity index 100% rename from packages/element-library/src/constants.js rename to packages/element-library/src/constants.ts diff --git a/packages/element-library/src/types.ts b/packages/element-library/src/types.ts new file mode 100644 index 000000000000..230f6aa71b55 --- /dev/null +++ b/packages/element-library/src/types.ts @@ -0,0 +1,23 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// Temporary workaround while this package is not fully converted yet. +// Adjust tsconfig.json and "types" field in package.json and then +// delete this file once complete. + +export * from './constants'; + +export {}; diff --git a/packages/element-library/tsconfig.json b/packages/element-library/tsconfig.json index 2906883c4fd0..df221e726ec2 100644 --- a/packages/element-library/tsconfig.json +++ b/packages/element-library/tsconfig.json @@ -18,5 +18,5 @@ { "path": "../transform" }, { "path": "../units" } ], - "include": ["src/types/**/*"] + "include": ["src/constants.ts", "src/types.ts"] } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index da6fbe1c0c5a..3c737ae4f8a4 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -117,11 +117,11 @@ export const combineElements = ( propsFromFirst.push('flip', 'overlay', 'width', 'height', 'x', 'y'); } - const newElement: Element = { + const newElement = { // First copy everything from existing element except if it was default background ...objectWithout(secondElement, ['isDefaultBackground']), // Then set sensible default attributes - ...DEFAULT_ATTRIBUTES_FOR_MEDIA, + ...(DEFAULT_ATTRIBUTES_FOR_MEDIA as Partial), // Then copy all relevant attributes from new element ...objectPick(element, propsFromFirst), } as Element; diff --git a/packages/story-editor/src/utils/objectPick.ts b/packages/story-editor/src/utils/objectPick.ts index f18f0d46c20b..dd409fa40f57 100644 --- a/packages/story-editor/src/utils/objectPick.ts +++ b/packages/story-editor/src/utils/objectPick.ts @@ -14,12 +14,14 @@ * limitations under the License. */ -export default function pick(o: Record, fields: string[] = []) { +export default function pick(o: T, fields: string[] = []): Partial { if (!o || typeof o !== 'object') { return {}; } return Object.assign( {}, - ...fields.map((prop) => (o && prop in o ? { [prop]: o && o[prop] } : {})) - ) as Record; + ...fields.map((prop) => + o && prop in o ? { [prop]: o && o[prop as keyof T] } : {} + ) + ) as Partial; } diff --git a/packages/story-editor/src/utils/objectWithout.ts b/packages/story-editor/src/utils/objectWithout.ts index 36e6d9f508e8..18b0b74d3a20 100644 --- a/packages/story-editor/src/utils/objectWithout.ts +++ b/packages/story-editor/src/utils/objectWithout.ts @@ -17,7 +17,7 @@ export default function objectWithout( obj: T, propertiesToRemove: string[] -) { +): Partial { return Object.keys(obj) .filter((key) => !propertiesToRemove.includes(key)) .reduce((newObj, key) => ({ ...newObj, [key]: obj[key as keyof T] }), {}); diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index 2a080879d61e..d2d0e2dd1650 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -8,6 +8,7 @@ { "path": "../dom" }, { "path": "../design-system" }, { "path": "../elements" }, + { "path": "../element-library" }, { "path": "../i18n" }, { "path": "../masks" }, { "path": "../migration" }, diff --git a/tsconfig.json b/tsconfig.json index 085d3fbf3782..7526b059014a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ { "path": "packages/design-system" }, { "path": "packages/dom" }, { "path": "packages/elements" }, + { "path": "packages/element-library" }, { "path": "packages/fonts" }, { "path": "packages/i18n" }, { "path": "packages/masks" }, From 6eadf16349330e12bd514e15aef26c2193893cc8 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Mon, 28 Nov 2022 15:38:22 -0300 Subject: [PATCH 70/99] restore --- .../src/app/story/useStoryReducer/reducers/restore.ts | 5 +++-- .../src/app/story/useStoryReducer/useStoryReducer.ts | 3 +-- packages/story-editor/src/types/storyProvider.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 03a6d58b85fd..6e40a3997a6c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -18,6 +18,7 @@ * External dependencies */ import { produce } from 'immer'; +import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -37,12 +38,12 @@ import type { RestoreProps, ReducerState } from '../../../../types'; export const restore = ( draft: ReducerState, { pages, current, selection, story, capabilities }: RestoreProps -) => { +): ReducerState | undefined => { if (!Array.isArray(pages) || pages.length === 0) { return undefined; } - const newReducerState = typeof story === 'object' ? story : {}; + const newReducerState = typeof story === 'object' ? story : ({} as Story); const newCapabilities = typeof capabilities === 'object' ? capabilities : {}; const oldCurrent = current ?? draft.current; const newCurrent = pages.some(({ id }) => id === oldCurrent) diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index bae6984e8103..9558ca5cd4bd 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -29,7 +29,6 @@ import type { InternalActions, ReducerState, ReducerProviderState, - CopiedElementState, } from '../../../types'; import { DispatchType, exposedActions, internalActions } from './actions'; import reducer from './reducer'; @@ -41,7 +40,7 @@ export const INITIAL_STATE = { selection: [], story: {} as Story, animationState: STORY_ANIMATION_STATE.RESET as string, - copiedElementState: {} as CopiedElementState, + copiedElementState: {}, }; /** diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 9f933f9b3b75..7bc5d3680c4e 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -420,8 +420,8 @@ export interface ReducerProviderState { export interface CopiedElementState { animations?: Animation[]; - styles: Record; - type: string; + styles?: Record; + type?: string; } export interface ReducerState { story: Story; From eb5b8b02faa88af3fd629fbfd863f06dbfc66475 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 29 Nov 2022 10:07:19 -0300 Subject: [PATCH 71/99] Post-merge import fixes --- .../src/app/story/storyProvider.tsx | 5 +++-- .../app/story/useStoryReducer/reducers/utils.ts | 17 +++++++++-------- .../story-editor/src/types/storyProvider.ts | 16 ++++++---------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 7737f8598a72..6644aa91a0a7 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -19,7 +19,8 @@ */ import type { PropsWithChildren } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; -import type { Animation, Page } from '@googleforcreators/elements'; +import type { Page } from '@googleforcreators/elements'; +import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies @@ -105,7 +106,7 @@ function StoryProvider({ return STABLE_ARRAY; } const animations = (currentPageAnimations || []).reduce( - (acc: Animation[], { targets, ...properties }) => { + (acc: StoryAnimation[], { targets, ...properties }) => { if (targets.some((id) => selection && selection.includes(id))) { return [...acc, { targets, ...properties }]; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index f7a67967a695..bbe833e79e13 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -17,7 +17,8 @@ /** * External dependencies */ -import type { Animation, Element, Page } from '@googleforcreators/elements'; +import type { Element, Page } from '@googleforcreators/elements'; +import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies @@ -119,24 +120,24 @@ export function updateElementWithUpdater( } export function removeAnimationsWithElementIds( - animations: Animation[] = [], + animations: StoryAnimation[] = [], ids: string[] = [] ) { - return animations.reduce((accum: Animation[], animation) => { + return animations.reduce((accum: StoryAnimation[], animation) => { if (ids.some((id) => animation.targets?.includes(id))) { return accum; } return [...accum, animation]; - }, [] as Animation[]); + }, [] as StoryAnimation[]); } export function updateAnimations( - oldAnimations: Animation[], - animationUpdates: Animation[] + oldAnimations: StoryAnimation[], + animationUpdates: StoryAnimation[] ) { const newAnimations = oldAnimations.reduce( - (animations: Animation[], animation) => { - const updatedAnimation = animationUpdates[animation.id] as Animation; + (animations: StoryAnimation[], animation) => { + const updatedAnimation = animationUpdates[animation.id]; // remove animation from lookup delete animationUpdates[animation.id]; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 7bc5d3680c4e..2d08c21ff74c 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -17,14 +17,10 @@ /** * External dependencies */ -import type { - Page, - Element, - Animation, - Group, - Story, -} from '@googleforcreators/elements'; +import type { Page, Element, Group, Story } from '@googleforcreators/elements'; import type { ResourceId } from '@googleforcreators/media'; +import type { StoryAnimation } from '@googleforcreators/animation'; + /** * Internal dependencies */ @@ -231,7 +227,7 @@ export type UpdateAnimationStateAction = { }; export type AddAnimationsProps = { - animations: Animation[]; + animations: StoryAnimation[]; }; export type AddAnimationsAction = { type: typeof ActionTypes.AddAnimations; @@ -419,7 +415,7 @@ export interface ReducerProviderState { } export interface CopiedElementState { - animations?: Animation[]; + animations?: StoryAnimation[]; styles?: Record; type?: string; } @@ -440,7 +436,7 @@ export interface State extends Omit { currentPageNumber: number | null; selectedElementIds: string[]; selectedElements: Element[]; - selectedElementAnimations: Animation[]; + selectedElementAnimations: StoryAnimation[]; hasSelection: boolean; meta: { isSaving: boolean; From b4165592c9bed13f23a064f063749d33ec167256 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 29 Nov 2022 10:33:41 -0300 Subject: [PATCH 72/99] Fixes --- packages/animation/src/types/element.ts | 2 +- packages/story-editor/src/app/story/context.ts | 10 +++------- .../story-editor/src/app/story/storyProvider.tsx | 2 +- .../useStoryReducer/reducers/addAnimations.ts | 4 ++-- .../useStoryReducer/reducers/duplicateGroup.ts | 2 +- .../useStoryReducer/reducers/updateElements.ts | 7 +++++-- .../app/story/useStoryReducer/reducers/utils.ts | 14 +++++++++++--- packages/story-editor/src/types/storyProvider.ts | 6 +++--- 8 files changed, 27 insertions(+), 20 deletions(-) diff --git a/packages/animation/src/types/element.ts b/packages/animation/src/types/element.ts index 875414cb9c82..debc3ee43615 100644 --- a/packages/animation/src/types/element.ts +++ b/packages/animation/src/types/element.ts @@ -19,7 +19,7 @@ */ import type { DimensionableElement } from '@googleforcreators/units'; -export type ElementId = string | number; +export type ElementId = string; export interface Element extends DimensionableElement { id: ElementId; diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index 02f63056416f..2e38db8bb378 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -18,12 +18,8 @@ * External dependencies */ import { createContext } from '@googleforcreators/react'; -import type { - Animation, - Element, - Page, - Story, -} from '@googleforcreators/elements'; +import type { Element, Page, Story } from '@googleforcreators/elements'; +import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies @@ -43,7 +39,7 @@ export default createContext({ currentPageNumber: null, selectedElementIds: [], selectedElements: [] as Element[], - selectedElementAnimations: [] as Animation[], + selectedElementAnimations: [] as StoryAnimation[], hasSelection: false, meta: { isSaving: false, diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 6644aa91a0a7..390c25208182 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -105,7 +105,7 @@ function StoryProvider({ if (isCurrentPageEmpty) { return STABLE_ARRAY; } - const animations = (currentPageAnimations || []).reduce( + const animations: StoryAnimation[] = (currentPageAnimations || []).reduce( (acc: StoryAnimation[], { targets, ...properties }) => { if (targets.some((id) => selection && selection.includes(id))) { return [...acc, { targets, ...properties }]; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index 32fb881d13f3..1f3da5ebc22f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -18,7 +18,7 @@ * External dependencies */ import { produce } from 'immer'; -import type { Animation } from '@googleforcreators/elements'; +import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies @@ -55,7 +55,7 @@ export const addAnimations = ( page.animations = []; } page.animations = page.animations.concat( - exclusion(page.animations, animations) as Animation[] + exclusion(page.animations, animations) as StoryAnimation[] ); }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index cef04bb9d4b7..baac3af372bd 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -74,7 +74,7 @@ export const duplicateGroup = ( element.groupId = groupId; - if (elementAnimations.length) { + if (elementAnimations.length && page.animations) { // If duplicated element has animations, so does existing, so animations // array already exists page.animations.push(...elementAnimations); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index 6ada65df8c2c..c965a63c26ed 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -17,7 +17,10 @@ /** * External dependencies */ -import { StoryAnimationState } from '@googleforcreators/animation'; +import { + StoryAnimation, + StoryAnimationState, +} from '@googleforcreators/animation'; import { produce } from 'immer'; /** @@ -59,7 +62,7 @@ export const updateElements = ( if (!page || !idsToUpdate) { return; } - const animationLookup = {}; + const animationLookup: Record = {}; page.elements .filter(({ id }) => idsToUpdate.includes(id)) .forEach((element) => { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index bbe833e79e13..5fa6c84f7538 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -99,10 +99,18 @@ export function getAbsolutePosition({ } } +interface AllowedProperties extends Partial { + animation: StoryAnimation; +} +function isAnimationUpdate( + props: Partial | Element +): props is AllowedProperties { + return 'animation' in props; +} export function updateElementWithUpdater( element: Element, properties: Partial | ElementUpdater -): null | void { +): null | void | StoryAnimation { const updater = typeof properties === 'function' ? properties(element) : properties; const allowedProperties: Partial | Element = objectWithout( @@ -112,7 +120,7 @@ export function updateElementWithUpdater( if (Object.keys(allowedProperties).length === 0) { return null; } - if ('animation' in allowedProperties) { + if (isAnimationUpdate(allowedProperties)) { return allowedProperties.animation; } Object.assign(element, allowedProperties); @@ -133,7 +141,7 @@ export function removeAnimationsWithElementIds( export function updateAnimations( oldAnimations: StoryAnimation[], - animationUpdates: StoryAnimation[] + animationUpdates: Record ) { const newAnimations = oldAnimations.reduce( (animations: StoryAnimation[], animation) => { diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 2d08c21ff74c..b51520f92ef8 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -19,7 +19,7 @@ */ import type { Page, Element, Group, Story } from '@googleforcreators/elements'; import type { ResourceId } from '@googleforcreators/media'; -import type { StoryAnimation } from '@googleforcreators/animation'; +import type { StoryAnimation, StoryAnimationState } from '@googleforcreators/animation'; /** * Internal dependencies @@ -219,7 +219,7 @@ export type UpdateStoryAction = { }; export type UpdateAnimationStateProps = { - animationState: string; + animationState: StoryAnimationState; }; export type UpdateAnimationStateAction = { type: typeof ActionTypes.UpdateAnimationState; @@ -424,7 +424,7 @@ export interface ReducerState { selection: string[]; current: string | null; pages: Page[]; - animationState: string; + animationState: StoryAnimationState; capabilities: Capabilities; copiedElementState?: CopiedElementState; } From d4bf00c9578fe50db91d3611ebd33e7deaf571db Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Tue, 29 Nov 2022 10:44:45 -0300 Subject: [PATCH 73/99] Add cast --- packages/story-editor/src/app/story/context.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index 2e38db8bb378..20d9337cdb94 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -19,7 +19,7 @@ */ import { createContext } from '@googleforcreators/react'; import type { Element, Page, Story } from '@googleforcreators/elements'; -import type { StoryAnimation } from '@googleforcreators/animation'; +import type { StoryAnimation, StoryAnimationState } from '@googleforcreators/animation'; /** * Internal dependencies @@ -31,7 +31,7 @@ export default createContext({ state: { story: {} as Story, pages: [] as Page[], - animationState: '', + animationState: '' as StoryAnimationState, capabilities: {}, currentPage: null, currentPageId: null, From afa6d03e99238dac4cc895e414e8db9ecddb9087 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 11:29:46 -0300 Subject: [PATCH 74/99] PR feedback --- packages/elements/src/types/story.ts | 2 + packages/media/src/types/resource.ts | 2 - .../src/app/story/effects/useHistoryEntry.ts | 2 +- .../src/app/story/effects/useLoadStory.ts | 2 +- .../src/app/story/storyProvider.tsx | 12 +--- .../storyTriggers/storyTriggersProvider.tsx | 2 +- .../story-editor/src/app/story/useStory.tsx | 2 +- .../useStoryReducer/reducers/addAnimations.ts | 6 +- .../useStoryReducer/reducers/addElements.ts | 6 +- .../reducers/duplicateElementsById.ts | 4 -- .../story/useStoryReducer/reducers/utils.ts | 16 ++--- .../src/app/story/utils/deleteNestedKeys.ts | 3 - .../app/story/utils/getStoryPropsToSave.ts | 4 +- .../app/story/utils/pageContainsBlobUrl.ts | 8 ++- .../story-editor/src/types/configProvider.ts | 3 +- .../story-editor/src/types/storyEditor.ts | 3 + .../story-editor/src/types/storyProvider.ts | 69 ++++++++++--------- 17 files changed, 68 insertions(+), 78 deletions(-) diff --git a/packages/elements/src/types/story.ts b/packages/elements/src/types/story.ts index 1715ee09cf16..cd4b0f061dd8 100644 --- a/packages/elements/src/types/story.ts +++ b/packages/elements/src/types/story.ts @@ -46,6 +46,8 @@ interface GlobalStyles { colors: Pattern[]; textStyles: Partial; } + +// General story post data export interface Story { storyId: number; title: string; diff --git a/packages/media/src/types/resource.ts b/packages/media/src/types/resource.ts index 284569df104b..af2ba65a566b 100644 --- a/packages/media/src/types/resource.ts +++ b/packages/media/src/types/resource.ts @@ -87,8 +87,6 @@ export interface Resource { /** Resource author attribution */ attribution?: Attribution; - poster?: string; - // TODO: Figure out why sometimes _images_ end up having these properties. posterId?: ResourceId; isOptimized?: boolean; diff --git a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts index 8ec604db32fa..21a86591f965 100644 --- a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts +++ b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts @@ -65,7 +65,7 @@ function useHistoryEntry({ actions: { stateToHistory }, } = useHistory(); - const currentHistoryEntryRef = useRef(); + const currentHistoryEntryRef = useRef(null); useEffect(() => { if (currentEntry) { currentHistoryEntryRef.current = structuredClone(currentEntry); diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index 0c9d9a1dc317..e06e1eaeafa4 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -160,7 +160,7 @@ function loadStory( interface LoadStoryProps { storyId: number; - story: RawStory | undefined; + story?: RawStory; shouldLoad: boolean; restore: Restore; } diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 390c25208182..cace59ef94f9 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -102,17 +102,11 @@ function StoryProvider({ const currentPageAnimations = currentPage?.animations; const selectedElementAnimations = useMemo(() => { - if (isCurrentPageEmpty) { + if (isCurrentPageEmpty || selection.length === 0) { return STABLE_ARRAY; } - const animations: StoryAnimation[] = (currentPageAnimations || []).reduce( - (acc: StoryAnimation[], { targets, ...properties }) => { - if (targets.some((id) => selection && selection.includes(id))) { - return [...acc, { targets, ...properties }]; - } - return acc; - }, - [] + const animations: StoryAnimation[] = (currentPageAnimations || []).filter( + ({ targets }) => !targets.some((id) => selection.includes(id)) ); return animations.length > 0 ? animations : STABLE_ARRAY; }, [isCurrentPageEmpty, selection, currentPageAnimations]); diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index 74c29723147f..ea89035c2415 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -44,11 +44,11 @@ function createSubscriptionMap(): Record> { ); } +type StoryTuple = [State, State | null]; function reducer([currentStory]: StoryTuple, updatedStory: State): StoryTuple { return [updatedStory, currentStory]; } -type StoryTuple = [State, State | null]; export function StoryTriggersProvider({ children, story, diff --git a/packages/story-editor/src/app/story/useStory.tsx b/packages/story-editor/src/app/story/useStory.tsx index 32e0a8ae5b93..639960021457 100644 --- a/packages/story-editor/src/app/story/useStory.tsx +++ b/packages/story-editor/src/app/story/useStory.tsx @@ -28,7 +28,7 @@ export function useStory(): StoryProviderState; export function useStory( selector: (state: StoryProviderState) => T | StoryProviderState = identity ) { - return useContextSelector(Context, selector ?? identity); + return useContextSelector(Context, selector); } export default useStory; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index 1f3da5ebc22f..c410d219b57e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -41,10 +41,6 @@ export const addAnimations = ( draft: ReducerState, { animations }: AddAnimationsProps ) => { - if (!Array.isArray(animations)) { - return; - } - const page = draft.pages.find(({ id }) => id === draft.current); if (!page) { @@ -55,7 +51,7 @@ export const addAnimations = ( page.animations = []; } page.animations = page.animations.concat( - exclusion(page.animations, animations) as StoryAnimation[] + exclusion(page.animations, animations) ); }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index e75b5b7829c9..fd9f4008f627 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -47,10 +47,6 @@ export const addElements = ( draft: ReducerState, { elements, pageId, updateSelection = true }: AddElementsProps ) => { - if (!Array.isArray(elements)) { - return; - } - const page = draft.pages.find(({ id }) => pageId ? id === pageId : id === draft.current ); @@ -58,7 +54,7 @@ export const addElements = ( return; } - const newElements = exclusion(page.elements, elements) as Element[]; + const newElements = exclusion(page.elements, elements); if (newElements.length === 0) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index efb9acfeca72..7b10f9146d1a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -39,10 +39,6 @@ export const duplicateElementsById = ( draft: ReducerState, { elementIds }: DuplicateElementsByIdProps ) => { - if (!Array.isArray(elementIds)) { - return; - } - const page = draft.pages.find(({ id }) => id === draft.current); if (!page) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 5fa6c84f7538..08008f41dd0e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -17,7 +17,7 @@ /** * External dependencies */ -import type { Element, Page } from '@googleforcreators/elements'; +import type { Element } from '@googleforcreators/elements'; import type { StoryAnimation } from '@googleforcreators/animation'; /** @@ -29,7 +29,7 @@ import objectWithout from '../../../../utils/objectWithout'; import type { ElementUpdater } from '../../../../types'; export { objectWithout }; -export function intersect(first: string[], ...rest: string[][]) { +export function intersect(first: T[], ...rest: T[][]) { if (!first || !rest?.length) { return first; } @@ -45,8 +45,8 @@ export function isInsideRange(index: number, start: number, end: number) { return index >= start && index <= end; } -export function moveArrayElement( - array: Page[] | Element[], +export function moveArrayElement( + array: T[], oldPosition: number, newPosition: number ) { @@ -187,7 +187,7 @@ interface Entry { * @param entries - set of entries with possible duplicate Ids * @return New set of entries with only unique Ids */ -export function removeDuplicates(entries: Entry[] = []) { +export function removeDuplicates(entries: T[] = []) { // Use only last of multiple elements with same id by turning into an object and getting the values. return Object.values( Object.fromEntries(entries.map((entry) => [entry.id, entry])) @@ -202,7 +202,7 @@ export function removeDuplicates(entries: Entry[] = []) { * @param right - new entries * @return - right exclusion of sets set */ -export function exclusion(left: Entry[] = [], right: Entry[] = []) { +export function exclusion(left: T[] = [], right: T[] = []) { const rightSet = removeDuplicates(right); const leftJoinKeys = left.map(({ id }) => id); return rightSet.filter(({ id }) => !leftJoinKeys.includes(id)); @@ -224,7 +224,7 @@ export function getLastIndexOfGroup({ groupId: string; }) { const isMember = (e: Element) => e.groupId === groupId; - const firstGroupElemenIndex = elements.findIndex(isMember); + const firstGroupElementIndex = elements.findIndex(isMember); const groupSize = elements.filter(isMember).length; - return firstGroupElemenIndex + groupSize - 1; + return firstGroupElementIndex + groupSize - 1; } diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index 917288eeaaca..9d96a64c3c4c 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -22,9 +22,6 @@ */ function deleteNestedKeys>(paths: string[]) { return (object: T) => { - if (!Array.isArray(paths)) { - return; - } paths.forEach((path) => { const keys = path.split('.'); if (!keys.length) { diff --git a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts index 2ac433e5f861..5029943af646 100644 --- a/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts +++ b/packages/story-editor/src/app/story/utils/getStoryPropsToSave.ts @@ -23,14 +23,14 @@ import type { Page, Story } from '@googleforcreators/elements'; * Internal dependencies */ import objectPick from '../../../utils/objectPick'; -import type { StorySaveData, MetaData } from '../../../types'; +import type { StorySaveData, MetaData, Flags } from '../../../types'; import getAllProducts from './getAllProducts'; interface StoryPropsToSave { story: Story; pages: Page[]; metadata: MetaData; - flags: Record; + flags: Flags; } function getStoryPropsToSave({ story, diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts index 619b456c29b1..cc7311940053 100644 --- a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts +++ b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts @@ -17,7 +17,11 @@ * External dependencies */ import { isBlobURL } from '@googleforcreators/media'; -import type { MediaElement, Page } from '@googleforcreators/elements'; +import type { + MediaElement, + Page, + SequenceMediaElement, +} from '@googleforcreators/elements'; function pageContainsBlobUrl(pages: Page[]) { // skip entries that have a blob url @@ -26,7 +30,7 @@ function pageContainsBlobUrl(pages: Page[]) { page.elements.some( (element) => isBlobURL((element as MediaElement)?.resource?.src) || - isBlobURL((element as MediaElement)?.resource?.poster) + isBlobURL((element as SequenceMediaElement)?.resource?.poster) ) ); } diff --git a/packages/story-editor/src/types/configProvider.ts b/packages/story-editor/src/types/configProvider.ts index f75fd3e82ff9..e157567907dc 100644 --- a/packages/story-editor/src/types/configProvider.ts +++ b/packages/story-editor/src/types/configProvider.ts @@ -23,6 +23,7 @@ import type { Page } from '@googleforcreators/elements'; * Internal dependencies */ import type { APICallbacks } from './apiProvider'; +import type { Flags } from './storyEditor'; export interface Capabilities { /** If the user has permissions to upload files. */ @@ -122,6 +123,6 @@ export interface ConfigState { shoppingProvider: string; mediainfoUrl: string; /** Feature flags */ - flags: Record; + flags: Flags; additionalTips: Record; } diff --git a/packages/story-editor/src/types/storyEditor.ts b/packages/story-editor/src/types/storyEditor.ts index 14f9deed49e9..75d122c6fbc5 100644 --- a/packages/story-editor/src/types/storyEditor.ts +++ b/packages/story-editor/src/types/storyEditor.ts @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +export type Flags = Record; + export interface RESTError { message?: string; data?: { diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index b51520f92ef8..cedd0a14bfe6 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -19,7 +19,10 @@ */ import type { Page, Element, Group, Story } from '@googleforcreators/elements'; import type { ResourceId } from '@googleforcreators/media'; -import type { StoryAnimation, StoryAnimationState } from '@googleforcreators/animation'; +import type { + StoryAnimation, + StoryAnimationState, +} from '@googleforcreators/animation'; /** * Internal dependencies @@ -34,7 +37,7 @@ export type AddPageProps = { updateSelection: boolean; }; export type AddPageAction = { - type: typeof ActionTypes.AddPage; + type: ActionTypes.AddPage; payload: AddPageProps; }; @@ -42,7 +45,7 @@ export type DeletePageProps = { pageId: string | null; }; export type DeletePageAction = { - type: typeof ActionTypes.DeletePage; + type: ActionTypes.DeletePage; payload: DeletePageProps; }; @@ -51,7 +54,7 @@ export type UpdatePageProps = { properties: Partial; }; export type UpdatePageAction = { - type: typeof ActionTypes.UpdatePage; + type: ActionTypes.UpdatePage; payload: UpdatePageProps; }; @@ -60,7 +63,7 @@ export type ArrangePageProps = { position: number; }; export type ArrangePageAction = { - type: typeof ActionTypes.ArrangePage; + type: ActionTypes.ArrangePage; payload: ArrangePageProps; }; @@ -68,7 +71,7 @@ export type SetCurrentPageProps = { pageId: string; }; export type SetCurrentPagePageAction = { - type: typeof ActionTypes.SetCurrentPage; + type: ActionTypes.SetCurrentPage; payload: SetCurrentPageProps; }; @@ -79,7 +82,7 @@ export type AddElementsProps = { }; export type AddElementsAction = { - type: typeof ActionTypes.AddElements; + type: ActionTypes.AddElements; payload: AddElementsProps; }; @@ -87,7 +90,7 @@ export type DeleteElementsProps = { elementIds: string[] | null; }; export type DeleteElementsAction = { - type: typeof ActionTypes.DeleteElements; + type: ActionTypes.DeleteElements; payload: DeleteElementsProps; }; @@ -97,7 +100,7 @@ export type UpdateElementsProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsAction = { - type: typeof ActionTypes.UpdateElements; + type: ActionTypes.UpdateElements; payload: UpdateElementsProps; }; @@ -106,7 +109,7 @@ export type UpdateElementsByResourceIdProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsByResourceIdAction = { - type: typeof ActionTypes.UpdateElementsByResourceId; + type: ActionTypes.UpdateElementsByResourceId; payload: UpdateElementsByResourceIdProps; }; @@ -114,7 +117,7 @@ export type DeleteElementsByResourceIdProps = { id: ResourceId; }; export type DeleteElementsByResourceIdAction = { - type: typeof ActionTypes.DeleteElementsByResourceId; + type: ActionTypes.DeleteElementsByResourceId; payload: DeleteElementsByResourceIdProps; }; @@ -124,7 +127,7 @@ export type CombineElementsProps = { shouldRetainAnimations: boolean; }; export type CombineElementsAction = { - type: typeof ActionTypes.CombineElements; + type: ActionTypes.CombineElements; payload: CombineElementsProps; }; @@ -132,7 +135,7 @@ export type SetBackgroundElementProps = { elementId: string | null; }; export type SetBackgroundElementAction = { - type: typeof ActionTypes.SetBackgroundElement; + type: ActionTypes.SetBackgroundElement; payload: SetBackgroundElementProps; }; @@ -142,7 +145,7 @@ export type ArrangeElementProps = { groupId?: string | boolean; }; export type ArrangeElementAction = { - type: typeof ActionTypes.ArrangeElement; + type: ActionTypes.ArrangeElement; payload: ArrangeElementProps; }; @@ -151,7 +154,7 @@ export type ArrangeGroupProps = { position: number | string; }; export type ArrangeGroupAction = { - type: typeof ActionTypes.ArrangeGroup; + type: ActionTypes.ArrangeGroup; payload: ArrangeGroupProps; }; @@ -161,7 +164,7 @@ export type SetSelectedElementsProps = { withLinked?: boolean; }; export type SetSelectedElementsAction = { - type: typeof ActionTypes.SetSelectedElements; + type: ActionTypes.SetSelectedElements; payload: SetSelectedElementsProps; }; @@ -169,7 +172,7 @@ export type SelectElementProps = { elementId: string; }; export type SelectElementAction = { - type: typeof ActionTypes.SelectElement; + type: ActionTypes.SelectElement; payload: SelectElementProps; }; @@ -177,7 +180,7 @@ export type UnselectElementProps = { elementId: string; }; export type UnselectElementAction = { - type: typeof ActionTypes.UnselectElement; + type: ActionTypes.UnselectElement; payload: UnselectElementProps; }; @@ -186,7 +189,7 @@ export type ToggleElementInSelectionProps = { withLinked?: boolean; }; export type ToggleElementInSelectionAction = { - type: typeof ActionTypes.ToggleElementInSelection; + type: ActionTypes.ToggleElementInSelection; payload: ToggleElementInSelectionProps; }; @@ -197,7 +200,7 @@ export type ToggleLayerProps = { withLinked?: boolean; }; export type ToggleLayerAction = { - type: typeof ActionTypes.ToggleLayer; + type: ActionTypes.ToggleLayer; payload: ToggleLayerProps; }; @@ -205,7 +208,7 @@ export type DuplicateElementsByIdProps = { elementIds: string[]; }; export type DuplicateElementsByIdAction = { - type: typeof ActionTypes.DuplicateElementsById; + type: ActionTypes.DuplicateElementsById; payload: DuplicateElementsByIdProps; }; @@ -214,7 +217,7 @@ export type UpdateStoryProps = { properties: Partial | StoryUpdater; }; export type UpdateStoryAction = { - type: typeof ActionTypes.UpdateStory; + type: ActionTypes.UpdateStory; payload: UpdateStoryProps; }; @@ -222,7 +225,7 @@ export type UpdateAnimationStateProps = { animationState: StoryAnimationState; }; export type UpdateAnimationStateAction = { - type: typeof ActionTypes.UpdateAnimationState; + type: ActionTypes.UpdateAnimationState; payload: UpdateAnimationStateProps; }; @@ -230,18 +233,18 @@ export type AddAnimationsProps = { animations: StoryAnimation[]; }; export type AddAnimationsAction = { - type: typeof ActionTypes.AddAnimations; + type: ActionTypes.AddAnimations; payload: AddAnimationsProps; }; export type CopySelectedElementAction = { - type: typeof ActionTypes.CopySelectedElement; + type: ActionTypes.CopySelectedElement; payload: null; }; export type RestoreProps = Partial; export type RestoreAction = { - type: typeof ActionTypes.Restore; + type: ActionTypes.Restore; payload: RestoreProps; }; @@ -250,7 +253,7 @@ export type UpdateElementsByFontFamilyProps = { properties: Partial | ElementUpdater; }; export type UpdateElementsByFontFamilyAction = { - type: typeof ActionTypes.UpdateElementsByFontFamily; + type: ActionTypes.UpdateElementsByFontFamily; payload: UpdateElementsByFontFamilyProps; }; @@ -260,7 +263,7 @@ export type AddGroupProps = { isLocked?: boolean; }; export type AddGroupAction = { - type: typeof ActionTypes.AddGroup; + type: ActionTypes.AddGroup; payload: AddGroupProps; }; @@ -269,13 +272,13 @@ export type UpdateGroupProps = { properties: Partial; }; export type UpdateGroupAction = { - type: typeof ActionTypes.UpdateGroup; + type: ActionTypes.UpdateGroup; payload: UpdateGroupProps; }; export type DeleteGroupProps = { groupId: string; includeElements?: boolean }; export type DeleteGroupAction = { - type: typeof ActionTypes.DeleteGroup; + type: ActionTypes.DeleteGroup; payload: DeleteGroupProps; }; @@ -286,7 +289,7 @@ export type DuplicateGroupProps = { isLocked: boolean; }; export type DuplicateGroupAction = { - type: typeof ActionTypes.DuplicateGroup; + type: ActionTypes.DuplicateGroup; payload: DuplicateGroupProps; }; @@ -295,7 +298,7 @@ export type RemoveElementFromGroupProps = { groupId: string; }; export type RemoveElementFromGroupAction = { - type: typeof ActionTypes.RemoveElementFromGroup; + type: ActionTypes.RemoveElementFromGroup; payload: RemoveElementFromGroupProps; }; @@ -305,7 +308,7 @@ export type AddElementsAcrossPagesProps = { elements: Element[]; }; export type AddElementsAcrossPagesAction = { - type: typeof ActionTypes.AddElementsAcrossPages; + type: ActionTypes.AddElementsAcrossPages; payload: AddElementsAcrossPagesProps; }; From df6dedcaeec8b99232ec72f4f33741ed20a2e91d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 11:52:26 -0300 Subject: [PATCH 75/99] More PR feedback --- .../src/contexts/snackbar/useSnackbar.ts | 2 +- .../design-system/src/utils/localStore.ts | 12 ++++----- .../design-system/src/utils/sessionStore.ts | 2 +- packages/elements/src/types/data.ts | 1 + packages/elements/src/types/story.ts | 2 +- .../canvas/utils/getLayerArrangementProps.js | 12 ++++----- .../utils/test/getLayerArrangementProps.js | 8 +++--- .../src/app/story/actions/useLocalAutoSave.ts | 4 +-- .../storyTriggers/storyTriggersProvider.tsx | 6 ++--- .../useStoryReducer/reducers/test/utils.js | 14 +++++------ .../story/useStoryReducer/reducers/utils.ts | 25 +++++++------------ .../useStoryReducer/test/arrangeElement.js | 12 ++++----- packages/story-editor/src/constants/index.ts | 12 ++++----- .../story-editor/src/types/storyProvider.ts | 5 ++-- 14 files changed, 55 insertions(+), 62 deletions(-) diff --git a/packages/design-system/src/contexts/snackbar/useSnackbar.ts b/packages/design-system/src/contexts/snackbar/useSnackbar.ts index d7df97ecca1a..745f1e5abc0b 100644 --- a/packages/design-system/src/contexts/snackbar/useSnackbar.ts +++ b/packages/design-system/src/contexts/snackbar/useSnackbar.ts @@ -29,5 +29,5 @@ export function useSnackbar(): SnackbarState; export function useSnackbar( selector: (state: SnackbarState) => T | SnackbarState = identity ) { - return useContextSelector(Context, selector ?? identity); + return useContextSelector(Context, selector); } diff --git a/packages/design-system/src/utils/localStore.ts b/packages/design-system/src/utils/localStore.ts index aa0d6eaace46..354e75ec7fa1 100644 --- a/packages/design-system/src/utils/localStore.ts +++ b/packages/design-system/src/utils/localStore.ts @@ -40,17 +40,15 @@ export const LOCAL_STORAGE_PREFIX = { MEDIA_RECORDING_VIDEO_EFFECT: 'web_stories_media_recording_video_effect', }; -function getMessage(err: unknown): string { - return err instanceof Error ? err.message : 'Unknown error'; -} - function getItemByKey(key: string): unknown { let parsed: unknown = null; try { const stored = localStorage.getItem(key); parsed = stored !== null ? JSON.parse(stored) : stored; } catch (err) { - void trackError('local_storage_read', getMessage(err)); + if (err instanceof Error) { + void trackError('local_storage_read', err.message); + } } return parsed; } @@ -59,7 +57,9 @@ function setItemByKey(key: string, data: unknown) { try { localStorage.setItem(key, JSON.stringify(data)); } catch (err) { - void trackError('local_storage_write', getMessage(err)); + if (err instanceof Error) { + void trackError('local_storage_write', err.message); + } } } diff --git a/packages/design-system/src/utils/sessionStore.ts b/packages/design-system/src/utils/sessionStore.ts index 1b333fb17992..1292460b76d1 100644 --- a/packages/design-system/src/utils/sessionStore.ts +++ b/packages/design-system/src/utils/sessionStore.ts @@ -28,7 +28,7 @@ export function getItemByKey(key: string) { try { const stored = window.sessionStorage.getItem(key); if (stored) { - parsed = JSON.parse(stored) as Record; + parsed = JSON.parse(stored) as unknown; } } catch (err) { if (err instanceof Error) { diff --git a/packages/elements/src/types/data.ts b/packages/elements/src/types/data.ts index b8bf9c22f097..0cd41f414da2 100644 --- a/packages/elements/src/types/data.ts +++ b/packages/elements/src/types/data.ts @@ -79,6 +79,7 @@ export interface ProductData { productUrl: string; } +// Data retrieved as part of the raw data from the backend, used for example in the templates, in migration. export interface StoryData { version: number; pages: Page[]; diff --git a/packages/elements/src/types/story.ts b/packages/elements/src/types/story.ts index cd4b0f061dd8..198917a4c796 100644 --- a/packages/elements/src/types/story.ts +++ b/packages/elements/src/types/story.ts @@ -47,7 +47,7 @@ interface GlobalStyles { textStyles: Partial; } -// General story post data +// General story post data as it is in the story state and history entry. export interface Story { storyId: number; title: string; diff --git a/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js b/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js index 03860c5d2303..ac23bd0664bb 100644 --- a/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js +++ b/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js @@ -26,10 +26,10 @@ function getLayerArrangementProps(key, shift, selectedElements, elements) { } let position = null; if (key === 'ArrowUp') { - position = shift ? LAYER_DIRECTIONS.FRONT : LAYER_DIRECTIONS.FORWARD; + position = shift ? LayerDirection.Front : LayerDirection.Forward; } if (key === 'ArrowDown') { - position = shift ? LAYER_DIRECTIONS.BACK : LAYER_DIRECTIONS.BACKWARD; + position = shift ? LayerDirection.Back : LayerDirection.Backward; } if (!position) { return {}; @@ -45,8 +45,8 @@ function getLayerArrangementProps(key, shift, selectedElements, elements) { const isLastInGroup = elements[currentPosition - 1]?.groupId !== groupId; const isFirstInGroup = elements[currentPosition + 1]?.groupId !== groupId; if ( - (isLastInGroup && position === LAYER_DIRECTIONS.BACKWARD) || - (isFirstInGroup && position === LAYER_DIRECTIONS.FORWARD) + (isLastInGroup && position === LayerDirection.Backward) || + (isFirstInGroup && position === LayerDirection.Forward) ) { return { position: currentPosition, @@ -57,7 +57,7 @@ function getLayerArrangementProps(key, shift, selectedElements, elements) { // If the element has a group below, just add it to the group. if ( elements[currentPosition - 1]?.groupId && - position === LAYER_DIRECTIONS.BACKWARD + position === LayerDirection.Backward ) { return { position: currentPosition, @@ -67,7 +67,7 @@ function getLayerArrangementProps(key, shift, selectedElements, elements) { // If the element has a group above, just add it to the group. if ( elements[currentPosition + 1]?.groupId && - position === LAYER_DIRECTIONS.FORWARD + position === LayerDirection.Forward ) { return { position: currentPosition, diff --git a/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js b/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js index 5f5b5461f238..6213cc05a4c2 100644 --- a/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js +++ b/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js @@ -43,10 +43,10 @@ describe('getLayerArrangementProps', () => { ]; expect( getLayerArrangementProps('ArrowUp', false, [{ id: 'b' }], elements) - ).toStrictEqual({ position: LAYER_DIRECTIONS.FORWARD }); + ).toStrictEqual({ position: LayerDirection.Forward }); expect( getLayerArrangementProps('ArrowDown', false, [{ id: 'c' }], elements) - ).toStrictEqual({ position: LAYER_DIRECTIONS.BACKWARD }); + ).toStrictEqual({ position: LayerDirection.Backward }); }); it('should get the layer group and position correctly for first/last layers of the group', () => { @@ -92,7 +92,7 @@ describe('getLayerArrangementProps', () => { [{ id: 'd', groupId: 'g1' }], elements ) - ).toStrictEqual({ position: LAYER_DIRECTIONS.FORWARD }); + ).toStrictEqual({ position: LayerDirection.Forward }); expect( getLayerArrangementProps( 'ArrowDown', @@ -100,7 +100,7 @@ describe('getLayerArrangementProps', () => { [{ id: 'd', groupId: 'g1' }], elements ) - ).toStrictEqual({ position: LAYER_DIRECTIONS.BACKWARD }); + ).toStrictEqual({ position: LayerDirection.Backward }); }); it('should get the layer group and position correctly when moving an element into a group', () => { diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index ca117a292713..e9c75efc521d 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -18,7 +18,7 @@ */ import { useCallback } from '@googleforcreators/react'; import { sessionStore } from '@googleforcreators/design-system'; -import type { Page } from '@googleforcreators/elements'; +import type {Page, Story} from '@googleforcreators/elements'; /** * Internal dependencies @@ -43,7 +43,7 @@ function useLocalAutoSave({ const restoreLocalAutoSave = useCallback(() => { const existingAutoSave = sessionStore.getItemByKey( getSessionStorageKey(storyId, isNew) - ); + ) as { story?: Story, pages?: Page[] }; // If either of the values is missing, nothing to do. if (!existingAutoSave?.story || !existingAutoSave?.pages) { return; diff --git a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx index ea89035c2415..03f01391a238 100644 --- a/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx +++ b/packages/story-editor/src/app/story/storyTriggers/storyTriggersProvider.tsx @@ -79,10 +79,8 @@ export function StoryTriggersProvider({ // Method to push events into the queue const dispatchStoryEvent = useCallback( - (eventType) => { - subscriptionMap[eventType as keyof typeof subscriptionMap]?.forEach( - (listener) => listener(currentStory) - ); + (eventType: string) => { + subscriptionMap[eventType]?.forEach((listener) => listener(currentStory)); }, [subscriptionMap, currentStory] ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/test/utils.js b/packages/story-editor/src/app/story/useStoryReducer/reducers/test/utils.js index bb9d442ebfc0..283c765d4975 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/test/utils.js +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/test/utils.js @@ -28,7 +28,7 @@ import { exclusion, getLastIndexOfGroup, } from '../utils'; -import { LAYER_DIRECTIONS } from '../../../../../constants'; +import { LayerDirection } from '../../../../../constants'; const ABC = ['A', 'B', 'C']; const BCD = ['B', 'C', 'D']; @@ -127,7 +127,7 @@ describe('getAbsolutePosition', () => { currentPosition: 10, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.BACK, + desiredPosition: LayerDirection.Back, }); expect(resultToBack).toBe(0); @@ -135,7 +135,7 @@ describe('getAbsolutePosition', () => { currentPosition: 10, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.FRONT, + desiredPosition: LayerDirection.Front, }); expect(resultToFront).toBe(20); }); @@ -145,7 +145,7 @@ describe('getAbsolutePosition', () => { currentPosition: 10, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.BACKWARD, + desiredPosition: LayerDirection.Backward, }); expect(resultGoingBackward).toBe(9); @@ -153,7 +153,7 @@ describe('getAbsolutePosition', () => { currentPosition: 0, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.BACKWARD, + desiredPosition: LayerDirection.Backward, }); expect(resultGoingBelow).toBe(0); @@ -161,7 +161,7 @@ describe('getAbsolutePosition', () => { currentPosition: 10, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.FORWARD, + desiredPosition: LayerDirection.Forward, }); expect(resultGoingForward).toBe(11); @@ -169,7 +169,7 @@ describe('getAbsolutePosition', () => { currentPosition: 20, minPosition: 0, maxPosition: 20, - desiredPosition: LAYER_DIRECTIONS.FORWARD, + desiredPosition: LayerDirection.Forward, }); expect(resultGoingAbove).toBe(20); }); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 08008f41dd0e..3be948046adc 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -23,7 +23,7 @@ import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies */ -import { LAYER_DIRECTIONS } from '../../../../constants'; +import { LayerDirection } from '../../../../constants'; import { ELEMENT_RESERVED_PROPERTIES } from '../types'; import objectWithout from '../../../../utils/objectWithout'; import type { ElementUpdater } from '../../../../types'; @@ -69,7 +69,7 @@ interface PositionProps { currentPosition: number; minPosition: number; maxPosition: number; - desiredPosition: string | number; + desiredPosition: LayerDirection | number; } export function getAbsolutePosition({ currentPosition, @@ -81,18 +81,14 @@ export function getAbsolutePosition({ return Math.min(maxPosition, Math.max(minPosition, desiredPosition)); } - if (typeof desiredPosition !== 'string') { - return currentPosition; - } - switch (desiredPosition) { - case LAYER_DIRECTIONS.FRONT: + case LayerDirection.Front: return maxPosition; - case LAYER_DIRECTIONS.BACK: + case LayerDirection.Back: return minPosition; - case LAYER_DIRECTIONS.FORWARD: + case LayerDirection.Forward: return Math.min(maxPosition, currentPosition + 1); - case LAYER_DIRECTIONS.BACKWARD: + case LayerDirection.Backward: return Math.max(minPosition, currentPosition - 1); default: return currentPosition; @@ -131,12 +127,9 @@ export function removeAnimationsWithElementIds( animations: StoryAnimation[] = [], ids: string[] = [] ) { - return animations.reduce((accum: StoryAnimation[], animation) => { - if (ids.some((id) => animation.targets?.includes(id))) { - return accum; - } - return [...accum, animation]; - }, [] as StoryAnimation[]); + return animations.filter( + ({ targets }) => !ids.some((id) => targets?.includes(id)) + ); } export function updateAnimations( diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js b/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js index 00542448e234..c89d1a4debf5 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js @@ -311,7 +311,7 @@ describe('arrangeElement', () => { const result = arrangeElement({ elementId: '234', - position: LAYER_DIRECTIONS.FRONT, + position: LayerDirection.Front, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ @@ -329,7 +329,7 @@ describe('arrangeElement', () => { const result = arrangeElement({ elementId: '456', - position: LAYER_DIRECTIONS.BACK, + position: LayerDirection.Back, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ @@ -347,7 +347,7 @@ describe('arrangeElement', () => { const result = arrangeElement({ elementId: '234', - position: LAYER_DIRECTIONS.FORWARD, + position: LayerDirection.Forward, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ @@ -365,7 +365,7 @@ describe('arrangeElement', () => { const result = arrangeElement({ elementId: '345', - position: LAYER_DIRECTIONS.BACKWARD, + position: LayerDirection.Backward, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ @@ -440,7 +440,7 @@ describe('arrangeElement', () => { // Try to move the element just above the background further backwards. const result = arrangeElement({ elementId: '234', - position: LAYER_DIRECTIONS.BACKWARD, + position: LayerDirection.Backward, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ @@ -459,7 +459,7 @@ describe('arrangeElement', () => { // Try to move any non-bg element to position BACK const result = arrangeElement({ elementId: '345', - position: LAYER_DIRECTIONS.BACK, + position: LayerDirection.Back, }); expect(getElementIdsFromCurrentPage(result)).toStrictEqual([ diff --git a/packages/story-editor/src/constants/index.ts b/packages/story-editor/src/constants/index.ts index ae938da9b7c6..abde15a17af7 100644 --- a/packages/story-editor/src/constants/index.ts +++ b/packages/story-editor/src/constants/index.ts @@ -53,12 +53,12 @@ export const DESIGN_SPACE_MARGIN = 48; export const TEXT_SET_SIZE = 150; -export const LAYER_DIRECTIONS = { - FRONT: 'FRONT', - BACK: 'BACK', - FORWARD: 'FORWARD', - BACKWARD: 'BACKWARD', -}; +export enum LayerDirection { + Front = 'FRONT', + Back = 'BACK', + Forward = 'FORWARD', + Backward = 'BACKWARD', +} export const FONT_WEIGHT = { NORMAL: 400, diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index cedd0a14bfe6..53fa97d398dc 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -28,6 +28,7 @@ import type { * Internal dependencies */ import type { ActionTypes } from '../app/story/useStoryReducer/types'; +import type { LayerDirection } from '../constants'; import type { StorySaveData } from './story'; import type { Capabilities } from './configProvider'; @@ -141,7 +142,7 @@ export type SetBackgroundElementAction = { export type ArrangeElementProps = { elementId: string | null; - position: number | string; + position: number | LayerDirection; groupId?: string | boolean; }; export type ArrangeElementAction = { @@ -151,7 +152,7 @@ export type ArrangeElementAction = { export type ArrangeGroupProps = { groupId: string; - position: number | string; + position: number | LayerDirection; }; export type ArrangeGroupAction = { type: ActionTypes.ArrangeGroup; From 07563bf3c6e29b6b4745b89e8a5d165a5412e861 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 12:00:53 -0300 Subject: [PATCH 76/99] More updates --- packages/animation/src/types/animation.ts | 1 - .../design-system/src/contexts/snackbar/snackbarProvider.tsx | 2 +- .../src/app/story/useStoryReducer/reducers/utils.ts | 5 ++++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/animation/src/types/animation.ts b/packages/animation/src/types/animation.ts index 5ea7682f8313..76f6353c2252 100644 --- a/packages/animation/src/types/animation.ts +++ b/packages/animation/src/types/animation.ts @@ -126,5 +126,4 @@ export type AnimationInputWithPreset = AnimationInput & { export type StoryAnimation = AnimationInputWithPreset & { id: string; targets: ElementId[]; - delete?: boolean; }; diff --git a/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx b/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx index aa6555f68abe..4da00578fe8c 100644 --- a/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx +++ b/packages/design-system/src/contexts/snackbar/snackbarProvider.tsx @@ -29,7 +29,7 @@ import Context from './context'; interface SnackbarProviderProps { children: ReactNode; - placement?: string; + placement?: 'bottom' | 'top'; } function SnackbarProvider({ children, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 3be948046adc..5271bf2eee50 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -132,6 +132,9 @@ export function removeAnimationsWithElementIds( ); } +type AnimationToDelete = StoryAnimation & { + delete?: boolean; +}; export function updateAnimations( oldAnimations: StoryAnimation[], animationUpdates: Record @@ -143,7 +146,7 @@ export function updateAnimations( // remove animation from lookup delete animationUpdates[animation.id]; - if (updatedAnimation?.delete) { + if ((updatedAnimation as AnimationToDelete)?.delete) { // delete animation return animations; } else if (updatedAnimation) { From 449bbfe3deec21407eeb7d2b2fa1033f199e2364 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 12:45:17 -0300 Subject: [PATCH 77/99] Fix the story triggers any type. --- .../src/app/story/storyTriggers/useStoryTriggers.ts | 8 ++------ packages/story-editor/src/types/storyTriggers.ts | 3 ++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts index aaa08c677d5a..4183f19a6816 100644 --- a/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts +++ b/packages/story-editor/src/app/story/storyTriggers/useStoryTriggers.ts @@ -25,7 +25,7 @@ import { /** * Internal dependencies */ -import type { StoryTriggersState } from '../../../types'; +import type { Listener, StoryTriggersState } from '../../../types'; import { Context } from './storyTriggersProvider'; export function useStoryTriggers(): StoryTriggersState; @@ -43,7 +43,6 @@ function getDispatch(v: StoryTriggersState) { return v[1]; } -type Listener = (props: T) => void; /** * Example usage: * ```js @@ -55,10 +54,7 @@ type Listener = (props: T) => void; }, []) ) */ -export function useStoryTriggerListener( - eventType: string, - listener: Listener -) { +export function useStoryTriggerListener(eventType: string, listener: Listener) { const addEventListener = useContextSelector(Context, getAddEventListener); useEffect( () => addEventListener(eventType, listener), diff --git a/packages/story-editor/src/types/storyTriggers.ts b/packages/story-editor/src/types/storyTriggers.ts index 53193ead55c6..b1907d991146 100644 --- a/packages/story-editor/src/types/storyTriggers.ts +++ b/packages/story-editor/src/types/storyTriggers.ts @@ -18,8 +18,9 @@ */ import type { State } from './storyProvider'; +export type Listener = (props?: State) => void; export type StoryTriggersState = ( - | ((eventType: string, listener: any) => () => void) + | ((eventType: string, listener: Listener) => () => void) | ((eventType: string) => void) )[]; From ae570f6f3d231c4f5e081d22044c23f053269b7d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 12:56:35 -0300 Subject: [PATCH 78/99] Remove now not needed tests. --- .../useStoryReducer/test/addAnimations.js | 14 ----------- .../story/useStoryReducer/test/addElements.js | 14 ----------- .../test/setSelectedElementsById.js | 25 ------------------- 3 files changed, 53 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/addAnimations.js b/packages/story-editor/src/app/story/useStoryReducer/test/addAnimations.js index 811a74dd3e1b..0fc152e79dce 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/addAnimations.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/addAnimations.js @@ -19,20 +19,6 @@ import { setupReducer } from './_utils'; describe('addAnimations', () => { - it('should ignore non-list arguments', () => { - const { restore, addAnimations } = setupReducer(); - - // Set an initial state with a current page and an animation. - const initialState = restore({ - pages: [{ id: '111', elements: [{ id: '000' }] }], - current: '111', - }); - - const result = addAnimations({ animations: false }); - - expect(result).toStrictEqual(initialState); - }); - it('should ignore an empty list', () => { const { restore, addAnimations } = setupReducer(); diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/addElements.js b/packages/story-editor/src/app/story/useStoryReducer/test/addElements.js index e48b74ca5d1c..e29c850bdb56 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/addElements.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/addElements.js @@ -20,20 +20,6 @@ import { setupReducer } from './_utils'; describe('addElements', () => { - it('should ignore non-list arguments', () => { - const { restore, addElements } = setupReducer(); - - // Set an initial state with a current page and other elements. - const initialState = restore({ - pages: [{ id: '111', elements: [{ id: '000' }] }], - current: '111', - }); - - const result = addElements({ elements: false }); - - expect(result).toStrictEqual(initialState); - }); - it('should ignore an empty list', () => { const { restore, addElements } = setupReducer(); diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/setSelectedElementsById.js b/packages/story-editor/src/app/story/useStoryReducer/test/setSelectedElementsById.js index 35e27e0f25e6..626a3d9e0def 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/setSelectedElementsById.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/setSelectedElementsById.js @@ -157,31 +157,6 @@ describe('setSelectedElementsById', () => { expect(result.selection).toStrictEqual(['e3', 'e2']); }); - it('should ignore non-list arguments', () => { - const { restore, setSelectedElementsById } = setupReducer(); - - // Set an initial state. - restore({ - pages: [ - { - id: '111', - elements: [ - { id: 'e1', isBackground: true }, - { id: 'e2' }, - { id: 'e3' }, - ], - }, - ], - current: '111', - selection: ['e1', 'e2'], - }); - - // Can't clear by setting to null (hint: use clearSelection) - const result = setSelectedElementsById({ elementIds: null }); - - expect(result.selection).toStrictEqual(['e1', 'e2']); - }); - it('should remove background if included among other elements', () => { const { restore, setSelectedElementsById } = setupReducer(); From 4daeae020d7bc02b53686878934497708b6f48f3 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 12:57:38 -0300 Subject: [PATCH 79/99] Remove test. --- .../app/story/utils/test/deleteNestedKeys.js | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/packages/story-editor/src/app/story/utils/test/deleteNestedKeys.js b/packages/story-editor/src/app/story/utils/test/deleteNestedKeys.js index 09e750ac6eb4..6af907682057 100644 --- a/packages/story-editor/src/app/story/utils/test/deleteNestedKeys.js +++ b/packages/story-editor/src/app/story/utils/test/deleteNestedKeys.js @@ -77,30 +77,6 @@ describe('deleteNestedKeys', () => { }); }); - it('should not do anything in case of incorrect paths', () => { - const object = { - bar: 'Hello World', - foo: { - bar: { - a: 'Hello', - b: 'World', - c: '!', - }, - }, - }; - deleteNestedKeys(13)(object); - expect(object).toStrictEqual({ - bar: 'Hello World', - foo: { - bar: { - a: 'Hello', - b: 'World', - c: '!', - }, - }, - }); - }); - it('should delete properties with `null` and `undefined` as values', () => { const object = { bar: 'Hello World', From f01cebfc9e38b0913ae49489f945e5f575eb14c3 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 15:02:51 -0300 Subject: [PATCH 80/99] Fix --- packages/story-editor/src/app/story/storyProvider.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index cace59ef94f9..8e8a17636674 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -105,8 +105,8 @@ function StoryProvider({ if (isCurrentPageEmpty || selection.length === 0) { return STABLE_ARRAY; } - const animations: StoryAnimation[] = (currentPageAnimations || []).filter( - ({ targets }) => !targets.some((id) => selection.includes(id)) + const animations = (currentPageAnimations || []).filter(({ targets }) => + targets.some((id) => selection && selection.includes(id)) ); return animations.length > 0 ? animations : STABLE_ARRAY; }, [isCurrentPageEmpty, selection, currentPageAnimations]); From ac54401dcce0d59497d63c60864ccded4f1051db Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 15:03:58 -0300 Subject: [PATCH 81/99] Import fix --- .../src/app/canvas/utils/getLayerArrangementProps.js | 2 +- .../src/app/canvas/utils/test/getLayerArrangementProps.js | 2 +- .../src/app/story/useStoryReducer/test/arrangeElement.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js b/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js index ac23bd0664bb..f886a7e7a2df 100644 --- a/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js +++ b/packages/story-editor/src/app/canvas/utils/getLayerArrangementProps.js @@ -17,7 +17,7 @@ /** * Internal dependencies */ -import { LAYER_DIRECTIONS } from '../../../constants'; +import { LayerDirection } from '../../../constants'; function getLayerArrangementProps(key, shift, selectedElements, elements) { // This only supports moving single layer. diff --git a/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js b/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js index 6213cc05a4c2..73931dd9e3d6 100644 --- a/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js +++ b/packages/story-editor/src/app/canvas/utils/test/getLayerArrangementProps.js @@ -18,7 +18,7 @@ * Internal dependencies */ import getLayerArrangementProps from '../getLayerArrangementProps'; -import { LAYER_DIRECTIONS } from '../../../../constants'; +import { LayerDirection } from '../../../../constants'; describe('getLayerArrangementProps', () => { it('should do nothing when more or less than one element is selected', () => { diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js b/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js index c89d1a4debf5..23495b9c9ec0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/arrangeElement.js @@ -17,7 +17,7 @@ /** * Internal dependencies */ -import { LAYER_DIRECTIONS } from '../../../../constants'; +import { LayerDirection } from '../../../../constants'; import { setupReducer } from './_utils'; describe('arrangeElement', () => { From df3a94efef738ab1291b934e70da94be6d2ee8dd Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Wed, 30 Nov 2022 15:18:27 -0300 Subject: [PATCH 82/99] Lint fix --- packages/story-editor/src/app/story/storyProvider.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/story-editor/src/app/story/storyProvider.tsx b/packages/story-editor/src/app/story/storyProvider.tsx index 8e8a17636674..011c5f182eee 100644 --- a/packages/story-editor/src/app/story/storyProvider.tsx +++ b/packages/story-editor/src/app/story/storyProvider.tsx @@ -20,7 +20,6 @@ import type { PropsWithChildren } from 'react'; import { useMemo, useEffect } from '@googleforcreators/react'; import type { Page } from '@googleforcreators/elements'; -import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies From e66e4bd6a5a67307149e170e1b968bcf4c4ee885 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 10:40:48 -0300 Subject: [PATCH 83/99] Add cast --- packages/story-editor/src/app/story/utils/deleteNestedKeys.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index 9d96a64c3c4c..f8b290890fe2 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -47,7 +47,7 @@ function deleteNestedKeys>(paths: string[]) { 'object' === typeof nextLastObj[nextLastKey] && nextLastObj[nextLastKey] ) { - delete nextLastObj[nextLastKey][lastKey]; + delete (nextLastObj[nextLastKey] as Record)[lastKey]; } }); }; From d9e166a7530fd87c97074e66147394d9f9712f6e Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 10:46:38 -0300 Subject: [PATCH 84/99] Object to unknown --- .../story-editor/src/app/story/effects/useHistoryEntry.ts | 4 +++- packages/story-editor/src/app/story/utils/deleteNestedKeys.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts index 21a86591f965..0a8bfb081867 100644 --- a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts +++ b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts @@ -82,7 +82,9 @@ function useHistoryEntry({ const deleteKeysFromPages = (list: Page[]) => { // Create a copy of the list not to influence the original. return structuredClone(list).map((page) => { - page.elements.forEach(deleteNestedKeys(ELEMENT_PROPS_TO_IGNORE)); + page.elements.forEach((element) => + deleteNestedKeys(ELEMENT_PROPS_TO_IGNORE)({ ...element }) + ); return page; }); }; diff --git a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts index f8b290890fe2..f9f050bcea45 100644 --- a/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts +++ b/packages/story-editor/src/app/story/utils/deleteNestedKeys.ts @@ -20,7 +20,7 @@ * * Note that this function mutates the original object. */ -function deleteNestedKeys>(paths: string[]) { +function deleteNestedKeys>(paths: string[]) { return (object: T) => { paths.forEach((path) => { const keys = path.split('.'); From 3b0a74551ac7dbd6a210aa1ad63abbda9af59b69 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 11:24:58 -0300 Subject: [PATCH 85/99] Immer fixes --- .../story/useStoryReducer/reducers/addAnimations.ts | 10 +++++++--- .../story/useStoryReducer/reducers/addElements.ts | 10 +++++++--- .../reducers/addElementsAcrossPages.ts | 8 +++++--- .../app/story/useStoryReducer/reducers/addGroup.ts | 10 +++++++--- .../app/story/useStoryReducer/reducers/addPage.ts | 10 +++++++--- .../story/useStoryReducer/reducers/arrangeElement.ts | 10 +++++++--- .../story/useStoryReducer/reducers/arrangeGroup.ts | 10 +++++++--- .../story/useStoryReducer/reducers/arrangePage.ts | 10 +++++++--- .../useStoryReducer/reducers/combineElements.ts | 10 +++++++--- .../useStoryReducer/reducers/copySelectedElement.ts | 6 +++--- .../story/useStoryReducer/reducers/deleteElements.ts | 10 +++++++--- .../reducers/deleteElementsByResourceId.ts | 7 +++++-- .../story/useStoryReducer/reducers/deleteGroup.ts | 10 +++++++--- .../app/story/useStoryReducer/reducers/deletePage.ts | 10 +++++++--- .../reducers/duplicateElementsById.ts | 12 +++++++++--- .../story/useStoryReducer/reducers/duplicateGroup.ts | 10 +++++++--- .../reducers/removeElementFromGroup.ts | 7 +++++-- .../app/story/useStoryReducer/reducers/restore.ts | 10 +++++++--- .../story/useStoryReducer/reducers/selectElement.ts | 10 +++++++--- .../useStoryReducer/reducers/setBackgroundElement.ts | 7 +++++-- .../story/useStoryReducer/reducers/setCurrentPage.ts | 10 +++++++--- .../useStoryReducer/reducers/setSelectedElements.ts | 12 +++++++++--- .../story/useStoryReducer/reducers/toggleElement.ts | 7 +++++-- .../story/useStoryReducer/reducers/toggleLayer.ts | 10 +++++++--- .../useStoryReducer/reducers/unselectElement.ts | 10 +++++++--- .../useStoryReducer/reducers/updateAnimationState.ts | 7 +++++-- .../story/useStoryReducer/reducers/updateElements.ts | 10 +++++++--- .../reducers/updateElementsByFontFamily.ts | 7 +++++-- .../reducers/updateElementsByResourceId.ts | 7 +++++-- .../story/useStoryReducer/reducers/updateGroup.ts | 10 +++++++--- .../app/story/useStoryReducer/reducers/updatePage.ts | 10 +++++++--- .../story/useStoryReducer/reducers/updateStory.ts | 10 +++++++--- packages/story-editor/src/types/storyProvider.ts | 2 ++ 33 files changed, 210 insertions(+), 89 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index c410d219b57e..520f1078dbc0 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -23,7 +23,11 @@ import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies */ -import type { AddAnimationsProps, ReducerState } from '../../../../types'; +import type { + AddAnimationsProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { exclusion } from './utils'; /** @@ -38,7 +42,7 @@ import { exclusion } from './utils'; * Animations will be added to the end of the list of animations on the current page. */ export const addAnimations = ( - draft: ReducerState, + draft: ReducerStateDraft, { animations }: AddAnimationsProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); @@ -55,4 +59,4 @@ export const addAnimations = ( ); }; -export default produce(addAnimations); +export default produce(addAnimations); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index fd9f4008f627..a80f0876afde 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -24,7 +24,11 @@ import { produce } from 'immer'; * Internal dependencies */ import { MAX_PRODUCTS_PER_PAGE } from '../../../../constants'; -import type { AddElementsProps, ReducerState } from '../../../../types'; +import type { + AddElementsProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { exclusion } from './utils'; const isProduct = ({ type }: Element) => type === ElementType.Product; @@ -44,7 +48,7 @@ const isNotProduct = ({ type }: Element) => type !== ElementType.Product; * Selection is set to be exactly the new elements by default. */ export const addElements = ( - draft: ReducerState, + draft: ReducerStateDraft, { elements, pageId, updateSelection = true }: AddElementsProps ) => { const page = draft.pages.find(({ id }) => @@ -99,4 +103,4 @@ export const addElements = ( } }; -export default produce(addElements); +export default produce(addElements); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts index b2dcbe248f21..325abb8687e1 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts @@ -25,7 +25,7 @@ import { produce } from 'immer'; */ import type { AddElementsAcrossPagesProps, - ReducerState, + ReducerState, ReducerStateDraft, } from '../../../../types'; import { addPage } from './addPage'; import { addElements } from './addElements'; @@ -38,7 +38,7 @@ import { addElements } from './addElements'; * Selection is unchanged afterwards. */ const addElementsAcrossPages = ( - draft: ReducerState, + draft: ReducerStateDraft, { page, position, elements }: AddElementsAcrossPagesProps ) => { elements.forEach((element, index) => { @@ -60,4 +60,6 @@ const addElementsAcrossPages = ( }); }; -export default produce(addElementsAcrossPages); +export default produce( + addElementsAcrossPages +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts index 6c7767024efa..c599d72a3f11 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addGroup.ts @@ -22,13 +22,17 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddGroupProps, ReducerState } from '../../../../types'; +import type { + AddGroupProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Add a group to the current page groups list (id, name). */ export const addGroup = ( - draft: ReducerState, + draft: ReducerStateDraft, { groupId, name, isLocked = false }: AddGroupProps ) => { if (!groupId || !name) { @@ -46,4 +50,4 @@ export const addGroup = ( page.groups[groupId] = { name, isLocked }; }; -export default produce(addGroup); +export default produce(addGroup); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts index 553fd3f3d54c..ed6a49a8e806 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addPage.ts @@ -22,7 +22,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { AddPageProps, ReducerState } from '../../../../types'; +import type { + AddPageProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { isInsideRange } from './utils'; /** @@ -37,7 +41,7 @@ import { isInsideRange } from './utils'; * Selection is cleared by default. */ export const addPage = ( - draft: ReducerState, + draft: ReducerStateDraft, { page, position, updateSelection = true }: AddPageProps ) => { // Ensure new page has at least one element @@ -60,4 +64,4 @@ export const addPage = ( } }; -export default produce(addPage); +export default produce(addPage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 9c59620b34e9..3e49bb389805 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -23,7 +23,11 @@ import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { ArrangeElementProps, ReducerState } from '../../../../types'; +import type { + ArrangeElementProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { getAbsolutePosition, moveArrayElement } from './utils'; /** @@ -57,7 +61,7 @@ import { getAbsolutePosition, moveArrayElement } from './utils'; * TODO: Handle multi-element re-order when UX and priority is finalized. */ export const arrangeElement = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId, position, groupId = false }: ArrangeElementProps ) => { if (elementId === null && draft.selection.length !== 1) { @@ -122,4 +126,4 @@ export const arrangeElement = ( page.elements = moveArrayElement(page.elements, currentPosition, newPosition) as Element[]; }; -export default produce(arrangeElement); +export default produce(arrangeElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts index 198c8693cbf2..ec3e42ba5e5a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeGroup.ts @@ -23,14 +23,18 @@ import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { ArrangeGroupProps, ReducerState } from '../../../../types'; +import type { + ArrangeGroupProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { getAbsolutePosition } from './utils'; /** * Move group to a new position */ export const arrangeGroup = ( - draft: ReducerState, + draft: ReducerStateDraft, { groupId, position }: ArrangeGroupProps ) => { if (!groupId) { @@ -78,4 +82,4 @@ export const arrangeGroup = ( elements.splice(newPosition, 0, ...groupSlice); }; -export default produce(arrangeGroup); +export default produce(arrangeGroup); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 6028aa37ccb3..953390bbd133 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -23,7 +23,11 @@ import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { ArrangePageProps, ReducerState } from '../../../../types'; +import type { + ArrangePageProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { isInsideRange, moveArrayElement } from './utils'; /** @@ -39,7 +43,7 @@ import { isInsideRange, moveArrayElement } from './utils'; * TODO: Handle multi-page re-order when UX and priority is finalized. */ export const arrangePage = ( - draft: ReducerState, + draft: ReducerStateDraft, { pageId, position }: ArrangePageProps ) => { // Abort if there's less than two elements (nothing to rearrange) @@ -61,4 +65,4 @@ export const arrangePage = ( draft.pages = moveArrayElement(draft.pages, pageIndex, position) as Page[]; }; -export default produce(arrangePage); +export default produce(arrangePage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 3c737ae4f8a4..c7abee942941 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -29,7 +29,11 @@ import { elementIs } from '@googleforcreators/elements'; */ import objectPick from '../../../../utils/objectPick'; import objectWithout from '../../../../utils/objectWithout'; -import type { CombineElementsProps, ReducerState } from '../../../../types'; +import type { + CombineElementsProps, + ReducerState, + ReducerStateDraft +} from '../../../../types'; import { removeAnimationsWithElementIds } from './utils'; /** @@ -51,7 +55,7 @@ import { removeAnimationsWithElementIds } from './utils'; * Updates selection to only include the second item after merge. */ export const combineElements = ( - draft: ReducerState, + draft: ReducerStateDraft, { firstElement, secondId, @@ -150,4 +154,4 @@ export const combineElements = ( draft.selection = [secondId]; }; -export default produce(combineElements); +export default produce(combineElements); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts index b7b2ff036396..75713909ba6e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/copySelectedElement.ts @@ -23,7 +23,7 @@ import { produce } from 'immer'; * Internal dependencies */ import objectPick from '../../../../utils/objectPick'; -import type { ReducerState } from '../../../../types'; +import type { ReducerState, ReducerStateDraft } from '../../../../types'; export const ATTRIBUTES_TO_COPY = [ 'background', @@ -48,7 +48,7 @@ export const ATTRIBUTES_TO_COPY = [ * Copies the styles and animations of the selected element * on the current page. */ -export const copySelectedElement = (draft: ReducerState) => { +export const copySelectedElement = (draft: ReducerStateDraft) => { // we can only copy one element and it has to exist if (draft.selection?.length !== 1 || !draft.selection[0]) { return; @@ -81,4 +81,4 @@ export const copySelectedElement = (draft: ReducerState) => { }; }; -export default produce(copySelectedElement); +export default produce(copySelectedElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts index 5cef86a2ff28..c50376f635b9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElements.ts @@ -23,7 +23,11 @@ import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { DeleteElementsProps, ReducerState } from '../../../../types'; +import type { + DeleteElementsProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { intersect } from './utils'; /** @@ -45,7 +49,7 @@ import { intersect } from './utils'; * Current page is unchanged. */ export const deleteElements = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementIds }: DeleteElementsProps ) => { const idsToDelete = elementIds === null ? draft.selection : elementIds; @@ -105,4 +109,4 @@ export const deleteElements = ( ); }; -export default produce(deleteElements); +export default produce(deleteElements); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index 808ea1065293..a27c4773a01e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -26,6 +26,7 @@ import { elementIs } from '@googleforcreators/elements'; import type { DeleteElementsByResourceIdProps, ReducerState, + ReducerStateDraft, } from '../../../../types'; /** @@ -38,7 +39,7 @@ import type { * If no element with the given resource id is found, state is changed. */ export const deleteElementsByResourceId = ( - draft: ReducerState, + draft: ReducerStateDraft, { id }: DeleteElementsByResourceIdProps ) => { if (id === null) { @@ -88,4 +89,6 @@ export const deleteElementsByResourceId = ( ); }; -export default produce(deleteElementsByResourceId); +export default produce( + deleteElementsByResourceId +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts index d9a65c5c8e42..ee43dbae543c 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts @@ -22,15 +22,19 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeleteGroupProps, ReducerState } from '../../../../types'; +import type { + DeleteGroupProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { deleteElements } from './deleteElements'; /** * Delete group by id. */ -const deleteGroup = produce( +const deleteGroup = produce( ( - draft: ReducerState, + draft: ReducerStateDraft, { groupId, includeElements = false }: DeleteGroupProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index f4cd9d5ecc20..54e3954f9b96 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -22,7 +22,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DeletePageProps, ReducerState } from '../../../../types'; +import type { + DeletePageProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Delete page by id or delete current page if no id given. @@ -37,7 +41,7 @@ import type { DeletePageProps, ReducerState } from '../../../../types'; * If a page is deleted, selection is cleared. */ export const deletePage = ( - draft: ReducerState, + draft: ReducerStateDraft, { pageId }: DeletePageProps ) => { if (draft.pages.length <= 1) { @@ -62,4 +66,4 @@ export const deletePage = ( draft.selection = []; }; -export default produce(deletePage); +export default produce(deletePage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts index 7b10f9146d1a..d6046c6dd534 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateElementsById.ts @@ -27,7 +27,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { DuplicateElementsByIdProps, ReducerState } from '../../../../types'; +import type { + DuplicateElementsByIdProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Duplicate all elements specified by `elementIds` on the current page. @@ -36,7 +40,7 @@ import type { DuplicateElementsByIdProps, ReducerState } from '../../../../types * If given `elementIds` are not a list, do nothing. */ export const duplicateElementsById = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementIds }: DuplicateElementsByIdProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); @@ -85,4 +89,6 @@ export const duplicateElementsById = ( }); }; -export default produce(duplicateElementsById); +export default produce( + duplicateElementsById +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index baac3af372bd..cbe30a6eead9 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -24,7 +24,11 @@ import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { DuplicateGroupProps, ReducerState } from '../../../../types'; +import type { + DuplicateGroupProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { addGroup } from './addGroup'; /** @@ -32,7 +36,7 @@ import { addGroup } from './addGroup'; * Set selected elements to be the newly created group. */ export const duplicateGroup = ( - draft: ReducerState, + draft: ReducerStateDraft, { oldGroupId, groupId, name, isLocked }: DuplicateGroupProps ) => { if (!oldGroupId || !groupId || !name) { @@ -90,4 +94,4 @@ export const duplicateGroup = ( draft.selection = newElements.map(({ id }) => id); }; -export default produce(duplicateGroup); +export default produce(duplicateGroup); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts index 676157f62e64..fd35fcd5253e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/removeElementFromGroup.ts @@ -25,6 +25,7 @@ import { produce } from 'immer'; import type { RemoveElementFromGroupProps, ReducerState, + ReducerStateDraft, } from '../../../../types'; import { arrangeElement } from './arrangeElement'; import { getLastIndexOfGroup } from './utils'; @@ -33,7 +34,7 @@ import { getLastIndexOfGroup } from './utils'; * Remove element from group. */ export const removeElementFromGroup = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId, groupId }: RemoveElementFromGroupProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); @@ -61,4 +62,6 @@ export const removeElementFromGroup = ( arrangeElement(draft, { elementId, position }); }; -export default produce(removeElementFromGroup); +export default produce( + removeElementFromGroup +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 6e40a3997a6c..9b0387e60bc5 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -23,7 +23,11 @@ import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { RestoreProps, ReducerState } from '../../../../types'; +import type { + RestoreProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Restore internal state completely from given state. @@ -36,7 +40,7 @@ import type { RestoreProps, ReducerState } from '../../../../types'; * - `story` is an object. */ export const restore = ( - draft: ReducerState, + draft: ReducerStateDraft, { pages, current, selection, story, capabilities }: RestoreProps ): ReducerState | undefined => { if (!Array.isArray(pages) || pages.length === 0) { @@ -62,4 +66,4 @@ export const restore = ( }; }; -export default produce(restore); +export default produce(restore); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index 8747be5802ae..c0b3d4324375 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -23,7 +23,11 @@ import { elementIs } from '@googleforcreators/elements'; /** * Internal dependencies */ -import type { SelectElementProps, ReducerState } from '../../../../types'; +import type { + SelectElementProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Add the given id to the current selection. @@ -31,7 +35,7 @@ import type { SelectElementProps, ReducerState } from '../../../../types'; * If no id is given or id is already in the current selection, nothing happens. */ export const selectElement = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId }: SelectElementProps ) => { if (!elementId || draft.selection.includes(elementId)) { @@ -67,4 +71,4 @@ export const selectElement = ( } }; -export default produce(selectElement); +export default produce(selectElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index fbd1e7ac1de2..776ea189893f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -26,6 +26,7 @@ import { elementIs, Element } from '@googleforcreators/elements'; import type { SetBackgroundElementProps, ReducerState, + ReducerStateDraft, } from '../../../../types'; import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; @@ -42,7 +43,7 @@ import { moveArrayElement, removeAnimationsWithElementIds } from './utils'; * element. */ export const setBackgroundElement = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId }: SetBackgroundElementProps ) => { const page = draft.pages.find(({ id }) => id === draft.current); @@ -137,4 +138,6 @@ export const setBackgroundElement = ( } }; -export default produce(setBackgroundElement); +export default produce( + setBackgroundElement +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts index b0753160d8b4..dfcbcc0e2265 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setCurrentPage.ts @@ -22,7 +22,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { SetCurrentPageProps, ReducerState } from '../../../../types'; +import type { + SetCurrentPageProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Set current page to the given id. @@ -32,7 +36,7 @@ import type { SetCurrentPageProps, ReducerState } from '../../../../types'; * If page is changed, selection is cleared */ export const setCurrentPage = ( - draft: ReducerState, + draft: ReducerStateDraft, { pageId }: SetCurrentPageProps ) => { const pageExists = draft.pages.some(({ id }) => id === pageId); @@ -45,4 +49,4 @@ export const setCurrentPage = ( draft.selection = []; }; -export default produce(setCurrentPage); +export default produce(setCurrentPage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts index 5a2590c67123..78e6f320d999 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setSelectedElements.ts @@ -24,7 +24,11 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ -import type { SetSelectedElementsProps, ReducerState } from '../../../../types'; +import type { + SetSelectedElementsProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { intersect } from './utils'; /** @@ -42,7 +46,7 @@ import { intersect } from './utils'; * Current page and pages are unchanged. */ export const setSelectedElements = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementIds, withLinked = false }: SetSelectedElementsProps ) => { const newElementIds = @@ -112,4 +116,6 @@ export const setSelectedElements = ( draft.selection = newSelection; }; -export default produce(setSelectedElements); +export default produce( + setSelectedElements +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts index c88836187bda..f61399a64e6b 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleElement.ts @@ -25,6 +25,7 @@ import { produce } from 'immer'; import type { ToggleElementInSelectionProps, ReducerState, + ReducerStateDraft, } from '../../../../types'; /** @@ -40,7 +41,7 @@ import type { * If no id is given, do nothing. */ export const toggleElement = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId, withLinked = false }: ToggleElementInSelectionProps ) => { if (!elementId) { @@ -108,4 +109,6 @@ export const toggleElement = ( draft.selection = draft.selection.filter((id) => !allIds.includes(id)); }; -export default produce(toggleElement); +export default produce( + toggleElement +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts index d7458497bb9d..0274b6d83b0f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/toggleLayer.ts @@ -22,12 +22,16 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { ToggleLayerProps, ReducerState } from '../../../../types'; +import type { + ToggleLayerProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { toggleElement } from './toggleElement'; import { setSelectedElements } from './setSelectedElements'; export const toggleLayer = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId, metaKey, shiftKey, withLinked = false }: ToggleLayerProps ) => { // Meta pressed. Toggle this layer in the selection. @@ -69,4 +73,4 @@ export const toggleLayer = ( }); }; -export default produce(toggleLayer); +export default produce(toggleLayer); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts index 3b6439fefa13..16c331e7b283 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/unselectElement.ts @@ -22,7 +22,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UnselectElementProps, ReducerState } from '../../../../types'; +import type { + UnselectElementProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Remove the given id from the current selection. @@ -30,7 +34,7 @@ import type { UnselectElementProps, ReducerState } from '../../../../types'; * If no id is given or id is not in the current selection, nothing happens. */ export const unselectElement = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementId }: UnselectElementProps ) => { const index = draft.selection.indexOf(elementId); @@ -40,4 +44,4 @@ export const unselectElement = ( draft.selection.splice(index, 1); }; -export default produce(unselectElement); +export default produce(unselectElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts index ba6bcab77283..b8869acd8c23 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateAnimationState.ts @@ -24,6 +24,7 @@ import { produce } from 'immer'; */ import type { ReducerState, + ReducerStateDraft, UpdateAnimationStateProps, } from '../../../../types'; @@ -32,10 +33,12 @@ import type { * active pages animations. */ export const updateAnimationState = ( - draft: ReducerState, + draft: ReducerStateDraft, { animationState }: UpdateAnimationStateProps ) => { draft.animationState = animationState; }; -export default produce(updateAnimationState); +export default produce( + updateAnimationState +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts index c965a63c26ed..7e8854e22d69 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElements.ts @@ -26,7 +26,11 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { UpdateElementsProps, ReducerState } from '../../../../types'; +import type { + UpdateElementsProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { updateElementWithUpdater, updateAnimations } from './utils'; /** @@ -44,7 +48,7 @@ import { updateElementWithUpdater, updateAnimations } from './utils'; * Current selection and page is unchanged. */ export const updateElements = ( - draft: ReducerState, + draft: ReducerStateDraft, { elementIds, properties: propertiesOrUpdater }: UpdateElementsProps ) => { if ( @@ -84,4 +88,4 @@ export const updateElements = ( } }; -export default produce(updateElements); +export default produce(updateElements); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts index 9deef72a3aff..0c654881e292 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts @@ -25,6 +25,7 @@ import { elementIs } from '@googleforcreators/elements'; */ import type { ReducerState, + ReducerStateDraft, UpdateElementsByFontFamilyProps, } from '../../../../types'; import { updateElementWithUpdater } from './utils'; @@ -43,7 +44,7 @@ import { updateElementWithUpdater } from './utils'; * Current selection and page is unchanged. */ export const updateElementsByFontFamily = ( - draft: ReducerState, + draft: ReducerStateDraft, { family, properties: propertiesOrUpdater }: UpdateElementsByFontFamilyProps ) => { if (!family) { @@ -61,4 +62,6 @@ export const updateElementsByFontFamily = ( }); }; -export default produce(updateElementsByFontFamily); +export default produce( + updateElementsByFontFamily +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index 389a14aebde9..4e1efe4c0d23 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -26,6 +26,7 @@ import { elementIs } from '@googleforcreators/elements'; import type { UpdateElementsByResourceIdProps, ReducerState, + ReducerStateDraft, } from '../../../../types'; import { updateElementWithUpdater } from './utils'; @@ -43,7 +44,7 @@ import { updateElementWithUpdater } from './utils'; * Current selection and page is unchanged. */ export const updateElementsByResourceId = ( - draft: ReducerState, + draft: ReducerStateDraft, { id, properties: propertiesOrUpdater }: UpdateElementsByResourceIdProps ) => { if (!id) { @@ -61,4 +62,6 @@ export const updateElementsByResourceId = ( }); }; -export default produce(updateElementsByResourceId); +export default produce( + updateElementsByResourceId +); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts index c3bc6f644007..895e2cc557c8 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateGroup.ts @@ -22,13 +22,17 @@ import { produce } from 'immer'; /** * Internal dependencies */ -import type { ReducerState, UpdateGroupProps } from '../../../../types'; +import type { + ReducerState, + ReducerStateDraft, + UpdateGroupProps, +} from '../../../../types'; /** * Update group by id. */ export const updateGroup = ( - draft: ReducerState, + draft: ReducerStateDraft, { groupId, properties }: UpdateGroupProps ) => { if (!groupId) { @@ -49,4 +53,4 @@ export const updateGroup = ( Object.assign(groups[groupId], properties); }; -export default produce(updateGroup); +export default produce(updateGroup); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index d4442033df87..5abe74549b0f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -23,7 +23,11 @@ import { produce } from 'immer'; * Internal dependencies */ import { PAGE_RESERVED_PROPERTIES } from '../types'; -import type { UpdatePageProps, ReducerState } from '../../../../types'; +import type { + UpdatePageProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; import { objectWithout } from './utils'; /** @@ -34,7 +38,7 @@ import { objectWithout } from './utils'; * Current page and selection is unchanged. */ export const updatePage = ( - draft: ReducerState, + draft: ReducerStateDraft, { pageId, properties }: UpdatePageProps ) => { const idToUpdate = (pageId === null ? draft.current : pageId) as @@ -48,4 +52,4 @@ export const updatePage = ( Object.assign(page, allowedProperties); }; -export default produce(updatePage); +export default produce(updatePage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index 40e8c3d8e963..04c930c3dbc4 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -22,7 +22,11 @@ import { produce, current } from 'immer'; /** * Internal dependencies */ -import type { UpdateStoryProps, ReducerState } from '../../../../types'; +import type { + UpdateStoryProps, + ReducerState, + ReducerStateDraft, +} from '../../../../types'; /** * Update story properties. @@ -30,7 +34,7 @@ import type { UpdateStoryProps, ReducerState } from '../../../../types'; * No validation is performed and existing values are overwritten. */ export const updateStory = ( - draft: ReducerState, + draft: ReducerStateDraft, { properties }: UpdateStoryProps ) => { // If properties is a callback, replace story with callback response @@ -42,4 +46,4 @@ export const updateStory = ( Object.assign(draft.story, properties); }; -export default produce(updateStory); +export default produce(updateStory); diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 53fa97d398dc..bbbd787debd9 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -23,6 +23,7 @@ import type { StoryAnimation, StoryAnimationState, } from '@googleforcreators/animation'; +import type { Draft } from 'immer'; /** * Internal dependencies @@ -432,6 +433,7 @@ export interface ReducerState { capabilities: Capabilities; copiedElementState?: CopiedElementState; } +export type ReducerStateDraft = Draft; export interface State extends Omit { currentPage: Page | null; From c5931474af846b619e1c70101c19797ddb34a99d Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 14:54:06 -0300 Subject: [PATCH 86/99] PR feedback --- packages/elements/src/utils/elementIs.ts | 7 ++++++- .../src/app/story/effects/useHistoryEntry.ts | 6 +++--- .../story-editor/src/app/story/effects/useLoadStory.ts | 9 ++++----- .../app/story/useStoryReducer/reducers/addAnimations.ts | 3 +-- .../app/story/useStoryReducer/reducers/arrangeElement.ts | 7 +++---- .../app/story/useStoryReducer/reducers/arrangePage.ts | 3 +-- .../story/useStoryReducer/reducers/combineElements.ts | 5 +---- .../reducers/deleteElementsByResourceId.ts | 2 +- .../src/app/story/useStoryReducer/reducers/deletePage.ts | 2 +- .../app/story/useStoryReducer/reducers/duplicateGroup.ts | 2 -- .../src/app/story/useStoryReducer/reducers/restore.ts | 4 ++-- .../app/story/useStoryReducer/reducers/selectElement.ts | 2 +- .../useStoryReducer/reducers/setBackgroundElement.ts | 6 +++--- .../reducers/updateElementsByFontFamily.ts | 2 +- .../reducers/updateElementsByResourceId.ts | 2 +- .../src/app/story/useStoryReducer/reducers/updatePage.ts | 4 +--- .../src/app/story/utils/pageContainsBlobUrl.ts | 8 +++++--- packages/story-editor/src/types/story.ts | 3 ++- packages/story-editor/src/types/storyProvider.ts | 2 +- packages/story-editor/src/utils/getUniquePresets.ts | 9 +++++---- packages/story-editor/src/utils/objectPick.ts | 8 ++++---- packages/story-editor/tsconfig.json | 3 +-- 22 files changed, 48 insertions(+), 51 deletions(-) diff --git a/packages/elements/src/utils/elementIs.ts b/packages/elements/src/utils/elementIs.ts index 2904a9d3d362..616b3632aca5 100644 --- a/packages/elements/src/utils/elementIs.ts +++ b/packages/elements/src/utils/elementIs.ts @@ -22,7 +22,7 @@ import type { Element, MediaElement, TextElement, - ProductElement, + ProductElement, SequenceMediaElement, } from '../types'; function isMediaElement(e: Element): e is MediaElement { @@ -46,12 +46,17 @@ function isProduct(e: Element): e is ProductElement { return 'product' in e; } +function isSequenceMediaElement(e: MediaElement): e is SequenceMediaElement { + return 'poster' in e.resource; +} + const elementIs = { media: isMediaElement, text: isTextElement, defaultBackground: isDefaultBackgroundElement, backgroundable: isBackgroundable, product: isProduct, + sequenceMedia: isSequenceMediaElement, }; export default elementIs; diff --git a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts index 0a8bfb081867..1bd074448c4b 100644 --- a/packages/story-editor/src/app/story/effects/useHistoryEntry.ts +++ b/packages/story-editor/src/app/story/effects/useHistoryEntry.ts @@ -104,9 +104,9 @@ function useHistoryEntry({ story, capabilities, }; - const onlyPagesChanged = Object.keys(withoutPages).every( - (key) => - JSON.stringify(withoutPages[key as keyof typeof withoutPages]) === + const onlyPagesChanged = Object.entries(withoutPages).every( + ([key, value]) => + JSON.stringify(value) === JSON.stringify( currentHistoryEntryRef.current?.[key as keyof HistoryEntry] ) diff --git a/packages/story-editor/src/app/story/effects/useLoadStory.ts b/packages/story-editor/src/app/story/effects/useLoadStory.ts index e06e1eaeafa4..4a21f86ac4b5 100644 --- a/packages/story-editor/src/app/story/effects/useLoadStory.ts +++ b/packages/story-editor/src/app/story/effects/useLoadStory.ts @@ -19,8 +19,7 @@ */ import { useEffect } from '@googleforcreators/react'; import { migrate } from '@googleforcreators/migration'; -import { createPage } from '@googleforcreators/elements'; -import type { Pattern } from '@googleforcreators/patterns'; +import { createPage, TextElement } from '@googleforcreators/elements'; /** * Internal dependencies @@ -102,10 +101,10 @@ function loadStory( // Otherwise ensure the saved presets are unique. const newGlobalStoryStyles = { colors: globalStoryStyles.colors - ? (getUniquePresets(globalStoryStyles.colors) as Pattern[]) + ? getUniquePresets(globalStoryStyles.colors) : [], textStyles: globalStoryStyles.textStyles - ? (getUniquePresets(globalStoryStyles.textStyles) as Partial[]) + ? getUniquePresets>(globalStoryStyles.textStyles) : [], }; @@ -131,7 +130,7 @@ function loadStory( revisions, currentStoryStyles: { colors: storyData?.currentStoryStyles?.colors - ? (getUniquePresets(storyData.currentStoryStyles.colors) as Pattern[]) + ? getUniquePresets(storyData.currentStoryStyles.colors) : [], }, globalStoryStyles: newGlobalStoryStyles, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts index 520f1078dbc0..fabbccfc7797 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addAnimations.ts @@ -18,7 +18,6 @@ * External dependencies */ import { produce } from 'immer'; -import type { StoryAnimation } from '@googleforcreators/animation'; /** * Internal dependencies @@ -55,7 +54,7 @@ export const addAnimations = ( page.animations = []; } page.animations = page.animations.concat( - exclusion(page.animations, animations) + exclusion(page.animations, animations) ); }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 3e49bb389805..0d96176eb0e7 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -18,7 +18,6 @@ * External dependencies */ import { produce } from 'immer'; -import type { Element } from '@googleforcreators/elements'; /** * Internal dependencies @@ -104,10 +103,10 @@ export const arrangeElement = ( // Update group id on current element if (groupId) { // Can only change groups to a group that exists - if (!page.groups?.[groupId as string]) { + if (!page.groups?.groupId) { return; } - page.elements[currentPosition].groupId = groupId as string; + page.elements[currentPosition].groupId = groupId; } else if (groupId === undefined || groupId === null) { delete page.elements[currentPosition].groupId; } @@ -123,7 +122,7 @@ export const arrangeElement = ( } // Then reorder if relevant - page.elements = moveArrayElement(page.elements, currentPosition, newPosition) as Element[]; + page.elements = moveArrayElement(page.elements, currentPosition, newPosition); }; export default produce(arrangeElement); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts index 953390bbd133..dcd4fa09f11f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangePage.ts @@ -18,7 +18,6 @@ * External dependencies */ import { produce } from 'immer'; -import type { Page } from '@googleforcreators/elements'; /** * Internal dependencies @@ -62,7 +61,7 @@ export const arrangePage = ( return; } - draft.pages = moveArrayElement(draft.pages, pageIndex, position) as Page[]; + draft.pages = moveArrayElement(draft.pages, pageIndex, position); }; export default produce(arrangePage); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index c7abee942941..6c4c1ecb75a3 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -105,10 +105,7 @@ export const combineElements = ( ]; // If the element we're dropping into is not background, maintain link and border. - if ( - !('isBackground' in secondElement) || - (elementIs.backgroundable(secondElement) && !secondElement.isBackground) - ) { + if (elementIs.backgroundable(secondElement) && !secondElement.isBackground) { propsFromFirst.push('link'); propsFromFirst.push('border'); if (canSupportMultiBorder(secondElement)) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index a27c4773a01e..aa2395d17653 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -48,7 +48,7 @@ export const deleteElementsByResourceId = ( const hasElementWithResourceId = draft.pages.some((page) => page.elements.some( - (element) => elementIs.media(element) && element.resource?.id === id + (element) => elementIs.media(element) && element.resource.id === id ) ); diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts index 54e3954f9b96..9a8776b77b65 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deletePage.ts @@ -48,7 +48,7 @@ export const deletePage = ( return; } - const idToDelete = (pageId === null ? draft.current : pageId); + const idToDelete = pageId === null ? draft.current : pageId; const pageIndex = draft.pages.findIndex(({ id }) => id === idToDelete); if (pageIndex === -1) { diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts index cbe30a6eead9..aff1388ff7fb 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/duplicateGroup.ts @@ -79,8 +79,6 @@ export const duplicateGroup = ( element.groupId = groupId; if (elementAnimations.length && page.animations) { - // If duplicated element has animations, so does existing, so animations - // array already exists page.animations.push(...elementAnimations); } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts index 9b0387e60bc5..af80e7d2c5e3 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/restore.ts @@ -47,7 +47,7 @@ export const restore = ( return undefined; } - const newReducerState = typeof story === 'object' ? story : ({} as Story); + const newStory = typeof story === 'object' ? story : ({} as Story); const newCapabilities = typeof capabilities === 'object' ? capabilities : {}; const oldCurrent = current ?? draft.current; const newCurrent = pages.some(({ id }) => id === oldCurrent) @@ -59,7 +59,7 @@ export const restore = ( pages, current: newCurrent, selection: newSelection, - story: newReducerState, + story: newStory, animationState: draft.animationState, capabilities: newCapabilities, copiedElementState: {}, diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts index c0b3d4324375..94a25b2a01fa 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/selectElement.ts @@ -38,7 +38,7 @@ export const selectElement = ( draft: ReducerStateDraft, { elementId }: SelectElementProps ) => { - if (!elementId || draft.selection.includes(elementId)) { + if (draft.selection.includes(elementId)) { return; } diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts index 776ea189893f..7f086dced450 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/setBackgroundElement.ts @@ -127,13 +127,13 @@ export const setBackgroundElement = ( // Remove any applied background animations // or exising element animations. - const backgroundElementId = page.elements.find( + const backgroundElement = page.elements.find( (element) => elementIs.backgroundable(element) && element.isBackground ); - if (backgroundElementId) { + if (backgroundElement) { page.animations = removeAnimationsWithElementIds(page.animations, [ elementId as string, - backgroundElementId.id, + backgroundElement.id, ]); } }; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts index 0c654881e292..03ded95424c2 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByFontFamily.ts @@ -54,7 +54,7 @@ export const updateElementsByFontFamily = ( draft.pages.forEach((page) => { page.elements .filter( - (element) => elementIs.text(element) && element.font?.family === family + (element) => elementIs.text(element) && element.font.family === family ) .forEach((element) => updateElementWithUpdater(element, propertiesOrUpdater) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts index 4e1efe4c0d23..59217c792b12 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateElementsByResourceId.ts @@ -54,7 +54,7 @@ export const updateElementsByResourceId = ( draft.pages.forEach((page) => { page.elements .filter( - (element) => elementIs.media(element) && element.resource?.id === id + (element) => elementIs.media(element) && element.resource.id === id ) .forEach((element) => updateElementWithUpdater(element, propertiesOrUpdater) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts index 5abe74549b0f..cada0adda61f 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updatePage.ts @@ -41,9 +41,7 @@ export const updatePage = ( draft: ReducerStateDraft, { pageId, properties }: UpdatePageProps ) => { - const idToUpdate = (pageId === null ? draft.current : pageId) as - | string - | undefined; + const idToUpdate = pageId === null ? (draft.current as string) : pageId; const page = draft.pages.find(({ id }) => id === idToUpdate); if (!page) { return; diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts index cc7311940053..05d8f7e99561 100644 --- a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts +++ b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts @@ -18,10 +18,10 @@ */ import { isBlobURL } from '@googleforcreators/media'; import type { - MediaElement, Page, SequenceMediaElement, } from '@googleforcreators/elements'; +import { elementIs } from '@googleforcreators/elements'; function pageContainsBlobUrl(pages: Page[]) { // skip entries that have a blob url @@ -29,8 +29,10 @@ function pageContainsBlobUrl(pages: Page[]) { return pages.some((page) => page.elements.some( (element) => - isBlobURL((element as MediaElement)?.resource?.src) || - isBlobURL((element as SequenceMediaElement)?.resource?.poster) + elementIs.media(element) && + (isBlobURL(element.resource.src) || + (elementIs.sequenceMedia(element) && + isBlobURL((element as SequenceMediaElement)?.resource?.poster))) ) ); } diff --git a/packages/story-editor/src/types/story.ts b/packages/story-editor/src/types/story.ts index d900ec8c0217..2d405cfc0420 100644 --- a/packages/story-editor/src/types/story.ts +++ b/packages/story-editor/src/types/story.ts @@ -22,6 +22,7 @@ import type { ProductData, StoryData, Story, + TextElement, } from '@googleforcreators/elements'; import type { Pattern } from '@googleforcreators/patterns'; @@ -98,7 +99,7 @@ export interface RawStory { storyData: StoryData; stylePresets: { colors?: Pattern[]; - textStyles?: Partial[]; + textStyles?: Partial[]; }; previewLink: string; editLink: string; diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index bbbd787debd9..47548403f65f 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -144,7 +144,7 @@ export type SetBackgroundElementAction = { export type ArrangeElementProps = { elementId: string | null; position: number | LayerDirection; - groupId?: string | boolean; + groupId?: string | false; }; export type ArrangeElementAction = { type: ActionTypes.ArrangeElement; diff --git a/packages/story-editor/src/utils/getUniquePresets.ts b/packages/story-editor/src/utils/getUniquePresets.ts index 94e5e3694e5a..44cac3d42b65 100644 --- a/packages/story-editor/src/utils/getUniquePresets.ts +++ b/packages/story-editor/src/utils/getUniquePresets.ts @@ -17,12 +17,13 @@ * External dependencies */ import type { Pattern } from '@googleforcreators/patterns'; +import type { TextElement } from '@googleforcreators/elements'; -function getUniquePresets(presets: Pattern[] | Partial[]) { +function getUniquePresets>( + presets: T[] +): T[] { const list = presets.map((preset) => JSON.stringify(preset)); - return Array.from(new Set(list)).map( - (preset) => JSON.parse(preset) as Pattern | Partial - ); + return Array.from(new Set(list)).map((preset) => JSON.parse(preset) as T); } export default getUniquePresets; diff --git a/packages/story-editor/src/utils/objectPick.ts b/packages/story-editor/src/utils/objectPick.ts index dd409fa40f57..562a7a4dda7b 100644 --- a/packages/story-editor/src/utils/objectPick.ts +++ b/packages/story-editor/src/utils/objectPick.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -export default function pick(o: T, fields: string[] = []): Partial { - if (!o || typeof o !== 'object') { - return {}; - } +export default function pick( + o: T, + fields: string[] = [] +): Partial { return Object.assign( {}, ...fields.map((prop) => diff --git a/packages/story-editor/tsconfig.json b/packages/story-editor/tsconfig.json index f469d58cddec..eff6aa3ecf27 100644 --- a/packages/story-editor/tsconfig.json +++ b/packages/story-editor/tsconfig.json @@ -23,8 +23,7 @@ "src/app/currentUser/*", "src/app/helpCenter/**/*", "src/app/history", - "src/app/story/*", - "src/app/story/**/*", + "src/app/story", "src/types/*", "src/constants/*", "src/utils/*.ts", From 8fc1276d7bd3f79f3a120cb987cd3ec0c4f3fa95 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:07:29 -0300 Subject: [PATCH 87/99] More fixes --- .../reducers/deleteElementsByResourceId.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts index aa2395d17653..922c21c6ae23 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteElementsByResourceId.ts @@ -56,7 +56,7 @@ export const deleteElementsByResourceId = ( return; } - const idsToDelete: string[] = []; + const deletedElementIds: string[] = []; draft.pages.forEach((page) => { const { elements, animations } = page; @@ -66,7 +66,7 @@ export const deleteElementsByResourceId = ( page.elements = elements.filter((element) => { if (elementIs.media(element) && element.resource?.id === id) { - idsToDelete.push(element.id); + deletedElementIds.push(element.id); return false; } return true; @@ -79,13 +79,13 @@ export const deleteElementsByResourceId = ( // Remove animations associated with elements if (animations) { page.animations = animations.filter((anim) => - anim.targets.some((elementId) => !idsToDelete.includes(elementId)) + anim.targets.some((elementId) => !deletedElementIds.includes(elementId)) ); } }); draft.selection = draft.selection.filter( - (selectedId) => !idsToDelete.includes(selectedId) + (selectedId) => !deletedElementIds.includes(selectedId) ); }; From 2d80eaa61df96b97b2e256a730c2b3e09275e388 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:11:36 -0300 Subject: [PATCH 88/99] More immer fixes --- .../src/app/story/useStoryReducer/reducers/updateStory.ts | 5 +++-- packages/story-editor/src/types/storyProvider.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index 04c930c3dbc4..45ae88d8542a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -17,7 +17,8 @@ /** * External dependencies */ -import { produce, current } from 'immer'; +import { produce, current, Draft } from 'immer'; +import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -39,7 +40,7 @@ export const updateStory = ( ) => { // If properties is a callback, replace story with callback response if (typeof properties === 'function') { - draft.story = properties(current(draft.story)); + draft.story = properties>(current(draft.story)); return; } // Otherwise copy all the properties into the existing story object diff --git a/packages/story-editor/src/types/storyProvider.ts b/packages/story-editor/src/types/storyProvider.ts index 47548403f65f..805cd75c31cd 100644 --- a/packages/story-editor/src/types/storyProvider.ts +++ b/packages/story-editor/src/types/storyProvider.ts @@ -214,7 +214,7 @@ export type DuplicateElementsByIdAction = { payload: DuplicateElementsByIdProps; }; -type StoryUpdater = (story: Story) => Story; +type StoryUpdater = (story: T) => T; export type UpdateStoryProps = { properties: Partial | StoryUpdater; }; From b1cc98f459660372e8fa0bbaa7e814208638dafd Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:14:00 -0300 Subject: [PATCH 89/99] ShoppingAttachment --- packages/elements/src/types/page.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/elements/src/types/page.ts b/packages/elements/src/types/page.ts index e77048c05c9a..ab4c8b64d34e 100644 --- a/packages/elements/src/types/page.ts +++ b/packages/elements/src/types/page.ts @@ -66,4 +66,8 @@ export interface Page { ctaText: string; theme: string; }; + shoppingAttachment?: { + ctaText: string; + theme: string; + }; } From 9ca896a1c96279f03ac11a7f42e03b60b50f4516 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:33:29 -0300 Subject: [PATCH 90/99] Revert --- .../story-editor/src/app/story/utils/pageContainsBlobUrl.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts index 05d8f7e99561..003abf125419 100644 --- a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts +++ b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts @@ -30,7 +30,7 @@ function pageContainsBlobUrl(pages: Page[]) { page.elements.some( (element) => elementIs.media(element) && - (isBlobURL(element.resource.src) || + (isBlobURL(element.resource?.src) || (elementIs.sequenceMedia(element) && isBlobURL((element as SequenceMediaElement)?.resource?.poster))) ) From 8e97a9ebe686ee1fe4df3f4e63efe88fc92f1b15 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:42:18 -0300 Subject: [PATCH 91/99] Test fixes --- .../useStoryReducer/reducers/addElements.ts | 3 ++- .../reducers/arrangeElement.ts | 2 +- .../test/addElementToSelection.js | 24 ------------------- .../test/duplicateElementsById.js | 24 ------------------- 4 files changed, 3 insertions(+), 50 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts index a80f0876afde..065d41f82f1e 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElements.ts @@ -82,7 +82,8 @@ export const addElements = ( .map((e) => elementIs.product(e) && e.product?.productId); const uniqueProducts = newProducts.filter( - (e) => elementIs.product(e) && !currentProducts.includes(e.product?.productId) + (e) => + elementIs.product(e) && !currentProducts.includes(e.product?.productId) ); // Then, if the number of products after adding these would still be within diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts index 0d96176eb0e7..a418a4542080 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/arrangeElement.ts @@ -103,7 +103,7 @@ export const arrangeElement = ( // Update group id on current element if (groupId) { // Can only change groups to a group that exists - if (!page.groups?.groupId) { + if (!page.groups?.[groupId]) { return; } page.elements[currentPosition].groupId = groupId; diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/addElementToSelection.js b/packages/story-editor/src/app/story/useStoryReducer/test/addElementToSelection.js index 8f3c49771786..5800d6697a76 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/addElementToSelection.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/addElementToSelection.js @@ -50,30 +50,6 @@ describe('addElementToSelection', () => { expect(secondResult).toStrictEqual(firstResult); }); - it('should ignore missing element id', () => { - const { restore, addElementToSelection } = setupReducer(); - - // Set an initial state. - const initialState = restore({ - pages: [ - { - id: '111', - elements: [ - { id: 'e1', isBackground: true }, - { id: 'e2' }, - { id: 'e3' }, - ], - }, - ], - current: '111', - selection: ['e1', 'e2'], - }); - - // Add no element - const failedAttempt = addElementToSelection({ elementId: null }); - expect(failedAttempt).toStrictEqual(initialState); - }); - it('should not allow adding video placeholder to non-empty selection', () => { const { restore, addElementToSelection } = setupReducer(); diff --git a/packages/story-editor/src/app/story/useStoryReducer/test/duplicateElementsById.js b/packages/story-editor/src/app/story/useStoryReducer/test/duplicateElementsById.js index c206d2ad2740..1c5dbd6d669a 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/test/duplicateElementsById.js +++ b/packages/story-editor/src/app/story/useStoryReducer/test/duplicateElementsById.js @@ -30,30 +30,6 @@ describe('duplicateElementsById', () => { elementTypes.forEach(registerElementType); }); - it('should do nothing if not passed an array', () => { - const { restore, duplicateElementsById } = setupReducer(); - - // Set an initial state with a current page. - const initialState = restore({ - pages: [ - { - id: '111', - animations: [], - elements: [ - { id: '123', isBackground: true, type: 'shape' }, - { id: '456', x: 0, y: 0, type: 'shape' }, - { id: '789', x: 0, y: 0, type: 'shape' }, - ], - }, - ], - current: '111', - selection: ['789', '456'], - }); - - const result = duplicateElementsById({ elementIds: '123' }); - expect(result).toStrictEqual(initialState); - }); - it('duplicates an element at index after specified element', () => { const { restore, duplicateElementsById } = setupReducer(); From ce7e37e566ba9d5b7028cb5931aed75dc69dd464 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 15:53:29 -0300 Subject: [PATCH 92/99] More test fixes. --- .../app/story/utils/pageContainsBlobUrl.ts | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts index 003abf125419..506979710a91 100644 --- a/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts +++ b/packages/story-editor/src/app/story/utils/pageContainsBlobUrl.ts @@ -17,23 +17,24 @@ * External dependencies */ import { isBlobURL } from '@googleforcreators/media'; -import type { - Page, - SequenceMediaElement, -} from '@googleforcreators/elements'; +import type { Page } from '@googleforcreators/elements'; import { elementIs } from '@googleforcreators/elements'; function pageContainsBlobUrl(pages: Page[]) { // skip entries that have a blob url // https://github.com/GoogleForCreators/web-stories-wp/issues/10289 return pages.some((page) => - page.elements.some( - (element) => - elementIs.media(element) && - (isBlobURL(element.resource?.src) || - (elementIs.sequenceMedia(element) && - isBlobURL((element as SequenceMediaElement)?.resource?.poster))) - ) + page.elements.some((element) => { + if (!elementIs.media(element) || !element.resource) { + return false; + } + if (isBlobURL(element.resource.src)) { + return true; + } + return ( + elementIs.sequenceMedia(element) && isBlobURL(element.resource.poster) + ); + }) ); } From 801a85642ee2b149159f90242790b65adc463c31 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 16:16:18 -0300 Subject: [PATCH 93/99] Fix import --- .../story-editor/src/app/story/constants.ts | 30 +++++++++++++++++++ .../story-editor/src/app/story/context.ts | 7 +++-- .../story/useStoryReducer/useStoryReducer.ts | 13 +------- 3 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 packages/story-editor/src/app/story/constants.ts diff --git a/packages/story-editor/src/app/story/constants.ts b/packages/story-editor/src/app/story/constants.ts new file mode 100644 index 000000000000..b746a157b1d0 --- /dev/null +++ b/packages/story-editor/src/app/story/constants.ts @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * External dependencies + */ +import type { Story } from '@googleforcreators/elements'; +import { StoryAnimationState } from '@googleforcreators/animation'; + +export const INITIAL_STATE = { + pages: [], + capabilities: {}, + current: null, + selection: [], + story: {} as Story, + animationState: StoryAnimationState.Reset, + copiedElementState: {}, +}; diff --git a/packages/story-editor/src/app/story/context.ts b/packages/story-editor/src/app/story/context.ts index 20d9337cdb94..757fc3361e4c 100644 --- a/packages/story-editor/src/app/story/context.ts +++ b/packages/story-editor/src/app/story/context.ts @@ -19,13 +19,16 @@ */ import { createContext } from '@googleforcreators/react'; import type { Element, Page, Story } from '@googleforcreators/elements'; -import type { StoryAnimation, StoryAnimationState } from '@googleforcreators/animation'; +import type { + StoryAnimation, + StoryAnimationState, +} from '@googleforcreators/animation'; /** * Internal dependencies */ import type { StoryProviderState } from '../../types'; -import { INITIAL_STATE } from './useStoryReducer/useStoryReducer'; +import { INITIAL_STATE } from './constants'; export default createContext({ state: { diff --git a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts index c18d504939fb..48bb33bdbcec 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/useStoryReducer.ts @@ -18,8 +18,6 @@ * External dependencies */ import { useReducer, useMemo } from '@googleforcreators/react'; -import { StoryAnimationState } from '@googleforcreators/animation'; -import type { Story } from '@googleforcreators/elements'; /** * Internal dependencies @@ -30,19 +28,10 @@ import type { ReducerState, ReducerProviderState, } from '../../../types'; +import { INITIAL_STATE } from '../constants'; import { DispatchType, exposedActions, internalActions } from './actions'; import reducer from './reducer'; -export const INITIAL_STATE = { - pages: [], - capabilities: {}, - current: null, - selection: [], - story: {} as Story, - animationState: StoryAnimationState.Reset, - copiedElementState: {}, -}; - /** * More description to follow - especially about return value. * From 58ba1cc4ea138c710909b2dc32d32dd70c5f8fb5 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 16:24:57 -0300 Subject: [PATCH 94/99] Lint fixes --- packages/element-library/tsconfig.json | 6 +++++- packages/elements/src/utils/elementIs.ts | 3 ++- .../story-editor/src/app/story/actions/useLocalAutoSave.ts | 2 +- .../useStoryReducer/reducers/addElementsAcrossPages.ts | 3 ++- .../app/story/useStoryReducer/reducers/combineElements.ts | 2 +- .../src/app/story/useStoryReducer/reducers/deleteGroup.ts | 3 ++- .../src/app/story/useStoryReducer/reducers/updateStory.ts | 3 ++- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/element-library/tsconfig.json b/packages/element-library/tsconfig.json index df221e726ec2..35d5555d81cc 100644 --- a/packages/element-library/tsconfig.json +++ b/packages/element-library/tsconfig.json @@ -18,5 +18,9 @@ { "path": "../transform" }, { "path": "../units" } ], - "include": ["src/constants.ts", "src/types.ts"] + "include": [ + "src/constants.ts", + "src/types.ts", + "src/types" + ] } diff --git a/packages/elements/src/utils/elementIs.ts b/packages/elements/src/utils/elementIs.ts index 616b3632aca5..58865b98fe43 100644 --- a/packages/elements/src/utils/elementIs.ts +++ b/packages/elements/src/utils/elementIs.ts @@ -22,7 +22,8 @@ import type { Element, MediaElement, TextElement, - ProductElement, SequenceMediaElement, + ProductElement, + SequenceMediaElement, } from '../types'; function isMediaElement(e: Element): e is MediaElement { diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index e9c75efc521d..6a15d62f3ebc 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -43,7 +43,7 @@ function useLocalAutoSave({ const restoreLocalAutoSave = useCallback(() => { const existingAutoSave = sessionStore.getItemByKey( getSessionStorageKey(storyId, isNew) - ) as { story?: Story, pages?: Page[] }; + ) as { story?: Story; pages?: Page[] }; // If either of the values is missing, nothing to do. if (!existingAutoSave?.story || !existingAutoSave?.pages) { return; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts index 325abb8687e1..641e5be05e83 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/addElementsAcrossPages.ts @@ -25,7 +25,8 @@ import { produce } from 'immer'; */ import type { AddElementsAcrossPagesProps, - ReducerState, ReducerStateDraft, + ReducerState, + ReducerStateDraft, } from '../../../../types'; import { addPage } from './addPage'; import { addElements } from './addElements'; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 6c4c1ecb75a3..81af3319d9ef 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -32,7 +32,7 @@ import objectWithout from '../../../../utils/objectWithout'; import type { CombineElementsProps, ReducerState, - ReducerStateDraft + ReducerStateDraft, } from '../../../../types'; import { removeAnimationsWithElementIds } from './utils'; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts index ee43dbae543c..5e4602545e75 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/deleteGroup.ts @@ -60,6 +60,7 @@ const deleteGroup = produce( delete el.groupId; }); } -}); + } +); export default deleteGroup; diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts index 45ae88d8542a..8bb1f6042594 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/updateStory.ts @@ -17,7 +17,8 @@ /** * External dependencies */ -import { produce, current, Draft } from 'immer'; +import { produce, current } from 'immer'; +import type { Draft } from 'immer'; import type { Story } from '@googleforcreators/elements'; /** From c3f30b8390e3d90cf23d3c3456daf6065c3ba3f0 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 16:37:37 -0300 Subject: [PATCH 95/99] More lint fixes --- packages/story-editor/src/app/story/actions/useLocalAutoSave.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts index 6a15d62f3ebc..f780acc20a84 100644 --- a/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts +++ b/packages/story-editor/src/app/story/actions/useLocalAutoSave.ts @@ -18,7 +18,7 @@ */ import { useCallback } from '@googleforcreators/react'; import { sessionStore } from '@googleforcreators/design-system'; -import type {Page, Story} from '@googleforcreators/elements'; +import type { Page, Story } from '@googleforcreators/elements'; /** * Internal dependencies From 041aeae49bc1ea10bde3545c7a85c0df4c9ed93a Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 16:42:19 -0300 Subject: [PATCH 96/99] Fix --- .../useStoryReducer/reducers/combineElements.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts index 81af3319d9ef..4129f61b0481 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/combineElements.ts @@ -105,17 +105,17 @@ export const combineElements = ( ]; // If the element we're dropping into is not background, maintain link and border. - if (elementIs.backgroundable(secondElement) && !secondElement.isBackground) { + if (elementIs.backgroundable(secondElement) && secondElement.isBackground) { + // If we're dropping into background, maintain the flip and overlay, too. + // Only copy position properties for backgrounds, as they're ignored while being background + // For non-backgrounds, elements should keep original positions from secondElement + propsFromFirst.push('flip', 'overlay', 'width', 'height', 'x', 'y'); + } else { propsFromFirst.push('link'); propsFromFirst.push('border'); if (canSupportMultiBorder(secondElement)) { propsFromFirst.push('borderRadius'); } - } else { - // If we're dropping into background, maintain the flip and overlay, too. - // Only copy position properties for backgrounds, as they're ignored while being background - // For non-backgrounds, elements should keep original positions from secondElement - propsFromFirst.push('flip', 'overlay', 'width', 'height', 'x', 'y'); } const newElement = { From 06cd2427e5880ef12d2fa9e29cf26883d9e2b6cb Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Thu, 1 Dec 2022 20:09:33 -0300 Subject: [PATCH 97/99] Fix karma --- .../src/app/story/useStoryReducer/reducers/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts index 5271bf2eee50..67540f4e74ac 100644 --- a/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts +++ b/packages/story-editor/src/app/story/useStoryReducer/reducers/utils.ts @@ -98,7 +98,7 @@ export function getAbsolutePosition({ interface AllowedProperties extends Partial { animation: StoryAnimation; } -function isAnimationUpdate( +function isWithAnimation( props: Partial | Element ): props is AllowedProperties { return 'animation' in props; @@ -116,7 +116,7 @@ export function updateElementWithUpdater( if (Object.keys(allowedProperties).length === 0) { return null; } - if (isAnimationUpdate(allowedProperties)) { + if (isWithAnimation(allowedProperties) && allowedProperties.animation) { return allowedProperties.animation; } Object.assign(element, allowedProperties); From 3962feed0d13fbd820d97df4a2cc537f5bcc39af Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 2 Dec 2022 12:11:54 -0300 Subject: [PATCH 98/99] Type new utils --- packages/output/src/types.ts | 2 ++ ...FontData.js => populateElementFontData.ts} | 20 ++++++++++++++++--- packages/output/tsconfig.json | 1 + ...rties.js => cleanElementFontProperties.ts} | 12 ++++++++--- ...FromPages.js => getStoryFontsFromPages.ts} | 12 ++++++++--- 5 files changed, 38 insertions(+), 9 deletions(-) rename packages/output/src/utils/{populateElementFontData.js => populateElementFontData.ts} (64%) rename packages/story-editor/src/app/story/utils/{cleanElementFontProperties.js => cleanElementFontProperties.ts} (71%) rename packages/story-editor/src/app/story/utils/{getStoryFontsFromPages.js => getStoryFontsFromPages.ts} (70%) diff --git a/packages/output/src/types.ts b/packages/output/src/types.ts index 2b2fefe837e5..86586638897c 100644 --- a/packages/output/src/types.ts +++ b/packages/output/src/types.ts @@ -33,3 +33,5 @@ export declare function getStoryMarkup( metadata: MetaData, flags: Record ): string; + +export * from './utils/populateElementFontData'; diff --git a/packages/output/src/utils/populateElementFontData.js b/packages/output/src/utils/populateElementFontData.ts similarity index 64% rename from packages/output/src/utils/populateElementFontData.js rename to packages/output/src/utils/populateElementFontData.ts index 581f8cf954e6..9139e3d96342 100644 --- a/packages/output/src/utils/populateElementFontData.js +++ b/packages/output/src/utils/populateElementFontData.ts @@ -14,14 +14,28 @@ * limitations under the License. */ -function populateElementFontProperties({ elements, ...rest }, fonts) { +/** + * External dependencies + */ +import type { Page, FontData } from '@googleforcreators/elements'; +import { elementIs } from '@googleforcreators/elements'; + +type Fonts = Record; +function populateElementFontProperties( + { elements, ...rest }: Page, + fonts: Fonts +) { if (!fonts) { return { elements, ...rest }; } return { elements: elements.map((element) => { - if (element.type === 'text' && Boolean(element.font?.family)) { + if ( + elementIs.text(element) && + element.type === 'text' && + Boolean(element.font?.family) + ) { return { ...element, font: fonts[element.font?.family] }; } return element; @@ -30,6 +44,6 @@ function populateElementFontProperties({ elements, ...rest }, fonts) { }; } -export function populateElementFontData(data, fonts) { +export function populateElementFontData(data: Page[], fonts: Fonts): Page[] { return data.map((page) => populateElementFontProperties(page, fonts)); } diff --git a/packages/output/tsconfig.json b/packages/output/tsconfig.json index eb3533355d7c..00a61e9fc059 100644 --- a/packages/output/tsconfig.json +++ b/packages/output/tsconfig.json @@ -19,5 +19,6 @@ ], "include": [ "src/types.ts", + "src/utils/*.ts" ] } diff --git a/packages/story-editor/src/app/story/utils/cleanElementFontProperties.js b/packages/story-editor/src/app/story/utils/cleanElementFontProperties.ts similarity index 71% rename from packages/story-editor/src/app/story/utils/cleanElementFontProperties.js rename to packages/story-editor/src/app/story/utils/cleanElementFontProperties.ts index c01840871b05..52c360866a3f 100644 --- a/packages/story-editor/src/app/story/utils/cleanElementFontProperties.js +++ b/packages/story-editor/src/app/story/utils/cleanElementFontProperties.ts @@ -14,10 +14,16 @@ * limitations under the License. */ -function reduceElementFontProperties({ elements, ...rest }) { +/** + * External dependencies + */ +import type { Page } from '@googleforcreators/elements'; +import { elementIs } from '@googleforcreators/elements'; + +function reduceElementFontProperties({ elements, ...rest }: Page): Page { return { elements: elements.map((element) => { - if (element.type === 'text' && Boolean(element.font?.family)) { + if (elementIs.text(element) && Boolean(element.font?.family)) { return { ...element, font: { family: element.font.family } }; } return element; @@ -26,6 +32,6 @@ function reduceElementFontProperties({ elements, ...rest }) { }; } -export function cleanElementFontProperties(data) { +export function cleanElementFontProperties(data: Page[]) { return data.map((page) => reduceElementFontProperties(page)); } diff --git a/packages/story-editor/src/app/story/utils/getStoryFontsFromPages.js b/packages/story-editor/src/app/story/utils/getStoryFontsFromPages.ts similarity index 70% rename from packages/story-editor/src/app/story/utils/getStoryFontsFromPages.js rename to packages/story-editor/src/app/story/utils/getStoryFontsFromPages.ts index 797eafa20e34..398459bfe15c 100644 --- a/packages/story-editor/src/app/story/utils/getStoryFontsFromPages.js +++ b/packages/story-editor/src/app/story/utils/getStoryFontsFromPages.ts @@ -13,11 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export function getStoryFontsFromPages(pages) { - const fonts = {}; +/** + * External dependencies + */ +import type { FontData, Page } from '@googleforcreators/elements'; +import { elementIs } from '@googleforcreators/elements'; + +export function getStoryFontsFromPages(pages: Page[]) { + const fonts: Record = {}; pages.forEach(({ elements = [] }) => elements.forEach((element) => { - if (element.type === 'text' && Boolean(element.font?.family)) { + if (elementIs.text(element) && Boolean(element.font?.family)) { fonts[element.font.family] = element.font; } }) From 68d8590f5fc6d68204d86751e59440e8adb918c6 Mon Sep 17 00:00:00 2001 From: Miina Sikk Date: Fri, 2 Dec 2022 12:17:16 -0300 Subject: [PATCH 99/99] Type fix. --- packages/story-editor/src/types/story.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/story-editor/src/types/story.ts b/packages/story-editor/src/types/story.ts index 2d405cfc0420..c3e996080f8e 100644 --- a/packages/story-editor/src/types/story.ts +++ b/packages/story-editor/src/types/story.ts @@ -54,12 +54,13 @@ export interface StorySaveData | 'autoAdvance' | 'defaultPageDuration' | 'backgroundAudio' - | 'terms' > { storyId?: number; content: string; products: ProductData[]; pages: Page[]; + // Term IDs. + web_story_data?: number[]; } // Data that's returned from API after saving.