Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added src/components/menu-bar/icon--mesh-connected.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/components/menu-bar/menu-bar.css
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,12 @@
vertical-align: middle;
}

.mesh-icon {
width: 21px;
height: 21px;
margin-right: 0.5rem;
}

.collapsible-label {
margin: 0 .5rem 0 .25rem;
}
Expand Down
110 changes: 108 additions & 2 deletions src/components/menu-bar/menu-bar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import GoogleDriveSaverHOC from '../../containers/google-drive-saver-hoc.jsx';
import GoogleDriveSaveDialog from '../google-drive-save-dialog/google-drive-save-dialog.jsx';
import SettingsMenu from './settings-menu.jsx';

import {openDebugModal, openKoshienTestModal} from '../../reducers/modals';
import {openDebugModal, openKoshienTestModal, openConnectionModal} from '../../reducers/modals';
import {setConnectionModalExtensionId} from '../../reducers/connection-modal';
import {openBlockDisplayModal} from '../../reducers/block-display';
import {setPlayer} from '../../reducers/mode';
import {
Expand Down Expand Up @@ -76,6 +77,9 @@ import {
openKoshienMenu,
closeKoshienMenu,
koshienMenuOpen,
openMeshV2Menu,
closeMeshV2Menu,
meshV2MenuOpen,
openLoginMenu,
closeLoginMenu,
loginMenuOpen,
Expand All @@ -101,6 +105,8 @@ import fileIcon from './icon--file.svg';
import editIcon from './icon--edit.svg';
import debugIcon from '../debug-modal/icons/icon--debug.svg';
import koshienIcon from './icon--koshien.svg';
import meshConnectedIcon from './icon--mesh-connected.png';
import meshDisconnectedIcon from './icon--mesh-disconnected.png';

import smalrubyLogo from './hatti.svg';

Expand Down Expand Up @@ -219,6 +225,7 @@ class MenuBar extends React.Component {
'handleSaveDirectlyToGoogleDrive',
'handleExtensionAdded',
'handleClickKoshienEntryForm',
'handleMeshV2MenuClick',
'handleClickLearn'
]);
}
Expand All @@ -228,6 +235,9 @@ class MenuBar extends React.Component {
// Listen for extension load events
if (this.props.vm.runtime) {
this.props.vm.runtime.on('EXTENSION_ADDED', this.handleExtensionAdded);
this.props.vm.runtime.on('PERIPHERAL_CONNECTED', this.handleExtensionAdded);
this.props.vm.runtime.on('PERIPHERAL_DISCONNECTED', this.handleExtensionAdded);
this.props.vm.runtime.on('PERIPHERAL_REQUEST_ERROR', this.handleExtensionAdded);
}
}
componentWillUnmount () {
Expand All @@ -236,6 +246,9 @@ class MenuBar extends React.Component {
// Remove extension listener
if (this.props.vm.runtime) {
this.props.vm.runtime.off('EXTENSION_ADDED', this.handleExtensionAdded);
this.props.vm.runtime.off('PERIPHERAL_CONNECTED', this.handleExtensionAdded);
this.props.vm.runtime.off('PERIPHERAL_DISCONNECTED', this.handleExtensionAdded);
this.props.vm.runtime.off('PERIPHERAL_REQUEST_ERROR', this.handleExtensionAdded);
}
}
handleExtensionAdded () {
Expand All @@ -244,6 +257,52 @@ class MenuBar extends React.Component {
this.props.onExtensionLoaded();
}
}
getMeshV2Status () {
const vm = this.props.vm;

if (!vm) return {loaded: false};

// In Smalruby 3 / Scratch 3, extensionManager is directly on the vm instance
const extensionManager = vm.extensionManager;
if (!extensionManager) {
return {loaded: false};
}

const isLoaded = extensionManager.isExtensionLoaded('meshV2');

if (!isLoaded) {
return {loaded: false};
}

// peripheralExtensions is on vm.runtime
const runtime = vm.runtime;
if (!runtime || !runtime.peripheralExtensions) {
return {loaded: true, connected: false};
}

const extension = runtime.peripheralExtensions.meshV2;

if (!extension) {
return {loaded: true, connected: false};
}

const connected = extension.connectionState === 'connected';
const message = extension.menuMessage();

return {
loaded: true,
connected: connected,
message: message,
icon: connected ? meshConnectedIcon : meshDisconnectedIcon
};
}
handleMeshV2MenuClick () {
// Close the Mesh V2 menu
this.props.onRequestCloseMeshV2();

// Open connection modal
this.props.onOpenConnectionModal('meshV2');
}
handleClickNew () {
// if the project is dirty, and user owns the project, we will autosave.
// but if they are not logged in and can't save, user should consider
Expand Down Expand Up @@ -871,6 +930,42 @@ class MenuBar extends React.Component {
<FormattedMessage {...ariaMessages.debug} />
</span>
</div>
{(() => {
const meshV2Status = this.getMeshV2Status();
if (!meshV2Status.loaded) return null;

return (
<div
className={classNames(styles.menuBarItem, styles.noOffset, styles.hoverable, {
[styles.active]: this.props.meshV2MenuOpen
})}
onMouseUp={this.props.onClickMeshV2}
>
<img
className={styles.meshIcon}
src={meshV2Status.icon}
/>
<span className={styles.collapsibleLabel}>
<FormattedMessage
defaultMessage="Mesh"
description="Label for Mesh V2 menu"
id="gui.menuBar.meshV2"
/>
</span>
<img src={dropdownCaret} />
<MenuBarMenu
className={classNames(styles.menuBarMenu)}
open={this.props.meshV2MenuOpen}
place={this.props.isRtl ? 'left' : 'right'}
onRequestClose={this.props.onRequestCloseMeshV2}
>
<MenuItem onClick={this.handleMeshV2MenuClick}>
{meshV2Status.message}
</MenuItem>
</MenuBarMenu>
</div>
);
})()}
{this.props.vm.extensionManager &&
this.props.vm.extensionManager.isExtensionLoaded('koshien') && (
<div
Expand Down Expand Up @@ -1247,6 +1342,7 @@ MenuBar.propTypes = {
locale: PropTypes.string.isRequired,
loginMenuOpen: PropTypes.bool,
logo: PropTypes.string,
meshV2MenuOpen: PropTypes.bool,
mode1920: PropTypes.bool,
mode1990: PropTypes.bool,
mode2020: PropTypes.bool,
Expand All @@ -1268,6 +1364,7 @@ MenuBar.propTypes = {
onClickKoshien: PropTypes.func,
onClickLogin: PropTypes.func,
onClickLogo: PropTypes.func,
onClickMeshV2: PropTypes.func,
onClickMode: PropTypes.func,
onClickNew: PropTypes.func,
onClickRemix: PropTypes.func,
Expand All @@ -1277,8 +1374,9 @@ MenuBar.propTypes = {
onExtensionLoaded: PropTypes.func,
onLogOut: PropTypes.func,
onOpenRegistration: PropTypes.func,
onOpenDebugModal: PropTypes.func,
onOpenBlockDisplayModal: PropTypes.func,
onOpenConnectionModal: PropTypes.func,
onOpenDebugModal: PropTypes.func,
onOpenKoshienTestModal: PropTypes.func,
onProjectTelemetryEvent: PropTypes.func,
onRequestCloseAbout: PropTypes.func,
Expand All @@ -1287,6 +1385,7 @@ MenuBar.propTypes = {
onRequestCloseFile: PropTypes.func,
onRequestCloseKoshien: PropTypes.func,
onRequestCloseLogin: PropTypes.func,
onRequestCloseMeshV2: PropTypes.func,
onRequestCloseMode: PropTypes.func,
onRequestCloseSettings: PropTypes.func,
onRequestOpenAbout: PropTypes.func,
Expand Down Expand Up @@ -1332,6 +1431,7 @@ const mapStateToProps = (state, ownProps) => {
fileMenuOpen: fileMenuOpen(state),
editMenuOpen: editMenuOpen(state),
koshienMenuOpen: koshienMenuOpen(state),
meshV2MenuOpen: meshV2MenuOpen(state),
extensionLoadCounter: state.scratchGui.koshienFile.extensionLoadCounter,
aiSaveStatus: state.scratchGui.koshienFile.aiSaveStatus,
googleDriveFile: state.scratchGui.googleDriveFile,
Expand Down Expand Up @@ -1361,6 +1461,10 @@ const mapStateToProps = (state, ownProps) => {
const mapDispatchToProps = dispatch => ({
autoUpdateProject: () => dispatch(autoUpdateProject()),
onOpenDebugModal: () => dispatch(openDebugModal()),
onOpenConnectionModal: id => {
dispatch(setConnectionModalExtensionId(id));
dispatch(openConnectionModal());
},
onOpenBlockDisplayModal: () => dispatch(openBlockDisplayModal()),
onOpenKoshienTestModal: () => dispatch(openKoshienTestModal()),
onClickAccount: () => dispatch(openAccountMenu()),
Expand All @@ -1371,6 +1475,8 @@ const mapDispatchToProps = dispatch => ({
onRequestCloseEdit: () => dispatch(closeEditMenu()),
onClickKoshien: () => dispatch(openKoshienMenu()),
onRequestCloseKoshien: () => dispatch(closeKoshienMenu()),
onClickMeshV2: () => dispatch(openMeshV2Menu()),
onRequestCloseMeshV2: () => dispatch(closeMeshV2Menu()),
onClickLogin: () => dispatch(openLoginMenu()),
onRequestCloseLogin: () => dispatch(closeLoginMenu()),
onClickMode: () => dispatch(openModeMenu()),
Expand Down
4 changes: 4 additions & 0 deletions src/locales/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default {
"gui.smalruby3.previewInfo.invitation": "We're working on the next generation of Smalruby. We're excited for you to try it!",
"gui.smalruby3.previewInfo.welcome": "Welcome to the Smalruby 3.0 Preview",
'gui.smalruby3.menuBar.downloadRubyCodeToComputer': 'Save Ruby to your computer',
"gui.menuBar.meshV2": "Mesh",
"gui.smalruby3.menuBar.generateRubyFromCode": "Generate Ruby from Code",
"gui.smalruby3.unsupportedBrowser.notRecommended": "We are very sorry, but it looks like you are using a browser version that Smalruby 3.0 does not support. We recommend updating to the latest version of a supported browser such as Google Chrome, Mozilla Firefox, Microsoft Edge, or Apple Safari. ",
"gui.smalruby3.unsupportedBrowser.description": "We're very sorry, but Smalruby 3.0 does not support Internet Explorer, Vivaldi, Opera or Silk. We recommend trying a newer browser such as Google Chrome, Mozilla Firefox, or Microsoft Edge.",
Expand All @@ -28,6 +29,9 @@ export default {
'mesh.clientPeripheralName': 'Join Mesh [{ MESH_ID }]',
'mesh.registeredHost': 'Registered Host Mesh [{ MESH_ID }]',
'mesh.joinedMesh': 'Joined Mesh [{ MESH_ID }]',
'mesh.notConnectedMenu': '! Disconnected',
'mesh.registeredHostMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }',
'mesh.joinedMeshMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }',
'gui.smalruby3.extension.mesh.connectingMessage': 'Connecting',
'gui.smalruby3.extension.meshV2.name': 'Mesh V2',
'mesh.notConnected': 'Not connected (Mesh)',
Expand Down
4 changes: 4 additions & 0 deletions src/locales/ja-Hira.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default {
'gui.modal.reload': 'さいよみこみ',
'gui.menuBar.meshV2': 'メッシュ',
'gui.menuBar.loadFromUrl': 'Scratchからよみこむ',
'gui.urlLoader.loadError': 'プロジェクトURLのよみこみにしっぱいしました。',
'gui.urlLoader.invalidUrl': 'ゆうこうなScratchプロジェクトURLをにゅうりょくしてください。',
Expand Down Expand Up @@ -43,6 +44,9 @@ export default {
'mesh.registeredHost': 'ホストとしてメッシュにとうろくしました 【{ MESH_ID }】',
'mesh.notConnected': 'メッシュにせつぞくしていません',
'mesh.joinedMesh': 'メッシュにさんかしました 【{ MESH_ID }】',
'mesh.notConnectedMenu': '!せつぞくしていません',
'mesh.registeredHostMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }まで',
'mesh.joinedMeshMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }まで',
'gui.smalruby3.extension.smalrubotS1.name': 'スモウルボットS1 (エス1)',
'gui.smalruby3.extension.smalrubotS1.description': 'スモウルボットS1 (エス1) をせいぎょする。',
'gui.smalruby3.extension.smalrubotS1.connectingMessage': 'スモウルボットS1 (エス1) にせつぞくしています。',
Expand Down
8 changes: 6 additions & 2 deletions src/locales/ja.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export default {
'gui.modal.reload': '再読み込み',
'gui.modal.stop': '中止',
'gui.menuBar.loadFromUrl': 'Scratchから読み込む',
'gui.menuBar.meshV2': 'メッシュ',
'gui.menuBar.loadFromGoogleDrive': 'Google ドライブから読み込む',
'gui.menuBar.saveToGoogleDrive': 'Googleドライブにコピーを保存...',
'gui.menuBar.saveDirectlyToGoogleDrive': 'Googleドライブに直ちに保存',
Expand Down Expand Up @@ -75,11 +76,14 @@ export default {
'mesh.sensorValue': '[NAME] センサーの値',
'mesh.hostPeripheralName': 'メッシュのホストになる 【{ MESH_ID }】',
'mesh.clientPeripheralName': 'メッシュに参加する 【{ MESH_ID }】',
'mesh.registeredHost': 'ホストとしてメッシュに登録しました 【{ MESH_ID }】',
'mesh.joinedMesh': 'メッシュに参加しました 【{ MESH_ID }】',
'gui.smalruby3.extension.mesh.connectingMessage': 'メッシュのネットワークに接続しています',
'gui.smalruby3.extension.meshV2.name': 'メッシュ V2',
'mesh.notConnected': 'メッシュに接続していません',
'mesh.registeredHost': 'ホストとしてメッシュに登録しました 【{ MESH_ID }】',
'mesh.joinedMesh': 'メッシュに参加しました 【{ MESH_ID }】',
'mesh.notConnectedMenu': '!未接続',
'mesh.registeredHostMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }まで',
'mesh.joinedMeshMenu': '✔【{ MESH_ID }】 ⏳️{ EXPIRES_AT }まで',
'gui.smalruby3.extension.smalrubotS1.name': 'スモウルボットS1',
'gui.smalruby3.extension.smalrubotS1.description': 'スモウルボットS1を制御する。',
'gui.smalruby3.extension.smalrubotS1.connectingMessage': 'スモウルボットS1に接続しています。',
Expand Down
10 changes: 10 additions & 0 deletions src/reducers/menus.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const MENU_ACCOUNT = 'accountMenu';
const MENU_EDIT = 'editMenu';
const MENU_FILE = 'fileMenu';
const MENU_KOSHIEN = 'koshienMenu';
const MENU_MESH_V2 = 'meshV2Menu';
const MENU_LANGUAGE = 'languageMenu';
const MENU_LOGIN = 'loginMenu';
const MENU_MODE = 'modeMenu';
Expand Down Expand Up @@ -58,6 +59,7 @@ const rootMenu = new Menu('root')
.addChild(new Menu(MENU_EDIT))
.addChild(new Menu(MENU_MODE))
.addChild(new Menu(MENU_KOSHIEN))
.addChild(new Menu(MENU_MESH_V2))
.addChild(new Menu(MENU_SETTINGS))
.addChild(new Menu(MENU_LOGIN))
.addChild(new Menu(MENU_ACCOUNT))
Expand All @@ -69,6 +71,7 @@ const initialState = {
[MENU_EDIT]: false,
[MENU_FILE]: false,
[MENU_KOSHIEN]: false,
[MENU_MESH_V2]: false,
[MENU_LANGUAGE]: false,
[MENU_LOGIN]: false,
[MENU_MODE]: false,
Expand Down Expand Up @@ -153,6 +156,10 @@ const openKoshienMenu = () => openMenu(MENU_KOSHIEN);
const closeKoshienMenu = () => closeMenu(MENU_KOSHIEN);
const koshienMenuOpen = state => state.scratchGui.menus[MENU_KOSHIEN];

const openMeshV2Menu = () => openMenu(MENU_MESH_V2);
const closeMeshV2Menu = () => closeMenu(MENU_MESH_V2);
const meshV2MenuOpen = state => state.scratchGui.menus[MENU_MESH_V2];

export {
reducer as default,
initialState as menuInitialState,
Expand All @@ -171,6 +178,9 @@ export {
openKoshienMenu,
closeKoshienMenu,
koshienMenuOpen,
openMeshV2Menu,
closeMeshV2Menu,
meshV2MenuOpen,
openLanguageMenu,
closeLanguageMenu,
languageMenuOpen,
Expand Down
Loading