From 767d1ef8b698baea3a403737177a193e451af4c3 Mon Sep 17 00:00:00 2001
From: Paul Kaplan <pkaplan@media.mit.edu>
Date: Wed, 14 Nov 2018 10:30:44 -0500
Subject: [PATCH] Remove the hideIntro override and default preview modal to
 false

The use of an "override" prop that allowed the preview modal to be hidden without actually changing the redux state was causing a problem where the block editors where not closing when modals were opening. That is because it relied on the modal reducer being accurate.

I defaulted the preview state to false to make it simpler to consume the GUI, as www will not want the preview info to be true. I made it true in the playground instead.

This fixes https://github.com/LLK/scratch-gui/issues/3710
---
 src/containers/gui.jsx        |  6 ++----
 src/lib/app-state-hoc.jsx     | 26 +++++++++++++++-----------
 src/lib/hash-parser-hoc.jsx   | 18 ++++++++++--------
 src/playground/render-gui.jsx |  1 +
 src/reducers/gui.js           | 17 +++++++++++++----
 src/reducers/modals.js        |  2 +-
 6 files changed, 42 insertions(+), 28 deletions(-)

diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index 519d09a32..42a6d1ab7 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -84,7 +84,6 @@ class GUI extends React.Component {
             assetHost,
             cloudHost,
             error,
-            hideIntro,
             isError,
             isShowingProject,
             onStorageInit,
@@ -118,7 +117,6 @@ GUI.propTypes = {
     cloudHost: PropTypes.string,
     error: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
     fetchingProject: PropTypes.bool,
-    hideIntro: PropTypes.bool,
     importInfoVisible: PropTypes.bool,
     intl: intlShape,
     isError: PropTypes.bool,
@@ -143,7 +141,7 @@ GUI.defaultProps = {
     onUpdateProjectId: () => {}
 };
 
-const mapStateToProps = (state, ownProps) => {
+const mapStateToProps = state => {
     const loadingState = state.scratchGui.projectState.loadingState;
     return {
         activeTabIndex: state.scratchGui.editorTab.activeTabIndex,
@@ -161,7 +159,7 @@ const mapStateToProps = (state, ownProps) => {
         isRtl: state.locales.isRtl,
         isShowingProject: getIsShowingProject(loadingState),
         loadingStateVisible: state.scratchGui.modals.loadingProject,
-        previewInfoVisible: state.scratchGui.modals.previewInfo && !ownProps.hideIntro,
+        previewInfoVisible: state.scratchGui.modals.previewInfo,
         projectId: state.scratchGui.projectState.projectId,
         targetIsStage: (
             state.scratchGui.targets.stage &&
diff --git a/src/lib/app-state-hoc.jsx b/src/lib/app-state-hoc.jsx
index 9177c5219..2c3e4d792 100644
--- a/src/lib/app-state-hoc.jsx
+++ b/src/lib/app-state-hoc.jsx
@@ -31,10 +31,6 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
             let reducers = {};
             let enhancer;
 
-            this.state = {
-                tutorial: false
-            };
-
             let initializedLocales = localesInitialState;
             const locale = detectLocale(Object.keys(locales));
             if (locale !== 'en') {
@@ -56,6 +52,7 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
                     guiMiddleware,
                     initFullScreen,
                     initPlayer,
+                    initPreviewInfo,
                     initTutorialLibrary
                 } = guiRedux;
                 const {ScratchPaintReducer} = require('scratch-paint');
@@ -70,11 +67,17 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
                     }
                 } else {
                     const tutorialId = detectTutorialId();
-                    // handle ?tutorial=all for beta
-                    // if we decide to keep this for www, functionality should move to
-                    // setActiveCards in the GUI container
-                    if (tutorialId === 'all') initializedGui = initTutorialLibrary(initializedGui);
-                    if (tutorialId) this.state.tutorial = true;
+                    if (tutorialId === null) {
+                        if (props.showPreviewInfo) {
+                            // Show preview info if requested and no tutorial ID found
+                            initializedGui = initPreviewInfo(initializedGui);
+                        }
+                    } else if (tutorialId === 'all') {
+                        // Specific tutorials are set in setActiveCards in the GUI container.
+                        // Handle ?tutorial=all here for beta, if we decide to keep this for the
+                        // project page, this functionality should move to GUI container also.
+                        initializedGui = initTutorialLibrary(initializedGui);
+                    }
                 }
                 reducers = {
                     locales: localesReducer,
@@ -107,9 +110,9 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
             const {
                 isFullScreen, // eslint-disable-line no-unused-vars
                 isPlayerOnly, // eslint-disable-line no-unused-vars
+                showPreviewInfo, // eslint-disable-line no-unused-vars
                 ...componentProps
             } = this.props;
-            if (this.state.tutorial) componentProps.hideIntro = true;
             return (
                 <Provider store={this.store}>
                     <ConnectedIntlProvider>
@@ -123,7 +126,8 @@ const AppStateHOC = function (WrappedComponent, localesOnly) {
     }
     AppStateWrapper.propTypes = {
         isFullScreen: PropTypes.bool,
-        isPlayerOnly: PropTypes.bool
+        isPlayerOnly: PropTypes.bool,
+        showPreviewInfo: PropTypes.bool
     };
     return AppStateWrapper;
 };
diff --git a/src/lib/hash-parser-hoc.jsx b/src/lib/hash-parser-hoc.jsx
index 611f67699..bf169f279 100644
--- a/src/lib/hash-parser-hoc.jsx
+++ b/src/lib/hash-parser-hoc.jsx
@@ -9,6 +9,10 @@ import {
     setProjectId
 } from '../reducers/project-state';
 
+import {
+    closePreviewInfo
+} from '../reducers/modals';
+
 /* Higher Order Component to get the project id from location.hash
  * @param {React.Component} WrappedComponent: component to render
  * @returns {React.Component} component with hash parsing behavior
@@ -20,9 +24,6 @@ const HashParserHOC = function (WrappedComponent) {
             bindAll(this, [
                 'handleHashChange'
             ]);
-            this.state = {
-                hideIntro: false
-            };
         }
         componentDidMount () {
             window.addEventListener('hashchange', this.handleHashChange);
@@ -43,9 +44,6 @@ const HashParserHOC = function (WrappedComponent) {
             const hashMatch = window.location.hash.match(/#(\d+)/);
             const hashProjectId = hashMatch === null ? defaultProjectId : hashMatch[1];
             this.props.setProjectId(hashProjectId.toString());
-            if (hashProjectId !== defaultProjectId) {
-                this.setState({hideIntro: true});
-            }
         }
         render () {
             const {
@@ -58,7 +56,6 @@ const HashParserHOC = function (WrappedComponent) {
             } = this.props;
             return (
                 <WrappedComponent
-                    hideIntro={this.state.hideIntro}
                     {...componentProps}
                 />
             );
@@ -77,7 +74,12 @@ const HashParserHOC = function (WrappedComponent) {
         };
     };
     const mapDispatchToProps = dispatch => ({
-        setProjectId: projectId => dispatch(setProjectId(projectId))
+        setProjectId: projectId => {
+            dispatch(setProjectId(projectId));
+            if (projectId !== defaultProjectId) {
+                dispatch(closePreviewInfo());
+            }
+        }
     });
     // Allow incoming props to override redux-provided props. Used to mock in tests.
     const mergeProps = (stateProps, dispatchProps, ownProps) => Object.assign(
diff --git a/src/playground/render-gui.jsx b/src/playground/render-gui.jsx
index 4134b8c5f..fac1137e9 100644
--- a/src/playground/render-gui.jsx
+++ b/src/playground/render-gui.jsx
@@ -37,6 +37,7 @@ export default appTarget => {
         <WrappedGui
             backpackVisible
             showComingSoon
+            showPreviewInfo
             backpackHost={backpackHost}
         />,
         appTarget);
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index b41f72452..4be1fd19a 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -80,9 +80,6 @@ const initTutorialCard = function (currentState, deckId) {
         {},
         currentState,
         {
-            modals: {
-                previewInfo: false
-            },
             cards: {
                 visible: true,
                 content: decks,
@@ -102,13 +99,24 @@ const initTutorialLibrary = function (currentState) {
         currentState,
         {
             modals: {
-                previewInfo: false,
                 tipsLibrary: true
             }
         }
     );
 };
 
+const initPreviewInfo = function (currentState) {
+    return Object.assign(
+        {},
+        currentState,
+        {
+            modals: {
+                previewInfo: true
+            }
+        }
+    );
+};
+
 const guiReducer = combineReducers({
     alerts: alertsReducer,
     assetDrag: assetDragReducer,
@@ -141,6 +149,7 @@ export {
     guiMiddleware,
     initFullScreen,
     initPlayer,
+    initPreviewInfo,
     initTutorialCard,
     initTutorialLibrary
 };
diff --git a/src/reducers/modals.js b/src/reducers/modals.js
index d385f2613..c554536ad 100644
--- a/src/reducers/modals.js
+++ b/src/reducers/modals.js
@@ -23,7 +23,7 @@ const initialState = {
     [MODAL_EXTENSION_LIBRARY]: false,
     [MODAL_IMPORT_INFO]: false,
     [MODAL_LOADING_PROJECT]: false,
-    [MODAL_PREVIEW_INFO]: true,
+    [MODAL_PREVIEW_INFO]: false,
     [MODAL_SOUND_LIBRARY]: false,
     [MODAL_SPRITE_LIBRARY]: false,
     [MODAL_SOUND_RECORDER]: false,
-- 
GitLab