From 375e9c3f07959f1c5b7e6acd8fb83a55f65eba02 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Wed, 1 Aug 2018 11:08:00 -0400 Subject: [PATCH 01/13] Basic RTL --- src/components/gui/gui.jsx | 3 +++ src/containers/blocks.jsx | 5 ++++- src/containers/gui.jsx | 1 + src/reducers/locales.js | 7 +++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 8d251bd14..c3b7cff71 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -65,6 +65,7 @@ const GUIComponent = props => { importInfoVisible, intl, isPlayerOnly, + isRtl, loading, onExtensionButtonClick, onActivateCostumesTab, @@ -110,6 +111,7 @@ const GUIComponent = props => { ) : ( {previewInfoVisible ? ( @@ -282,6 +284,7 @@ GUIComponent.propTypes = { importInfoVisible: PropTypes.bool, intl: intlShape.isRequired, isPlayerOnly: PropTypes.bool, + isRtl: PropTypes.bool, loading: PropTypes.bool, onActivateCostumesTab: PropTypes.func, onActivateSoundsTab: PropTypes.func, diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx index 3862fa653..44d52664e 100644 --- a/src/containers/blocks.jsx +++ b/src/containers/blocks.jsx @@ -77,7 +77,7 @@ class Blocks extends React.Component { const workspaceConfig = defaultsDeep({}, Blocks.defaultOptions, this.props.options, - {toolbox: this.props.toolboxXML} + {rtl: this.props.isRtl, toolbox: this.props.toolboxXML} ); this.workspace = this.ScratchBlocks.inject(this.blocks, workspaceConfig); @@ -403,6 +403,7 @@ class Blocks extends React.Component { options, stageSize, vm, + isRtl, isVisible, onActivateColorPicker, updateToolboxState, @@ -467,6 +468,7 @@ Blocks.propTypes = { anyModalVisible: PropTypes.bool, customProceduresVisible: PropTypes.bool, extensionLibraryVisible: PropTypes.bool, + isRtl: PropTypes.bool, isVisible: PropTypes.bool, locale: PropTypes.string, messages: PropTypes.objectOf(PropTypes.string), @@ -541,6 +543,7 @@ const mapStateToProps = state => ({ state.scratchGui.mode.isFullScreen ), extensionLibraryVisible: state.scratchGui.modals.extensionLibrary, + isRtl: state.locales.isRtl, locale: state.locales.locale, messages: state.locales.messages, toolboxXML: state.scratchGui.toolbox.toolboxXML, diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 8db598c85..ffa099496 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -113,6 +113,7 @@ const mapStateToProps = state => ({ costumesTabVisible: state.scratchGui.editorTab.activeTabIndex === COSTUMES_TAB_INDEX, importInfoVisible: state.scratchGui.modals.importInfo, isPlayerOnly: state.scratchGui.mode.isPlayerOnly, + isRtl: state.locales.isRtl, loadingStateVisible: state.scratchGui.modals.loadingProject, previewInfoVisible: state.scratchGui.modals.previewInfo, targetIsStage: ( diff --git a/src/reducers/locales.js b/src/reducers/locales.js index fda8f9dc3..c2c072391 100644 --- a/src/reducers/locales.js +++ b/src/reducers/locales.js @@ -9,22 +9,28 @@ const UPDATE_LOCALES = 'scratch-gui/locales/UPDATE_LOCALES'; const SELECT_LOCALE = 'scratch-gui/locales/SELECT_LOCALE'; const initialState = { + isRtl: false, locale: 'en', messagesByLocale: editorMessages, messages: editorMessages.en }; +// TODO: this probably should be coming from scratch-l10n +const RtlLangs = ['he']; + const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; switch (action.type) { case SELECT_LOCALE: return Object.assign({}, state, { + isRtl: RtlLangs.indexOf(action.locale) !== -1, locale: action.locale, messagesByLocale: state.messagesByLocale, messages: state.messagesByLocale[action.locale] }); case UPDATE_LOCALES: return Object.assign({}, state, { + isRtl: state.isRtl, locale: state.locale, messagesByLocale: action.messagesByLocale, messages: action.messagesByLocale[state.locale] @@ -53,6 +59,7 @@ const initLocale = function (currentState, locale) { {}, currentState, { + isRtl: RtlLangs.indexOf(locale) !== -1, locale: locale, messagesByLocale: currentState.messagesByLocale, messages: currentState.messagesByLocale[locale] From 67f4496947c143efa3e24f6214b36bfc651f25e3 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Wed, 1 Aug 2018 11:37:10 -0400 Subject: [PATCH 02/13] Action menu RTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bled into normalizing z-indices for the action menus in the z-index.css. The tooltip id was not unique between action menus for ‘suprise’ and ‘paint’, so `mainTooltipId` was used as a prefix to make them unique. --- src/components/action-menu/action-menu.css | 6 ++++-- src/components/action-menu/action-menu.jsx | 2 +- src/components/asset-panel/selector.css | 1 + src/components/coming-soon/coming-soon.css | 2 +- src/components/sprite-selector/sprite-selector.css | 8 +++++++- src/components/stage-selector/stage-selector.css | 1 - src/css/z-index.css | 2 +- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/components/action-menu/action-menu.css b/src/components/action-menu/action-menu.css index 8f39946c1..682c3b242 100644 --- a/src/components/action-menu/action-menu.css +++ b/src/components/action-menu/action-menu.css @@ -1,4 +1,5 @@ @import "../../css/colors.css"; +@import "../../css/z-index.css"; $main-button-size: 2.75rem; $more-button-size: 2.25rem; @@ -44,7 +45,7 @@ button::-moz-focus-inner { width: $main-button-size; height: $main-button-size; box-shadow: 0 0 0 4px $motion-transparent; - z-index: 20; /* TODO reorder layout to prevent z-index need */ + z-index: $z-index-add-button; transition: transform, box-shadow 0.5s; } @@ -71,6 +72,7 @@ button::-moz-focus-inner { border-top-right-radius: $more-button-size; width: $more-button-size; margin-left: calc(($main-button-size - $more-button-size) / 2); + margin-right: calc(($main-button-size - $more-button-size) / 2); position: absolute; bottom: calc($main-button-size); @@ -150,7 +152,7 @@ button::-moz-focus-inner { border-radius: .25rem !important; box-shadow: 0 0 .5rem hsla(0, 0%, 0%, .25) !important; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important; - z-index: 100 !important; + z-index: $z-index-tooltip !important; } $arrow-size: 0.5rem; diff --git a/src/components/action-menu/action-menu.jsx b/src/components/action-menu/action-menu.jsx index 2725c502b..781549d3d 100644 --- a/src/components/action-menu/action-menu.jsx +++ b/src/components/action-menu/action-menu.jsx @@ -142,7 +142,7 @@ class ActionMenu extends React.Component { fileAccept, fileChange, fileInput}, keyId) => { const isComingSoon = !handleClick; const hasFileInput = fileInput; - const tooltipId = title; + const tooltipId = `${mainTooltipId}-${title}`; return (
-
+
{props.playhead ? (
Date: Thu, 2 Aug 2018 16:33:27 -0400 Subject: [PATCH 10/13] Flip the direction of a bunch of icons I think this switches all the icons we saw. I also switched the icons on the tabs (the blocks going the wrong way looked bad). --- src/components/action-menu/action-menu.css | 4 ++++ src/components/action-menu/action-menu.jsx | 8 +++++--- src/components/gui/gui.css | 5 +++++ src/components/sound-editor/sound-editor.css | 4 ++++ src/components/sound-editor/sound-editor.jsx | 2 ++ src/components/sprite-selector/sprite-selector.jsx | 3 ++- src/components/stage-selector/stage-selector.css | 1 - src/lib/rtl-locales.js | 3 +++ src/reducers/locales.js | 8 +++----- .../components/__snapshots__/sound-editor.test.jsx.snap | 2 ++ 10 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 src/lib/rtl-locales.js diff --git a/src/components/action-menu/action-menu.css b/src/components/action-menu/action-menu.css index 682c3b242..e82103ca1 100644 --- a/src/components/action-menu/action-menu.css +++ b/src/components/action-menu/action-menu.css @@ -59,6 +59,10 @@ button::-moz-focus-inner { height: calc($main-button-size - 1rem); } +[dir="rtl"] .main-icon { + transform: scaleX(-1); +} + .more-buttons-outer { /* Need to use two divs to set different overflow x/y diff --git a/src/components/action-menu/action-menu.jsx b/src/components/action-menu/action-menu.jsx index 781549d3d..90555dfd8 100644 --- a/src/components/action-menu/action-menu.jsx +++ b/src/components/action-menu/action-menu.jsx @@ -101,6 +101,7 @@ class ActionMenu extends React.Component { img: mainImg, title: mainTitle, moreButtons, + tooltipPlace, onClick } = this.props; @@ -134,7 +135,7 @@ class ActionMenu extends React.Component { className={styles.tooltip} effect="solid" id={mainTooltipId} - place="left" + place={tooltipPlace || 'left'} />
@@ -174,7 +175,7 @@ class ActionMenu extends React.Component { })} effect="solid" id={tooltipId} - place="left" + place={tooltipPlace || 'left'} />
); @@ -198,7 +199,8 @@ ActionMenu.propTypes = { fileInput: PropTypes.func // Optional, only for file upload })), onClick: PropTypes.func.isRequired, - title: PropTypes.node.isRequired + title: PropTypes.node.isRequired, + tooltipPlace: PropTypes.string }; export default ActionMenu; diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css index 87b75b837..1924bd8c4 100644 --- a/src/components/gui/gui.css +++ b/src/components/gui/gui.css @@ -130,6 +130,7 @@ [dir="rtl"] .tab img { margin-left: 0.125rem; + transform: scaleX(-1); } .tab.is-selected img { @@ -262,6 +263,10 @@ $fade-out-distance: 15px; height: 1.75rem; } +[dir="rtl"] .extension-button-icon { + transform: scaleX(-1); +} + .extension-button > div { margin-top: 0; } diff --git a/src/components/sound-editor/sound-editor.css b/src/components/sound-editor/sound-editor.css index 13a46d730..c6e620001 100644 --- a/src/components/sound-editor/sound-editor.css +++ b/src/components/sound-editor/sound-editor.css @@ -107,6 +107,10 @@ $border-radius: 0.25rem; /*min-width: 1.5rem;*/ } +[dir="rtl"] .undo-icon, [dir="rtl"] .redo-icon { + transform: scaleX(-1); +} + .trim-button { display: flex; align-items: center; diff --git a/src/components/sound-editor/sound-editor.jsx b/src/components/sound-editor/sound-editor.jsx index 6814b94ae..f97338e06 100644 --- a/src/components/sound-editor/sound-editor.jsx +++ b/src/components/sound-editor/sound-editor.jsx @@ -122,6 +122,7 @@ const SoundEditor = props => ( onClick={props.onUndo} > @@ -133,6 +134,7 @@ const SoundEditor = props => ( onClick={props.onRedo} > diff --git a/src/components/sprite-selector/sprite-selector.jsx b/src/components/sprite-selector/sprite-selector.jsx index e6948c5b7..04e2de63e 100644 --- a/src/components/sprite-selector/sprite-selector.jsx +++ b/src/components/sprite-selector/sprite-selector.jsx @@ -2,12 +2,12 @@ import PropTypes from 'prop-types'; import React from 'react'; import {defineMessages, injectIntl, intlShape} from 'react-intl'; - import Box from '../box/box.jsx'; import SpriteInfo from '../../containers/sprite-info.jsx'; import SpriteList from './sprite-list.jsx'; import ActionMenu from '../action-menu/action-menu.jsx'; import {STAGE_DISPLAY_SIZES} from '../../lib/layout-constants'; +import RtlLocales from '../../lib/rtl-locales'; import styles from './sprite-selector.css'; @@ -137,6 +137,7 @@ const SpriteSelectorComponent = function (props) { } ]} title={intl.formatMessage(messages.addSpriteFromLibrary)} + tooltipPlace={RtlLocales.indexOf(intl.locale) === -1 ? 'left' : 'right'} onClick={onNewSpriteClick} /> diff --git a/src/components/stage-selector/stage-selector.css b/src/components/stage-selector/stage-selector.css index 9bb846b1e..2669a6de5 100644 --- a/src/components/stage-selector/stage-selector.css +++ b/src/components/stage-selector/stage-selector.css @@ -1,6 +1,5 @@ @import "../../css/units.css"; @import "../../css/colors.css"; -@import "../../css/z-index.css"; $header-height: calc($stage-menu-height - 2px); diff --git a/src/lib/rtl-locales.js b/src/lib/rtl-locales.js new file mode 100644 index 000000000..b48ff7599 --- /dev/null +++ b/src/lib/rtl-locales.js @@ -0,0 +1,3 @@ +// TODO: this probably should be coming from scratch-l10n +// Tracking in https://github.com/LLK/scratch-l10n/issues/32 +export default ['he']; diff --git a/src/reducers/locales.js b/src/reducers/locales.js index c2c072391..14ca3bd37 100644 --- a/src/reducers/locales.js +++ b/src/reducers/locales.js @@ -2,6 +2,7 @@ import {addLocaleData} from 'react-intl'; import {localeData} from 'scratch-l10n'; import editorMessages from 'scratch-l10n/locales/editor-msgs'; +import RtlLocales from '../lib/rtl-locales'; addLocaleData(localeData); @@ -15,15 +16,12 @@ const initialState = { messages: editorMessages.en }; -// TODO: this probably should be coming from scratch-l10n -const RtlLangs = ['he']; - const reducer = function (state, action) { if (typeof state === 'undefined') state = initialState; switch (action.type) { case SELECT_LOCALE: return Object.assign({}, state, { - isRtl: RtlLangs.indexOf(action.locale) !== -1, + isRtl: RtlLocales.indexOf(action.locale) !== -1, locale: action.locale, messagesByLocale: state.messagesByLocale, messages: state.messagesByLocale[action.locale] @@ -59,7 +57,7 @@ const initLocale = function (currentState, locale) { {}, currentState, { - isRtl: RtlLangs.indexOf(locale) !== -1, + isRtl: RtlLocales.indexOf(locale) !== -1, locale: locale, messagesByLocale: currentState.messagesByLocale, messages: currentState.messagesByLocale[locale] diff --git a/test/unit/components/__snapshots__/sound-editor.test.jsx.snap b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap index 7b6a88c75..93ebc2cf6 100644 --- a/test/unit/components/__snapshots__/sound-editor.test.jsx.snap +++ b/test/unit/components/__snapshots__/sound-editor.test.jsx.snap @@ -39,6 +39,7 @@ exports[`Sound Editor Component matches snapshot 1`] = ` title="Undo" > @@ -50,6 +51,7 @@ exports[`Sound Editor Component matches snapshot 1`] = ` title="Redo" > From 11b2fee8a87652bc026e3b10c761b3831b27b0cd Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 3 Aug 2018 08:55:16 -0400 Subject: [PATCH 11/13] Add instrumentation for connecting and connected events for extensions --- src/containers/connection-modal.jsx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/containers/connection-modal.jsx b/src/containers/connection-modal.jsx index 50862fbd2..82b4dbd5f 100644 --- a/src/containers/connection-modal.jsx +++ b/src/containers/connection-modal.jsx @@ -3,6 +3,7 @@ import React from 'react'; 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'; class ConnectionModal extends React.Component { constructor (props) { @@ -43,6 +44,11 @@ class ConnectionModal extends React.Component { this.setState({ phase: PHASES.connecting }); + analytics.event({ + category: 'extensions', + action: 'connecting', + label: this.props.extensionId + }); } handleDisconnect () { this.props.onStatusButtonUpdate(this.props.extensionId, 'not ready'); @@ -68,6 +74,11 @@ class ConnectionModal extends React.Component { this.setState({ phase: PHASES.error }); + analytics.event({ + category: 'extensions', + action: 'connecting error', + label: this.props.extensionId + }); } } handleConnected () { @@ -75,9 +86,19 @@ class ConnectionModal extends React.Component { this.setState({ phase: PHASES.connected }); + analytics.event({ + category: 'extensions', + action: 'connected', + label: this.props.extensionId + }); } handleHelp () { window.open(this.props.helpLink, '_blank'); + analytics.event({ + category: 'extensions', + action: 'help', + label: this.props.extensionId + }); } render () { return ( From d80078a2242036f187f70cc40dd9722d326692f5 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Fri, 3 Aug 2018 08:56:30 -0400 Subject: [PATCH 12/13] Do not call handleConnected in componentDidMount Two reasons: 1. Avoid triggering "connected" event, because the device was already connected 2. It is not good to call `setState` in componentDidMount, which is effectively what it was doing. --- src/containers/connection-modal.jsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/containers/connection-modal.jsx b/src/containers/connection-modal.jsx index 82b4dbd5f..8edf15e43 100644 --- a/src/containers/connection-modal.jsx +++ b/src/containers/connection-modal.jsx @@ -17,18 +17,13 @@ class ConnectionModal extends React.Component { 'handleHelp' ]); this.state = { - phase: PHASES.scanning + phase: props.vm.getPeripheralIsConnected(props.extensionId) ? + PHASES.connected : PHASES.scanning }; } componentDidMount () { this.props.vm.on('PERIPHERAL_CONNECTED', this.handleConnected); this.props.vm.on('PERIPHERAL_ERROR', this.handleError); - - // Check if we're already connected - if (this.props.vm.getPeripheralIsConnected(this.props.extensionId)) { - this.handleConnected(); - } - } componentWillUnmount () { this.props.vm.removeListener('PERIPHERAL_CONNECTED', this.handleConnected); From a804064aa6d72746a8cf32253b80f232ac30b7f1 Mon Sep 17 00:00:00 2001 From: chrisgarrity Date: Fri, 3 Aug 2018 13:20:51 -0400 Subject: [PATCH 13/13] Update dependencies for translations * Update scratch-blocks * Update scratch-l10n --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 4bb36e401..70d47dc26 100644 --- a/package.json +++ b/package.json @@ -96,8 +96,8 @@ "redux-throttle": "0.1.1", "rimraf": "^2.6.1", "scratch-audio": "0.1.0-prerelease.20180625202813", - "scratch-blocks": "0.1.0-prerelease.1532446271", - "scratch-l10n": "3.0.20180719145856", + "scratch-blocks": "0.1.0-prerelease.1533301486", + "scratch-l10n": "3.0.20180803171042", "scratch-paint": "0.2.0-prerelease.20180802204251", "scratch-render": "0.1.0-prerelease.20180724152606", "scratch-storage": "0.5.1",