diff --git a/newIDE/app/src/AssetStore/AssetDetails.js b/newIDE/app/src/AssetStore/AssetDetails.js index 38ce6c70e773..176aeae88e3f 100644 --- a/newIDE/app/src/AssetStore/AssetDetails.js +++ b/newIDE/app/src/AssetStore/AssetDetails.js @@ -201,11 +201,11 @@ export const AssetDetails = React.forwardRef( React.useEffect( () => { - if (!asset) { + if (!asset || asset.id !== assetShortHeader.id) { loadAsset(); } }, - [asset, loadAsset] + [asset, loadAsset, assetShortHeader] ); const loadAuthorPublicProfiles = React.useCallback( diff --git a/newIDE/app/src/AssetStore/AssetStoreContext.js b/newIDE/app/src/AssetStore/AssetStoreContext.js index b70276616753..23e33b6041ac 100644 --- a/newIDE/app/src/AssetStore/AssetStoreContext.js +++ b/newIDE/app/src/AssetStore/AssetStoreContext.js @@ -29,9 +29,9 @@ import { AssetSwappingAssetStoreSearchFilter, } from './AssetStoreSearchFilter'; import { - type NavigationState, type AssetStorePageState, assetStoreHomePageState, + AssetStoreNavigatorContext, } from './AssetStoreNavigator'; import { type ChosenCategory } from '../UI/Search/FiltersChooser'; import AuthenticatedUserContext from '../Profile/AuthenticatedUserContext'; @@ -41,8 +41,6 @@ import { } from './AssetStoreUtils'; import useAlertDialog from '../UI/Alert/useAlertDialog'; -const defaultSearchText = ''; - export type AssetFiltersState = {| animatedFilter: AnimatedAssetStoreSearchFilter, setAnimatedFilter: AnimatedAssetStoreSearchFilter => void, @@ -78,12 +76,9 @@ type AssetStoreState = {| privateAssetPackListingDatasSearchResults: ?Array, fetchAssetsAndFilters: () => void, error: ?Error, - searchText: string, - setSearchText: string => void, assetFiltersState: AssetFiltersState, assetPackFiltersState: AssetPackFiltersState, clearAllFilters: () => void, - shopNavigationState: NavigationState, currentPage: AssetStorePageState, useSearchItem: ( searchText: string, @@ -108,8 +103,6 @@ export const initialAssetStoreState: AssetStoreState = { privateAssetPackListingDatasSearchResults: null, fetchAssetsAndFilters: () => {}, error: null, - searchText: '', - setSearchText: () => {}, assetFiltersState: { animatedFilter: new AnimatedAssetStoreSearchFilter(), setAnimatedFilter: filter => {}, @@ -131,30 +124,6 @@ export const initialAssetStoreState: AssetStoreState = { setTypeFilter: filter => {}, }, clearAllFilters: () => {}, - shopNavigationState: { - getCurrentPage: () => assetStoreHomePageState, - isRootPage: true, - backToPreviousPage: () => assetStoreHomePageState, - openHome: () => assetStoreHomePageState, - openAssetSwapping: () => assetStoreHomePageState, - clearHistory: () => {}, - clearPreviousPageFromHistory: () => {}, - openSearchResultPage: () => {}, - openTagPage: tag => {}, - openShopCategoryPage: category => {}, - openPackPage: ({ assetPack, previousSearchText }) => {}, - openAssetDetailPage: ({ assetShortHeader, previousSearchText }) => {}, - openPrivateAssetPackInformationPage: ({ - privateAssetPackListingData, - previousSearchText, - }) => {}, - openPrivateGameTemplateInformationPage: ({ - privateGameTemplateListingData, - previousSearchText, - }) => {}, - navigateInsideFolder: folder => {}, - goBackToFolderIndex: index => {}, - }, currentPage: assetStoreHomePageState, useSearchItem: (searchText, chosenCategory, chosenFilters, searchFilters) => null, @@ -167,7 +136,6 @@ export const AssetStoreContext = React.createContext( ); type AssetStoreStateProviderProps = {| - shopNavigationState: NavigationState, children: React.Node, |}; @@ -189,9 +157,11 @@ const getPrivateAssetPackListingDataSearchTerms = ( ) => privateAssetPack.name + '\n' + privateAssetPack.description; export const AssetStoreStateProvider = ({ - shopNavigationState, children, }: AssetStoreStateProviderProps) => { + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); + const { searchText } = shopNavigationState; + const [assetShortHeadersById, setAssetShortHeadersById] = React.useState(null); @@ -229,8 +199,6 @@ export const AssetStoreStateProvider = ({ const initialPackOpened = React.useRef(false); const { showAlert } = useAlertDialog(); - const [searchText, setSearchText] = React.useState(defaultSearchText); - const [ animatedFilter, setAnimatedFilter, @@ -403,7 +371,8 @@ export const AssetStoreStateProvider = ({ if (assetPack) { shopNavigationState.openPackPage({ assetPack, - previousSearchText: searchText, + storeSearchText: true, + clearSearchText: false, }); initialPackOpened.current = false; // Allow to open the pack again if the effect run again. setInitialPackUserFriendlySlug(null); @@ -421,7 +390,8 @@ export const AssetStoreStateProvider = ({ if (privateAssetPackListingData) { shopNavigationState.openPrivateAssetPackInformationPage({ privateAssetPackListingData, - previousSearchText: searchText, + storeSearchText: true, + clearSearchText: false, }); initialPackOpened.current = false; // Allow to open the pack again if the effect run again. setInitialPackUserFriendlySlug(null); @@ -441,7 +411,6 @@ export const AssetStoreStateProvider = ({ shopNavigationState, showAlert, initialPackUserFriendlySlug, - searchText, ] ); @@ -606,10 +575,7 @@ export const AssetStoreStateProvider = ({ environment, setEnvironment, error, - shopNavigationState, currentPage, - searchText, - setSearchText, assetFiltersState, assetPackFiltersState, clearAllFilters, @@ -643,9 +609,7 @@ export const AssetStoreStateProvider = ({ licenses, environment, error, - shopNavigationState, currentPage, - searchText, assetFiltersState, assetPackFiltersState, clearAllFilters, diff --git a/newIDE/app/src/AssetStore/AssetStoreFilterPanel.js b/newIDE/app/src/AssetStore/AssetStoreFilterPanel.js index f3c40fbc9a69..bf0d09693b4c 100644 --- a/newIDE/app/src/AssetStore/AssetStoreFilterPanel.js +++ b/newIDE/app/src/AssetStore/AssetStoreFilterPanel.js @@ -22,6 +22,7 @@ import { type RGBColor } from '../Utils/ColorTransformer'; import { HexColorField } from './HexColorField'; import Slider from '../UI/Slider'; import AuthenticatedUserContext from '../Profile/AuthenticatedUserContext'; +import { AssetStoreNavigatorContext } from './AssetStoreNavigator'; type Choice = {| label: React.Node, @@ -229,8 +230,9 @@ export const AssetStoreFilterPanel = ({ assetFiltersState, assetPackFiltersState, clearAllFilters, - shopNavigationState, } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); + const { receivedAssetPacks } = React.useContext(AuthenticatedUserContext); const onChoiceChange = React.useCallback( () => { diff --git a/newIDE/app/src/AssetStore/AssetStoreNavigator.js b/newIDE/app/src/AssetStore/AssetStoreNavigator.js index 4f97cfe68a21..b1cf6d5fd416 100644 --- a/newIDE/app/src/AssetStore/AssetStoreNavigator.js +++ b/newIDE/app/src/AssetStore/AssetStoreNavigator.js @@ -26,6 +26,8 @@ export type AssetStorePageState = {| |}; export type NavigationState = {| + searchText: string, + setSearchText: string => void, getCurrentPage: () => AssetStorePageState, isRootPage: boolean, backToPreviousPage: () => AssetStorePageState, @@ -38,19 +40,23 @@ export type NavigationState = {| openShopCategoryPage: string => void, openPackPage: ({| assetPack: PublicAssetPack | PrivateAssetPack, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => void, openPrivateAssetPackInformationPage: ({| privateAssetPackListingData: PrivateAssetPackListingData, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => void, openPrivateGameTemplateInformationPage: ({| privateGameTemplateListingData: PrivateGameTemplateListingData, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => void, openAssetDetailPage: ({| assetShortHeader: AssetShortHeader, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => void, navigateInsideFolder: string => void, goBackToFolderIndex: number => void, @@ -111,14 +117,44 @@ type AssetStorePageHistory = {| previousPages: Array, |}; -export const useShopNavigation = (): NavigationState => { +export const AssetStoreNavigatorContext = React.createContext({ + searchText: '', + setSearchText: () => {}, + getCurrentPage: () => assetStoreHomePageState, + isRootPage: true, + backToPreviousPage: () => assetStoreHomePageState, + openHome: () => assetStoreHomePageState, + openAssetSwapping: () => assetStoreHomePageState, + clearHistory: () => {}, + clearPreviousPageFromHistory: () => {}, + openSearchResultPage: () => {}, + openTagPage: string => {}, + openShopCategoryPage: string => {}, + openPackPage: () => {}, + openPrivateAssetPackInformationPage: () => {}, + openPrivateGameTemplateInformationPage: () => {}, + openAssetDetailPage: () => {}, + navigateInsideFolder: string => {}, + goBackToFolderIndex: number => {}, +}); + +type AssetStoreNavigatorStateProviderProps = {| + children: React.Node, +|}; + +export const AssetStoreNavigatorStateProvider = ( + props: AssetStoreNavigatorStateProviderProps +) => { + const [searchText, setSearchText] = React.useState(''); const [history, setHistory] = React.useState({ previousPages: [assetStoreHomePageState], }); const previousPages = history.previousPages; - return React.useMemo( + const state = React.useMemo( () => ({ + searchText, + setSearchText, getCurrentPage: () => previousPages[previousPages.length - 1], isRootPage: previousPages.length <= 1, backToPreviousPage: () => { @@ -244,10 +280,12 @@ export const useShopNavigation = (): NavigationState => { }, openPackPage: ({ assetPack, - previousSearchText, + storeSearchText, + clearSearchText, }: {| assetPack: PublicAssetPack | PrivateAssetPack, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => { setHistory(previousHistory => { const currentPage = @@ -256,7 +294,7 @@ export const useShopNavigation = (): NavigationState => { ]; const currentPageWithSearchText = { ...currentPage, - searchText: previousSearchText, + searchText: storeSearchText ? searchText : '', }; const previousPagesWithoutCurrentPage = previousHistory.previousPages.slice( 0, @@ -297,13 +335,16 @@ export const useShopNavigation = (): NavigationState => { ], }; }); + if (clearSearchText) setSearchText(''); }, openPrivateAssetPackInformationPage: ({ privateAssetPackListingData, - previousSearchText, + storeSearchText, + clearSearchText, }: {| privateAssetPackListingData: PrivateAssetPackListingData, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => { setHistory(previousHistory => { const currentPage = @@ -312,7 +353,7 @@ export const useShopNavigation = (): NavigationState => { ]; const currentPageWithSearchText = { ...currentPage, - searchText: previousSearchText, + searchText: storeSearchText ? searchText : '', }; const previousPagesWithoutCurrentPage = previousHistory.previousPages.slice( 0, @@ -339,13 +380,16 @@ export const useShopNavigation = (): NavigationState => { ], }; }); + if (clearSearchText) setSearchText(''); }, openAssetDetailPage: ({ assetShortHeader, - previousSearchText, + storeSearchText, + clearSearchText, }: {| assetShortHeader: AssetShortHeader, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => { setHistory(previousHistory => { const currentPage = @@ -354,7 +398,7 @@ export const useShopNavigation = (): NavigationState => { ]; const currentPageWithSearchText = { ...currentPage, - searchText: previousSearchText, + searchText: storeSearchText ? searchText : '', }; const previousPagesWithoutCurrentPage = previousHistory.previousPages.slice( 0, @@ -381,13 +425,16 @@ export const useShopNavigation = (): NavigationState => { ], }; }); + if (clearSearchText) setSearchText(''); }, openPrivateGameTemplateInformationPage: ({ privateGameTemplateListingData, - previousSearchText, + storeSearchText, + clearSearchText, }: {| privateGameTemplateListingData: PrivateGameTemplateListingData, - previousSearchText: string, + storeSearchText: boolean, + clearSearchText: boolean, |}) => { setHistory(previousHistory => { const currentPage = @@ -396,7 +443,7 @@ export const useShopNavigation = (): NavigationState => { ]; const currentPageWithSearchText = { ...currentPage, - searchText: previousSearchText, + searchText: storeSearchText ? searchText : '', }; const previousPagesWithoutCurrentPage = previousHistory.previousPages.slice( 0, @@ -423,6 +470,7 @@ export const useShopNavigation = (): NavigationState => { ], }; }); + if (clearSearchText) setSearchText(''); }, navigateInsideFolder: (folderTag: string) => { setHistory(previousHistory => { @@ -476,6 +524,12 @@ export const useShopNavigation = (): NavigationState => { }); }, }), - [previousPages] + [searchText, previousPages] + ); + + return ( + + {props.children} + ); }; diff --git a/newIDE/app/src/AssetStore/AssetSwappingDialog.js b/newIDE/app/src/AssetStore/AssetSwappingDialog.js index 3e679b2108e3..1958bfb09294 100644 --- a/newIDE/app/src/AssetStore/AssetSwappingDialog.js +++ b/newIDE/app/src/AssetStore/AssetSwappingDialog.js @@ -6,7 +6,6 @@ import Dialog from '../UI/Dialog'; import FlatButton from '../UI/FlatButton'; import { AssetStore, type AssetStoreInterface } from '.'; import { type ResourceManagementProps } from '../ResourcesList/ResourceSource'; -import { AssetStoreContext } from './AssetStoreContext'; import ErrorBoundary from '../UI/ErrorBoundary'; import LoaderModal from '../UI/LoaderModal'; import { useInstallAsset } from './NewObjectDialog'; @@ -14,6 +13,7 @@ import { swapAsset } from './AssetSwapper'; import PixiResourcesLoader from '../ObjectsRendering/PixiResourcesLoader'; import useAlertDialog from '../UI/Alert/useAlertDialog'; import RaisedButton from '../UI/RaisedButton'; +import { AssetStoreNavigatorContext } from './AssetStoreNavigator'; type Props = {| project: gdProject, @@ -37,7 +37,7 @@ function AssetSwappingDialog({ onClose, minimalUI, }: Props) { - const { shopNavigationState } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); const { openedAssetShortHeader } = shopNavigationState.getCurrentPage(); const [ diff --git a/newIDE/app/src/AssetStore/NewObjectDialog.js b/newIDE/app/src/AssetStore/NewObjectDialog.js index ccfe33475e58..b33eeea18b04 100644 --- a/newIDE/app/src/AssetStore/NewObjectDialog.js +++ b/newIDE/app/src/AssetStore/NewObjectDialog.js @@ -42,6 +42,7 @@ import { getAssetShortHeadersToDisplay } from './AssetsList'; import ErrorBoundary from '../UI/ErrorBoundary'; import type { ObjectFolderOrObjectWithContext } from '../ObjectsList/EnumerateObjectFolderOrObject'; import LoaderModal from '../UI/LoaderModal'; +import { AssetStoreNavigatorContext } from './AssetStoreNavigator'; const isDev = Window.isDev(); @@ -130,7 +131,7 @@ export const useInstallAsset = ({ targetObjectFolderOrObjectWithContext?: ?ObjectFolderOrObjectWithContext, resourceManagementProps: ResourceManagementProps, |}) => { - const { shopNavigationState } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); const { openedAssetPack } = shopNavigationState.getCurrentPage(); const eventsFunctionsExtensionsState = React.useContext( EventsFunctionsExtensionsContext @@ -261,10 +262,10 @@ function NewObjectDialog({ const { assetShortHeadersSearchResults, - shopNavigationState, environment, setEnvironment, } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); const { openedAssetPack, openedAssetShortHeader, diff --git a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateStoreContext.js b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateStoreContext.js index 75487ad86c59..3221926e324d 100644 --- a/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateStoreContext.js +++ b/newIDE/app/src/AssetStore/PrivateGameTemplates/PrivateGameTemplateStoreContext.js @@ -12,7 +12,7 @@ import { type PrivateGameTemplateListingData, } from '../../Utils/GDevelopServices/Shop'; import { capitalize } from 'lodash'; -import { type NavigationState } from '../AssetStoreNavigator'; +import { AssetStoreNavigatorContext } from '../AssetStoreNavigator'; import { getPrivateGameTemplateListingDataFromUserFriendlySlug } from '../AssetStoreUtils'; import useAlertDialog from '../../UI/Alert/useAlertDialog'; import { t } from '@lingui/macro'; @@ -40,8 +40,6 @@ type PrivateGameTemplateStoreState = {| error: ?Error, shop: { privateGameTemplateListingDatasSearchResults: ?Array, - searchText: string, - setSearchText: string => void, filtersState: FiltersState, setInitialGameTemplateUserFriendlySlug: string => void, }, @@ -63,8 +61,6 @@ export const initialPrivateGameTemplateStoreState: PrivateGameTemplateStoreState error: null, shop: { privateGameTemplateListingDatasSearchResults: null, - searchText: '', - setSearchText: () => {}, filtersState: { chosenFilters: new Set(), addFilter: () => {}, @@ -95,14 +91,17 @@ export const PrivateGameTemplateStoreContext = React.createContext { + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); + const { + searchText: shopSearchText, + setSearchText: setShopSearchText, + } = shopNavigationState; const { limits } = React.useContext(AuthenticatedUserContext); const [ @@ -123,7 +122,6 @@ export const PrivateGameTemplateStoreStateProvider = ({ const isLoading = React.useRef(false); const { showAlert } = useAlertDialog(); - const [shopSearchText, setShopSearchText] = React.useState(defaultSearchText); const [exampleStoreSearchText, setExampleStoreSearchText] = React.useState( defaultSearchText ); @@ -224,7 +222,8 @@ export const PrivateGameTemplateStoreStateProvider = ({ }); shopNavigationState.openPrivateGameTemplateInformationPage({ privateGameTemplateListingData, - previousSearchText: shopSearchText, + storeSearchText: true, + clearSearchText: false, }); initialGameTemplateOpened.current = false; // Allow to open the game template again if the effect run again. setInitialGameTemplateUserFriendlySlug(null); @@ -242,7 +241,6 @@ export const PrivateGameTemplateStoreStateProvider = ({ shopNavigationState, showAlert, initialGameTemplateUserFriendlySlug, - shopSearchText, ] ); @@ -341,6 +339,7 @@ export const PrivateGameTemplateStoreStateProvider = ({ privateGameTemplateListingDatasSearchResultsForExampleStore, privateGameTemplateListingDatasSearchResultsForShop, shopSearchText, + setShopSearchText, exampleStoreSearchText, currentPage.filtersState, filtersStateForExampleStore, diff --git a/newIDE/app/src/AssetStore/index.js b/newIDE/app/src/AssetStore/index.js index 3eabb100358d..9ebbba501e44 100644 --- a/newIDE/app/src/AssetStore/index.js +++ b/newIDE/app/src/AssetStore/index.js @@ -47,6 +47,7 @@ import AlertMessage from '../UI/AlertMessage'; import AuthenticatedUserContext from '../Profile/AuthenticatedUserContext'; import { LineStackLayout } from '../UI/Layout'; import { + AssetStoreNavigatorContext, isHomePage, isSearchResultPage, type AssetStorePageState, @@ -121,14 +122,17 @@ export const AssetStore = React.forwardRef( privateAssetPackListingDatas, error: assetStoreError, fetchAssetsAndFilters, - shopNavigationState, - searchText, - setSearchText: setAssetStoreSearchText, clearAllFilters: clearAllAssetStoreFilters, assetFiltersState, getAssetShortHeaderFromId, } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); + const { + searchText, + setSearchText: setAssetStoreSearchText, + } = shopNavigationState; + const assetSwappedObjectPtr = React.useRef(null); React.useEffect( () => { @@ -169,10 +173,7 @@ export const AssetStore = React.forwardRef( privateGameTemplateListingDatas, error: privateGameTemplateStoreError, fetchGameTemplates, - shop: { - privateGameTemplateListingDatasSearchResults, - setSearchText: setPrivateGameTemplateSearchText, - }, + shop: { privateGameTemplateListingDatasSearchResults }, } = React.useContext(PrivateGameTemplateStoreContext); const currentPage = shopNavigationState.getCurrentPage(); const { @@ -226,9 +227,8 @@ export const AssetStore = React.forwardRef( const setSearchText = React.useCallback( (newSearchText: string) => { setAssetStoreSearchText(newSearchText); - setPrivateGameTemplateSearchText(newSearchText); }, - [setAssetStoreSearchText, setPrivateGameTemplateSearchText] + [setAssetStoreSearchText] ); const fetchAssetsAndGameTemplates = React.useCallback( @@ -344,12 +344,10 @@ export const AssetStore = React.forwardRef( assetPackKind, }); saveScrollPosition(); - const previousSearchText = searchText; - // Don't reset search text when opening an asset as the search bar is not active. - // This helps speeding up the navigation when going back to the results page. shopNavigationState.openAssetDetailPage({ assetShortHeader, - previousSearchText, + storeSearchText: true, + clearSearchText: false, }); }, [ @@ -358,7 +356,6 @@ export const AssetStore = React.forwardRef( privateAssetPackListingDatas, saveScrollPosition, shopNavigationState, - searchText, ] ); @@ -378,19 +375,15 @@ export const AssetStore = React.forwardRef( Window.openExternalURL(assetPack.externalWebLink); } else { saveScrollPosition(); - const previousSearchText = searchText; - setSearchText(''); // Reset search text when opening a pack. - shopNavigationState.openPackPage({ assetPack, previousSearchText }); + shopNavigationState.openPackPage({ + assetPack, + storeSearchText: true, + clearSearchText: true, + }); openFiltersPanelIfAppropriate(); } }, - [ - shopNavigationState, - searchText, - saveScrollPosition, - setSearchText, - openFiltersPanelIfAppropriate, - ] + [shopNavigationState, saveScrollPosition, openFiltersPanelIfAppropriate] ); // When a private pack is selected from the home page, @@ -417,11 +410,10 @@ export const AssetStore = React.forwardRef( assetPackKind: 'private', }); saveScrollPosition(); - const previousSearchText = searchText; - setSearchText(''); // Reset search text when opening a pack. shopNavigationState.openPrivateAssetPackInformationPage({ privateAssetPackListingData, - previousSearchText, + storeSearchText: true, + clearSearchText: true, }); return; } @@ -435,11 +427,10 @@ export const AssetStore = React.forwardRef( source: 'store-home', }); saveScrollPosition(); - const previousSearchText = searchText; - setSearchText(''); // Reset search text when opening a pack. shopNavigationState.openPackPage({ assetPack: receivedAssetPack, - previousSearchText, + storeSearchText: true, + clearSearchText: true, }); openFiltersPanelIfAppropriate(); }, @@ -447,9 +438,7 @@ export const AssetStore = React.forwardRef( receivedAssetPacks, saveScrollPosition, shopNavigationState, - setSearchText, openFiltersPanelIfAppropriate, - searchText, ] ); @@ -475,14 +464,13 @@ export const AssetStore = React.forwardRef( source: 'store', }); saveScrollPosition(); - const previousSearchText = searchText; - setSearchText(''); // Reset search text when opening a template. shopNavigationState.openPrivateGameTemplateInformationPage({ privateGameTemplateListingData, - previousSearchText, + storeSearchText: true, + clearSearchText: true, }); }, - [saveScrollPosition, setSearchText, searchText, shopNavigationState] + [saveScrollPosition, shopNavigationState] ); const selectShopCategory = React.useCallback( @@ -505,16 +493,17 @@ export const AssetStore = React.forwardRef( publicAssetPacks && publicAssetPacks.starterPacks.find(pack => pack.tag === tag); saveScrollPosition(); - setSearchText(''); if (privateAssetPack) { shopNavigationState.openPackPage({ assetPack: privateAssetPack, - previousSearchText: '', // We were on an asset page. + storeSearchText: false, + clearSearchText: true, }); } else if (publicAssetPack) { shopNavigationState.openPackPage({ assetPack: publicAssetPack, - previousSearchText: '', // We were on an asset page. + storeSearchText: false, + clearSearchText: true, }); } else { shopNavigationState.openTagPage(tag); @@ -523,7 +512,6 @@ export const AssetStore = React.forwardRef( openFiltersPanelIfAppropriate(); }, [ - setSearchText, receivedAssetPacks, publicAssetPacks, saveScrollPosition, diff --git a/newIDE/app/src/EventsSheet/EventsSearcher.js b/newIDE/app/src/EventsSheet/EventsSearcher.js index 55e0ddea13c9..7bafa8f55b34 100644 --- a/newIDE/app/src/EventsSheet/EventsSearcher.js +++ b/newIDE/app/src/EventsSheet/EventsSearcher.js @@ -50,6 +50,25 @@ type Props = {| |}) => React.Node, |}; +const deduplicateEventSearchResults = ( + eventsSearchResults: gdVectorEventsSearchResult +) => { + const resultEventsWithDuplicates = mapFor( + 0, + eventsSearchResults.size(), + eventIndex => { + const eventsSearchResult = eventsSearchResults.at(eventIndex); + return eventsSearchResult.isEventValid() + ? eventsSearchResult.getEvent() + : null; + } + ).filter(Boolean); + + // Store a list of unique events, because browsing for results in the events + // tree is made event by event. + return uniqBy(resultEventsWithDuplicates, event => event.ptr); +}; + /** * Computes the positions of the first selected event and the search results * in the flatten event tree and looks for the search result just after the @@ -116,25 +135,6 @@ export default class EventsSearcher extends React.Component { }); }; - _deduplicateEventSearchResults = ( - eventsSearchResults: gdVectorEventsSearchResult - ) => { - const resultEventsWithDuplicates = mapFor( - 0, - eventsSearchResults.size(), - eventIndex => { - const eventsSearchResult = eventsSearchResults.at(eventIndex); - return eventsSearchResult.isEventValid() - ? eventsSearchResult.getEvent() - : null; - } - ).filter(Boolean); - - // Store a list of unique events, because browsing for results in the events - // tree is made event by event. - return uniqBy(resultEventsWithDuplicates, event => event.ptr); - }; - _doReplaceInEvents = ( { searchInSelection, @@ -181,7 +181,7 @@ export default class EventsSearcher extends React.Component { cb(); } ); - return this._deduplicateEventSearchResults(modifiedEvents); + return deduplicateEventSearchResults(modifiedEvents); }; _doSearchInEvents = ( @@ -238,9 +238,7 @@ export default class EventsSearcher extends React.Component { return; } - this._resultEvents = this._deduplicateEventSearchResults( - eventsSearchResults - ); + this._resultEvents = deduplicateEventSearchResults(eventsSearchResults); }; _goToSearchResults = (step: number): ?gdBaseEvent => { diff --git a/newIDE/app/src/MainFrame/EditorContainers/HomePage/StoreSection/index.js b/newIDE/app/src/MainFrame/EditorContainers/HomePage/StoreSection/index.js index 4bde6e27021d..93531cee1fc0 100644 --- a/newIDE/app/src/MainFrame/EditorContainers/HomePage/StoreSection/index.js +++ b/newIDE/app/src/MainFrame/EditorContainers/HomePage/StoreSection/index.js @@ -12,6 +12,7 @@ import { enumerateAssetStoreIds } from '../../../../AssetStore/EnumerateAssetSto import { type PrivateGameTemplateListingData } from '../../../../Utils/GDevelopServices/Shop'; import ErrorBoundary from '../../../../UI/ErrorBoundary'; import { getAssetShortHeadersToDisplay } from '../../../../AssetStore/AssetsList'; +import { AssetStoreNavigatorContext } from '../../../../AssetStore/AssetStoreNavigator'; type Props = {| project: ?gdProject, @@ -32,10 +33,10 @@ const StoreSection = ({ isAssetPackDialogInstallOpen, setIsAssetPackDialogInstallOpen, ] = React.useState(false); - const { - assetShortHeadersSearchResults, - shopNavigationState, - } = React.useContext(AssetStoreContext); + const shopNavigationState = React.useContext(AssetStoreNavigatorContext); + const { assetShortHeadersSearchResults } = React.useContext( + AssetStoreContext + ); const { openedAssetPack, openedAssetShortHeader, diff --git a/newIDE/app/src/MainFrame/Providers.js b/newIDE/app/src/MainFrame/Providers.js index 964537d56fa6..a41fd28f989f 100644 --- a/newIDE/app/src/MainFrame/Providers.js +++ b/newIDE/app/src/MainFrame/Providers.js @@ -35,7 +35,7 @@ import { SubscriptionSuggestionProvider } from '../Profile/Subscription/Subscrip import { RouterContextProvider } from './RouterContext'; import ErrorBoundary from '../UI/ErrorBoundary'; import { FullThemeProvider } from '../UI/Theme/FullThemeProvider'; -import { useShopNavigation } from '../AssetStore/AssetStoreNavigator'; +import { AssetStoreNavigatorStateProvider } from '../AssetStore/AssetStoreNavigator'; import { Trans } from '@lingui/macro'; import { CreditsPackageStoreStateProvider } from '../AssetStore/CreditsPackages/CreditsPackageStoreContext'; import { ProductLicenseStoreStateProvider } from '../AssetStore/ProductLicense/ProductLicenseStoreContext'; @@ -65,7 +65,6 @@ const Providers = ({ eventsFunctionsExtensionWriter, eventsFunctionsExtensionOpener, }: Props) => { - const shopNavigationState = useShopNavigation(); return ( @@ -101,43 +100,37 @@ const Providers = ({ > - - - - - - - - - - - - - - {children({ - i18n, - })} - - - - - - - - - - - - - + + + + + + + + + + + + + + + {children({ + i18n, + })} + + + + + + + + + + + + + + diff --git a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js index b88cfede07ab..54f414a05a92 100644 --- a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js +++ b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetDetails.stories.js @@ -10,7 +10,7 @@ import { import { AssetStoreStateProvider } from '../../../../AssetStore/AssetStoreContext'; import { GDevelopUserApi } from '../../../../Utils/GDevelopServices/ApiConfigs'; import PublicProfileProvider from '../../../../Profile/PublicProfileProvider'; -import { useShopNavigation } from '../../../../AssetStore/AssetStoreNavigator'; +import { AssetStoreNavigatorStateProvider } from '../../../../AssetStore/AssetStoreNavigator'; export default { title: 'AssetStore/AssetStore/AssetDetails', @@ -19,12 +19,11 @@ export default { }; const Wrapper = ({ children }: {| children: React.Node |}) => { - const navigationState = useShopNavigation(); return ( - - {children} - + + {children} + ); }; diff --git a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetPackInstallDialog.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetPackInstallDialog.stories.js index 7dc5aa3b94b7..b6b8d26d00b5 100644 --- a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetPackInstallDialog.stories.js +++ b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetPackInstallDialog.stories.js @@ -17,8 +17,8 @@ import { testProject } from '../../../GDevelopJsInitializerDecorator'; import PrivateAssetsAuthorizationContext from '../../../../AssetStore/PrivateAssets/PrivateAssetsAuthorizationContext'; import EventsFunctionsExtensionsContext from '../../../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsContext'; import fakeResourceManagementProps from '../../../FakeResourceManagement'; -import { useShopNavigation } from '../../../../AssetStore/AssetStoreNavigator'; import { fakeEventsFunctionsExtensionsState } from '../../../FakeEventsFunctionsExtensionsContext'; +import { AssetStoreNavigatorStateProvider } from '../../../../AssetStore/AssetStoreNavigator'; export default { title: 'AssetStore/AssetStore/AssetPackInstallDialog', @@ -76,14 +76,13 @@ const mockFailedApiDataForPublicAsset1 = [ ]; const Wrapper = ({ children }: {| children: React.Node |}) => { - const navigationState = useShopNavigation(); return ( - - {children} - + + {children} + ); }; @@ -170,8 +169,6 @@ LayoutPublicAssetSomeAlreadyInstalled.parameters = { }; export const LayoutPrivateAssetInstallSuccess = () => { - const navigationState = useShopNavigation(); - return ( { 'https://resources.gevelop.io/path/to/audio/archive', }} > - - ()} - onClose={action('onClose')} - onAssetsAdded={action('onAssetsAdded')} - project={testProject.project} - objectsContainer={testProject.testLayout.getObjects()} - resourceManagementProps={{ - ...fakeResourceManagementProps, - canInstallPrivateAsset: () => true, - }} - /> - + + + ()} + onClose={action('onClose')} + onAssetsAdded={action('onAssetsAdded')} + project={testProject.project} + objectsContainer={testProject.testLayout.getObjects()} + resourceManagementProps={{ + ...fakeResourceManagementProps, + canInstallPrivateAsset: () => true, + }} + /> + + ); }; export const LayoutPrivateAssetInstallFailure = () => { - const navigationState = useShopNavigation(); - return ( { 'https://resources.gevelop.io/path/to/audio/archive', }} > - - ()} - onClose={action('onClose')} - onAssetsAdded={action('onAssetsAdded')} - project={testProject.project} - objectsContainer={testProject.testLayout.getObjects()} - resourceManagementProps={{ - ...fakeResourceManagementProps, - canInstallPrivateAsset: () => true, - }} - /> - + + + ()} + onClose={action('onClose')} + onAssetsAdded={action('onAssetsAdded')} + project={testProject.project} + objectsContainer={testProject.testLayout.getObjects()} + resourceManagementProps={{ + ...fakeResourceManagementProps, + canInstallPrivateAsset: () => true, + }} + /> + + ); }; diff --git a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetStore.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetStore.stories.js index 1998b5e58c24..530a9138b608 100644 --- a/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetStore.stories.js +++ b/newIDE/app/src/stories/componentStories/AssetStore/AssetStore/AssetStore.stories.js @@ -10,7 +10,7 @@ import { fakeSilverAuthenticatedUser, } from '../../../../fixtures/GDevelopServicesTestData'; import AuthenticatedUserContext from '../../../../Profile/AuthenticatedUserContext'; -import { useShopNavigation } from '../../../../AssetStore/AssetStoreNavigator'; +import { AssetStoreNavigatorStateProvider } from '../../../../AssetStore/AssetStoreNavigator'; export default { title: 'AssetStore/AssetStore', @@ -41,13 +41,12 @@ const apiDataFakePacks = { }; const Wrapper = ({ children }: {| children: React.Node |}) => { - const navigationState = useShopNavigation(); return ( - - {children} - + + {children} + ); diff --git a/newIDE/app/src/stories/componentStories/AssetStore/CustomObjectPackResults.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/CustomObjectPackResults.stories.js index 986eab1c59b3..2248a94a0a0d 100644 --- a/newIDE/app/src/stories/componentStories/AssetStore/CustomObjectPackResults.stories.js +++ b/newIDE/app/src/stories/componentStories/AssetStore/CustomObjectPackResults.stories.js @@ -6,7 +6,7 @@ import paperDecorator from '../../PaperDecorator'; import { AssetStoreStateProvider } from '../../../AssetStore/AssetStoreContext'; import { CustomObjectPackResults } from '../../../AssetStore/NewObjectFromScratch'; import FixedHeightFlexContainer from '../../FixedHeightFlexContainer'; -import { useShopNavigation } from '../../../AssetStore/AssetStoreNavigator'; +import { AssetStoreNavigatorStateProvider } from '../../../AssetStore/AssetStoreNavigator'; export default { title: 'AssetStore/CustomObjectPackResults', @@ -15,12 +15,11 @@ export default { }; const Wrapper = ({ children }: {| children: React.Node |}) => { - const navigationState = useShopNavigation(); return ( - - {children} - + + {children} + ); }; diff --git a/newIDE/app/src/stories/componentStories/AssetStore/NewObjectDialog.stories.js b/newIDE/app/src/stories/componentStories/AssetStore/NewObjectDialog.stories.js index 58d0b8445388..40c0868a6a8f 100644 --- a/newIDE/app/src/stories/componentStories/AssetStore/NewObjectDialog.stories.js +++ b/newIDE/app/src/stories/componentStories/AssetStore/NewObjectDialog.stories.js @@ -8,7 +8,7 @@ import NewObjectDialog from '../../../AssetStore/NewObjectDialog'; import { AssetStoreStateProvider } from '../../../AssetStore/AssetStoreContext'; import { testProject } from '../../GDevelopJsInitializerDecorator'; import fakeResourceManagementProps from '../../FakeResourceManagement'; -import { useShopNavigation } from '../../../AssetStore/AssetStoreNavigator'; +import { AssetStoreNavigatorStateProvider } from '../../../AssetStore/AssetStoreNavigator'; export default { title: 'AssetStore/NewObjectDialog', @@ -17,23 +17,24 @@ export default { }; export const Default = () => { - const navigationState = useShopNavigation(); return ( - - - {({ i18n }) => ( - - )} - - + + + + {({ i18n }) => ( + + )} + + + ); };