mirror of
https://github.com/4ian/GDevelop.git
synced 2025-10-15 10:19:04 +00:00
Order extensions according to what is specified in the extensions repository (#4080)
Don't show in changelog
This commit is contained in:
@@ -8,12 +8,13 @@ import {
|
||||
} from '../../Utils/GDevelopServices/Example';
|
||||
import { type Filters } from '../../Utils/GDevelopServices/Filters';
|
||||
import {
|
||||
useSearchItem,
|
||||
useSearchStructuredItem,
|
||||
type SearchMatch,
|
||||
} from '../../UI/Search/UseSearchStructuredItem';
|
||||
|
||||
const defaultSearchText = '';
|
||||
const excludedTiers = new Set(); // No tiers for examples.
|
||||
const firstExampleIds = [];
|
||||
|
||||
type ExampleStoreState = {|
|
||||
filters: ?Filters,
|
||||
@@ -128,13 +129,13 @@ export const ExampleStoreStateProvider = ({
|
||||
const searchResults: ?Array<{|
|
||||
item: ExampleShortHeader,
|
||||
matches: SearchMatch[],
|
||||
|}> = useSearchItem(
|
||||
exampleShortHeadersById,
|
||||
|}> = useSearchStructuredItem(exampleShortHeadersById, {
|
||||
searchText,
|
||||
chosenCategory,
|
||||
chosenFilters,
|
||||
excludedTiers
|
||||
);
|
||||
excludedTiers,
|
||||
defaultFirstSearchItemIds: firstExampleIds,
|
||||
});
|
||||
|
||||
const exampleStoreState = React.useMemo(
|
||||
() => ({
|
||||
|
@@ -8,7 +8,7 @@ import {
|
||||
} from '../../Utils/GDevelopServices/Extension';
|
||||
import { type Filters } from '../../Utils/GDevelopServices/Filters';
|
||||
import {
|
||||
useSearchItem,
|
||||
useSearchStructuredItem,
|
||||
type SearchMatch,
|
||||
} from '../../UI/Search/UseSearchStructuredItem';
|
||||
import PreferencesContext from '../../MainFrame/Preferences/PreferencesContext';
|
||||
@@ -67,6 +67,9 @@ export const ExtensionStoreStateProvider = ({
|
||||
const preferences = React.useContext(PreferencesContext);
|
||||
const { showCommunityExtensions } = preferences.values;
|
||||
const [filters, setFilters] = React.useState<?Filters>(null);
|
||||
const [firstExtensionIds, setFirstExtensionIds] = React.useState<
|
||||
Array<string>
|
||||
>([]);
|
||||
const [error, setError] = React.useState<?Error>(null);
|
||||
const isLoading = React.useRef<boolean>(false);
|
||||
|
||||
@@ -112,6 +115,11 @@ export const ExtensionStoreStateProvider = ({
|
||||
defaultTags: sortedTags,
|
||||
tagsTree: [],
|
||||
});
|
||||
setFirstExtensionIds(
|
||||
extensionRegistry.views
|
||||
? extensionRegistry.views.default.firstExtensionIds
|
||||
: []
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`Unable to load the extensions from the extension store:`,
|
||||
@@ -146,13 +154,15 @@ export const ExtensionStoreStateProvider = ({
|
||||
const searchResults: ?Array<{|
|
||||
item: ExtensionShortHeader,
|
||||
matches: SearchMatch[],
|
||||
|}> = useSearchItem(
|
||||
extensionShortHeadersByName,
|
||||
|}> = useSearchStructuredItem(extensionShortHeadersByName, {
|
||||
searchText,
|
||||
chosenCategory,
|
||||
chosenFilters,
|
||||
showCommunityExtensions ? noExcludedTiers : excludedCommunityTiers
|
||||
);
|
||||
excludedTiers: showCommunityExtensions
|
||||
? noExcludedTiers
|
||||
: excludedCommunityTiers,
|
||||
defaultFirstSearchItemIds: firstExtensionIds,
|
||||
});
|
||||
|
||||
const extensionStoreState = React.useMemo(
|
||||
() => ({
|
||||
|
@@ -14,6 +14,14 @@ export type SearchResult<T> = {|
|
||||
matches: SearchMatch[],
|
||||
|};
|
||||
|
||||
type SearchOptions = {|
|
||||
searchText: string,
|
||||
chosenCategory: ?ChosenCategory,
|
||||
chosenFilters: Set<string>,
|
||||
excludedTiers: Set<string>,
|
||||
defaultFirstSearchItemIds: Array<string>,
|
||||
|};
|
||||
|
||||
export const sharedFuseConfiguration = {
|
||||
minMatchCharLength: 1,
|
||||
threshold: 0.35,
|
||||
@@ -68,11 +76,11 @@ export const filterSearchResults = <
|
||||
+tier?: string,
|
||||
}
|
||||
>(
|
||||
searchResults: ?Array<{| item: SearchItem, matches: SearchMatch[] |}>,
|
||||
searchResults: ?Array<SearchResult<SearchItem>>,
|
||||
chosenCategory: ?ChosenCategory,
|
||||
chosenFilters: Set<string>,
|
||||
excludedTiers: Set<string>
|
||||
): ?Array<{| item: SearchItem, matches: SearchMatch[] |}> => {
|
||||
): ?Array<SearchResult<SearchItem>> => {
|
||||
if (!searchResults) return null;
|
||||
|
||||
const startTime = performance.now();
|
||||
@@ -121,7 +129,7 @@ export const filterSearchResults = <
|
||||
* then returns the results of the search (according to the
|
||||
* search text and the chosen category/filters).
|
||||
*/
|
||||
export const useSearchItem = <
|
||||
export const useSearchStructuredItem = <
|
||||
SearchItem: {
|
||||
// All search items have tags:
|
||||
tags: Array<string>,
|
||||
@@ -130,10 +138,13 @@ export const useSearchItem = <
|
||||
}
|
||||
>(
|
||||
searchItemsById: ?{ [string]: SearchItem },
|
||||
searchText: string,
|
||||
chosenCategory: ?ChosenCategory,
|
||||
chosenFilters: Set<string>,
|
||||
excludedTiers: Set<string>
|
||||
{
|
||||
searchText,
|
||||
chosenCategory,
|
||||
chosenFilters,
|
||||
excludedTiers,
|
||||
defaultFirstSearchItemIds,
|
||||
}: SearchOptions
|
||||
): ?Array<{| item: SearchItem, matches: SearchMatch[] |}> => {
|
||||
const searchApiRef = React.useRef<?any>(null);
|
||||
const [searchResults, setSearchResults] = React.useState<?Array<{|
|
||||
@@ -143,18 +154,26 @@ export const useSearchItem = <
|
||||
|
||||
// Keep in memory a list of all the items, shuffled for
|
||||
// easing random discovery of items when no search is done.
|
||||
const shuffledSearchResults = React.useMemo(
|
||||
const orderedSearchResults: Array<
|
||||
SearchResult<SearchItem>
|
||||
> | null = React.useMemo(
|
||||
() => {
|
||||
if (!searchItemsById || !Object.keys(searchItemsById).length) return null;
|
||||
|
||||
return shuffle(
|
||||
Object.keys(searchItemsById).map(id => ({
|
||||
const alreadyOrderedIds = new Set<string>(defaultFirstSearchItemIds);
|
||||
const nonOrderedIds = Object.keys(searchItemsById).filter(
|
||||
id => !alreadyOrderedIds.has(id)
|
||||
);
|
||||
|
||||
// Return the ordered results first, and shuffle the rest.
|
||||
return [...defaultFirstSearchItemIds, ...shuffle(nonOrderedIds)].map(
|
||||
id => ({
|
||||
item: searchItemsById[id],
|
||||
matches: [],
|
||||
}))
|
||||
})
|
||||
);
|
||||
},
|
||||
[searchItemsById]
|
||||
[searchItemsById, defaultFirstSearchItemIds]
|
||||
);
|
||||
|
||||
// Index items that have been loaded.
|
||||
@@ -206,7 +225,7 @@ export const useSearchItem = <
|
||||
if (!searchText) {
|
||||
setSearchResults(
|
||||
filterSearchResults(
|
||||
shuffledSearchResults,
|
||||
orderedSearchResults,
|
||||
chosenCategory,
|
||||
chosenFilters,
|
||||
excludedTiers
|
||||
@@ -252,7 +271,7 @@ export const useSearchItem = <
|
||||
};
|
||||
},
|
||||
[
|
||||
shuffledSearchResults,
|
||||
orderedSearchResults,
|
||||
searchItemsById,
|
||||
searchText,
|
||||
chosenCategory,
|
||||
|
@@ -48,6 +48,11 @@ export type ExtensionsRegistry = {
|
||||
version: string,
|
||||
allTags: Array<string>,
|
||||
extensionShortHeaders: Array<ExtensionShortHeader>,
|
||||
views?: {
|
||||
default: {
|
||||
firstExtensionIds: Array<string>,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -424,6 +424,15 @@ export const fakeExtensionsRegistry: ExtensionsRegistry = {
|
||||
'sdk',
|
||||
'ads',
|
||||
],
|
||||
views: {
|
||||
default: {
|
||||
firstExtensionIds: [
|
||||
'SomeAlreadyInstalledExtension',
|
||||
'Bounce',
|
||||
'BoidsMovement',
|
||||
],
|
||||
},
|
||||
},
|
||||
extensionShortHeaders: [
|
||||
{
|
||||
tier: 'reviewed',
|
||||
|
Reference in New Issue
Block a user