Unverified Commit 80de164d authored by chrisgarrity's avatar chrisgarrity Committed by GitHub

Handle See inside button (#1890)

* Handle See inside button

Import GUI reducers, initial state and middleware (throttle).

Update render to handle state and middleware.

Remove preview mode state and use scratchGui.mode from redux instead.

URL is getting updated, and mode will be updated based on URL. However, the history needs work - it doesn’t work with the modal back.

* Update to latest GUI

This is the minimum version of GUI that is needed for see-inside

* Really remove cruft.
parent 15779d83
...@@ -14,11 +14,13 @@ require('../main.scss'); ...@@ -14,11 +14,13 @@ require('../main.scss');
/** /**
* Function to render views into a full page * Function to render views into a full page
* @param {object} jsx jsx component of the view * @param {object} jsx jsx component of the view
* @param {object} element html element to render to on the template * @param {object} element html element to render to on the template
* @param {array} reducers list of view-specific reducers * @param {array} reducers list of view-specific reducers
* @param {object} initialState optional initialState for store
* @param {bool} enhancer whether or not to apply redux-throttle middleware
*/ */
const render = (jsx, element, reducers) => { const render = (jsx, element, reducers, initialState, enhancer) => {
// Get locale and messages from global namespace (see "init.js") // Get locale and messages from global namespace (see "init.js")
let locale = window._locale || 'en'; let locale = window._locale || 'en';
let messages = {}; let messages = {};
...@@ -35,9 +37,20 @@ const render = (jsx, element, reducers) => { ...@@ -35,9 +37,20 @@ const render = (jsx, element, reducers) => {
} }
const allReducers = reducer(reducers); const allReducers = reducer(reducers);
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || redux.compose;
const enhancers = enhancer ?
composeEnhancers(
redux.applyMiddleware(thunk),
enhancer
) :
composeEnhancers(
redux.applyMiddleware(thunk)
);
const store = redux.createStore( const store = redux.createStore(
allReducers, allReducers,
redux.applyMiddleware(thunk) initialState || {},
enhancers
); );
// Render view component // Render view component
......
...@@ -306,7 +306,7 @@ PreviewPresentation.propTypes = { ...@@ -306,7 +306,7 @@ PreviewPresentation.propTypes = {
onLoveClicked: PropTypes.func, onLoveClicked: PropTypes.func,
onSeeInside: PropTypes.func, onSeeInside: PropTypes.func,
onUpdate: PropTypes.func, onUpdate: PropTypes.func,
projectId: PropTypes.number, projectId: PropTypes.string,
projectInfo: PropTypes.shape({ projectInfo: PropTypes.shape({
id: PropTypes.number, id: PropTypes.number,
title: PropTypes.string, title: PropTypes.string,
......
...@@ -10,21 +10,26 @@ const PreviewPresentation = require('./presentation.jsx'); ...@@ -10,21 +10,26 @@ const PreviewPresentation = require('./presentation.jsx');
const sessionActions = require('../../redux/session.js'); const sessionActions = require('../../redux/session.js');
const previewActions = require('../../redux/preview.js'); const previewActions = require('../../redux/preview.js');
const GUI = require('scratch-gui').default;
const IntlGUI = injectIntl(GUI); const GUI = require('scratch-gui');
const IntlGUI = injectIntl(GUI.default);
class Preview extends React.Component { class Preview extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
bindAll(this, [ bindAll(this, [
'addEventListeners',
'handleFavoriteToggle', 'handleFavoriteToggle',
'handleLoveToggle', 'handleLoveToggle',
'handlePermissions', 'handlePermissions',
'handlePopState',
'handleSeeInside', 'handleSeeInside',
'handleUpdate', 'handleUpdate',
'initCounts' 'initCounts',
'pushHistory'
]); ]);
this.state = this.initState(); this.state = this.initState();
this.addEventListeners();
} }
componentDidUpdate (prevProps) { componentDidUpdate (prevProps) {
if (this.props.sessionStatus !== prevProps.sessionStatus && if (this.props.sessionStatus !== prevProps.sessionStatus &&
...@@ -52,6 +57,51 @@ class Preview extends React.Component { ...@@ -52,6 +57,51 @@ class Preview extends React.Component {
this.props.getCreditInfo(this.props.projectInfo.remix.root); this.props.getCreditInfo(this.props.projectInfo.remix.root);
} }
} }
if (this.props.playerMode !== prevProps.playerMode || this.props.fullScreen !== prevProps.fullScreen) {
this.pushHistory(history.state === null);
}
}
componentWillUnmount () {
this.removeEventListeners();
}
addEventListeners () {
window.addEventListener('popstate', this.handlePopState);
}
removeEventListeners () {
window.removeEventListener('popstate', this.handlePopState);
}
handlePopState () {
const path = window.location.pathname.toLowerCase();
const playerMode = path.indexOf('editor') === -1;
const fullScreen = path.indexOf('fullscreen') !== -1;
if (this.props.playerMode !== playerMode) {
this.props.setPlayer(playerMode);
}
if (this.props.fullScreen !== fullScreen) {
this.props.setFullScreen(fullScreen);
}
}
pushHistory (push) {
// update URI to match mode
const idPath = this.state.projectId ? `${this.state.projectId}/` : '';
let modePath = '';
if (!this.props.playerMode) modePath = 'editor/';
// fullscreen overrides editor
if (this.props.fullScreen) modePath = 'fullscreen/';
const newPath = `/preview/${idPath}${modePath}`;
if (push) {
history.pushState(
{},
document.title,
newPath
);
} else {
history.replaceState(
{},
document.title,
newPath
);
}
} }
initState () { initState () {
const pathname = window.location.pathname.toLowerCase(); const pathname = window.location.pathname.toLowerCase();
...@@ -62,10 +112,8 @@ class Preview extends React.Component { ...@@ -62,10 +112,8 @@ class Preview extends React.Component {
return { return {
editable: false, editable: false,
favoriteCount: 0, favoriteCount: 0,
inEditor: parts.indexOf('editor') !== -1,
isFullScreen: parts.indexOf('fullscreen') !== -1,
loveCount: 0, loveCount: 0,
projectId: parts[1] === 'editor' ? null : parts[1] projectId: parts[1] === 'editor' ? 0 : parts[1]
}; };
} }
handleFavoriteToggle () { handleFavoriteToggle () {
...@@ -109,8 +157,7 @@ class Preview extends React.Component { ...@@ -109,8 +157,7 @@ class Preview extends React.Component {
} }
} }
handleSeeInside () { handleSeeInside () {
this.setState({inEditor: true}); this.props.setPlayer(false);
history.pushState({}, document.title, `/preview/${this.state.projectId}/editor`);
} }
handleUpdate (jsonData) { handleUpdate (jsonData) {
this.props.updateProject( this.props.updateProject(
...@@ -128,13 +175,7 @@ class Preview extends React.Component { ...@@ -128,13 +175,7 @@ class Preview extends React.Component {
} }
render () { render () {
return ( return (
this.state.inEditor ? this.props.playerMode ?
<IntlGUI
basePath="/"
className="gui"
isPlayerOnly={false}
projectId={this.state.projectId}
/> :
<Page> <Page>
<PreviewPresentation <PreviewPresentation
comments={this.props.comments} comments={this.props.comments}
...@@ -156,7 +197,13 @@ class Preview extends React.Component { ...@@ -156,7 +197,13 @@ class Preview extends React.Component {
onSeeInside={this.handleSeeInside} onSeeInside={this.handleSeeInside}
onUpdate={this.handleUpdate} onUpdate={this.handleUpdate}
/> />
</Page> </Page> :
<IntlGUI
enableCommunity
basePath="/"
className="gui"
projectId={this.state.projectId}
/>
); );
} }
} }
...@@ -186,6 +233,7 @@ Preview.propTypes = { ...@@ -186,6 +233,7 @@ Preview.propTypes = {
}) })
}), }),
faved: PropTypes.bool, faved: PropTypes.bool,
fullScreen: PropTypes.bool,
getCreditInfo: PropTypes.func.isRequired, getCreditInfo: PropTypes.func.isRequired,
getFavedStatus: PropTypes.func.isRequired, getFavedStatus: PropTypes.func.isRequired,
getLovedStatus: PropTypes.func.isRequired, getLovedStatus: PropTypes.func.isRequired,
...@@ -193,6 +241,7 @@ Preview.propTypes = { ...@@ -193,6 +241,7 @@ Preview.propTypes = {
getRemixes: PropTypes.func.isRequired, getRemixes: PropTypes.func.isRequired,
getStudios: PropTypes.func.isRequired, getStudios: PropTypes.func.isRequired,
loved: PropTypes.bool, loved: PropTypes.bool,
playerMode: PropTypes.bool,
projectInfo: PropTypes.shape({ projectInfo: PropTypes.shape({
author: PropTypes.shape({ author: PropTypes.shape({
id: PropTypes.number, id: PropTypes.number,
...@@ -219,7 +268,9 @@ Preview.propTypes = { ...@@ -219,7 +268,9 @@ Preview.propTypes = {
remixes: PropTypes.arrayOf(PropTypes.object), remixes: PropTypes.arrayOf(PropTypes.object),
sessionStatus: PropTypes.string, sessionStatus: PropTypes.string,
setFavedStatus: PropTypes.func.isRequired, setFavedStatus: PropTypes.func.isRequired,
setFullScreen: PropTypes.func.isRequired,
setLovedStatus: PropTypes.func.isRequired, setLovedStatus: PropTypes.func.isRequired,
setPlayer: PropTypes.func.isRequired,
studios: PropTypes.arrayOf(PropTypes.object), studios: PropTypes.arrayOf(PropTypes.object),
updateProject: PropTypes.func.isRequired, updateProject: PropTypes.func.isRequired,
user: PropTypes.shape({ user: PropTypes.shape({
...@@ -248,7 +299,9 @@ const mapStateToProps = state => ({ ...@@ -248,7 +299,9 @@ const mapStateToProps = state => ({
remixes: state.preview.remixes, remixes: state.preview.remixes,
sessionStatus: state.session.status, sessionStatus: state.session.status,
studios: state.preview.studios, studios: state.preview.studios,
user: state.session.session.user user: state.session.session.user,
playerMode: state.scratchGui.mode.isPlayerOnly,
fullScreen: state.scratchGui.mode.isFullScreen
}); });
...@@ -285,6 +338,12 @@ const mapDispatchToProps = dispatch => ({ ...@@ -285,6 +338,12 @@ const mapDispatchToProps = dispatch => ({
}, },
updateProject: (id, formData, username, token) => { updateProject: (id, formData, username, token) => {
dispatch(previewActions.updateProject(id, formData, username, token)); dispatch(previewActions.updateProject(id, formData, username, token));
},
setPlayer: player => {
dispatch(GUI.setPlayer(player));
},
setFullScreen: fullscreen => {
dispatch(GUI.setFullScreen(fullscreen));
} }
}); });
...@@ -293,8 +352,29 @@ const ConnectedPreview = connect( ...@@ -293,8 +352,29 @@ const ConnectedPreview = connect(
mapDispatchToProps mapDispatchToProps
)(Preview); )(Preview);
GUI.setAppElement(document.getElementById('app'));
const initGuiState = guiInitialState => {
const pathname = window.location.pathname.toLowerCase();
const parts = pathname.split('/').filter(Boolean);
// parts[0]: 'preview'
// parts[1]: either :id or 'editor'
// parts[2]: undefined if no :id, otherwise either 'editor' or 'fullscreen'
if (parts.indexOf('editor') === -1) {
guiInitialState = GUI.initPlayer(guiInitialState);
}
if (parts.indexOf('fullscreen') !== -1) {
guiInitialState = GUI.initFullScreen(guiInitialState);
}
return guiInitialState;
};
render( render(
<ConnectedPreview />, <ConnectedPreview />,
document.getElementById('app'), document.getElementById('app'),
{preview: previewActions.previewReducer} {
preview: previewActions.previewReducer,
...GUI.guiReducers
},
{scratchGui: initGuiState(GUI.guiInitialState)},
GUI.guiMiddleware
); );
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment