mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
317 lines
8.7 KiB
JavaScript
317 lines
8.7 KiB
JavaScript
// @flow
|
|
import * as React from 'react';
|
|
import { type FiltersState, useFilters } from '../UI/Search/FiltersChooser';
|
|
import { type Filters } from '../Utils/GDevelopServices/Filters';
|
|
import {
|
|
type AssetShortHeader,
|
|
type AssetPacks,
|
|
type Author,
|
|
type License,
|
|
listAllAssets,
|
|
listAllAuthors,
|
|
listAllLicenses,
|
|
} from '../Utils/GDevelopServices/Asset';
|
|
import { useSearchItem, SearchFilter } from '../UI/Search/UseSearchItem';
|
|
import {
|
|
TagAssetStoreSearchFilter,
|
|
AnimatedAssetStoreSearchFilter,
|
|
ObjectTypeAssetStoreSearchFilter,
|
|
ColorAssetStoreSearchFilter,
|
|
LicenseAssetStoreSearchFilter,
|
|
DimensionAssetStoreSearchFilter,
|
|
} from './AssetStoreSearchFilter';
|
|
|
|
const defaultSearchText = '';
|
|
|
|
export type AssetFiltersState = {|
|
|
animatedFilter: AnimatedAssetStoreSearchFilter,
|
|
setAnimatedFilter: AnimatedAssetStoreSearchFilter => void,
|
|
viewpointFilter: TagAssetStoreSearchFilter,
|
|
setViewpointFilter: TagAssetStoreSearchFilter => void,
|
|
dimensionFilter: DimensionAssetStoreSearchFilter,
|
|
setDimensionFilter: DimensionAssetStoreSearchFilter => void,
|
|
objectTypeFilter: ObjectTypeAssetStoreSearchFilter,
|
|
setObjectTypeFilter: ObjectTypeAssetStoreSearchFilter => void,
|
|
colorFilter: ColorAssetStoreSearchFilter,
|
|
setColorFilter: ColorAssetStoreSearchFilter => void,
|
|
licenseFilter: LicenseAssetStoreSearchFilter,
|
|
setLicenseFilter: LicenseAssetStoreSearchFilter => void,
|
|
|};
|
|
|
|
type AssetStoreState = {|
|
|
filters: ?Filters,
|
|
assetPacks: ?AssetPacks,
|
|
authors: ?Array<Author>,
|
|
licenses: ?Array<License>,
|
|
searchResults: ?Array<AssetShortHeader>,
|
|
fetchAssetsAndFilters: () => void,
|
|
error: ?Error,
|
|
isOnHomePage: boolean,
|
|
setIsOnHomePage: boolean => void,
|
|
openedAssetShortHeader: ?AssetShortHeader,
|
|
setOpenedAssetShortHeader: (?AssetShortHeader) => void,
|
|
searchText: string,
|
|
setSearchText: string => void,
|
|
filtersState: FiltersState,
|
|
assetFiltersState: AssetFiltersState,
|
|
|};
|
|
|
|
export const AssetStoreContext = React.createContext<AssetStoreState>({
|
|
filters: null,
|
|
assetPacks: null,
|
|
authors: null,
|
|
licenses: null,
|
|
searchResults: null,
|
|
fetchAssetsAndFilters: () => {},
|
|
error: null,
|
|
isOnHomePage: true,
|
|
setIsOnHomePage: () => {},
|
|
openedAssetShortHeader: null,
|
|
setOpenedAssetShortHeader: () => {},
|
|
searchText: '',
|
|
setSearchText: () => {},
|
|
filtersState: {
|
|
chosenFilters: new Set(),
|
|
addFilter: () => {},
|
|
removeFilter: () => {},
|
|
chosenCategory: null,
|
|
setChosenCategory: () => {},
|
|
},
|
|
assetFiltersState: {
|
|
animatedFilter: new AnimatedAssetStoreSearchFilter(),
|
|
setAnimatedFilter: filter => {},
|
|
viewpointFilter: new TagAssetStoreSearchFilter(),
|
|
setViewpointFilter: filter => {},
|
|
dimensionFilter: new DimensionAssetStoreSearchFilter(),
|
|
setDimensionFilter: filter => {},
|
|
objectTypeFilter: new ObjectTypeAssetStoreSearchFilter(),
|
|
setObjectTypeFilter: filter => {},
|
|
colorFilter: new ColorAssetStoreSearchFilter(),
|
|
setColorFilter: filter => {},
|
|
licenseFilter: new LicenseAssetStoreSearchFilter(),
|
|
setLicenseFilter: filter => {},
|
|
},
|
|
});
|
|
|
|
type AssetStoreStateProviderProps = {|
|
|
children: React.Node,
|
|
|};
|
|
|
|
const getAssetShortHeaderSearchTerms = (assetShortHeader: AssetShortHeader) => {
|
|
return (
|
|
assetShortHeader.name +
|
|
'\n' +
|
|
assetShortHeader.shortDescription +
|
|
'\n' +
|
|
assetShortHeader.tags.join(', ')
|
|
);
|
|
};
|
|
|
|
export const AssetStoreStateProvider = ({
|
|
children,
|
|
}: AssetStoreStateProviderProps) => {
|
|
const [assetShortHeadersById, setAssetShortHeadersById] = React.useState<?{
|
|
[string]: AssetShortHeader,
|
|
}>(null);
|
|
const [filters, setFilters] = React.useState<?Filters>(null);
|
|
const [assetPacks, setAssetPacks] = React.useState<?AssetPacks>(null);
|
|
const [authors, setAuthors] = React.useState<?Array<Author>>(null);
|
|
const [licenses, setLicenses] = React.useState<?Array<License>>(null);
|
|
const [error, setError] = React.useState<?Error>(null);
|
|
const isLoading = React.useRef<boolean>(false);
|
|
|
|
const [isOnHomePage, setIsOnHomePage] = React.useState(true);
|
|
const [
|
|
openedAssetShortHeader,
|
|
setOpenedAssetShortHeader,
|
|
] = React.useState<?AssetShortHeader>(null);
|
|
const [searchText, setSearchText] = React.useState(defaultSearchText);
|
|
const filtersState = useFilters();
|
|
|
|
const [
|
|
animatedFilter,
|
|
setAnimatedFilter,
|
|
] = React.useState<AnimatedAssetStoreSearchFilter>(
|
|
new AnimatedAssetStoreSearchFilter()
|
|
);
|
|
const [
|
|
viewpointFilter,
|
|
setViewpointFilter,
|
|
] = React.useState<TagAssetStoreSearchFilter>(
|
|
new TagAssetStoreSearchFilter()
|
|
);
|
|
const [
|
|
dimensionFilter,
|
|
setDimensionFilter,
|
|
] = React.useState<DimensionAssetStoreSearchFilter>(
|
|
new DimensionAssetStoreSearchFilter()
|
|
);
|
|
const [
|
|
objectTypeFilter,
|
|
setObjectTypeFilter,
|
|
] = React.useState<ObjectTypeAssetStoreSearchFilter>(
|
|
new ObjectTypeAssetStoreSearchFilter()
|
|
);
|
|
const [
|
|
colorFilter,
|
|
setColorFilter,
|
|
] = React.useState<ColorAssetStoreSearchFilter>(
|
|
new ColorAssetStoreSearchFilter()
|
|
);
|
|
const [
|
|
licenseFilter,
|
|
setLicenseFilter,
|
|
] = React.useState<LicenseAssetStoreSearchFilter>(
|
|
new LicenseAssetStoreSearchFilter()
|
|
);
|
|
// When one of the filter change, we need to rebuild the array
|
|
// for the search.
|
|
const searchFilters = React.useMemo<Array<SearchFilter<AssetShortHeader>>>(
|
|
() => [
|
|
animatedFilter,
|
|
viewpointFilter,
|
|
dimensionFilter,
|
|
objectTypeFilter,
|
|
colorFilter,
|
|
licenseFilter,
|
|
],
|
|
[
|
|
animatedFilter,
|
|
viewpointFilter,
|
|
dimensionFilter,
|
|
objectTypeFilter,
|
|
colorFilter,
|
|
licenseFilter,
|
|
]
|
|
);
|
|
|
|
const fetchAssetsAndFilters = React.useCallback(
|
|
() => {
|
|
// Don't attempt to load again assets and filters if they
|
|
// were loaded already.
|
|
if (assetShortHeadersById || isLoading.current) return;
|
|
|
|
(async () => {
|
|
setError(null);
|
|
isLoading.current = true;
|
|
|
|
try {
|
|
const {
|
|
assetShortHeaders,
|
|
filters,
|
|
assetPacks,
|
|
} = await listAllAssets();
|
|
const authors = await listAllAuthors();
|
|
const licenses = await listAllLicenses();
|
|
|
|
const assetShortHeadersById = {};
|
|
assetShortHeaders.forEach(assetShortHeader => {
|
|
assetShortHeadersById[assetShortHeader.id] = assetShortHeader;
|
|
});
|
|
|
|
console.info(
|
|
`Loaded ${assetShortHeaders.length} assets from the asset store.`
|
|
);
|
|
setAssetShortHeadersById(assetShortHeadersById);
|
|
setFilters(filters);
|
|
setAssetPacks(assetPacks);
|
|
setAuthors(authors);
|
|
setLicenses(licenses);
|
|
} catch (error) {
|
|
console.error(
|
|
`Unable to load the assets from the asset store:`,
|
|
error
|
|
);
|
|
setError(error);
|
|
}
|
|
|
|
isLoading.current = false;
|
|
})();
|
|
},
|
|
[assetShortHeadersById, isLoading]
|
|
);
|
|
|
|
React.useEffect(
|
|
() => {
|
|
// Don't attempt to load again assets and filters if they
|
|
// were loaded already.
|
|
if (assetShortHeadersById || isLoading.current) return;
|
|
|
|
const timeoutId = setTimeout(() => {
|
|
console.info('Pre-fetching assets from asset store...');
|
|
fetchAssetsAndFilters();
|
|
}, 6000);
|
|
return () => clearTimeout(timeoutId);
|
|
},
|
|
[fetchAssetsAndFilters, assetShortHeadersById, isLoading]
|
|
);
|
|
|
|
const { chosenCategory, chosenFilters } = filtersState;
|
|
const searchResults: ?Array<AssetShortHeader> = useSearchItem(
|
|
assetShortHeadersById,
|
|
getAssetShortHeaderSearchTerms,
|
|
searchText,
|
|
chosenCategory,
|
|
chosenFilters,
|
|
searchFilters
|
|
);
|
|
|
|
const assetStoreState = React.useMemo(
|
|
() => ({
|
|
searchResults,
|
|
fetchAssetsAndFilters,
|
|
filters,
|
|
assetPacks,
|
|
authors,
|
|
licenses,
|
|
error,
|
|
isOnHomePage,
|
|
setIsOnHomePage,
|
|
openedAssetShortHeader,
|
|
setOpenedAssetShortHeader,
|
|
searchText,
|
|
setSearchText,
|
|
filtersState,
|
|
assetFiltersState: {
|
|
animatedFilter,
|
|
setAnimatedFilter,
|
|
viewpointFilter,
|
|
setViewpointFilter,
|
|
dimensionFilter,
|
|
setDimensionFilter,
|
|
objectTypeFilter,
|
|
setObjectTypeFilter,
|
|
colorFilter,
|
|
setColorFilter,
|
|
licenseFilter,
|
|
setLicenseFilter,
|
|
},
|
|
}),
|
|
[
|
|
searchResults,
|
|
fetchAssetsAndFilters,
|
|
filters,
|
|
assetPacks,
|
|
authors,
|
|
licenses,
|
|
error,
|
|
isOnHomePage,
|
|
openedAssetShortHeader,
|
|
searchText,
|
|
filtersState,
|
|
animatedFilter,
|
|
viewpointFilter,
|
|
dimensionFilter,
|
|
objectTypeFilter,
|
|
colorFilter,
|
|
licenseFilter,
|
|
]
|
|
);
|
|
|
|
return (
|
|
<AssetStoreContext.Provider value={assetStoreState}>
|
|
{children}
|
|
</AssetStoreContext.Provider>
|
|
);
|
|
};
|