Skip to content

Commit 6d5183f

Browse files
authored
Merge pull request scratchfoundation#4567 from paulkaplan/project-thumbnailer
Add a way for GUI consumer to retrieve snapshots of the stage
2 parents 2ab48e0 + d301794 commit 6d5183f

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

src/lib/project-saver-hoc.jsx

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
4747
constructor (props) {
4848
super(props);
4949
bindAll(this, [
50+
'getProjectThumbnail',
5051
'leavePageConfirm',
5152
'tryToAutoSave'
5253
]);
@@ -57,6 +58,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
5758
// but then it'd be hard to turn this listening off in our tests
5859
window.onbeforeunload = e => this.leavePageConfirm(e);
5960
}
61+
this.props.onSetProjectThumbnailer(this.getProjectThumbnail);
6062
}
6163
componentDidUpdate (prevProps) {
6264
if (this.props.projectChanged && !prevProps.projectChanged) {
@@ -104,6 +106,8 @@ const ProjectSaverHOC = function (WrappedComponent) {
104106
// i.e. if another of this component has been mounted before this one gets unmounted
105107
// which happens when going from project to editor view.
106108
// window.onbeforeunload = undefined; // eslint-disable-line no-undefined
109+
// Remove project thumbnailer function since the components are unmounting
110+
this.props.onSetProjectThumbnailer(null);
107111
}
108112
leavePageConfirm (e) {
109113
if (this.props.projectChanged) {
@@ -282,20 +286,25 @@ const ProjectSaverHOC = function (WrappedComponent) {
282286
*/
283287
storeProjectThumbnail (projectId) {
284288
try {
285-
this.props.vm.postIOData('video', {forceTransparentPreview: true});
286-
this.props.vm.renderer.requestSnapshot(dataURI => {
287-
this.props.vm.postIOData('video', {forceTransparentPreview: false});
288-
this.props.onUpdateProjectThumbnail(
289-
projectId, dataURItoBlob(dataURI));
289+
this.getProjectThumbnail(dataURI => {
290+
this.props.onUpdateProjectThumbnail(projectId, dataURItoBlob(dataURI));
290291
});
291-
this.props.vm.renderer.draw();
292292
} catch (e) {
293293
log.error('Project thumbnail save error', e);
294294
// This is intentionally fire/forget because a failure
295295
// to save the thumbnail is not vitally important to the user.
296296
}
297297
}
298298

299+
getProjectThumbnail (callback) {
300+
this.props.vm.postIOData('video', {forceTransparentPreview: true});
301+
this.props.vm.renderer.requestSnapshot(dataURI => {
302+
this.props.vm.postIOData('video', {forceTransparentPreview: false});
303+
callback(dataURI);
304+
});
305+
this.props.vm.renderer.draw();
306+
}
307+
299308
render () {
300309
const {
301310
/* eslint-disable no-unused-vars */
@@ -318,6 +327,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
318327
onProjectError,
319328
onRemixing,
320329
onSetProjectUnchanged,
330+
onSetProjectThumbnailer,
321331
onShowAlert,
322332
onShowCopySuccessAlert,
323333
onShowRemixSuccessAlert,
@@ -378,7 +388,8 @@ const ProjectSaverHOC = function (WrappedComponent) {
378388
};
379389
ProjectSaverComponent.defaultProps = {
380390
autoSaveIntervalSecs: 120,
381-
onRemixing: () => {}
391+
onRemixing: () => {},
392+
onSetProjectThumbnailer: () => {}
382393
};
383394
const mapStateToProps = (state, ownProps) => {
384395
const loadingState = state.scratchGui.projectState.loadingState;

test/unit/util/project-saver-hoc.test.jsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,27 @@ describe('projectSaverHOC', () => {
439439
});
440440
expect(mockedOnRemixing).toHaveBeenCalledWith(false);
441441
});
442+
443+
test('uses onSetProjectThumbnailer on mount/unmount', () => {
444+
const Component = () => <div />;
445+
const WrappedComponent = projectSaverHOC(Component);
446+
const setThumb = jest.fn();
447+
const mounted = mount(
448+
<WrappedComponent
449+
store={store}
450+
vm={vm}
451+
onSetProjectThumbnailer={setThumb}
452+
/>
453+
);
454+
// Set project thumbnailer should be called on mount
455+
expect(setThumb).toHaveBeenCalledTimes(1);
456+
457+
// And it should not pass that function on to wrapped element
458+
expect(mounted.find(Component).props().onSetProjectThumbnailer).toBeUndefined();
459+
460+
// Unmounting should call it again with null
461+
mounted.unmount();
462+
expect(setThumb).toHaveBeenCalledTimes(2);
463+
expect(setThumb.mock.calls[1][0]).toBe(null);
464+
});
442465
});

0 commit comments

Comments
 (0)