diff --git a/extensions/geolonia/gui/index.jsx b/extensions/geolonia/gui/index.jsx
index 63a101078..5c1c6656b 100644
--- a/extensions/geolonia/gui/index.jsx
+++ b/extensions/geolonia/gui/index.jsx
@@ -70,275 +70,4 @@ export default [
),
featured: true
},
- {
- name: (
-
- ),
- extensionId: 'music',
- iconURL: musicIconURL,
- insetIconURL: musicInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'pen',
- iconURL: penIconURL,
- insetIconURL: penInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'videoSensing',
- iconURL: videoSensingIconURL,
- insetIconURL: videoSensingInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'text2speech',
- collaborator: 'Amazon Web Services',
- iconURL: text2speechIconURL,
- insetIconURL: text2speechInsetIconURL,
- description: (
-
- ),
- featured: true,
- internetConnectionRequired: true
- },
- {
- name: (
-
- ),
- extensionId: 'translate',
- collaborator: 'Google',
- iconURL: translateIconURL,
- insetIconURL: translateInsetIconURL,
- description: (
-
- ),
- featured: true,
- internetConnectionRequired: true
- },
- {
- name: 'Makey Makey',
- extensionId: 'makeymakey',
- collaborator: 'JoyLabz',
- iconURL: makeymakeyIconURL,
- insetIconURL: makeymakeyInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: 'micro:bit',
- extensionId: 'microbit',
- collaborator: 'micro:bit',
- iconURL: microbitIconURL,
- insetIconURL: microbitInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: microbitConnectionIconURL,
- connectionSmallIconURL: microbitConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/microbit'
- },
- {
- name: 'LEGO MINDSTORMS EV3',
- extensionId: 'ev3',
- collaborator: 'LEGO',
- iconURL: ev3IconURL,
- insetIconURL: ev3InsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: ev3ConnectionIconURL,
- connectionSmallIconURL: ev3ConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/ev3'
- },
- {
- name: 'LEGO BOOST',
- extensionId: 'boost',
- collaborator: 'LEGO',
- iconURL: boostIconURL,
- insetIconURL: boostInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: true,
- connectionIconURL: boostConnectionIconURL,
- connectionSmallIconURL: boostConnectionSmallIconURL,
- connectionTipIconURL: boostConnectionTipIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/boost'
- },
- {
- name: 'LEGO Education WeDo 2.0',
- extensionId: 'wedo2',
- collaborator: 'LEGO',
- iconURL: wedo2IconURL,
- insetIconURL: wedo2InsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: true,
- connectionIconURL: wedo2ConnectionIconURL,
- connectionSmallIconURL: wedo2ConnectionSmallIconURL,
- connectionTipIconURL: wedo2ConnectionTipIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/wedo'
- },
- {
- name: 'Go Direct Force & Acceleration',
- extensionId: 'gdxfor',
- collaborator: 'Vernier',
- iconURL: gdxforIconURL,
- insetIconURL: gdxforInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: gdxforConnectionIconURL,
- connectionSmallIconURL: gdxforConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/vernier'
- },
-];
+]
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index a44604898..599cf8ca9 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -39,6 +39,7 @@ import addExtensionIcon from './icon--extensions.svg';
import codeIcon from './icon--code.svg';
import costumesIcon from './icon--costumes.svg';
import soundsIcon from './icon--sounds.svg';
+import { setModalExtension } from '../../reducers/modal-choose-extension.js';
const messages = defineMessages({
addExtension: {
@@ -51,316 +52,327 @@ const messages = defineMessages({
// Cache this value to only retrieve it once the first time.
// Assume that it doesn't change for a session.
let isRendererSupported = null;
-
-const GUIComponent = props => {
- const {
- accountNavOpen,
- activeTabIndex,
- alertsVisible,
- authorId,
- authorThumbnailUrl,
- authorUsername,
- basePath,
- backdropLibraryVisible,
- backpackHost,
- backpackVisible,
- blocksTabVisible,
- cardsVisible,
- canChangeLanguage,
- canCreateNew,
- canEditTitle,
- canManageFiles,
- canRemix,
- canSave,
- canCreateCopy,
- canShare,
- canUseCloud,
- children,
- connectionModalVisible,
- costumeLibraryVisible,
- costumesTabVisible,
- enableCommunity,
- intl,
- isCreating,
- isFullScreen,
- isPlayerOnly,
- isRtl,
- isShared,
- isTelemetryEnabled,
- loading,
- logo,
- renderLogin,
- onClickAbout,
- onClickAccountNav,
- onCloseAccountNav,
- onLogOut,
- onOpenRegistration,
- onToggleLoginOpen,
- onActivateCostumesTab,
- onActivateSoundsTab,
- onActivateTab,
- onClickLogo,
- onExtensionButtonClick,
- onProjectTelemetryEvent,
- onRequestCloseBackdropLibrary,
- onRequestCloseCostumeLibrary,
- onRequestCloseTelemetryModal,
- onSeeCommunity,
- onShare,
- onShowPrivacyPolicy,
- onStartSelectingFileUpload,
- onTelemetryModalCancel,
- onTelemetryModalOptIn,
- onTelemetryModalOptOut,
- showComingSoon,
- soundsTabVisible,
- stageSizeMode,
- targetIsStage,
- telemetryModalVisible,
- tipsLibraryVisible,
- vm,
- ...componentProps
- } = omit(props, 'dispatch');
- if (children) {
- return {children};
+class GUIComponent extends React.Component {
+ componentDidUpdate() {
+ const { projectId, onShowExtension } = this.props;
+ if (projectId === '0') {
+ onShowExtension(false);
+ }
}
+ render(){
+ const {
+ children,
+ projectId,
+ showExtension,
+ accountNavOpen,
+ activeTabIndex,
+ alertsVisible,
+ authorId,
+ authorThumbnailUrl,
+ authorUsername,
+ basePath,
+ backdropLibraryVisible,
+ backpackHost,
+ backpackVisible,
+ blocksTabVisible,
+ cardsVisible,
+ canChangeLanguage,
+ canCreateNew,
+ canEditTitle,
+ canManageFiles,
+ canRemix,
+ canSave,
+ canCreateCopy,
+ canShare,
+ canUseCloud,
+ connectionModalVisible,
+ costumeLibraryVisible,
+ costumesTabVisible,
+ enableCommunity,
+ intl,
+ isCreating,
+ isFullScreen,
+ isPlayerOnly,
+ isRtl,
+ isShared,
+ isTelemetryEnabled,
+ loading,
+ logo,
+ renderLogin,
+ modalChooseExtensionAlreadyBeenOpened,
+ onClickAbout,
+ onClickAccountNav,
+ onCloseAccountNav,
+ onLogOut,
+ onOpenRegistration,
+ onToggleLoginOpen,
+ onActivateCostumesTab,
+ onActivateSoundsTab,
+ onActivateTab,
+ onClickLogo,
+ onProjectTelemetryEvent,
+ onRequestCloseBackdropLibrary,
+ onRequestCloseCostumeLibrary,
+ onRequestCloseTelemetryModal,
+ onSeeCommunity,
+ onShare,
+ onShowPrivacyPolicy,
+ onStartSelectingFileUpload,
+ onTelemetryModalCancel,
+ onTelemetryModalOptIn,
+ onTelemetryModalOptOut,
+ onShowExtension,
+ showComingSoon,
+ soundsTabVisible,
+ stageSizeMode,
+ setModalExtensionVisibility,
+ targetIsStage,
+ telemetryModalVisible,
+ tipsLibraryVisible,
+ vm,
+ ...componentProps
+ } = omit(this.props, 'dispatch');
- const tabClassNames = {
- tabs: styles.tabs,
- tab: classNames(tabStyles.reactTabsTab, styles.tab),
- tabList: classNames(tabStyles.reactTabsTabList, styles.tabList),
- tabPanel: classNames(tabStyles.reactTabsTabPanel, styles.tabPanel),
- tabPanelSelected: classNames(tabStyles.reactTabsTabPanelSelected, styles.isSelected),
- tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected)
- };
+ if (children) {
+ return {children};
+ }
- if (isRendererSupported === null) {
- isRendererSupported = Renderer.isSupported();
- }
+ const tabClassNames = {
+ tabs: styles.tabs,
+ tab: classNames(tabStyles.reactTabsTab, styles.tab),
+ tabList: classNames(tabStyles.reactTabsTabList, styles.tabList),
+ tabPanel: classNames(tabStyles.reactTabsTabPanel, styles.tabPanel),
+ tabPanelSelected: classNames(tabStyles.reactTabsTabPanelSelected, styles.isSelected),
+ tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected)
+ };
- return ({isFullSize => {
- const stageSize = resolveStageSize(stageSizeMode, isFullSize);
+ if (isRendererSupported === null) {
+ isRendererSupported = Renderer.isSupported();
+ }
+ return ({isFullSize => {
+ const stageSize = resolveStageSize(stageSizeMode, isFullSize);
- return isPlayerOnly ? (
-
- {alertsVisible ? (
-
- ) : null}
-
- ) : (
-
- {telemetryModalVisible ? (
-
- ) : null}
- {loading ? (
-
- ) : null}
- {isCreating ? (
-
- ) : null}
- {isRendererSupported ? null : (
-
- )}
- {tipsLibraryVisible ? (
-
- ) : null}
- {cardsVisible ? (
-
- ) : null}
- {alertsVisible ? (
-
- ) : null}
- {connectionModalVisible ? (
-
+ {alertsVisible ? (
+
+ ) : null}
+
+ ) : (
+
+ {telemetryModalVisible ? (
+
+ ) : null}
+ {loading ? (
+
+ ) : null}
+ {isCreating ? (
+
+ ) : null}
+ {isRendererSupported ? null : (
+
+ )}
+ {tipsLibraryVisible ? (
+
+ ) : null}
+ {cardsVisible ? (
+
+ ) : null}
+ {alertsVisible ? (
+
+ ) : null}
+ {connectionModalVisible ? (
+
+ ) : null}
+ {costumeLibraryVisible ? (
+
+ ) : null}
+ {backdropLibraryVisible ? (
+
+ ) : null}
+
- ) : null}
- {costumeLibraryVisible ? (
-
- ) : null}
- {backdropLibraryVisible ? (
-
- ) : null}
-
-
-
-
-
-
-
-
-
-
-
-
- {targetIsStage ? (
-
+
+
+
+
+
+
- ) : (
- )}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {costumesTabVisible ? : null}
-
-
- {soundsTabVisible ? : null}
-
-
- {backpackVisible ? (
-
- ) : null}
-
+ {targetIsStage ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {costumesTabVisible ? : null}
+
+
+ {soundsTabVisible ? : null}
+
+
+ {backpackVisible ? (
+
+ ) : null}
+
-
-
-
-
+
+
+
+
+
-
-
- );
- }});
-};
+ );
+ }})
+ }
+}
GUIComponent.propTypes = {
accountNavOpen: PropTypes.bool,
@@ -395,13 +407,14 @@ GUIComponent.propTypes = {
isShared: PropTypes.bool,
loading: PropTypes.bool,
logo: PropTypes.string,
+ modalChooseExtensionAlreadyBeenOpened: PropTypes.bool,
+ onShowExtension: PropTypes.func,
onActivateCostumesTab: PropTypes.func,
onActivateSoundsTab: PropTypes.func,
onActivateTab: PropTypes.func,
onClickAccountNav: PropTypes.func,
onClickLogo: PropTypes.func,
onCloseAccountNav: PropTypes.func,
- onExtensionButtonClick: PropTypes.func,
onLogOut: PropTypes.func,
onOpenRegistration: PropTypes.func,
onRequestCloseBackdropLibrary: PropTypes.func,
@@ -416,10 +429,12 @@ GUIComponent.propTypes = {
onTelemetryModalOptIn: PropTypes.func,
onTelemetryModalOptOut: PropTypes.func,
onToggleLoginOpen: PropTypes.func,
+ projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
renderLogin: PropTypes.func,
showComingSoon: PropTypes.bool,
soundsTabVisible: PropTypes.bool,
stageSizeMode: PropTypes.oneOf(Object.keys(STAGE_SIZE_MODES)),
+ setModalExtensionVisibility: PropTypes.func,
targetIsStage: PropTypes.bool,
telemetryModalVisible: PropTypes.bool,
tipsLibraryVisible: PropTypes.bool,
@@ -446,11 +461,19 @@ GUIComponent.defaultProps = {
stageSizeMode: STAGE_SIZE_MODES.large
};
-const mapStateToProps = state => ({
- // This is the button's mode, as opposed to the actual current state
- stageSizeMode: state.scratchGui.stageSize.stageSize
+const mapStateToProps = state => {
+ return {
+ // This is the button's mode, as opposed to the actual current state
+ stageSizeMode: state.scratchGui.stageSize.stageSize,
+ projectId: state.scratchGui.projectState.projectId,
+ modalChooseExtensionAlreadyBeenOpened: state.scratchGui.modalChooseExtensionAlreadyBeenOpened
+ }
+};
+
+const mapDispatchToProps = dispatch => ({
+ setModalExtensionVisibility: (isOpened) => dispatch(setModalExtension(isOpened)),
});
export default injectIntl(connect(
- mapStateToProps
+ mapStateToProps, mapDispatchToProps
)(GUIComponent));
diff --git a/src/components/menu-bar/icon--profile.png b/src/components/menu-bar/icon--profile.png
deleted file mode 100644
index 41e62b614..000000000
Binary files a/src/components/menu-bar/icon--profile.png and /dev/null differ
diff --git a/src/components/menu-bar/logo.svg b/src/components/menu-bar/logo.svg
new file mode 100644
index 000000000..d750ad5c0
--- /dev/null
+++ b/src/components/menu-bar/logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx
index 126f0d460..fc00b7a41 100644
--- a/src/components/menu-bar/menu-bar.jsx
+++ b/src/components/menu-bar/menu-bar.jsx
@@ -67,15 +67,15 @@ import styles from './menu-bar.css';
import helpIcon from '../../lib/assets/icon--tutorials.svg';
import mystuffIcon from './icon--mystuff.png';
-import profileIcon from './icon--profile.png';
import remixIcon from './icon--remix.svg';
import dropdownCaret from './dropdown-caret.svg';
import languageIcon from '../language-selector/language-icon.svg';
import aboutIcon from './icon--about.svg';
-import scratchLogo from './scratch-logo.svg';
+import siteLogo from './logo.svg';
import sharedMessages from '../../lib/shared-messages';
+import { setModalExtension } from '../../reducers/modal-choose-extension.js';
const ariaMessages = defineMessages({
language: {
@@ -194,6 +194,9 @@ class MenuBar extends React.Component {
this.props.onClickNew(this.props.canSave && this.props.canCreateNew);
}
this.props.onRequestCloseFile();
+ // set modalAlreadyOpened to false so that the modal will show when the new default project renders
+ this.props.setModalExtensionVisibility(false);
+
}
handleClickRemix () {
this.props.onClickRemix();
@@ -390,7 +393,7 @@ class MenuBar extends React.Component {
-
- */}
+ {/*
-
- {this.props.canEditTitle ? (
+ */}
+ {/* hide this code for first release */}
+ {/* {this.props.canEditTitle ? (
- ) : null)}
-
+ ) : null)} */}
+ {/* hide share button for first release */}
+ {/*
{this.props.canShare ? (
(this.props.isShowingProject || this.props.isUpdating) && (
@@ -572,11 +578,11 @@ class MenuBar extends React.Component {
{
this.handleClickShare(waitForUpdate);
}}
- /* eslint-enable react/jsx-no-bind */
+ // eslint-enable react/jsx-no-bind
/>
)
}
@@ -590,8 +596,9 @@ class MenuBar extends React.Component {
) : []
)}
{this.props.canRemix ? remixButton : []}
-
-
+
*/}
+ {/* hide community button for first release */}
+ {/*
{this.props.enableCommunity ? (
(this.props.isShowingProject || this.props.isUpdating) && (
@@ -599,11 +606,11 @@ class MenuBar extends React.Component {
waitForUpdate => (
{
this.handleClickSeeCommunity(waitForUpdate);
}}
- /* eslint-enable react/jsx-no-bind */
+ // eslint-enable react/jsx-no-bind
/>
)
}
@@ -614,7 +621,7 @@ class MenuBar extends React.Component {
) : [])}
-
+
*/}
{/* show the proper UI in the account menu, given whether the user is
@@ -728,12 +735,13 @@ class MenuBar extends React.Component {
styles.accountNavMenu
)}
>
-
+ /> */}
- {'scratch-cat'}
+ {'username'}
{}
};
@@ -873,7 +882,8 @@ const mapDispatchToProps = dispatch => ({
onClickRemix: () => dispatch(remixProject()),
onClickSave: () => dispatch(manualUpdateProject()),
onClickSaveAsCopy: () => dispatch(saveProjectAsCopy()),
- onSeeCommunity: () => dispatch(setPlayer(true))
+ onSeeCommunity: () => dispatch(setPlayer(true)),
+ setModalExtensionVisibility: (isOpened) => dispatch(setModalExtension(isOpened)),
});
export default compose(
diff --git a/src/components/menu-bar/scratch-logo.svg b/src/components/menu-bar/scratch-logo.svg
deleted file mode 100644
index 28b62731d..000000000
--- a/src/components/menu-bar/scratch-logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx
index 4084f6bfc..c5204e142 100644
--- a/src/components/stage-header/stage-header.jsx
+++ b/src/components/stage-header/stage-header.jsx
@@ -16,7 +16,7 @@ import largeStageIcon from './icon--large-stage.svg';
import smallStageIcon from './icon--small-stage.svg';
import unFullScreenIcon from './icon--unfullscreen.svg';
-import scratchLogo from '../menu-bar/scratch-logo.svg';
+import siteLogo from '../menu-bar/logo.svg';
import styles from './stage-header.css';
const messages = defineMessages({
@@ -73,8 +73,8 @@ const StageHeaderComponent = function (props) {
target="_blank"
>
diff --git a/src/containers/extension-library.jsx b/src/containers/extension-library.jsx
index b46d992c0..2a85a24df 100644
--- a/src/containers/extension-library.jsx
+++ b/src/containers/extension-library.jsx
@@ -2,26 +2,21 @@ import bindAll from 'lodash.bindall';
import PropTypes from 'prop-types';
import React from 'react';
import VM from 'scratch-vm';
+import {compose} from 'redux';
import {defineMessages, injectIntl, intlShape} from 'react-intl';
import extensionLibraryContent from '../lib/libraries/extensions/index.jsx';
-
import LibraryComponent from '../components/library/library.jsx';
import extensionIcon from '../components/action-menu/icon--sprite.svg';
+import TranslationHOC from '../lib/translation-hoc.jsx';
const messages = defineMessages({
- extensionTitle: {
- defaultMessage: 'Choose an Extension',
- description: 'Heading for the extension library',
- id: 'gui.extensionLibrary.chooseAnExtension'
- },
extensionUrl: {
defaultMessage: 'Enter the URL of the extension',
description: 'Prompt for unoffical extension url',
id: 'gui.extensionLibrary.extensionUrl'
}
});
-
class ExtensionLibrary extends React.PureComponent {
constructor (props) {
super(props);
@@ -56,7 +51,7 @@ class ExtensionLibrary extends React.PureComponent {
data={extensionLibraryThumbnailData}
filterable={false}
id="extensionLibrary"
- title={this.props.intl.formatMessage(messages.extensionTitle)}
+ title={this.props.messagesTranslation.chooseExtensionModalTitle || ""}
visible={this.props.visible}
onItemSelected={this.handleItemSelect}
onRequestClose={this.props.onRequestClose}
@@ -67,10 +62,11 @@ class ExtensionLibrary extends React.PureComponent {
ExtensionLibrary.propTypes = {
intl: intlShape.isRequired,
+ messagesTranslation: PropTypes.object,
onCategorySelected: PropTypes.func,
onRequestClose: PropTypes.func,
visible: PropTypes.bool,
vm: PropTypes.instanceOf(VM).isRequired // eslint-disable-line react/no-unused-prop-types
};
-export default injectIntl(ExtensionLibrary);
+export default compose(injectIntl, TranslationHOC)(ExtensionLibrary);
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index e577feb55..e0f8bca82 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -41,8 +41,13 @@ import cloudManagerHOC from '../lib/cloud-manager-hoc.jsx';
import GUIComponent from '../components/gui/gui.jsx';
import {setIsScratchDesktop} from '../lib/isScratchDesktop.js';
+import { setModalExtension } from '../reducers/modal-choose-extension.js';
class GUI extends React.Component {
+ constructor (props) {
+ super(props);
+ this.handleShowExtension = this.handleShowExtension.bind(this);
+ }
componentDidMount () {
this.fetchUserSessionFromApi();
setIsScratchDesktop(this.props.isScratchDesktop);
@@ -80,6 +85,15 @@ class GUI extends React.Component {
this.props.onProjectError(error);
});
}
+ handleShowExtension(isFromButtonClick = false) {
+ if(isFromButtonClick) {
+ this.props.showExtension();
+ }
+ else if(this.props.projectId === '0' && !this.props.modalChooseExtensionAlreadyBeenOpened) {
+ this.props.setModalExtensionVisibility(true);
+ this.props.showExtension();
+ }
+ }
render () {
if (this.props.isError) {
throw new Error(
@@ -101,6 +115,7 @@ class GUI extends React.Component {
onProjectError,
projectHost,
projectId,
+ showExtension,
/* eslint-enable no-unused-vars */
children,
fetchingProject,
@@ -111,6 +126,7 @@ class GUI extends React.Component {
return (
this.handleShowExtension(open)}
{...componentProps}
>
{children}
@@ -131,6 +147,7 @@ GUI.propTypes = {
isScratchDesktop: PropTypes.bool,
isShowingProject: PropTypes.bool,
loadingStateVisible: PropTypes.bool,
+ modalChooseExtensionAlreadyBeenOpened: PropTypes.bool,
onProjectLoaded: PropTypes.func,
onSeeCommunity: PropTypes.func,
onStorageInit: PropTypes.func,
@@ -140,6 +157,8 @@ GUI.propTypes = {
onProjectError: PropTypes.func,
projectHost: PropTypes.string,
projectId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ setModalExtensionVisibility: PropTypes.func,
+ // showExtension: PropTypes.func,
telemetryModalVisible: PropTypes.bool,
vm: PropTypes.instanceOf(VM).isRequired
};
@@ -170,6 +189,7 @@ const mapStateToProps = state => {
isRtl: state.locales.isRtl,
isShowingProject: getIsShowingProject(loadingState),
loadingStateVisible: state.scratchGui.modals.loadingProject,
+ modalChooseExtensionAlreadyBeenOpened: state.scratchGui.modalChooseExtensionAlreadyBeenOpened,
projectId: state.scratchGui.projectState.projectId,
soundsTabVisible: state.scratchGui.editorTab.activeTabIndex === SOUNDS_TAB_INDEX,
targetIsStage: (
@@ -183,7 +203,6 @@ const mapStateToProps = state => {
};
const mapDispatchToProps = dispatch => ({
- onExtensionButtonClick: () => dispatch(openExtensionLibrary()),
onActivateTab: tab => dispatch(activateTab(tab)),
onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)),
onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)),
@@ -192,6 +211,8 @@ const mapDispatchToProps = dispatch => ({
onRequestCloseTelemetryModal: () => dispatch(closeTelemetryModal()),
onSetSession: (token) => dispatch(setSession(token)),
onProjectError: error => dispatch(projectError(error)),
+ showExtension: () => dispatch(openExtensionLibrary()),
+ setModalExtensionVisibility: (isOpened) => dispatch(setModalExtension(isOpened)),
});
const ConnectedGUI = injectIntl(connect(
diff --git a/src/css/colors.css b/src/css/colors.css
index 6f38510e2..539b67635 100644
--- a/src/css/colors.css
+++ b/src/css/colors.css
@@ -14,7 +14,7 @@ $ui-black-transparent: hsla(0, 0%, 0%, 0.15); /* 15% transparent version of blac
$text-primary: hsla(225, 15%, 40%, 1); /* #575E75 */
$text-primary-transparent: hsla(225, 15%, 40%, 0.75);
-$motion-primary: hsla(215, 100%, 65%, 1); /* #4C97FF */
+$motion-primary: hsl(208, 38%, 18%); /* #1C2E3E */
$motion-tertiary: hsla(215, 60%, 50%, 1); /* #3373CC */
$motion-transparent: hsla(215, 100%, 65%, 0.35); /* 35% transparent version of motion-primary */
$motion-light-transparent: hsla(215, 100%, 65%, 0.15); /* 15% transparent version of motion-primary */
diff --git a/src/lib/default-project/bcf454acf82e4504149f7ffe07081dbc.svg b/src/lib/default-project/bcf454acf82e4504149f7ffe07081dbc.svg
index 03df23e29..1981b79fb 100644
--- a/src/lib/default-project/bcf454acf82e4504149f7ffe07081dbc.svg
+++ b/src/lib/default-project/bcf454acf82e4504149f7ffe07081dbc.svg
@@ -1,42 +1 @@
-
\ No newline at end of file
+
diff --git a/src/lib/default-project/index.js b/src/lib/default-project/index.js
index 6e733f705..af98632da 100644
--- a/src/lib/default-project/index.js
+++ b/src/lib/default-project/index.js
@@ -5,7 +5,6 @@ import popWav from '!arraybuffer-loader!./83a9787d4cb6f3b7632b4ddfebf74367.wav';
import meowWav from '!arraybuffer-loader!./83c36d806dc92327b9e7049a565c6bff.wav';
import backdrop from '!raw-loader!./cd21514d0531fdffb22204e0ec5ed84a.svg';
import costume1 from '!raw-loader!./bcf454acf82e4504149f7ffe07081dbc.svg';
-import costume2 from '!raw-loader!./0fb9be3e8397c983338cb71dc84d0b25.svg';
/* eslint-enable import/no-unresolved */
const defaultProject = translator => {
@@ -44,11 +43,6 @@ const defaultProject = translator => {
assetType: 'ImageVector',
dataFormat: 'SVG',
data: encoder.encode(costume1)
- }, {
- id: '0fb9be3e8397c983338cb71dc84d0b25',
- assetType: 'ImageVector',
- dataFormat: 'SVG',
- data: encoder.encode(costume2)
}];
};
diff --git a/src/lib/default-project/project-data.js b/src/lib/default-project/project-data.js
index 9ee63b237..e6e5dfe0f 100644
--- a/src/lib/default-project/project-data.js
+++ b/src/lib/default-project/project-data.js
@@ -81,15 +81,6 @@ const projectData = translateFunction => {
dataFormat: 'svg',
rotationCenterX: 48,
rotationCenterY: 50
- },
- {
- assetId: '0fb9be3e8397c983338cb71dc84d0b25',
- name: translator(messages.costume, {index: 2}),
- bitmapResolution: 1,
- md5ext: '0fb9be3e8397c983338cb71dc84d0b25.svg',
- dataFormat: 'svg',
- rotationCenterX: 46,
- rotationCenterY: 53
}
],
sounds: [
diff --git a/src/lib/libraries/costumes.json b/src/lib/libraries/costumes.json
index 6abccd68a..7484b9910 100644
--- a/src/lib/libraries/costumes.json
+++ b/src/lib/libraries/costumes.json
@@ -1692,42 +1692,6 @@
"rotationCenterX": 44,
"rotationCenterY": 46
},
- {
- "name": "Cat-a",
- "tags": [
- "animals",
- "cat",
- "kitten",
- "kitty",
- "mammal",
- "orange",
- "scratch cat"
- ],
- "assetId": "bcf454acf82e4504149f7ffe07081dbc",
- "bitmapResolution": 1,
- "dataFormat": "svg",
- "md5ext": "bcf454acf82e4504149f7ffe07081dbc.svg",
- "rotationCenterX": 48,
- "rotationCenterY": 50
- },
- {
- "name": "Cat-b",
- "tags": [
- "animals",
- "cat",
- "kitten",
- "kitty",
- "mammal",
- "orange",
- "scratch cat"
- ],
- "assetId": "0fb9be3e8397c983338cb71dc84d0b25",
- "bitmapResolution": 1,
- "dataFormat": "svg",
- "md5ext": "0fb9be3e8397c983338cb71dc84d0b25.svg",
- "rotationCenterX": 46,
- "rotationCenterY": 53
- },
{
"name": "Catcher-a",
"tags": [
@@ -12819,4 +12783,4 @@
"rotationCenterX": 17,
"rotationCenterY": 23
}
-]
\ No newline at end of file
+]
diff --git a/src/lib/libraries/extensions/index.jsx b/src/lib/libraries/extensions/index.jsx
index 63a101078..5c1c6656b 100644
--- a/src/lib/libraries/extensions/index.jsx
+++ b/src/lib/libraries/extensions/index.jsx
@@ -70,275 +70,4 @@ export default [
),
featured: true
},
- {
- name: (
-
- ),
- extensionId: 'music',
- iconURL: musicIconURL,
- insetIconURL: musicInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'pen',
- iconURL: penIconURL,
- insetIconURL: penInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'videoSensing',
- iconURL: videoSensingIconURL,
- insetIconURL: videoSensingInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: (
-
- ),
- extensionId: 'text2speech',
- collaborator: 'Amazon Web Services',
- iconURL: text2speechIconURL,
- insetIconURL: text2speechInsetIconURL,
- description: (
-
- ),
- featured: true,
- internetConnectionRequired: true
- },
- {
- name: (
-
- ),
- extensionId: 'translate',
- collaborator: 'Google',
- iconURL: translateIconURL,
- insetIconURL: translateInsetIconURL,
- description: (
-
- ),
- featured: true,
- internetConnectionRequired: true
- },
- {
- name: 'Makey Makey',
- extensionId: 'makeymakey',
- collaborator: 'JoyLabz',
- iconURL: makeymakeyIconURL,
- insetIconURL: makeymakeyInsetIconURL,
- description: (
-
- ),
- featured: true
- },
- {
- name: 'micro:bit',
- extensionId: 'microbit',
- collaborator: 'micro:bit',
- iconURL: microbitIconURL,
- insetIconURL: microbitInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: microbitConnectionIconURL,
- connectionSmallIconURL: microbitConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/microbit'
- },
- {
- name: 'LEGO MINDSTORMS EV3',
- extensionId: 'ev3',
- collaborator: 'LEGO',
- iconURL: ev3IconURL,
- insetIconURL: ev3InsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: ev3ConnectionIconURL,
- connectionSmallIconURL: ev3ConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/ev3'
- },
- {
- name: 'LEGO BOOST',
- extensionId: 'boost',
- collaborator: 'LEGO',
- iconURL: boostIconURL,
- insetIconURL: boostInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: true,
- connectionIconURL: boostConnectionIconURL,
- connectionSmallIconURL: boostConnectionSmallIconURL,
- connectionTipIconURL: boostConnectionTipIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/boost'
- },
- {
- name: 'LEGO Education WeDo 2.0',
- extensionId: 'wedo2',
- collaborator: 'LEGO',
- iconURL: wedo2IconURL,
- insetIconURL: wedo2InsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: true,
- connectionIconURL: wedo2ConnectionIconURL,
- connectionSmallIconURL: wedo2ConnectionSmallIconURL,
- connectionTipIconURL: wedo2ConnectionTipIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/wedo'
- },
- {
- name: 'Go Direct Force & Acceleration',
- extensionId: 'gdxfor',
- collaborator: 'Vernier',
- iconURL: gdxforIconURL,
- insetIconURL: gdxforInsetIconURL,
- description: (
-
- ),
- featured: true,
- disabled: false,
- bluetoothRequired: true,
- internetConnectionRequired: true,
- launchPeripheralConnectionFlow: true,
- useAutoScan: false,
- connectionIconURL: gdxforConnectionIconURL,
- connectionSmallIconURL: gdxforConnectionSmallIconURL,
- connectingMessage: (
-
- ),
- helpLink: 'https://scratch.mit.edu/vernier'
- },
-];
+]
diff --git a/src/lib/libraries/sprites.json b/src/lib/libraries/sprites.json
index be4cb21fa..ea4a1646c 100644
--- a/src/lib/libraries/sprites.json
+++ b/src/lib/libraries/sprites.json
@@ -2027,52 +2027,6 @@
],
"blocks": {}
},
- {
- "name": "Cat",
- "tags": [
- "animals",
- "cat",
- "kitten",
- "kitty",
- "mammal",
- "orange",
- "scratch cat"
- ],
- "isStage": false,
- "variables": {},
- "costumes": [
- {
- "assetId": "bcf454acf82e4504149f7ffe07081dbc",
- "name": "cat-a",
- "bitmapResolution": 1,
- "md5ext": "bcf454acf82e4504149f7ffe07081dbc.svg",
- "dataFormat": "svg",
- "rotationCenterX": 48,
- "rotationCenterY": 50
- },
- {
- "assetId": "0fb9be3e8397c983338cb71dc84d0b25",
- "name": "cat-b",
- "bitmapResolution": 1,
- "md5ext": "0fb9be3e8397c983338cb71dc84d0b25.svg",
- "dataFormat": "svg",
- "rotationCenterX": 46,
- "rotationCenterY": 53
- }
- ],
- "sounds": [
- {
- "assetId": "83c36d806dc92327b9e7049a565c6bff",
- "name": "Meow",
- "dataFormat": "wav",
- "format": "",
- "rate": 44100,
- "sampleCount": 37376,
- "md5ext": "83c36d806dc92327b9e7049a565c6bff.wav"
- }
- ],
- "blocks": {}
- },
{
"name": "Cat 2",
"tags": [
@@ -17203,4 +17157,4 @@
],
"blocks": {}
}
-]
\ No newline at end of file
+]
diff --git a/src/lib/translation-hoc.jsx b/src/lib/translation-hoc.jsx
new file mode 100644
index 000000000..ecd030bef
--- /dev/null
+++ b/src/lib/translation-hoc.jsx
@@ -0,0 +1,59 @@
+import React from "react";
+import {connect} from 'react-redux';
+import PropTypes from 'prop-types';
+
+const messagesEnglish = {
+ "chooseExtensionModalTitle": "Optional Extensions for Your Project :)"
+ }
+
+const messagesJapanese = {
+ "chooseExtensionModalTitle": "プロジェクトのオプション拡張機能 :)"
+ }
+
+const TranslationHOC = function(WrappedComponent) {
+ class TranslationContainer extends React.PureComponent {
+ constructor (props) {
+ super(props);
+ }
+ state = {
+ messages: {},
+ };
+ componentDidMount() {
+ this.updateTranslation();
+ }
+ componentDidUpdate(){
+ this.updateTranslation();
+ }
+ updateTranslation = () => {
+ if (this.props.currentLocale === 'ja') {
+ this.setState({
+ messages: messagesJapanese,
+ });
+ } else {
+ this.setState({
+ messages: messagesEnglish,
+ });
+ }
+ }
+ render () {
+ return ();
+ }
+ }
+ TranslationContainer.propTypes = {
+ currentLocale: PropTypes.string.isRequired,
+ };
+ const mapStateToProps = state => {
+ return {
+ currentLocale: state.locales.locale,
+ }
+ }
+ return connect(
+ mapStateToProps,
+ )(TranslationContainer);
+
+};
+
+export default TranslationHOC;
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index 378a3203c..5187010d3 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -18,6 +18,7 @@ import projectChangedReducer, {projectChangedInitialState} from './project-chang
import projectStateReducer, {projectStateInitialState} from './project-state';
import projectTitleReducer, {projectTitleInitialState} from './project-title';
import fontsLoadedReducer, {fontsLoadedInitialState} from './fonts-loaded';
+import modalChooseExtensionReducer, {modalChooseExtensionInitialState} from './modal-choose-extension';
import restoreDeletionReducer, {restoreDeletionInitialState} from './restore-deletion';
import stageSizeReducer, {stageSizeInitialState} from './stage-size';
import targetReducer, {targetsInitialState} from './targets';
@@ -53,6 +54,7 @@ const guiInitialState = {
projectState: projectStateInitialState,
projectTitle: projectTitleInitialState,
fontsLoaded: fontsLoadedInitialState,
+ modalChooseExtensionAlreadyBeenOpened: modalChooseExtensionInitialState,
restoreDeletion: restoreDeletionInitialState,
targets: targetsInitialState,
timeout: timeoutInitialState,
@@ -152,6 +154,7 @@ const guiReducer = combineReducers({
projectState: projectStateReducer,
projectTitle: projectTitleReducer,
fontsLoaded: fontsLoadedReducer,
+ modalChooseExtensionAlreadyBeenOpened: modalChooseExtensionReducer,
restoreDeletion: restoreDeletionReducer,
targets: targetReducer,
timeout: timeoutReducer,
diff --git a/src/reducers/modal-choose-extension.js b/src/reducers/modal-choose-extension.js
new file mode 100644
index 000000000..d395d7dd6
--- /dev/null
+++ b/src/reducers/modal-choose-extension.js
@@ -0,0 +1,25 @@
+const SET_HAS_MODAL_EXTENSION_ALREADY_BEEN_OPENED = 'modalChooseExtension/SET_HAS_MODAL_EXTENSION_ALREADY_BEEN_OPENED';
+
+const initialState = false;
+
+const reducer = function (state, action) {
+ if (typeof state === 'undefined') state = initialState;
+ switch (action.type) {
+ case SET_HAS_MODAL_EXTENSION_ALREADY_BEEN_OPENED:
+ return action.opened;
+ default:
+ return state;
+ }
+};
+const setModalExtension = (isOpened) => {
+ return {
+ type: SET_HAS_MODAL_EXTENSION_ALREADY_BEEN_OPENED,
+ opened: isOpened
+ }
+}
+
+export {
+ reducer as default,
+ initialState as modalChooseExtensionInitialState,
+ setModalExtension
+};