From 29e7f7d7a48b6039c296356a7aa04eb52fc564da Mon Sep 17 00:00:00 2001 From: AlexandreS <32449369+AlexandreSi@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:07:22 +0100 Subject: [PATCH] Remove build section ref and effect (#5901) Don't show in changelog --- .../HomePage/BuildSection/index.js | 582 +++++++++--------- .../EditorContainers/HomePage/index.js | 17 +- 2 files changed, 283 insertions(+), 316 deletions(-) diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/index.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/index.js index 31673070f5de..0f5458e71617 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/index.js +++ b/newIDE/app/src/MainFrame/EditorContainers/HomePage/BuildSection/index.js @@ -27,7 +27,6 @@ import { checkIfHasTooManyCloudProjects, MaxProjectCountAlertMessage, } from './MaxProjectCountAlertMessage'; -import useForceUpdate from '../../../../Utils/UseForceUpdate'; import { ExampleStoreContext } from '../../../../AssetStore/ExampleStore/ExampleStoreContext'; import { SubscriptionSuggestionContext } from '../../../../Profile/Subscription/SubscriptionSuggestionContext'; import { type ExampleShortHeader } from '../../../../Utils/GDevelopServices/Example'; @@ -79,325 +78,308 @@ type Props = {| i18n: I18nType, |}; -export type BuildSectionInterface = {| - forceUpdate: () => void, -|}; +const BuildSection = ({ + project, + currentFileMetadata, + canOpen, + onChooseProject, + onOpenNewProjectSetupDialog, + onShowAllExamples, + onSelectExampleShortHeader, + onSelectPrivateGameTemplateListingData, + onOpenRecentFile, + storageProviders, + i18n, +}: Props) => { + const { getRecentProjectFiles } = React.useContext(PreferencesContext); + const { exampleShortHeaders } = React.useContext(ExampleStoreContext); + const { privateGameTemplateListingDatas } = React.useContext( + PrivateGameTemplateStoreContext + ); + const authenticatedUser = React.useContext(AuthenticatedUserContext); + const { openSubscriptionDialog } = React.useContext( + SubscriptionSuggestionContext + ); + const { + profile, + cloudProjects, + limits, + cloudProjectsFetchingErrorLabel, + onCloudProjectsChanged, + } = authenticatedUser; + const windowWidth = useResponsiveWindowWidth(); + const isMobile = windowWidth === 'small'; + const [ + lastModifiedInfoByProjectId, + setLastModifiedInfoByProjectId, + ] = React.useState({}); -const BuildSection = React.forwardRef( - ( - { - project, - currentFileMetadata, - canOpen, - onChooseProject, - onOpenNewProjectSetupDialog, - onShowAllExamples, - onSelectExampleShortHeader, - onSelectPrivateGameTemplateListingData, - onOpenRecentFile, - storageProviders, - i18n, - }, - ref - ) => { - const { getRecentProjectFiles } = React.useContext(PreferencesContext); - const { exampleShortHeaders } = React.useContext(ExampleStoreContext); - const { privateGameTemplateListingDatas } = React.useContext( - PrivateGameTemplateStoreContext - ); - const authenticatedUser = React.useContext(AuthenticatedUserContext); - const { openSubscriptionDialog } = React.useContext( - SubscriptionSuggestionContext - ); - const { - profile, - cloudProjects, - limits, - cloudProjectsFetchingErrorLabel, - onCloudProjectsChanged, - } = authenticatedUser; - const windowWidth = useResponsiveWindowWidth(); - const isMobile = windowWidth === 'small'; - const forceUpdate = useForceUpdate(); - const [ - lastModifiedInfoByProjectId, - setLastModifiedInfoByProjectId, - ] = React.useState({}); - - React.useImperativeHandle(ref, () => ({ - forceUpdate, - })); + let projectFiles: Array = getRecentProjectFiles().filter( + file => file.fileMetadata + ); - let projectFiles: Array = getRecentProjectFiles().filter( - file => file.fileMetadata + if (cloudProjects) { + projectFiles = projectFiles.concat( + transformCloudProjectsIntoFileMetadataWithStorageProviderName( + cloudProjects + ) ); + } - if (cloudProjects) { - projectFiles = projectFiles.concat( - transformCloudProjectsIntoFileMetadataWithStorageProviderName( - cloudProjects - ) - ); - } - - // Look at projects where lastCommittedBy is not the current user, and fetch - // public profiles of the users that have modified them. - React.useEffect( - () => { - const updateModificationInfoByProjectId = async () => { - if (!cloudProjects || !profile) return; + // Look at projects where lastCommittedBy is not the current user, and fetch + // public profiles of the users that have modified them. + React.useEffect( + () => { + const updateModificationInfoByProjectId = async () => { + if (!cloudProjects || !profile) return; - const _lastModifiedInfoByProjectId = await getLastModifiedInfoByProjectId( - { - cloudProjects, - profile, - } - ); - setLastModifiedInfoByProjectId(_lastModifiedInfoByProjectId); - }; + const _lastModifiedInfoByProjectId = await getLastModifiedInfoByProjectId( + { + cloudProjects, + profile, + } + ); + setLastModifiedInfoByProjectId(_lastModifiedInfoByProjectId); + }; - updateModificationInfoByProjectId(); - }, - [cloudProjects, profile] - ); + updateModificationInfoByProjectId(); + }, + [cloudProjects, profile] + ); - const hasTooManyCloudProjects = checkIfHasTooManyCloudProjects( - authenticatedUser - ); + const hasTooManyCloudProjects = checkIfHasTooManyCloudProjects( + authenticatedUser + ); - const [isRefreshing, setIsRefreshing] = React.useState(false); - const refreshCloudProjects = React.useCallback( - async () => { - if (isRefreshing) return; - try { - setIsRefreshing(true); - await onCloudProjectsChanged(); - } finally { - // Wait a bit to avoid spam as we don't have a "loading" state. - setTimeout(() => setIsRefreshing(false), 2000); - } - }, - [onCloudProjectsChanged, isRefreshing] - ); + const [isRefreshing, setIsRefreshing] = React.useState(false); + const refreshCloudProjects = React.useCallback( + async () => { + if (isRefreshing) return; + try { + setIsRefreshing(true); + await onCloudProjectsChanged(); + } finally { + // Wait a bit to avoid spam as we don't have a "loading" state. + setTimeout(() => setIsRefreshing(false), 2000); + } + }, + [onCloudProjectsChanged, isRefreshing] + ); - projectFiles.sort((a, b) => { - if (!a.fileMetadata.lastModifiedDate) return 1; - if (!b.fileMetadata.lastModifiedDate) return -1; - return b.fileMetadata.lastModifiedDate - a.fileMetadata.lastModifiedDate; - }); + projectFiles.sort((a, b) => { + if (!a.fileMetadata.lastModifiedDate) return 1; + if (!b.fileMetadata.lastModifiedDate) return -1; + return b.fileMetadata.lastModifiedDate - a.fileMetadata.lastModifiedDate; + }); - const skeletonLineHeight = getProjectLineHeight(windowWidth); + const skeletonLineHeight = getProjectLineHeight(windowWidth); - // Show a premium game template every 3 examples. - const examplesAndTemplatesToDisplay = React.useMemo( - () => - getExampleAndTemplateItemsForCarousel({ - authenticatedUser, - privateGameTemplateListingDatas, - exampleShortHeaders, - onSelectPrivateGameTemplateListingData, - onSelectExampleShortHeader, - i18n, - }), - [ + // Show a premium game template every 3 examples. + const examplesAndTemplatesToDisplay = React.useMemo( + () => + getExampleAndTemplateItemsForCarousel({ authenticatedUser, + privateGameTemplateListingDatas, exampleShortHeaders, - onSelectExampleShortHeader, onSelectPrivateGameTemplateListingData, - privateGameTemplateListingDatas, + onSelectExampleShortHeader, i18n, - ] - ); + }), + [ + authenticatedUser, + exampleShortHeaders, + onSelectExampleShortHeader, + onSelectPrivateGameTemplateListingData, + privateGameTemplateListingDatas, + i18n, + ] + ); - return ( - <> - My projects} - renderFooter={ - limits && hasTooManyCloudProjects - ? () => ( - - - - openSubscriptionDialog({ - reason: 'Cloud Project limit reached', - }) - } - /> - - - ) - : undefined - } - > - - Game templates} - displayItemTitles={false} - browseAllLabel={Browse all templates} - onBrowseAllClick={onShowAllExamples} - items={examplesAndTemplatesToDisplay} - browseAllIcon={} - roundedImages - hideArrows - /> - - - - - - - My projects - - - - - - - - - Create - ) : ( - Create a project - ) - } - onClick={onOpenNewProjectSetupDialog} - icon={} - id="home-create-project-button" - /> - {canOpen && ( - <> - - or - - - Open - ) : ( - Open a project - ) - } - onClick={onChooseProject} - /> - - )} - - - - {cloudProjectsFetchingErrorLabel && ( - - - - {cloudProjectsFetchingErrorLabel} - - - - )} + return ( + <> + My projects} + renderFooter={ + limits && hasTooManyCloudProjects + ? () => ( + + + + openSubscriptionDialog({ + reason: 'Cloud Project limit reached', + }) + } + /> + + + ) + : undefined + } + > + + Game templates} + displayItemTitles={false} + browseAllLabel={Browse all templates} + onBrowseAllClick={onShowAllExamples} + items={examplesAndTemplatesToDisplay} + browseAllIcon={} + roundedImages + hideArrows + /> + + + + + + + My projects + + + + + + + + + Create + ) : ( + Create a project + ) + } + onClick={onOpenNewProjectSetupDialog} + icon={} + id="home-create-project-button" + /> + {canOpen && ( + <> + + or + + + Open + ) : ( + Open a project + ) + } + onClick={onChooseProject} + /> + + )} + + + + {cloudProjectsFetchingErrorLabel && ( - - {!isMobile && ( - - - - File name - - - - - Location - - + + + {cloudProjectsFetchingErrorLabel} + + + + )} + + + {!isMobile && ( + + + + File name + + + + + Location + + + + + Last edited + + + + )} + + {authenticatedUser.loginState === 'loggingIn' && + projectFiles.length === 0 ? ( // Only show skeleton on first load + new Array(10).fill(0).map((_, index) => ( + + + + + + + + )) + ) : projectFiles.length > 0 ? ( + projectFiles.map(file => ( + + )) + ) : ( + - - Last edited - + + + No projects yet. + + + + Create your first project using one of our templates + or start from scratch. + + + - + )} - - {authenticatedUser.loginState === 'loggingIn' && - projectFiles.length === 0 ? ( // Only show skeleton on first load - new Array(10).fill(0).map((_, index) => ( - - - - - - - - )) - ) : projectFiles.length > 0 ? ( - projectFiles.map(file => ( - - )) - ) : ( - - - - - No projects yet. - - - - Create your first project using one of our - templates or start from scratch. - - - - - - )} - - - - - - - ); - } -); + + + + + + + ); +}; const BuildSectionWithErrorBoundary = (props: Props) => ( ( values: { showGetStartedSection }, setShowGetStartedSection, } = React.useContext(PreferencesContext); - const buildSectionRef = React.useRef(null); const windowWidth = useResponsiveWindowWidth(); const isMobile = windowWidth === 'small'; @@ -180,19 +179,6 @@ export const HomePage = React.memo( [isActive, authenticated, onCloudProjectsChanged] ); - // Refresh build section when homepage becomes active - React.useEffect( - () => { - if (isActive && activeTab === 'build' && buildSectionRef.current) { - buildSectionRef.current.forceUpdate(); - } - }, - // Active tab is excluded from the dependencies because switching tab - // mounts and unmounts section, so the data is already up to date. - // eslint-disable-next-line react-hooks/exhaustive-deps - [isActive] - ); - const getProject = React.useCallback(() => { return undefined; }, []); @@ -304,7 +290,6 @@ export const HomePage = React.memo( )} {activeTab === 'build' && (