Skip to content

Commit 25f15a5

Browse files
authored
Refactor EventsFunctionsExtensionsProvider into a function (#8019)
1 parent 5f8f1af commit 25f15a5

File tree

4 files changed

+142
-133
lines changed

4 files changed

+142
-133
lines changed

newIDE/app/src/EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider.js

Lines changed: 139 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -30,163 +30,172 @@ type Props = {|
3030
eventsFunctionsExtensionOpener: ?EventsFunctionsExtensionOpener,
3131
|};
3232

33-
type State = EventsFunctionsExtensionsState;
34-
3533
/**
3634
* Allow children components to request the loading (or unloading) of
3735
* the events functions extensions of the project.
3836
* Useful when dealing with events functions extensions (new extension created,
3937
* removed, pasted, installed, etc...).
4038
*/
41-
export default class EventsFunctionsExtensionsProvider extends React.Component<
42-
Props,
43-
State
44-
> {
45-
_eventsFunctionCodeWriter: ?EventsFunctionCodeWriter = this.props.makeEventsFunctionCodeWriter(
46-
{
47-
onWriteFile: this._onWriteFile.bind(this),
48-
}
39+
export const EventsFunctionsExtensionsProvider = ({
40+
children,
41+
i18n,
42+
makeEventsFunctionCodeWriter,
43+
eventsFunctionsExtensionWriter,
44+
eventsFunctionsExtensionOpener,
45+
}: Props) => {
46+
const [
47+
eventsFunctionsExtensionsError,
48+
setEventsFunctionsExtensionsError,
49+
] = React.useState<Error | null>(null);
50+
const includeFileHashs = React.useRef<{ [string]: number }>({});
51+
const lastLoadPromise = React.useRef<?Promise<void>>(null);
52+
53+
const onWriteFile = React.useCallback(
54+
({ includeFile, content }: IncludeFileContent) => {
55+
includeFileHashs.current[includeFile] = xxhashjs
56+
.h32(content, 0xabcd)
57+
.toNumber();
58+
},
59+
[]
60+
);
61+
62+
const eventsFunctionCodeWriter: ?EventsFunctionCodeWriter = React.useMemo(
63+
() => makeEventsFunctionCodeWriter({ onWriteFile }),
64+
[onWriteFile, makeEventsFunctionCodeWriter]
4965
);
50-
_includeFileHashs: { [string]: number } = {};
51-
_lastLoadPromise: ?Promise<void> = null;
52-
state = {
53-
eventsFunctionsExtensionsError: null,
54-
loadProjectEventsFunctionsExtensions: this._loadProjectEventsFunctionsExtensions.bind(
55-
this
56-
),
57-
unloadProjectEventsFunctionsExtensions: this._unloadProjectEventsFunctionsExtensions.bind(
58-
this
59-
),
60-
unloadProjectEventsFunctionsExtension: this._unloadProjectEventsFunctionsExtension.bind(
61-
this
62-
),
63-
reloadProjectEventsFunctionsExtensions: this._reloadProjectEventsFunctionsExtensions.bind(
64-
this
65-
),
66-
reloadProjectEventsFunctionsExtensionMetadata: this._reloadProjectEventsFunctionsExtensionMetadata.bind(
67-
this
68-
),
69-
ensureLoadFinished: this._ensureLoadFinished.bind(this),
70-
getEventsFunctionsExtensionWriter: () =>
71-
this.props.eventsFunctionsExtensionWriter,
72-
getEventsFunctionsExtensionOpener: () =>
73-
this.props.eventsFunctionsExtensionOpener,
74-
getIncludeFileHashs: () => this._includeFileHashs,
75-
};
76-
77-
_onWriteFile({ includeFile, content }: IncludeFileContent) {
78-
this._includeFileHashs[includeFile] = xxhashjs
79-
.h32(content, 0xabcd)
80-
.toNumber();
81-
}
82-
83-
_ensureLoadFinished(): Promise<void> {
84-
if (this._lastLoadPromise) {
66+
67+
const ensureLoadFinished = React.useCallback((): Promise<void> => {
68+
if (lastLoadPromise.current) {
8569
console.info(
8670
'Waiting on the events functions extensions to finish loading...'
8771
);
8872
} else {
8973
console.info('Events functions extensions are ready.');
9074
}
9175

92-
return this._lastLoadPromise
93-
? this._lastLoadPromise.then(() => {
76+
return lastLoadPromise.current
77+
? lastLoadPromise.current.then(() => {
9478
console.info('Events functions extensions finished loading.');
9579
})
9680
: Promise.resolve();
97-
}
81+
}, []);
82+
83+
const _loadProjectEventsFunctionsExtensions = React.useCallback(
84+
(project: ?gdProject): Promise<void> => {
85+
if (!project || !eventsFunctionCodeWriter) return Promise.resolve();
86+
87+
const previousLastLoadPromise =
88+
lastLoadPromise.current || Promise.resolve();
89+
90+
lastLoadPromise.current = previousLastLoadPromise
91+
.then(() =>
92+
loadProjectEventsFunctionsExtensions(
93+
project,
94+
eventsFunctionCodeWriter,
95+
i18n
96+
)
97+
)
98+
.then(() => setEventsFunctionsExtensionsError(null))
99+
.catch((eventsFunctionsExtensionsError: Error) => {
100+
setEventsFunctionsExtensionsError(eventsFunctionsExtensionsError);
101+
showErrorBox({
102+
message: i18n._(
103+
t`An error has occurred during functions generation. If GDevelop is installed, verify that nothing is preventing GDevelop from writing on disk. If you're running GDevelop online, verify your internet connection and refresh functions from the Project Manager.`
104+
),
105+
rawError: eventsFunctionsExtensionsError,
106+
errorId: 'events-functions-extensions-load-error',
107+
});
108+
})
109+
.then(() => {
110+
lastLoadPromise.current = null;
111+
});
98112

99-
_loadProjectEventsFunctionsExtensions(project: ?gdProject): Promise<void> {
100-
const { i18n } = this.props;
101-
const eventsFunctionCodeWriter = this._eventsFunctionCodeWriter;
102-
if (!project || !eventsFunctionCodeWriter) return Promise.resolve();
113+
return lastLoadPromise.current;
114+
},
115+
[eventsFunctionCodeWriter, i18n]
116+
);
103117

104-
const lastLoadPromise = this._lastLoadPromise || Promise.resolve();
118+
const _reloadProjectEventsFunctionsExtensionMetadata = React.useCallback(
119+
(project: ?gdProject, extension: gdEventsFunctionsExtension): void => {
120+
if (!project || !eventsFunctionCodeWriter) return;
105121

106-
this._lastLoadPromise = lastLoadPromise
107-
.then(() =>
108-
loadProjectEventsFunctionsExtensions(
122+
try {
123+
reloadProjectEventsFunctionsExtensionMetadata(
109124
project,
125+
extension,
110126
eventsFunctionCodeWriter,
111127
i18n
112-
)
113-
)
114-
.then(() =>
115-
this.setState({
116-
eventsFunctionsExtensionsError: null,
117-
})
118-
)
119-
.catch((eventsFunctionsExtensionsError: Error) => {
120-
this.setState({
121-
eventsFunctionsExtensionsError,
122-
});
128+
);
129+
} catch (eventsFunctionsExtensionsError) {
130+
setEventsFunctionsExtensionsError(eventsFunctionsExtensionsError);
123131
showErrorBox({
124132
message: i18n._(
125133
t`An error has occurred during functions generation. If GDevelop is installed, verify that nothing is preventing GDevelop from writing on disk. If you're running GDevelop online, verify your internet connection and refresh functions from the Project Manager.`
126134
),
127135
rawError: eventsFunctionsExtensionsError,
128136
errorId: 'events-functions-extensions-load-error',
129137
});
130-
})
131-
.then(() => {
132-
this._lastLoadPromise = null;
133-
});
134-
135-
return this._lastLoadPromise;
136-
}
137-
138-
_reloadProjectEventsFunctionsExtensionMetadata(
139-
project: ?gdProject,
140-
extension: gdEventsFunctionsExtension
141-
): void {
142-
const { i18n } = this.props;
143-
const eventsFunctionCodeWriter = this._eventsFunctionCodeWriter;
144-
if (!project || !eventsFunctionCodeWriter) return;
145-
146-
try {
147-
reloadProjectEventsFunctionsExtensionMetadata(
148-
project,
149-
extension,
150-
eventsFunctionCodeWriter,
151-
i18n
152-
);
153-
} catch (eventsFunctionsExtensionsError) {
154-
this.setState({
155-
eventsFunctionsExtensionsError,
156-
});
157-
showErrorBox({
158-
message: i18n._(
159-
t`An error has occurred during functions generation. If GDevelop is installed, verify that nothing is preventing GDevelop from writing on disk. If you're running GDevelop online, verify your internet connection and refresh functions from the Project Manager.`
160-
),
161-
rawError: eventsFunctionsExtensionsError,
162-
errorId: 'events-functions-extensions-load-error',
163-
});
164-
}
165-
}
166-
167-
_unloadProjectEventsFunctionsExtensions(project: gdProject) {
168-
unloadProjectEventsFunctionsExtensions(project);
169-
}
170-
171-
_unloadProjectEventsFunctionsExtension(
172-
project: gdProject,
173-
extensionName: string
174-
) {
175-
unloadProjectEventsFunctionsExtension(project, extensionName);
176-
}
177-
178-
_reloadProjectEventsFunctionsExtensions(project: ?gdProject): Promise<void> {
179-
if (project) {
180-
this._unloadProjectEventsFunctionsExtensions(project);
181-
}
182-
return this._loadProjectEventsFunctionsExtensions(project);
183-
}
184-
185-
render() {
186-
return (
187-
<EventsFunctionsExtensionsContext.Provider value={this.state}>
188-
{this.props.children}
189-
</EventsFunctionsExtensionsContext.Provider>
190-
);
191-
}
192-
}
138+
}
139+
},
140+
[eventsFunctionCodeWriter, i18n]
141+
);
142+
143+
const _unloadProjectEventsFunctionsExtensions = React.useCallback(
144+
(project: gdProject) => {
145+
unloadProjectEventsFunctionsExtensions(project);
146+
},
147+
[]
148+
);
149+
150+
const _unloadProjectEventsFunctionsExtension = React.useCallback(
151+
(project: gdProject, extensionName: string) => {
152+
unloadProjectEventsFunctionsExtension(project, extensionName);
153+
},
154+
[]
155+
);
156+
157+
const _reloadProjectEventsFunctionsExtensions = React.useCallback(
158+
(project: ?gdProject): Promise<void> => {
159+
if (project) {
160+
_unloadProjectEventsFunctionsExtensions(project);
161+
}
162+
return _loadProjectEventsFunctionsExtensions(project);
163+
},
164+
[
165+
_loadProjectEventsFunctionsExtensions,
166+
_unloadProjectEventsFunctionsExtensions,
167+
]
168+
);
169+
170+
const state = React.useMemo<EventsFunctionsExtensionsState>(
171+
() => ({
172+
eventsFunctionsExtensionsError,
173+
loadProjectEventsFunctionsExtensions: _loadProjectEventsFunctionsExtensions,
174+
unloadProjectEventsFunctionsExtensions: _unloadProjectEventsFunctionsExtensions,
175+
unloadProjectEventsFunctionsExtension: _unloadProjectEventsFunctionsExtension,
176+
reloadProjectEventsFunctionsExtensions: _reloadProjectEventsFunctionsExtensions,
177+
reloadProjectEventsFunctionsExtensionMetadata: _reloadProjectEventsFunctionsExtensionMetadata,
178+
ensureLoadFinished,
179+
getEventsFunctionsExtensionWriter: () => eventsFunctionsExtensionWriter,
180+
getEventsFunctionsExtensionOpener: () => eventsFunctionsExtensionOpener,
181+
getIncludeFileHashs: () => includeFileHashs.current,
182+
}),
183+
[
184+
ensureLoadFinished,
185+
_loadProjectEventsFunctionsExtensions,
186+
_reloadProjectEventsFunctionsExtensionMetadata,
187+
_reloadProjectEventsFunctionsExtensions,
188+
_unloadProjectEventsFunctionsExtension,
189+
_unloadProjectEventsFunctionsExtensions,
190+
eventsFunctionsExtensionOpener,
191+
eventsFunctionsExtensionWriter,
192+
eventsFunctionsExtensionsError,
193+
]
194+
);
195+
196+
return (
197+
<EventsFunctionsExtensionsContext.Provider value={state}>
198+
{children}
199+
</EventsFunctionsExtensionsContext.Provider>
200+
);
201+
};

newIDE/app/src/MainFrame/Providers.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import PreferencesContext from './Preferences/PreferencesContext';
99
import GDI18nProvider from '../Utils/i18n/GDI18nProvider';
1010
import { I18n } from '@lingui/react';
1111
import { type I18n as I18nType } from '@lingui/core';
12-
import EventsFunctionsExtensionsProvider from '../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
12+
import { EventsFunctionsExtensionsProvider } from '../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
1313
import {
1414
type EventsFunctionCodeWriter,
1515
type EventsFunctionCodeWriterCallbacks,

newIDE/app/src/stories/componentStories/AssetStore/ExtensionStore/ExtensionsSearchDialog.stories.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { action } from '@storybook/addon-actions';
55
import paperDecorator from '../../../PaperDecorator';
66
import ExtensionsSearchDialog from '../../../../AssetStore/ExtensionStore/ExtensionsSearchDialog';
77
import { I18n } from '@lingui/react';
8-
import EventsFunctionsExtensionsProvider from '../../../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
8+
import { EventsFunctionsExtensionsProvider } from '../../../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
99
import { ExtensionStoreStateProvider } from '../../../../AssetStore/ExtensionStore/ExtensionStoreContext';
1010
import { testProject } from '../../../GDevelopJsInitializerDecorator';
1111
import { GDevelopAssetApi } from '../../../../Utils/GDevelopServices/ApiConfigs';

newIDE/app/src/stories/componentStories/EventsFunctionsExtensionEditor/OptionsEditorDialog.stories.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import fakeResourceManagementProps from '../../FakeResourceManagement';
99
import { testProject } from '../../GDevelopJsInitializerDecorator';
1010

1111
import OptionsEditorDialog from '../../../EventsFunctionsExtensionEditor/OptionsEditorDialog';
12-
import EventsFunctionsExtensionsProvider from '../../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
12+
import { EventsFunctionsExtensionsProvider } from '../../../EventsFunctionsExtensionsLoader/EventsFunctionsExtensionsProvider';
1313

1414
export default {
1515
title: 'EventsFunctionsExtensionEditor/OptionsEditorDialog',

0 commit comments

Comments
 (0)