From 0d62d9b03e9c92d8bc86f79a16bd96945f9487c3 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Thu, 1 Jan 2026 22:38:25 +0900 Subject: [PATCH 01/13] feat: display meshV2 connection status in menu bar - Added meshV2 menu state to reducers/menus.js - Added Mesh V2 menu item to menu-bar.jsx - Display group name and expiry time in menu item - Visual connection status indicator with icons - Updated ja, en, ja-Hira translations Issue: smalruby/smalruby3-gui#494 Co-Authored-By: Gemini --- .../menu-bar/icon--mesh-connected.png | Bin 0 -> 1948 bytes .../menu-bar/icon--mesh-disconnected.png | Bin 0 -> 1932 bytes src/components/menu-bar/menu-bar.css | 6 ++ src/components/menu-bar/menu-bar.jsx | 90 ++++++++++++++++++ src/locales/en.js | 7 +- src/locales/ja-Hira.js | 7 +- src/locales/ja.js | 7 +- src/reducers/menus.js | 10 ++ 8 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 src/components/menu-bar/icon--mesh-connected.png create mode 100644 src/components/menu-bar/icon--mesh-disconnected.png diff --git a/src/components/menu-bar/icon--mesh-connected.png b/src/components/menu-bar/icon--mesh-connected.png new file mode 100644 index 0000000000000000000000000000000000000000..5d9fa76e11af53008722c5f4f22a1c237a514694 GIT binary patch literal 1948 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 )} + {(() => { + const meshV2Status = this.getMeshV2Status(); + if (!meshV2Status.loaded) return null; + + return ( +
+ +
+ + + + + + + {meshV2Status.message} + + +
+
+ ); + })()} @@ -1247,6 +1331,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, @@ -1268,6 +1353,7 @@ MenuBar.propTypes = { onClickKoshien: PropTypes.func, onClickLogin: PropTypes.func, onClickLogo: PropTypes.func, + onClickMeshV2: PropTypes.func, onClickMode: PropTypes.func, onClickNew: PropTypes.func, onClickRemix: PropTypes.func, @@ -1287,6 +1373,7 @@ MenuBar.propTypes = { onRequestCloseFile: PropTypes.func, onRequestCloseKoshien: PropTypes.func, onRequestCloseLogin: PropTypes.func, + onRequestCloseMeshV2: PropTypes.func, onRequestCloseMode: PropTypes.func, onRequestCloseSettings: PropTypes.func, onRequestOpenAbout: PropTypes.func, @@ -1332,6 +1419,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, @@ -1371,6 +1459,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()), diff --git a/src/locales/en.js b/src/locales/en.js index d0f323e3fc0..2d49317758f 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -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.", @@ -26,11 +27,11 @@ export default { 'mesh.sensorValue': '[NAME] sensor value', 'mesh.hostPeripheralName': 'Become Mesh Host [{ MESH_ID }]', 'mesh.clientPeripheralName': 'Join Mesh [{ MESH_ID }]', - 'mesh.registeredHost': 'Registered Host Mesh [{ MESH_ID }]', - 'mesh.joinedMesh': 'Joined Mesh [{ MESH_ID }]', + 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', + 'mesh.joinedMesh': '{ MESH_ID } ({ EXPIRES_AT })', 'gui.smalruby3.extension.mesh.connectingMessage': 'Connecting', 'gui.smalruby3.extension.meshV2.name': 'Mesh V2', - 'mesh.notConnected': 'Not connected (Mesh)', + 'mesh.notConnected': 'Disconnected', 'gui.smalruby3.extension.smalrubotS1.name': 'Smalrubot S1', 'gui.smalruby3.extension.smalrubotS1.description': 'Control the Smalrubot S1.', 'gui.smalruby3.extension.smalrubotS1.connectingMessage': 'Connecting the Smalrubot S1', diff --git a/src/locales/ja-Hira.js b/src/locales/ja-Hira.js index 09f1c8572f0..f8748913f02 100644 --- a/src/locales/ja-Hira.js +++ b/src/locales/ja-Hira.js @@ -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をにゅうりょくしてください。', @@ -40,9 +41,9 @@ export default { 'mesh.hostPeripheralName': 'メッシュのホストになる 【{ MESH_ID }】', 'mesh.clientPeripheralName': 'メッシュにさんかする 【{ MESH_ID }】', 'gui.smalruby3.extension.meshV2.name': 'メッシュ V2', - 'mesh.registeredHost': 'ホストとしてメッシュにとうろくしました 【{ MESH_ID }】', - 'mesh.notConnected': 'メッシュにせつぞくしていません', - 'mesh.joinedMesh': 'メッシュにさんかしました 【{ MESH_ID }】', + 'mesh.notConnected': 'せつぞくしていません', + 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', + 'mesh.joinedMesh': '{ 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) にせつぞくしています。', diff --git a/src/locales/ja.js b/src/locales/ja.js index 71baa8f79b2..c486fc1e2ce 100644 --- a/src/locales/ja.js +++ b/src/locales/ja.js @@ -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ドライブに直ちに保存', @@ -75,11 +76,11 @@ 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.notConnected': '未接続', + 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', + 'mesh.joinedMesh': '{ MESH_ID } ({ EXPIRES_AT })', 'gui.smalruby3.extension.smalrubotS1.name': 'スモウルボットS1', 'gui.smalruby3.extension.smalrubotS1.description': 'スモウルボットS1を制御する。', 'gui.smalruby3.extension.smalrubotS1.connectingMessage': 'スモウルボットS1に接続しています。', diff --git a/src/reducers/menus.js b/src/reducers/menus.js index 00765a0b868..4c5d5fae2bc 100644 --- a/src/reducers/menus.js +++ b/src/reducers/menus.js @@ -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'; @@ -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)) @@ -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, @@ -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, @@ -171,6 +178,9 @@ export { openKoshienMenu, closeKoshienMenu, koshienMenuOpen, + openMeshV2Menu, + closeMeshV2Menu, + meshV2MenuOpen, openLanguageMenu, closeLanguageMenu, languageMenuOpen, From 3ce2133e1c3cf27543db39556070270066fa850f Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Thu, 1 Jan 2026 23:29:34 +0900 Subject: [PATCH 02/13] feat: improve Mesh V2 menu item and fix connection status display - Moved Mesh V2 menu to the tool group next to Koshien/Debug - Aligned menu structure with project conventions (Koshien-style) - Fixed connection status update by listening to peripheral events - Used concise messages for menu and detailed for connection modal - Fixed extension instance access using peripheralExtensions Co-Authored-By: Gemini --- src/components/menu-bar/menu-bar.jsx | 91 ++++++++++++++-------------- src/locales/en.js | 9 ++- src/locales/ja-Hira.js | 9 ++- src/locales/ja.js | 9 ++- 4 files changed, 65 insertions(+), 53 deletions(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 1ecc9f599de..6d7a15cf706 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -234,6 +234,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 () { @@ -242,6 +245,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 () { @@ -262,13 +268,13 @@ class MenuBar extends React.Component { } // Get extension instance - const extension = vm.runtime.ext_meshV2; + const extension = vm.runtime.peripheralExtensions.meshV2; if (!extension) { return {loaded: true, connected: false}; } const connected = extension.connectionState === 'connected'; - const message = extension.connectedMessage(); + const message = extension.menuMessage(); return { loaded: true, @@ -278,6 +284,9 @@ class MenuBar extends React.Component { }; } handleMeshV2MenuClick () { + // Close the Mesh V2 menu + this.props.onRequestCloseMeshV2(); + // Open connection modal if (this.props.vm.runtime && this.props.vm.runtime.emit) { this.props.vm.runtime.emit( @@ -913,6 +922,42 @@ class MenuBar extends React.Component { + {(() => { + const meshV2Status = this.getMeshV2Status(); + if (!meshV2Status.loaded) return null; + + return ( +
+ + + + + + + + {meshV2Status.message} + + +
+ ); + })()} {this.props.vm.extensionManager && this.props.vm.extensionManager.isExtensionLoaded('koshien') && (
)} - {(() => { - const meshV2Status = this.getMeshV2Status(); - if (!meshV2Status.loaded) return null; - - return ( -
- -
- - - - - - - {meshV2Status.message} - - -
-
- ); - })()} diff --git a/src/locales/en.js b/src/locales/en.js index 2d49317758f..4196fc80fec 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -27,11 +27,14 @@ export default { 'mesh.sensorValue': '[NAME] sensor value', 'mesh.hostPeripheralName': 'Become Mesh Host [{ MESH_ID }]', 'mesh.clientPeripheralName': 'Join Mesh [{ MESH_ID }]', - 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', - 'mesh.joinedMesh': '{ MESH_ID } ({ EXPIRES_AT })', + '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': 'Disconnected', + 'mesh.notConnected': 'Not connected (Mesh)', 'gui.smalruby3.extension.smalrubotS1.name': 'Smalrubot S1', 'gui.smalruby3.extension.smalrubotS1.description': 'Control the Smalrubot S1.', 'gui.smalruby3.extension.smalrubotS1.connectingMessage': 'Connecting the Smalrubot S1', diff --git a/src/locales/ja-Hira.js b/src/locales/ja-Hira.js index f8748913f02..15934d43c0c 100644 --- a/src/locales/ja-Hira.js +++ b/src/locales/ja-Hira.js @@ -41,9 +41,12 @@ export default { 'mesh.hostPeripheralName': 'メッシュのホストになる 【{ MESH_ID }】', 'mesh.clientPeripheralName': 'メッシュにさんかする 【{ MESH_ID }】', 'gui.smalruby3.extension.meshV2.name': 'メッシュ V2', - 'mesh.notConnected': 'せつぞくしていません', - 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', - 'mesh.joinedMesh': '{ MESH_ID } ({ EXPIRES_AT })', + '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) にせつぞくしています。', diff --git a/src/locales/ja.js b/src/locales/ja.js index c486fc1e2ce..e708422c71b 100644 --- a/src/locales/ja.js +++ b/src/locales/ja.js @@ -78,9 +78,12 @@ export default { 'mesh.clientPeripheralName': 'メッシュに参加する 【{ MESH_ID }】', 'gui.smalruby3.extension.mesh.connectingMessage': 'メッシュのネットワークに接続しています', 'gui.smalruby3.extension.meshV2.name': 'メッシュ V2', - 'mesh.notConnected': '未接続', - 'mesh.registeredHost': '{ MESH_ID } ({ EXPIRES_AT })', - 'mesh.joinedMesh': '{ MESH_ID } ({ EXPIRES_AT })', + '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に接続しています。', From 8c72c0a224680fff86ce1fe8167eb92931cf756a Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Thu, 1 Jan 2026 23:51:24 +0900 Subject: [PATCH 03/13] fix: add verbose logging to MenuBar to investigate meshV2 visibility issues --- src/components/menu-bar/menu-bar.jsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 6d7a15cf706..8eb8ac0400f 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -251,6 +251,7 @@ class MenuBar extends React.Component { } } handleExtensionAdded () { + console.log('MenuBar: handleExtensionAdded triggered'); // Dispatch Redux action to trigger re-render if (this.props.onExtensionLoaded) { this.props.onExtensionLoaded(); @@ -259,22 +260,34 @@ class MenuBar extends React.Component { getMeshV2Status () { const vm = this.props.vm; if (!vm.runtime || !vm.runtime.extensionManager) { + console.log('MenuBar: getMeshV2Status - vm.runtime or extensionManager missing'); return {loaded: false}; } + const loadedExtensions = Array.from(vm.runtime.extensionManager._loadedExtensions.keys()); + console.log('MenuBar: getMeshV2Status - Loaded extensions:', loadedExtensions); + const isLoaded = vm.runtime.extensionManager.isExtensionLoaded('meshV2'); + console.log('MenuBar: getMeshV2Status - isLoaded(meshV2):', isLoaded); + if (!isLoaded) { return {loaded: false}; } // Get extension instance + const peripheralExtensions = Object.keys(vm.runtime.peripheralExtensions || {}); + console.log('MenuBar: getMeshV2Status - Peripheral extensions:', peripheralExtensions); + const extension = vm.runtime.peripheralExtensions.meshV2; + console.log('MenuBar: getMeshV2Status - meshV2 extension instance:', extension); + if (!extension) { return {loaded: true, connected: false}; } const connected = extension.connectionState === 'connected'; const message = extension.menuMessage(); + console.log('MenuBar: getMeshV2Status - connectionState:', extension.connectionState, 'connected:', connected, 'message:', message); return { loaded: true, @@ -523,6 +536,7 @@ class MenuBar extends React.Component { }; } render () { + console.log('MenuBar: render called'); const saveNowMessage = ( Date: Fri, 2 Jan 2026 00:01:11 +0900 Subject: [PATCH 04/13] fix: access extensionManager directly from vm instead of runtime --- src/components/menu-bar/menu-bar.jsx | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 8eb8ac0400f..a376995f46d 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -259,26 +259,38 @@ class MenuBar extends React.Component { } getMeshV2Status () { const vm = this.props.vm; - if (!vm.runtime || !vm.runtime.extensionManager) { - console.log('MenuBar: getMeshV2Status - vm.runtime or extensionManager missing'); + + console.log('MenuBar: getMeshV2Status - vm:', vm); + if (!vm) return {loaded: false}; + + // In Smalruby 3 / Scratch 3, extensionManager is directly on the vm instance + const extensionManager = vm.extensionManager; + if (!extensionManager) { + console.log('MenuBar: getMeshV2Status - extensionManager missing on vm'); return {loaded: false}; } - const loadedExtensions = Array.from(vm.runtime.extensionManager._loadedExtensions.keys()); + const loadedExtensions = Array.from(extensionManager._loadedExtensions.keys()); console.log('MenuBar: getMeshV2Status - Loaded extensions:', loadedExtensions); - const isLoaded = vm.runtime.extensionManager.isExtensionLoaded('meshV2'); + const isLoaded = extensionManager.isExtensionLoaded('meshV2'); console.log('MenuBar: getMeshV2Status - isLoaded(meshV2):', isLoaded); if (!isLoaded) { return {loaded: false}; } - // Get extension instance - const peripheralExtensions = Object.keys(vm.runtime.peripheralExtensions || {}); + // peripheralExtensions is on vm.runtime + const runtime = vm.runtime; + if (!runtime || !runtime.peripheralExtensions) { + console.log('MenuBar: getMeshV2Status - runtime or peripheralExtensions missing'); + return {loaded: true, connected: false}; + } + + const peripheralExtensions = Object.keys(runtime.peripheralExtensions || {}); console.log('MenuBar: getMeshV2Status - Peripheral extensions:', peripheralExtensions); - const extension = vm.runtime.peripheralExtensions.meshV2; + const extension = runtime.peripheralExtensions.meshV2; console.log('MenuBar: getMeshV2Status - meshV2 extension instance:', extension); if (!extension) { From 2f40d6f2fdcabd6cee45aa54cf10345cb9906926 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 00:13:01 +0900 Subject: [PATCH 05/13] fix: correctly open connection modal for meshV2 from MenuBar --- src/components/menu-bar/menu-bar.jsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index a376995f46d..0657d32caa4 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -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 { @@ -309,16 +310,13 @@ class MenuBar extends React.Component { }; } handleMeshV2MenuClick () { + console.log('MenuBar: handleMeshV2MenuClick triggered'); // Close the Mesh V2 menu this.props.onRequestCloseMeshV2(); // Open connection modal - if (this.props.vm.runtime && this.props.vm.runtime.emit) { - this.props.vm.runtime.emit( - this.props.vm.runtime.constructor.PERIPHERAL_SCAN_START, - 'meshV2' - ); - } + console.log('MenuBar: Opening connection modal for meshV2'); + this.props.onOpenConnectionModal('meshV2'); } handleClickNew () { // if the project is dirty, and user owns the project, we will autosave. @@ -1478,6 +1476,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()), From 71e16407ab1162f945662f8c55571df2255b84e0 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 00:13:41 +0900 Subject: [PATCH 06/13] fix: add onOpenConnectionModal to MenuBar propTypes --- src/components/menu-bar/menu-bar.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 0657d32caa4..7022df4ee9c 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -1390,8 +1390,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, From e6f55f51e7b96220f93ef185557c70da5073f62b Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 02:15:51 +0900 Subject: [PATCH 07/13] fix: shorten long console.log line in MenuBar --- src/components/menu-bar/menu-bar.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 7022df4ee9c..66ff45a1f4b 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -300,7 +300,11 @@ class MenuBar extends React.Component { const connected = extension.connectionState === 'connected'; const message = extension.menuMessage(); - console.log('MenuBar: getMeshV2Status - connectionState:', extension.connectionState, 'connected:', connected, 'message:', message); + console.log('MenuBar: getMeshV2Status', { + connectionState: extension.connectionState, + connected, + message + }); return { loaded: true, From 779c9074b167fa51380415cfe54308912e2aef9f Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 11:11:27 +0900 Subject: [PATCH 08/13] style: update meshV2 connection status icons --- .../menu-bar/icon--mesh-connected.png | Bin 1948 -> 5561 bytes .../menu-bar/icon--mesh-disconnected.png | Bin 1932 -> 5552 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/components/menu-bar/icon--mesh-connected.png b/src/components/menu-bar/icon--mesh-connected.png index 5d9fa76e11af53008722c5f4f22a1c237a514694..3528e4150c94d9c3d52677afb094b7cedfdb2c0c 100644 GIT binary patch literal 5561 zcmZu#cQjn<*FH0&MGT@u^w9-l1kqcRs526x*XV*MBZEX2(TQGzgecKM)F65%IzeLe z-icm*a_{}_@B7yJ_F3=Q&%4jFpZ)IlpR?8ud4y7g64DR?00321lGnKQkNzwIyz6)5 zt-Yda2SRHo$^ymT=~k~duPt?zt&m87>lzaPxF9kB@`rN$03aFw_b&_pDj?c_u?C3q z9}XA*f@}ete>nQr{*NhLuj}l8JR}qJU&T!DzwAeukpJR8Y0Z;NYS-?Dlad}90B(~1 zSs)-K?asBDp6wG|S6!r+PZEK@#hQT9xor_U+wEui9b;>br)O9 z>&k!hrS3`m#r!|9f9gme{uKXThxxnHzoOTzN)bvR{=GISLTck#d;lP~RhED7#2vJm z=JEDthgQe(q}+Oi_KH4zB(FVWZ2HoK7;kFhK&PduD{cQ&{0HGDC=(Yvv=p;E>+ z>N@Ip_VVKNca=$l_b*8e&JhAA4h?}IsSRvECeu#_;)e(RJK$b_iy&i_IIQi%Y2G>E ztdodO&Y8F5F@my@uhIR4t7&%;mki7WJD?1;WqgkkTy_l}WvL%#R_B(%31{>~`buCS z_{4&47)-HVrM;dtXB>85WTXzB$St9GX5EiZD#__xr&Zd>LXd55xhT+o0IxmYyE#@~ zSy>$RFpEmA>MkAeg@p)RO%i7PL|gNa+_NZ-YVYKyJS&;e*a!vO)y++g7L~YLV&Q{Y zST<_*c4~FVf3lXN#Ofj{ zpl}9dRx(GoxuFWI}q_~%ycA&2N25$P{x-pD}1A4#jDeSp-?E}dAx5c9~IGdkSNu` z#)a0_)-g17E3P#Im0XfX(TO^=vZ!cu1J;E*750spVuosKWkuw551NQ^5Aq3H>$d%Y zBg=n#BK5a^tdg2Bi{M1G$=(nlQAV+FP6SekH`XJ#Zxy#9Ya<+7O(D8Y-|z4GZU0xT zn<8kN?_}=B!4FDR`r}yj1kd&-TxZ4r&%x1A&s~zupEc;aG?FFf!OwW(Vt<$KXH@O) zso<0v3CAi+asr~s=ON_JzSC3i7x|p{(8$;LtW3$f)NHWQc6YS)Y#%RPq^qPzc}c%- z2_iv1<42ktgo;v9`&WWxs3R@LW5@WtRXlFwe+@0!N`45*n19u~J5;(8hab$7A`^IKhA6|VJOOHe=95B%y?V^oWo*i;ph-0?J+8oMQw=yv$~w*#w`ln#DN zOUot_i7ZG-O&yo{!bAf#q9E=Na!#M_1%#a|jXSCWyOJ0f8JEeJJzu*(c~xF2FPnpw zCznKcr`1eM7VHwkJ9qUy7#xoTH6WQ!#Bguq7Q58+jw?|OcP&`QbS>n#d%7s{i|#+R zddVSsb#s^8Q@VYV8c2(?StcAYpe#+;V?2KUh_lZ)E+;R-k)#B1$K2DWt#coHcC_6f z^V>pQug6O|EOhk;fKzC|M!{qddi$I^PCoVS?NI7Q4Kc+uH((OhrtpnDz$=IKRS{D$Gz<=9k1rP99)TZ7IdxbZgRY zCFn6Y&ZPh&IPW{uPbN-q9QEZ)O6lAS3)Uz3U^bsCwsK`{WwoJ#FaH@QpMU3bO9P7- zu5MD_$BeGh(o$qG(vy@L7A+@oqVnmB7wEk+r|m=4+Pgc zuWe_n$bh3~)$SubXhG4V|s-=zxj@+ zDEp~OI9wmanOIp>WfC%w$b6tMV2qnowXbr-?_ryS_da)IM%;bJbog*{O2B5xU}`eK zIl%mbfzN<*S2W}1>gum*kNqX#VXWg`k(t0ad)ckaYPqK)@JrP^utC$RAE_p*+_9dA1yEZ+7Tk+hG51=2?-4Yr0 z<@R3;0_jI2Q2Fv@>hT=9gYI|QjTcalo4uE>*qCUJ2?KWYO#xZc=LDucL(#8x>?elUTT;7kSL99~lj8&Vo_?fB zX|C*Eu;lQm*Uci-#1;kb0J<`dVt8Cy?8Tdhu>!!dLw$$?t$TXdqjnlJ`P#D zq`D|Zi^{Dw?3uWjSKPK9X1JwQ4v1^Lh3d``Val!$N+mj&&&HKEoDl^m#Yy*v*IFtB z=85|o@97x$n|!r3B5T~oqhucnA*sQH4b#yK{%kMFm>tBr!^L@~(YU{+Z!d1Txf*_k z(?ragKCF7w?%;fEmV}{1lI! zo7gvZ&6_fTDy3w3Uos@lIrQ}vG3Ka!yK@*3CRLo5-#=GSQKDNqhx;?UfRk3uQp2so z?4G2DRaYvU72beomf3F0O#?RyN0YQQ4<3FRk1 ze+L3%a&?Um=Pf+VhsX3qO-PKW%##ud@gN^0{Q2wh(doKur{H;(}AaN_PQCiw!KS#Er#+9Kan^c$^`Lz^ydJP+EGgD-J?gkNF4 ztl>FbIGjmV@iB+v8+7@A;1Hgmr!@SMXh?_*uMTQpFU(I9u$EZ_e#?(8eP$o0#em~= z9=wf?)EUiJTGV2SPdQ-|8=Pt)(NcCX&ir(z8a$~NM6i=sV}FRxW%U_TfihZ65Xn&O zSz4>PMG7UL=oM5CU5bMP{o@a&;NEl-QaCnOzCu10uI1I|ts&-zSsW`b7j6th$=EK% zf=6;6sO4ESUlz+9=AIDem3;LeBHl_2dp{M!tpBC$esL8#+F%DP&}laiTuq2hK4=I* zK-6~G;_$*BK!swJ>yRF}Yt;#5KNbVZ{cf68%BxEDUG_wkm}szE=wmR*yBu!8qc3i_ z)EgP&90j}OYJ{A571F z7U-j0Gg%J~U%_^D;o_){T>mP<-6KCxawVj5KB_@D5HvUKI?Ju>} zkB`C_*p9`33nA=sQgw+_*BOL8W_k1{X&o0bFy#sEn6EICel&KCaeX`@5;wTWCnH0v zbK@t^bAqSDTwMxwnRiZ6x_HF zU5(4BV?!==)}n_46TUgQ9oWT59*P@upnUHG=PdK8ABU|f(*d~^rYTX(*%O}^V)T5i z4nYB6aur$GUj7~q5vd}|iW2VoMcXA}q-?4)Ekm*~6Fh*7sw@BB;Fu@f=+iIfda=OlX(EJ zdPRDV##vKRR-DL6L9pt^U^KDA_jR6i_u1g7A%Xd=RZkuo!Sb-WhuzT18y7Cr`zhq0 zJ(~DgL-+4@_;$3>~Rx z6DAV1l*?ZB;TNIUGX;eGbj34)vV9AoSPyFB47WPe_a9w32^zF)<%9#-&U?29q^<%E zMW;T|xBAt*m##IjV6)9n;g5&t&Kc@|O1jNZz#qjoc=dY7GxQR(^D9ErX^z!MnR<3M zQED=YeqUI4Ow0HD_Q}F@FGfaI zDhAfz$FES8K$^>Rylo1Ot5|Lrep7;@s4uTWB{5(!G=;$};Y;uA^Ub#NF&JvkZ_ki7 zTQWAdJ)&2LW>WLH6L!Bofck`Tn&6wF(T?ep!N+emx2A{7%-Rfe*03#YX0y<9ba9yN zc-P5cqIv0(oin1?-qGa5yt~|PX+_bILCf!yeXY!<=^c?PW0Xw)=x~EIP7&OCw*&9$ z?($YcrrMP@@**Fl_paghSj>E^UK8FDe!#QdG!|KlS!EZYiP}=J)+fdp(G^lNJKO!rOxpr_kaYO7R~tf z`Im-$-C;Blg;qmjut)eNdT#e)&5CKs&DdIaxWkZ6mkym+grdPtH_Yf!Xv zi;h;`ywmKTGh=KEM?rEwAy127Q|}$7X`i%pYd&Y}8j4h`;T8}oV>`7liM2W5@G7C` zO8;I!osKCjbuWMlZIV&UKl{Z#ik8VV`dF`HeAakQll^Ax(Iv5+;fxLK@Mvx22Y}A+ z34?@9t5tc=x>8U79u(XViu4x_UZ@?-0K2}}JZ4)vy=oTzVd%--y>Q=V?mVQO{qbVD zRafbqf_of++&|_NJIT)xC8$%)<`D>oy{hZS1~3^iwv>KnkwL!gHK1e|>@)hn*h}`+ z8^J;2`R8R1KKi3!83rYEqvXKJ#lOH=h@|f+Nny~3aUR< z?u-$VW5g`O4*kt8^Sx|2xz{45p+G3^-7V63iCppGyY?b=Ml?fpn9a#19TUle+k(!B zH#$1<)DEnRjNlN((z`TMLqkI^=Pk@!k``--Qole9UgEbK6#HLUm+7PUw}xEmzfQk8sgWQ<1NJWsAd5?pk(YlYMMCvNxO%%pvbAN}Ro>0`QiY~FnWyyB*HeDSOw zty0=Y1;8-$j-pdIKJd(!qlf7Vk|pY%ra5CvbQ8?U?0X~4AZ-}m=>s<4!@*~rgWH7f zTiza&*+-e39b7TbSSMpX*=qSFmTP64Cfw%cT)Hw6aTDy%UQ#y#LUke5zW1X{)03m@ zd@Xv6?7u6#J+FS&_5zaE4zRqO5c8M`^*RG!-E~F>lM0Vn{+|ifzay(3x6;SfUvZnt30fDYTSO5S3 literal 1948 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 M*3egfr)m}aKYgGiVE_OC literal 1932 zcmZ{ic~H}59>#wZ5Q-Pl3PCN4tf-~64Im7Lge2r3A-^OLlMo2VkwZ=)B%p+Fh6o8r zp-4%>5sm;FkSl@|1i7gkx*F&LVi&TOF|i0AN3nfTbDz@b9uTHSU`G46V@|IRqLR0K_K&AUh8LwvAWW8vu|31%MY3 z002`0fL&5mUmzR+-s1*ZL4Ptx^7ki%hlge7WXWWCnVA{+`B$5o8f$AcYPDM1s8y>~ettNROrlW97!10i zqP(zB5fDI$i;Ec;yo<&9G8pGIni>KDkHcY9DrH5*S4gA}k%*6tjc#hvCM3iW33xuA zTV8%0gYl(ODJ?C!pdbc^6UF0kYin!r@^XbjK~YhmuP^HSd7AM#Xf(2{?918N8M(Zm zuuv||%c-nXwYRrLMuuO$oFbLxkVyVFZZwUI4A0C=>vT7kmKN96*4o-``S`#|pg)yD z?&|F5?d@r6YyGmU6o>Pzs#0IQDiev4v$8TWGb9Q{fk2Q%4WNJ^F(ib=<3*)Q#Fdrm zx_V7t-`ByxK{Q$bjYhq6DPAnTl9?&V$;pn6=6&%+aeaMlU0v<%+g)sSFdFTXk|Ih@ z7BHD~KR;|^qc-7Ee06nIb8}N(o)nMA@pv2#C(_#+CXu8gkqERe@>)@0a&l69LabKX z(Auh-pP!S<^K+%yrKKgYak0L>=!l35VsRP@<#X{OFDfb=iG)v1PE1WtO-+5Xwzj&v zyW7#x-qX|F-`^*bNvo+QW$TwHYJN-Bdv7o`Xr8tMb6 z6gV7)K)^*JVWnCfA0LZCAuoi5vVxfBX@S;@!r$36i6Z%7YcyRAdyNMR5s{3ucwu6) z-@)n4XRcdD9+6@?OGJyj?3k3C$d8HVIf~Mfc#c;Rk^sQ#S~Y{zwG6df7AlUR_n3Vv z*fD&@NZcyc>`C)^HA7-d=t`ZBZ#2m~et!41Fmrrumf-oLPkQJ5F=k6!XwfY-TaQUy zZ)o3KQgwa@avJ;SPa8LW!kMREjMM5rKQQSsxDh!25|29M%{R-&i zq?rW$sB`>>mJto#O7lM*P5N66=n&b_bFw-3O^DZTKi3Y+w69C=y|UR(W~W?EhD*FsUzI+p?gt;&N7C~ixo>Bf4YO8ah_KOMJCXKKO>+W4hVK zJ~m{g48e%!Dkc_t0=Fy&%v)FHP|Qz>)P{D2gGqpybNaf+d3OE5lFK&M+J_BP)(0gTU^%AXDlvMVR`|?K zij&CdupW#&RL9(@)_@k(hJ$C($?cDS$ZFnEyMzhfon`c`Z^!6FvmTqjbYtzV9X$7@ z=ppW*pmlgOW=u*cC|(yVD9KBi`_gPT?8QfhqvyW2;H6y{S)M$Mxl{Raa3|S2-+AfD zJ-OAm8)La-P0@@zf=TUUe&ir9(&a3|u|(WR5f8>m<{1regSvU1fw~%p4)uh&y20Ge zeFBBTpwRBIdmjH2NJ!+y@YDW(U`%BpHwI4sr$H2xz!QohjhOydiK{!z9SUK@7I2?1FW*K z_U5uY92Pe|=6s@2%Tq2ca2Fv9kmt`2e^~yT*L8*$eSXe^1v!2a8XFt4`Ev8ck4GU# z>?@USul26bE>~#B$EwasHY+6f=)%HMr)AgaMeh#4{G;lsu+XQ=2>8HVMzC^$#ezT} z66KWC`ee+^b~Kw#YG0W4sp`yTHSxirsux- z=}Fc~gnqDe-}G@?TRxw;XAggP)UWBjFwOyyDzS6F2SAI=&t=z*?x7FOOthv&*?oev u?s&iEtc8_Z?#T7hYdE>R4PvL6VhZRF#qzwu-cA~S9U$T;*f!sY+ Date: Fri, 2 Jan 2026 11:12:43 +0900 Subject: [PATCH 09/13] chore: remove debug console logs from MenuBar --- src/components/menu-bar/menu-bar.jsx | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 66ff45a1f4b..de98adc5f61 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -252,7 +252,6 @@ class MenuBar extends React.Component { } } handleExtensionAdded () { - console.log('MenuBar: handleExtensionAdded triggered'); // Dispatch Redux action to trigger re-render if (this.props.onExtensionLoaded) { this.props.onExtensionLoaded(); @@ -261,21 +260,15 @@ class MenuBar extends React.Component { getMeshV2Status () { const vm = this.props.vm; - console.log('MenuBar: getMeshV2Status - vm:', vm); if (!vm) return {loaded: false}; // In Smalruby 3 / Scratch 3, extensionManager is directly on the vm instance const extensionManager = vm.extensionManager; if (!extensionManager) { - console.log('MenuBar: getMeshV2Status - extensionManager missing on vm'); return {loaded: false}; } - const loadedExtensions = Array.from(extensionManager._loadedExtensions.keys()); - console.log('MenuBar: getMeshV2Status - Loaded extensions:', loadedExtensions); - const isLoaded = extensionManager.isExtensionLoaded('meshV2'); - console.log('MenuBar: getMeshV2Status - isLoaded(meshV2):', isLoaded); if (!isLoaded) { return {loaded: false}; @@ -284,15 +277,10 @@ class MenuBar extends React.Component { // peripheralExtensions is on vm.runtime const runtime = vm.runtime; if (!runtime || !runtime.peripheralExtensions) { - console.log('MenuBar: getMeshV2Status - runtime or peripheralExtensions missing'); return {loaded: true, connected: false}; } - const peripheralExtensions = Object.keys(runtime.peripheralExtensions || {}); - console.log('MenuBar: getMeshV2Status - Peripheral extensions:', peripheralExtensions); - const extension = runtime.peripheralExtensions.meshV2; - console.log('MenuBar: getMeshV2Status - meshV2 extension instance:', extension); if (!extension) { return {loaded: true, connected: false}; @@ -300,11 +288,6 @@ class MenuBar extends React.Component { const connected = extension.connectionState === 'connected'; const message = extension.menuMessage(); - console.log('MenuBar: getMeshV2Status', { - connectionState: extension.connectionState, - connected, - message - }); return { loaded: true, @@ -314,12 +297,10 @@ class MenuBar extends React.Component { }; } handleMeshV2MenuClick () { - console.log('MenuBar: handleMeshV2MenuClick triggered'); // Close the Mesh V2 menu this.props.onRequestCloseMeshV2(); // Open connection modal - console.log('MenuBar: Opening connection modal for meshV2'); this.props.onOpenConnectionModal('meshV2'); } handleClickNew () { @@ -550,7 +531,6 @@ class MenuBar extends React.Component { }; } render () { - console.log('MenuBar: render called'); const saveNowMessage = ( Date: Fri, 2 Jan 2026 11:19:22 +0900 Subject: [PATCH 10/13] style: enhance meshV2 menu status with symbols --- src/locales/en.js | 6 +++--- src/locales/ja-Hira.js | 6 +++--- src/locales/ja.js | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/locales/en.js b/src/locales/en.js index 4196fc80fec..c79ec91b3e2 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -29,9 +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 })', + '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)', diff --git a/src/locales/ja-Hira.js b/src/locales/ja-Hira.js index 15934d43c0c..5db09729f9f 100644 --- a/src/locales/ja-Hira.js +++ b/src/locales/ja-Hira.js @@ -44,9 +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 })', + '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) にせつぞくしています。', diff --git a/src/locales/ja.js b/src/locales/ja.js index e708422c71b..93fde03b9dd 100644 --- a/src/locales/ja.js +++ b/src/locales/ja.js @@ -81,9 +81,9 @@ export default { 'mesh.notConnected': 'メッシュに接続していません', 'mesh.registeredHost': 'ホストとしてメッシュに登録しました 【{ MESH_ID }】', 'mesh.joinedMesh': 'メッシュに参加しました 【{ MESH_ID }】', - 'mesh.notConnectedMenu': '未接続', - 'mesh.registeredHostMenu': '{ MESH_ID } ({ EXPIRES_AT })', - 'mesh.joinedMeshMenu': '{ MESH_ID } ({ EXPIRES_AT })', + '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に接続しています。', From c608e58ddc0ac53a8d7f7c9cf17f7c9b4fa657c0 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 11:25:55 +0900 Subject: [PATCH 11/13] style: refine Mesh V2 menu status expression in English --- src/locales/en.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/locales/en.js b/src/locales/en.js index c79ec91b3e2..9c1c2376cfb 100644 --- a/src/locales/en.js +++ b/src/locales/en.js @@ -29,9 +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 })', + '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)', From 6f33d5354cd3a2bef0da3a8f5368277eb1dd0aa4 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 11:30:23 +0900 Subject: [PATCH 12/13] style: refine Mesh V2 menu status expression in Japanese and Hiragana --- src/locales/ja-Hira.js | 4 ++-- src/locales/ja.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/locales/ja-Hira.js b/src/locales/ja-Hira.js index 5db09729f9f..5d34dc38247 100644 --- a/src/locales/ja-Hira.js +++ b/src/locales/ja-Hira.js @@ -45,8 +45,8 @@ export default { 'mesh.notConnected': 'メッシュにせつぞくしていません', 'mesh.joinedMesh': 'メッシュにさんかしました 【{ MESH_ID }】', 'mesh.notConnectedMenu': '!せつぞくしていません', - 'mesh.registeredHostMenu': '✔【{ MESH_ID }】 (⏳️{ EXPIRES_AT })', - 'mesh.joinedMeshMenu': '✔【{ MESH_ID }】 (⏳️{ EXPIRES_AT })', + '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) にせつぞくしています。', diff --git a/src/locales/ja.js b/src/locales/ja.js index 93fde03b9dd..175505f1189 100644 --- a/src/locales/ja.js +++ b/src/locales/ja.js @@ -82,8 +82,8 @@ export default { 'mesh.registeredHost': 'ホストとしてメッシュに登録しました 【{ MESH_ID }】', 'mesh.joinedMesh': 'メッシュに参加しました 【{ MESH_ID }】', 'mesh.notConnectedMenu': '!未接続', - 'mesh.registeredHostMenu': '✔【{ MESH_ID }】 (⏳️{ EXPIRES_AT })', - 'mesh.joinedMeshMenu': '✔【{ MESH_ID }】 (⏳️{ EXPIRES_AT })', + '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に接続しています。', From 377b6a5f6768358d93db58a6678d678ffb1aa96c Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 2 Jan 2026 12:12:20 +0900 Subject: [PATCH 13/13] feat: update scratch-vm --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 3adbd53f176..bdd42dcdd4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28942,7 +28942,7 @@ }, "node_modules/scratch-vm": { "version": "5.0.300", - "resolved": "git+ssh://git@github.com/smalruby/scratch-vm.git#2ddca55f7d10e8549251181a09a5d0506bc474e6", + "resolved": "git+ssh://git@github.com/smalruby/scratch-vm.git#db5982d2756da0fa7128e0b17bf6bbe54d2f2a4a", "license": "AGPL-3.0-only", "dependencies": { "@vernier/godirect": "^1.5.0",