diff --git a/src/components/connection-modal/connection-modal.jsx b/src/components/connection-modal/connection-modal.jsx
index 99c9a6a53..8631ab2ac 100644
--- a/src/components/connection-modal/connection-modal.jsx
+++ b/src/components/connection-modal/connection-modal.jsx
@@ -28,6 +28,7 @@ const ConnectionModalComponent = props => (
contentLabel={props.name}
headerClassName={styles.header}
headerImage={props.smallPeripheralImage}
+ id="connectionModal"
onHelp={props.onHelp}
onRequestClose={props.onCancel}
>
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 389f63d63..176dea6e1 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -30,6 +30,7 @@ import TipsLibrary from '../../containers/tips-library.jsx';
import Cards from '../../containers/cards.jsx';
import Alerts from '../../containers/alerts.jsx';
import DragLayer from '../../containers/drag-layer.jsx';
+import ConnectionModal from '../../containers/connection-modal.jsx';
import layout, {STAGE_SIZE_MODES} from '../../lib/layout-constants';
import {resolveStageSize} from '../../lib/screen-utils';
@@ -68,6 +69,7 @@ const GUIComponent = props => {
canSaveAsCopy,
canShare,
children,
+ connectionModalVisible,
costumeLibraryVisible,
costumesTabVisible,
enableCommunity,
@@ -157,6 +159,11 @@ const GUIComponent = props => {
{alertsVisible ? (
) : null}
+ {connectionModalVisible ? (
+
+ ) : null}
{costumeLibraryVisible ? (
ext.extensionId === extensionId);
- if (extension) {
- this.setState({connectionModal: {
- extensionId: extensionId,
- useAutoScan: extension.useAutoScan,
- peripheralImage: extension.peripheralImage,
- smallPeripheralImage: extension.smallPeripheralImage,
- peripheralButtonImage: extension.peripheralButtonImage,
- name: extension.name,
- connectingMessage: extension.connectingMessage,
- helpLink: extension.helpLink
- }});
- }
- }
- handleConnectionModalClose () {
- this.setState({connectionModal: null});
+ this.props.onOpenConnectionModal(extensionId);
}
handleStatusButtonUpdate () {
this.ScratchBlocks.refreshStatusButtons(this.workspace);
@@ -434,6 +416,7 @@ class Blocks extends React.Component {
isRtl,
isVisible,
onActivateColorPicker,
+ onOpenConnectionModal,
onOpenSoundRecorder,
updateToolboxState,
onActivateCustomProcedures,
@@ -460,14 +443,6 @@ class Blocks extends React.Component {
onOk={this.handlePromptCallback}
/>
) : null}
- {this.state.connectionModal ? (
-
- ) : null}
{extensionLibraryVisible ? (
({
const mapDispatchToProps = dispatch => ({
onActivateColorPicker: callback => dispatch(activateColorPicker(callback)),
onActivateCustomProcedures: (data, callback) => dispatch(activateCustomProcedures(data, callback)),
+ onOpenConnectionModal: id => {
+ dispatch(setConnectionModalExtensionId(id));
+ dispatch(openConnectionModal());
+ },
onOpenSoundRecorder: () => {
dispatch(activateTab(SOUNDS_TAB_INDEX));
dispatch(openSoundRecorder());
diff --git a/src/containers/connection-modal.jsx b/src/containers/connection-modal.jsx
index ecf6ab052..c0eb38b77 100644
--- a/src/containers/connection-modal.jsx
+++ b/src/containers/connection-modal.jsx
@@ -4,12 +4,16 @@ import bindAll from 'lodash.bindall';
import ConnectionModalComponent, {PHASES} from '../components/connection-modal/connection-modal.jsx';
import VM from 'scratch-vm';
import analytics from '../lib/analytics';
+import extensionData from '../lib/libraries/extensions/index.jsx';
+import {connect} from 'react-redux';
+import {closeConnectionModal} from '../reducers/modals';
class ConnectionModal extends React.Component {
constructor (props) {
super(props);
bindAll(this, [
'handleScanning',
+ 'handleCancel',
'handleConnected',
'handleConnecting',
'handleDisconnect',
@@ -17,6 +21,7 @@ class ConnectionModal extends React.Component {
'handleHelp'
]);
this.state = {
+ extension: extensionData.find(ext => ext.extensionId === props.extensionId),
phase: props.vm.getPeripheralIsConnected(props.extensionId) ?
PHASES.connected : PHASES.scanning
};
@@ -46,19 +51,24 @@ class ConnectionModal extends React.Component {
});
}
handleDisconnect () {
- this.props.onStatusButtonUpdate(this.props.extensionId, 'not ready');
- this.props.vm.disconnectPeripheral(this.props.extensionId);
- this.props.onCancel();
+ try {
+ this.props.vm.disconnectPeripheral(this.props.extensionId);
+ } finally {
+ this.props.onCancel();
+ }
}
handleCancel () {
- // If we're not connected to a peripheral, close the websocket so we stop scanning.
- if (!this.props.vm.getPeripheralIsConnected(this.props.extensionId)) {
- this.props.vm.disconnectPeripheral(this.props.extensionId);
+ try {
+ // If we're not connected to a peripheral, close the websocket so we stop scanning.
+ if (!this.props.vm.getPeripheralIsConnected(this.props.extensionId)) {
+ this.props.vm.disconnectPeripheral(this.props.extensionId);
+ }
+ } finally {
+ // Close the modal.
+ this.props.onCancel();
}
- this.props.onCancel();
}
handleError () {
- this.props.onStatusButtonUpdate();
// Assume errors that come in during scanning phase are the result of not
// having scratch-link installed.
if (this.state.phase === PHASES.scanning || this.state.phase === PHASES.unavailable) {
@@ -77,7 +87,6 @@ class ConnectionModal extends React.Component {
}
}
handleConnected () {
- this.props.onStatusButtonUpdate();
this.setState({
phase: PHASES.connected
});
@@ -88,7 +97,7 @@ class ConnectionModal extends React.Component {
});
}
handleHelp () {
- window.open(this.props.helpLink, '_blank');
+ window.open(this.state.extension.helpLink, '_blank');
analytics.event({
category: 'extensions',
action: 'help',
@@ -98,17 +107,17 @@ class ConnectionModal extends React.Component {
render () {
return (
({
+ extensionId: state.scratchGui.connectionModal.extensionId
+});
+
+const mapDispatchToProps = dispatch => ({
+ onCancel: () => {
+ dispatch(closeConnectionModal());
+ }
+});
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(ConnectionModal);
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index eeb3f83ce..ed5dc9272 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -132,6 +132,7 @@ const mapStateToProps = (state, ownProps) => {
backdropLibraryVisible: state.scratchGui.modals.backdropLibrary,
blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX,
cardsVisible: state.scratchGui.cards.visible,
+ connectionModalVisible: state.scratchGui.modals.connectionModal,
costumeLibraryVisible: state.scratchGui.modals.costumeLibrary,
costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX,
importInfoVisible: state.scratchGui.modals.importInfo,
diff --git a/src/reducers/connection-modal.js b/src/reducers/connection-modal.js
new file mode 100644
index 000000000..abac45e20
--- /dev/null
+++ b/src/reducers/connection-modal.js
@@ -0,0 +1,30 @@
+const SET_ID = 'scratch-gui/connection-modal/setId';
+
+const initialState = {
+ extensionId: null
+};
+
+const reducer = function (state, action) {
+ if (typeof state === 'undefined') state = initialState;
+ switch (action.type) {
+ case SET_ID:
+ return Object.assign({}, state, {
+ extensionId: action.extensionId
+ });
+ default:
+ return state;
+ }
+};
+
+const setConnectionModalExtensionId = function (extensionId) {
+ return {
+ type: SET_ID,
+ extensionId: extensionId
+ };
+};
+
+export {
+ reducer as default,
+ initialState as connectionModalInitialState,
+ setConnectionModalExtensionId
+};
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index 1eb254b47..682913f62 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -3,6 +3,7 @@ import alertsReducer, {alertsInitialState} from './alerts';
import assetDragReducer, {assetDragInitialState} from './asset-drag';
import cardsReducer, {cardsInitialState} from './cards';
import colorPickerReducer, {colorPickerInitialState} from './color-picker';
+import connectionModalReducer, {connectionModalInitialState} from './connection-modal';
import customProceduresReducer, {customProceduresInitialState} from './custom-procedures';
import blockDragReducer, {blockDragInitialState} from './block-drag';
import editorTabReducer, {editorTabInitialState} from './editor-tab';
@@ -33,6 +34,7 @@ const guiInitialState = {
blockDrag: blockDragInitialState,
cards: cardsInitialState,
colorPicker: colorPickerInitialState,
+ connectionModal: connectionModalInitialState,
customProcedures: customProceduresInitialState,
editorTab: editorTabInitialState,
mode: modeInitialState,
@@ -100,6 +102,7 @@ const guiReducer = combineReducers({
blockDrag: blockDragReducer,
cards: cardsReducer,
colorPicker: colorPickerReducer,
+ connectionModal: connectionModalReducer,
customProcedures: customProceduresReducer,
editorTab: editorTabReducer,
mode: modeReducer,
diff --git a/src/reducers/modals.js b/src/reducers/modals.js
index ddcb50806..d385f2613 100644
--- a/src/reducers/modals.js
+++ b/src/reducers/modals.js
@@ -13,10 +13,9 @@ const MODAL_PREVIEW_INFO = 'previewInfo';
const MODAL_SOUND_LIBRARY = 'soundLibrary';
const MODAL_SPRITE_LIBRARY = 'spriteLibrary';
const MODAL_SOUND_RECORDER = 'soundRecorder';
-
+const MODAL_CONNECTION = 'connectionModal';
const MODAL_TIPS_LIBRARY = 'tipsLibrary';
-
const initialState = {
[MODAL_BACKDROP_LIBRARY]: false,
[MODAL_CAMERA_CAPTURE]: false,
@@ -28,6 +27,7 @@ const initialState = {
[MODAL_SOUND_LIBRARY]: false,
[MODAL_SPRITE_LIBRARY]: false,
[MODAL_SOUND_RECORDER]: false,
+ [MODAL_CONNECTION]: false,
[MODAL_TIPS_LIBRARY]: false
};
@@ -98,6 +98,10 @@ const openSoundRecorder = function () {
analytics.pageview('/modals/microphone');
return openModal(MODAL_SOUND_RECORDER);
};
+const openConnectionModal = function () {
+ analytics.pageview('/modals/connection');
+ return openModal(MODAL_CONNECTION);
+};
const openTipsLibrary = function () {
analytics.pageview('/modals/tips');
return openModal(MODAL_TIPS_LIBRARY);
@@ -135,6 +139,9 @@ const closeSoundRecorder = function () {
const closeTipsLibrary = function () {
return closeModal(MODAL_TIPS_LIBRARY);
};
+const closeConnectionModal = function () {
+ return closeModal(MODAL_CONNECTION);
+};
export {
reducer as default,
initialState as modalsInitialState,
@@ -149,6 +156,7 @@ export {
openSpriteLibrary,
openSoundRecorder,
openTipsLibrary,
+ openConnectionModal,
closeBackdropLibrary,
closeCameraCapture,
closeCostumeLibrary,
@@ -159,5 +167,6 @@ export {
closeSpriteLibrary,
closeSoundLibrary,
closeSoundRecorder,
- closeTipsLibrary
+ closeTipsLibrary,
+ closeConnectionModal
};