Derive isScratchDesktop state from a GUI prop

This commit is contained in:
Christopher Willis-Ford committed 2018-12-19 01:10:27 -08:00
1 parent aa23b4109a
commit b9dc953ded
6 files changed
+76 -70

No files matched your search

+5
View File
@@ -36,6 +36,7 @@ import vmManagerHOC from '../lib/vm-manager-hoc.jsx';
import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx';
import GUIComponent from '../components/gui/gui.jsx';
import {setIsScratchDesktop} from '../lib/isScratchDesktop.js';
const messages = defineMessages({
defaultProjectTitle: {
@@ -47,6 +48,7 @@ const messages = defineMessages({
class GUI extends React.Component {
componentDidMount () {
setIsScratchDesktop(this.props.isScratchDesktop);
this.setReduxTitle(this.props.projectTitle);
this.props.onStorageInit(storage);
}
@@ -78,6 +80,7 @@ class GUI extends React.Component {
cloudHost,
error,
isError,
isScratchDesktop,
isShowingProject,
onStorageInit,
onUpdateProjectId,
@@ -113,6 +116,7 @@ GUI.propTypes = {
intl: intlShape,
isError: PropTypes.bool,
isLoading: PropTypes.bool,
isScratchDesktop: PropTypes.bool,
isShowingProject: PropTypes.bool,
loadingStateVisible: PropTypes.bool,
onSeeCommunity: PropTypes.func,
@@ -128,6 +132,7 @@ GUI.propTypes = {
};
GUI.defaultProps = {
isScratchDesktop: false,
onStorageInit: storageInstance => storageInstance.addOfficialScratchWebStores(),
onUpdateProjectId: () => {}
};
+17 -10
View File
@@ -7,6 +7,8 @@ import decksLibraryContent from '../lib/libraries/decks/index.jsx';
import tutorialTags from '../lib/libraries/tutorial-tags';
import analytics from '../lib/analytics';
import {notScratchDesktop} from '../lib/isScratchDesktop';
import LibraryComponent from '../components/library/library.jsx';
import {connect} from 'react-redux';
@@ -56,16 +58,21 @@ class TipsLibrary extends React.PureComponent {
});
}
render () {
const decksLibraryThumbnailData = Object.keys(decksLibraryContent).map(id => ({
rawURL: decksLibraryContent[id].img,
id: id,
name: decksLibraryContent[id].name,
featured: true,
tags: decksLibraryContent[id].tags,
urlId: decksLibraryContent[id].urlId,
requiredProjectId: decksLibraryContent[id].requiredProjectId,
hidden: decksLibraryContent[id].hidden || false
}));
const decksLibraryThumbnailData = Object.entries(decksLibraryContent)
.filter(([, item]) =>
// Scratch Desktop doesn't want tutorials with `requiredProjectId`
notScratchDesktop() || !item.hasOwnProperty('requiredProjectId')
)
.map(([id, item]) => ({
rawURL: item.img,
id: id,
name: item.name,
featured: true,
tags: item.tags,
urlId: item.urlId,
requiredProjectId: item.requiredProjectId,
hidden: item.hidden || false
}));
if (!this.props.visible) return null;
return (
+25 -31
View File
@@ -1,43 +1,37 @@
/**
* @returns {boolean} - true if is seems like the GUI is running under Scratch Desktop; false otherwise.
* This affects various things throughout the GUI. Ideally we should use some other way to check for this, but it
* should still be possible to override it externally for testing purposes. For example, maybe this should be a
* property on the GUI element or part of the global GUI state. Calls to this function should be taken as a
* placeholder for a future, better approach.
* Internal stored state. Not valid until after at least one call to `setIsScratchDesktop()`.
* @type {boolean}
*/
const isScratchDesktop = function () {
if (isScratchDesktop.override !== null) {
return isScratchDesktop.override;
}
const userAgent = navigator.userAgent.toLowerCase();
const isElectron = (userAgent.indexOf(' electron/') > -1);
return isElectron;
let _isScratchDesktop; // undefined = not ready yet
/**
* Tell the `isScratchDesktop()` whether or not the GUI is running under Scratch Desktop.
* @param {boolean} value - the new value which `isScratchDesktop()` should return in the future.
*/
const setIsScratchDesktop = function (value) {
_isScratchDesktop = value;
};
/**
* Set this value to non-null to force `isScratchDesktop` to return that value for testing & dev purposes.
* @returns {boolean} - true if it seems like the GUI is running under Scratch Desktop; false otherwise.
*/
isScratchDesktop.override = null;
const isScratchDesktop = function () {
if (typeof _isScratchDesktop === 'undefined') {
throw new Error('isScratchDesktop is not ready yet');
}
return _isScratchDesktop;
};
/**
* Parse an HREF string and extract an `isScratchDesktop` override value if present.
* The value is set in `isScratchDesktop.override`.
* Activate this by adding "?isScratchDesktop=1" or similar to the URL.
* @param {string} href - the `window.location.href` value (or equivalent) to parse
* @returns {boolean} - false if it seems like the GUI is running under Scratch Desktop; true otherwise.
*/
const setIsScratchDesktopOverrideFromHref = function (href) {
const scratchDesktopMatches = href.match(/[?&]isScratchDesktop=([^&]+)/);
if (scratchDesktopMatches) {
try {
// parse 'true' into `true`, 'false' into `false`, etc.
isScratchDesktop.override = JSON.parse(scratchDesktopMatches[1]);
} catch {
// it's not JSON so just use the string
// note that a typo like "falsy" will be treated as true
isScratchDesktop.override = scratchDesktopMatches[1];
}
}
const notScratchDesktop = function () {
return !isScratchDesktop();
};
export default isScratchDesktop;
export {setIsScratchDesktopOverrideFromHref};
export {
isScratchDesktop,
notScratchDesktop,
setIsScratchDesktop
};
+2 -15
View File
@@ -1,8 +1,6 @@
import React from 'react';
import {FormattedMessage} from 'react-intl';
import isScratchDesktop from '../../../lib/isScratchDesktop';
// Intro
import libraryIntro from './intro/lib-getting-started.jpg';
import stepMove from './intro/intro1.gif';
@@ -118,7 +116,8 @@ import addEffectsThumb from './videos/add-effects.jpg';
import moveArrowKeysThumb from './videos/move-arrow-keys.jpg';
import spinThumb from './videos/spin.jpg';
const decksRaw = {
export default {
'intro-move-sayhello': {
name: (
<FormattedMessage
@@ -1205,15 +1204,3 @@ const decksRaw = {
hidden: true
}
};
const decks = isScratchDesktop() ?
Object.entries(decksRaw)
// reject any deck with a required project ID
.filter(([, deckInfo]) => !deckInfo.hasOwnProperty('requiredProjectId'))
.reduce((newDecks, [key, deckInfo]) => {
newDecks[key] = deckInfo;
return newDecks;
}, {}) :
decksRaw;
export default decks;
-4
View File
@@ -7,10 +7,6 @@ import 'intl'; // For Safari 9
import React from 'react';
import ReactDOM from 'react-dom';
// this should be done before our other imports in case any use `isScratchDesktop()` right away
import {setIsScratchDesktopOverrideFromHref} from '../lib/isScratchDesktop';
setIsScratchDesktopOverrideFromHref(window.location.href);
import analytics from '../lib/analytics';
import AppStateHOC from '../lib/app-state-hoc.jsx';
import BrowserModalComponent from '../components/browser-modal/browser-modal.jsx';
+27 -10
View File
@@ -2,8 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom';
import {compose} from 'redux';
import isScratchDesktop from '../lib/isScratchDesktop';
import AppStateHOC from '../lib/app-state-hoc.jsx';
import GUI from '../containers/gui.jsx';
import HashParserHOC from '../lib/hash-parser-hoc.jsx';
@@ -34,19 +32,38 @@ export default appTarget => {
const backpackHostMatches = window.location.href.match(/[?&]backpack_host=([^&]*)&?/);
const backpackHost = backpackHostMatches ? backpackHostMatches[1] : null;
const scratchDesktopMatches = window.location.href.match(/[?&]isScratchDesktop=([^&]+)/);
let simulateScratchDesktop;
if (scratchDesktopMatches) {
try {
// parse 'true' into `true`, 'false' into `false`, etc.
simulateScratchDesktop = JSON.parse(scratchDesktopMatches[1]);
} catch {
// it's not JSON so just use the string
// note that a typo like "falsy" will be treated as true
simulateScratchDesktop = scratchDesktopMatches[1];
}
}
if (process.env.NODE_ENV === 'production' && typeof window === 'object') {
// Warn before navigating away
window.onbeforeunload = () => true;
}
ReactDOM.render(
<WrappedGui
backpackHost={backpackHost}
backpackVisible={!isScratchDesktop()}
canSave={false}
showComingSoon={!isScratchDesktop()}
showPreviewInfo={!isScratchDesktop()}
onClickLogo={isScratchDesktop() ? null : onClickLogo}
/>,
// important: this is checking whether `simulateScratchDesktop` is truthy, not just defined!
simulateScratchDesktop ?
<WrappedGui
isScratchDesktop
canSave={false}
/> :
<WrappedGui
backpackVisible
showComingSoon
showPreviewInfo
backpackHost={backpackHost}
canSave={false}
onClickLogo={onClickLogo}
/>,
appTarget);
};