Skip to content

Commit

Permalink
Добавление возможности подключения нескольких устройств.
Browse files Browse the repository at this point in the history
  • Loading branch information
s.gologuzov committed Mar 27, 2024
1 parent c603612 commit 59fd3a9
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 48 deletions.
46 changes: 25 additions & 21 deletions src/components/menu-bar/menu-bar.jsx
Expand Up @@ -348,7 +348,7 @@ class MenuBar extends React.Component {
}
}
handleConnectionMouseUp () {
if (this.props.deviceId) {
if (Object.keys(this.props.devices).length > 0) {
this.props.onOpenConnectionModal();
} else {
this.props.onDeviceIsEmpty();
Expand Down Expand Up @@ -384,8 +384,8 @@ class MenuBar extends React.Component {
}
}
handleUploadFirmware () {
if (this.props.deviceId) {
this.props.vm.uploadFirmwareToPeripheral(this.props.deviceId);
if (Object.keys(this.props.devices).length > 0) {
this.props.vm.uploadFirmwareToPeripheral(this.props.devices.id);
this.props.onSetRealtimeConnection(false);
this.props.onOpenUploadProgress();
} else {
Expand Down Expand Up @@ -670,6 +670,21 @@ class MenuBar extends React.Component {
</MenuBarMenu>
</div>
<Divider className={classNames(styles.divider)} />
{Object.values(this.props.devices).map(device => (
<div
key={device.deviceId}
className={classNames(styles.menuBarItem, styles.hoverable)}
onMouseUp={this.handleSelectDeviceMouseUp}
>
<img
className={styles.deviceIcon}
src={device.iconURL}
/>
<div>
{device.name}
</div>
</div>
))}
<div
className={classNames(styles.menuBarItem, styles.hoverable)}
onMouseUp={this.handleSelectDeviceMouseUp}
Expand All @@ -678,18 +693,11 @@ class MenuBar extends React.Component {
className={styles.deviceIcon}
src={deviceIcon}
/>
{
this.props.deviceName ? (
<div>
{this.props.deviceName}
</div>
) : (
<FormattedMessage
defaultMessage="No device selected"
description="Text for menubar no device select button"
id="gui.menuBar.noDeviceSelected"
/>
)}
<FormattedMessage
defaultMessage="Connect new device"
description="Connect new device"
id="gui.menuBar.connectNewDevice"
/>
</div>
<Divider className={classNames(styles.divider)} />
<div
Expand Down Expand Up @@ -1008,9 +1016,7 @@ MenuBar.propTypes = {
onWorkspaceIsNotEmpty: PropTypes.func.isRequired,
onOpenDeviceLibrary: PropTypes.func,
onSetStageLarge: PropTypes.func.isRequired,
deviceId: PropTypes.string,
deviceName: PropTypes.string,
deviceNames: PropTypes.arrayOf(PropTypes.string),
devices: PropTypes.objectOf(PropTypes.object),
onDeviceIsEmpty: PropTypes.func
};

Expand Down Expand Up @@ -1046,9 +1052,7 @@ const mapStateToProps = (state, ownProps) => {
stageSizeMode: state.scratchGui.stageSize.stageSize,
vm: state.scratchGui.vm,
peripheralName: state.scratchGui.connectionModal.peripheralName,
deviceId: state.scratchGui.device.deviceId,
deviceName: state.scratchGui.device.deviceName,
deviceNames: state.scratchGui.device.deviceName
devices: state.scratchGui.devices
};
};

Expand Down
37 changes: 17 additions & 20 deletions src/containers/blocks.jsx
Expand Up @@ -30,6 +30,7 @@ import {activateCustomProcedures, deactivateCustomProcedures} from '../reducers/
import {updateMetrics} from '../reducers/workspace-metrics';
import {setCodeEditorValue} from '../reducers/code';
import {setDeviceId, setDeviceName, setDeviceType} from '../reducers/device';
import {addDevice} from '../reducers/devices';
import {setSupportSwitchMode} from '../reducers/program-mode';
import {setBaudrate} from '../reducers/hardware-console';

Expand Down Expand Up @@ -412,9 +413,7 @@ class Blocks extends React.Component {
const targetSounds = target.getSounds();
const dynamicBlocksXML = this.props.vm.runtime.getBlocksXML(target);

const device = this.props.deviceData.find(item => item.deviceId === this.props.deviceId);

return makeToolboxXML(false, device, target.isStage, target.id, dynamicBlocksXML,
return makeToolboxXML(false, this.props.devices, target.isStage, target.id, dynamicBlocksXML,
this.props.isRealtimeMode,
targetCostumes[targetCostumes.length - 1].name,
stageCostumes[stageCostumes.length - 1].name,
Expand Down Expand Up @@ -476,7 +475,7 @@ class Blocks extends React.Component {

if (deviceId) {
const dev = this.props.deviceData.find(ext => ext.deviceId === deviceId);
this.props.onDeviceSelected(dev.deviceId, dev.name, dev.type);
this.props.onDeviceSelected(dev);
this.ScratchBlocks.Device.setDevice(dev.deviceId, dev.type);
if (dev.defaultBaudRate) {
this.props.onSetBaudrate(dev.defaultBaudRate);
Expand Down Expand Up @@ -560,7 +559,7 @@ class Blocks extends React.Component {
}
handleScratchExtensionRemoved (extensionInfo) {
if (extensionInfo && extensionInfo.deviceId) {
this.props.onDeviceSelected(null, null, null);
this.props.onDeviceSelected(null);
this.props.vm.runtime.setRealtimeMode(true);
this.props.onSetSupportSwitchMode(false);
}
Expand All @@ -570,6 +569,7 @@ class Blocks extends React.Component {
}
}
handleDeviceExtensionAdded (deviceExtensionsRegister) {
console.log('[handleDeviceExtensionAdded]');
if (deviceExtensionsRegister.defineMessages) {
this.ScratchBlocks = deviceExtensionsRegister.defineMessages(this.ScratchBlocks);
}
Expand All @@ -588,6 +588,7 @@ class Blocks extends React.Component {
}
}
handleDeviceExtensionRemoved () {
console.log('[handleDeviceExtensionRemoved]');
const toolboxXML = this.getToolboxXML();
if (toolboxXML) {
this.props.updateToolboxState(toolboxXML);
Expand All @@ -607,15 +608,13 @@ class Blocks extends React.Component {
this.workspace.toolbox_.setSelectedCategoryById(categoryId);
});
}
handleDeviceSelected (categoryId) {
const device = this.props.deviceData.find(ext => ext.deviceId === categoryId);

handleDeviceSelected (device) {
console.log('[handleDeviceSelected] device:', device);
if (device && device.launchPeripheralConnectionFlow) {
this.handleConnectionModalStart();
}

this.withToolboxUpdates(() => {
this.workspace.toolbox_.setSelectedCategoryById(categoryId);
this.workspace.toolbox_.setSelectedCategoryById(device.deviceId);
});
}
setBlocks (blocks) {
Expand Down Expand Up @@ -703,9 +702,8 @@ class Blocks extends React.Component {
canUseCloud,
customProceduresVisible,
deviceData,
deviceId,
devices,
deviceLibraryVisible,
deviceType,
peripheralName,
extensionLibraryVisible,
options,
Expand Down Expand Up @@ -789,8 +787,7 @@ Blocks.propTypes = {
canUseCloud: PropTypes.bool,
customProceduresVisible: PropTypes.bool,
deviceData: PropTypes.instanceOf(Array).isRequired,
deviceId: PropTypes.string,
deviceType: PropTypes.string,
devices: PropTypes.objectOf(PropTypes.object),
peripheralName: PropTypes.string,
deviceLibraryVisible: PropTypes.bool,
extensionLibraryVisible: PropTypes.bool,
Expand Down Expand Up @@ -891,8 +888,7 @@ const mapStateToProps = state => ({
state.scratchGui.mode.isFullScreen
),
deviceData: state.scratchGui.deviceData.deviceData,
deviceId: state.scratchGui.device.deviceId,
deviceType: state.scratchGui.device.deviceType,
devices: state.scratchGui.devices,
peripheralName: state.scratchGui.connectionModal.peripheralName,
deviceLibraryVisible: state.scratchGui.modals.deviceLibrary,
extensionLibraryVisible: state.scratchGui.modals.extensionLibrary,
Expand All @@ -909,10 +905,11 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({
onActivateColorPicker: callback => dispatch(activateColorPicker(callback)),
onActivateCustomProcedures: (data, callback) => dispatch(activateCustomProcedures(data, callback)),
onDeviceSelected: (id, name, type) => {
dispatch(setDeviceId(id));
dispatch(setDeviceName(name));
dispatch(setDeviceType(type));
onDeviceSelected: device => {
dispatch(addDevice(device));
dispatch(setDeviceId(device.deviceId));
dispatch(setDeviceName(device.name));
dispatch(setDeviceType(device.type));
},
onOpenConnectionModal: () => {
dispatch(openConnectionModal());
Expand Down
8 changes: 5 additions & 3 deletions src/containers/device-library.jsx
Expand Up @@ -66,20 +66,22 @@ class DeviceLibrary extends React.PureComponent {

requestLoadDevice (device) {
const id = device.deviceId;
const deviceType = device.type;
const pnpidList = device.pnpidList;
const deviceExtensions = device.deviceExtensions;

if (id && !device.disabled) {
if (this.props.vm.extensionManager.isDeviceLoaded(id)) {
this.props.onDeviceSelected(id);
this.props.onDeviceSelected(device);
} else {
this.props.vm.extensionManager.loadDeviceURL(device).then(() => {
this.props.vm.extensionManager.loadDeviceURL(id, deviceType, pnpidList).then(() => {
this.props.vm.extensionManager.getDeviceExtensionsList().then(() => {
// TODO: Add a event for install device extension
// the large extensions will take many times to load
// A loading interface should be launched.
this.props.vm.installDeviceExtensions(Object.assign([], deviceExtensions));
});
this.props.onDeviceSelected(id);
this.props.onDeviceSelected(device);
analytics.event({
category: 'devices',
action: 'select device',
Expand Down
9 changes: 5 additions & 4 deletions src/lib/make-toolbox-xml.js
Expand Up @@ -723,7 +723,7 @@ const xmlClose = '</xml>';
/**
* @param {!boolean} isInitialSetup - Whether the toolbox is for initial setup. If the mode is "initial setup",
* blocks with localized default parameters (e.g. ask and wait) should not be loaded. (LLK/scratch-gui#5445)
* @param {?object} device - Full data of current selected deivce.
* @param {?object} devices - Full data of current selected deivces.
* @param {?boolean} isStage - Whether the toolbox is for a stage-type target. This is always set to true
* when isInitialSetup is true.
* @param {?string} targetId - The current editing target
Expand All @@ -737,7 +737,7 @@ const xmlClose = '</xml>';
* @param {?string} soundName - The name of the default selected sound dropdown.
* @returns {string} - a ScratchBlocks-style XML document for the contents of the toolbox.
*/
const makeToolboxXML = function (isInitialSetup, device = null, isStage = true, targetId, categoriesXML = [],
const makeToolboxXML = function (isInitialSetup, devices = null, isStage = true, targetId, categoriesXML = [],
isRealtimeMode = true,
costumeName = '', backdropName = '', soundName = '') {
isStage = isInitialSetup || isStage;
Expand All @@ -759,10 +759,11 @@ const makeToolboxXML = function (isInitialSetup, device = null, isStage = true,

let everything = [xmlOpen];

if (device) {
console.log('[makeToolboxXML] devices:', devices);
if (devices && Object.keys(devices).length > 0) {
const device = devices[Object.keys(devices)[0]];
const baseToolboxXml = device.baseToolBoxXml(isInitialSetup, isStage, targetId, isRealtimeMode,
costumeName, backdropName, soundName);

everything = everything.concat(baseToolboxXml);
} else {
const motionXML = moveCategory('motion') || motion(isInitialSetup, isStage, targetId);
Expand Down
44 changes: 44 additions & 0 deletions src/reducers/devices.js
@@ -0,0 +1,44 @@
const ADD_DEVICE = 'scratch-gui/devices/add';
const REMOVE_DEVICE = 'scratch-gui/devices/remove';

const initialState = {
};

const reducer = function (state, action) {
if (typeof state === 'undefined') state = initialState;
const newState = Object.assign({}, state);
switch (action.type) {
case ADD_DEVICE: {
newState[action.deviceId] = action.device;
return newState;
}
case REMOVE_DEVICE: {
delete newState[action.deviceId];
return newState;
}
default:
return state;
}
};

const addDevice = function (device) {
return {
type: ADD_DEVICE,
deviceId: device.deviceId,
device: device
};
};

const removeDevice = function (deviceId) {
return {
type: REMOVE_DEVICE,
deviceId: deviceId
};
};

export {
reducer as default,
initialState as devicesInitialState,
addDevice,
removeDevice
};
3 changes: 3 additions & 0 deletions src/reducers/gui.js
Expand Up @@ -31,6 +31,7 @@ import programModeReducer, {programModeInitialState} from './program-mode';
import codeReducer, {codeInitialState} from './code';
import deviceReducer, {deviceInitialState} from './device';
import deviceDataReducer, {deviceDataInitialState} from './device-data';
import devicesReducer, {devicesInitialState} from './devices';
import hardwareConsoleReducer, {hardwareConsoleInitialState} from './hardware-console';
import updateReducer, {updateInitialState} from './update';

Expand All @@ -49,6 +50,7 @@ const guiInitialState = {
customProcedures: customProceduresInitialState,
device: deviceInitialState,
deviceData: deviceDataInitialState,
devices: devicesInitialState,
hardwareConsole: hardwareConsoleInitialState,
editorTab: editorTabInitialState,
mode: modeInitialState,
Expand Down Expand Up @@ -154,6 +156,7 @@ const guiReducer = combineReducers({
customProcedures: customProceduresReducer,
device: deviceReducer,
deviceData: deviceDataReducer,
devices: devicesReducer,
editorTab: editorTabReducer,
mode: modeReducer,
hardwareConsole: hardwareConsoleReducer,
Expand Down

0 comments on commit 59fd3a9

Please sign in to comment.