Merge branch 'develop' into greenkeeper/scratch-paint-0.2.0-prerelease.20180803171604
This commit is contained in:
25 files changed
+233
-54
No files matched your search
+2
-2
@@ -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.1533219167",
|
||||
"scratch-l10n": "3.0.20180719145856",
|
||||
"scratch-blocks": "0.1.0-prerelease.1533301486",
|
||||
"scratch-l10n": "3.0.20180803171042",
|
||||
"scratch-paint": "0.2.0-prerelease.20180803171604",
|
||||
"scratch-render": "0.1.0-prerelease.20180724152606",
|
||||
"scratch-storage": "0.5.1",
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -58,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
|
||||
@@ -71,6 +76,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 +156,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;
|
||||
|
||||
@@ -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'}
|
||||
/>
|
||||
<div className={styles.moreButtonsOuter}>
|
||||
<div className={styles.moreButtons}>
|
||||
@@ -142,7 +143,7 @@ class ActionMenu extends React.Component {
|
||||
fileAccept, fileChange, fileInput}, keyId) => {
|
||||
const isComingSoon = !handleClick;
|
||||
const hasFileInput = fileInput;
|
||||
const tooltipId = title;
|
||||
const tooltipId = `${mainTooltipId}-${title}`;
|
||||
return (
|
||||
<div key={`${tooltipId}-${keyId}`}>
|
||||
<button
|
||||
@@ -174,7 +175,7 @@ class ActionMenu extends React.Component {
|
||||
})}
|
||||
effect="solid"
|
||||
id={tooltipId}
|
||||
place="left"
|
||||
place={tooltipPlace || 'left'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -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;
|
||||
@@ -32,6 +32,7 @@ $fade-out-distance: 100px;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right:0;
|
||||
background: linear-gradient(rgba(232,237,241, 0),rgba(232,237,241, 1));
|
||||
height: $fade-out-distance;
|
||||
width: 100%;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important;
|
||||
font-size: 1rem !important;
|
||||
line-height: 1.25rem !important;
|
||||
z-index: $z-index-coming-soon !important;
|
||||
z-index: $z-index-tooltip !important;
|
||||
}
|
||||
|
||||
.coming-soon:after {
|
||||
|
||||
@@ -9,13 +9,20 @@
|
||||
|
||||
.input-label, .input-label-secondary {
|
||||
font-size: 0.625rem;
|
||||
margin-right: .5rem;
|
||||
user-select: none;
|
||||
cursor: default;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[dir="ltr"] .input-label, .input-label-secondary {
|
||||
margin-right: .5rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .input-label, .input-label-secondary {
|
||||
margin-left: .5rem;
|
||||
}
|
||||
|
||||
.input-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -63,7 +63,6 @@
|
||||
flex-grow: 1;
|
||||
height: 80%;
|
||||
margin-bottom: 0;
|
||||
margin-left: -0.5rem;
|
||||
|
||||
border-radius: 1rem 1rem 0 0;
|
||||
border: 1px solid $ui-black-transparent;
|
||||
@@ -82,9 +81,24 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
[dir="ltr"] .tab {
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .tab {
|
||||
margin-right: -0.5rem;
|
||||
}
|
||||
|
||||
[dir="ltr"] .tab:nth-of-type(1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .tab:nth-of-type(1) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Use z-indices to force left-on-top for tabs */
|
||||
.tab:nth-of-type(1) {
|
||||
margin-left: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
.tab:nth-of-type(2) {
|
||||
@@ -106,11 +120,19 @@
|
||||
}
|
||||
|
||||
.tab img {
|
||||
margin-right: 0.125rem;
|
||||
width: 1.375rem;
|
||||
filter: grayscale(100%);
|
||||
}
|
||||
|
||||
[dir="ltr"] .tab img {
|
||||
margin-right: 0.125rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .tab img {
|
||||
margin-left: 0.125rem;
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.tab.is-selected img {
|
||||
filter: none;
|
||||
}
|
||||
@@ -191,7 +213,7 @@
|
||||
padding-right: $space;
|
||||
|
||||
min-height: 0; /* this makes it work in Firefox */
|
||||
|
||||
|
||||
/*
|
||||
For making the sprite-selector a scrollable pane
|
||||
@todo: Not working in Safari
|
||||
@@ -206,6 +228,7 @@
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: $z-index-extension-button;
|
||||
background: $motion-primary;
|
||||
|
||||
@@ -240,6 +263,10 @@ $fade-out-distance: 15px;
|
||||
height: 1.75rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .extension-button-icon {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
.extension-button > div {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -65,6 +65,7 @@ const GUIComponent = props => {
|
||||
importInfoVisible,
|
||||
intl,
|
||||
isPlayerOnly,
|
||||
isRtl,
|
||||
loading,
|
||||
onExtensionButtonClick,
|
||||
onActivateCostumesTab,
|
||||
@@ -110,6 +111,7 @@ const GUIComponent = props => {
|
||||
) : (
|
||||
<Box
|
||||
className={styles.pageWrapper}
|
||||
dir={isRtl ? 'rtl' : 'ltr'}
|
||||
{...componentProps}
|
||||
>
|
||||
{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,
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[dir="rtl"] .row-reverse {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.row + .row {
|
||||
margin-top: calc(2 * $space);
|
||||
}
|
||||
@@ -23,15 +27,31 @@
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.input-group + .input-group {
|
||||
[dir="ltr"] .input-group + .input-group {
|
||||
margin-left: calc(2 * $space);
|
||||
}
|
||||
|
||||
.input-group {
|
||||
[dir="rtl"] .input-group + .input-group {
|
||||
margin-right: calc(2 * $space);
|
||||
}
|
||||
|
||||
[dir="ltr"] .input-group {
|
||||
padding-right: calc(2 * $space);
|
||||
border-right: 1px dashed $ui-black-transparent;
|
||||
}
|
||||
|
||||
[dir="rtl"] .input-group {
|
||||
padding-left: calc(2 * $space);
|
||||
border-left: 1px dashed $ui-black-transparent;
|
||||
}
|
||||
|
||||
[dir="rtl"] .row-reverse > .input-group {
|
||||
padding-left: 0;
|
||||
padding-right: calc(2 * $space);
|
||||
border-left: none;
|
||||
border-right: 1px dashed $ui-black-transparent;
|
||||
}
|
||||
|
||||
.waveform-container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
@@ -87,26 +107,31 @@ $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;
|
||||
color: $text-primary;
|
||||
font-size: 0.625rem;
|
||||
margin-left: 1rem;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
[dir="ltr"] .trim-button {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .trim-button {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.trim-button > img {
|
||||
width: 1.25rem;
|
||||
margin-bottom: -0.375rem;
|
||||
}
|
||||
|
||||
.input-group-right {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.effect-button {
|
||||
flex-basis: 60px;
|
||||
color: $text-primary;
|
||||
@@ -124,26 +149,47 @@ $border-radius: 0.25rem;
|
||||
margin-bottom: -0.375rem;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
[dir="ltr"] .button-group {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .button-group {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.button-group .button {
|
||||
border-radius: 0;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
.button-group .button:last-of-type {
|
||||
[dir="ltr"] .button-group .button {
|
||||
border-left: none;
|
||||
}
|
||||
[dir="rtl"] .button-group .button {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
[dir="ltr"] .button-group .button:last-of-type {
|
||||
border-top-right-radius: $border-radius;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
}
|
||||
|
||||
.button-group .button:first-of-type {
|
||||
[dir="ltr"] .button-group .button:first-of-type {
|
||||
border-left: 1px solid $ui-black-transparent;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-bottom-left-radius: $border-radius;
|
||||
}
|
||||
|
||||
[dir="rtl"] .button-group .button:last-of-type {
|
||||
border-top-left-radius: $border-radius;
|
||||
border-bottom-left-radius: $border-radius;
|
||||
}
|
||||
|
||||
[dir="rtl"] .button-group .button:first-of-type {
|
||||
border-right: 1px solid $ui-black-transparent;
|
||||
border-top-right-radius: $border-radius;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
}
|
||||
|
||||
.button:disabled > img {
|
||||
opacity: 0.25;
|
||||
}
|
||||
@@ -122,6 +122,7 @@ const SoundEditor = props => (
|
||||
onClick={props.onUndo}
|
||||
>
|
||||
<img
|
||||
className={styles.undoIcon}
|
||||
draggable={false}
|
||||
src={undoIcon}
|
||||
/>
|
||||
@@ -133,6 +134,7 @@ const SoundEditor = props => (
|
||||
onClick={props.onRedo}
|
||||
>
|
||||
<img
|
||||
className={styles.redoIcon}
|
||||
draggable={false}
|
||||
src={redoIcon}
|
||||
/>
|
||||
@@ -168,7 +170,7 @@ const SoundEditor = props => (
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.row}>
|
||||
<div className={classNames(styles.row, styles.rowReverse)}>
|
||||
<div className={styles.inputGroup}>
|
||||
{props.playhead ? (
|
||||
<button
|
||||
|
||||
@@ -59,27 +59,45 @@
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.radio-left {
|
||||
.radio-first {
|
||||
border: 1px solid $ui-black-transparent;
|
||||
}
|
||||
|
||||
[dir="ltr"] .radio-first {
|
||||
border-top-left-radius: $form-radius;
|
||||
border-bottom-left-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-left:focus {
|
||||
[dir="rtl"] .radio-first {
|
||||
border-top-right-radius: $form-radius;
|
||||
border-bottom-right-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-first:focus {
|
||||
border-color: $motion-primary;
|
||||
box-shadow: inset 0 0 0 -2px $ui-black-transparent;
|
||||
}
|
||||
|
||||
.radio-right {
|
||||
.radio-last {
|
||||
border-bottom: 1px solid $ui-black-transparent;
|
||||
border-top: 1px solid $ui-black-transparent;
|
||||
}
|
||||
|
||||
[dir="ltr"] .radio-last {
|
||||
border-right: 1px solid $ui-black-transparent;
|
||||
border-left: 1px solid $ui-black-transparent;
|
||||
border-top-right-radius: $form-radius;
|
||||
border-bottom-right-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-right:focus {
|
||||
[dir="rtl"] .radio-last {
|
||||
border-left: 1px solid $ui-black-transparent;
|
||||
border-right: 1px solid $ui-black-transparent;
|
||||
border-top-left-radius: $form-radius;
|
||||
border-bottom-left-radius: $form-radius;
|
||||
}
|
||||
|
||||
.radio-last:focus {
|
||||
border-color: $motion-primary;
|
||||
box-shadow: inset 0 0 0 -2px $ui-black-transparent;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ class SpriteInfo extends React.Component {
|
||||
<div
|
||||
className={classNames(
|
||||
styles.radio,
|
||||
styles.radioLeft,
|
||||
styles.radioFirst,
|
||||
styles.iconWrapper,
|
||||
{
|
||||
[styles.isActive]: this.props.visible && !this.props.disabled,
|
||||
@@ -195,7 +195,7 @@ class SpriteInfo extends React.Component {
|
||||
<div
|
||||
className={classNames(
|
||||
styles.radio,
|
||||
styles.radioRight,
|
||||
styles.radioLast,
|
||||
styles.iconWrapper,
|
||||
{
|
||||
[styles.isActive]: !this.props.visible && !this.props.disabled,
|
||||
|
||||
@@ -80,15 +80,29 @@
|
||||
.delete-button {
|
||||
position: absolute;
|
||||
top: 0.125rem;
|
||||
right: 0.125rem;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
[dir="ltr"] .delete-button {
|
||||
right: 0.125rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .delete-button {
|
||||
left: 0.125rem;
|
||||
}
|
||||
|
||||
.number {
|
||||
position: absolute;
|
||||
top: 0.15rem;
|
||||
left: 0.15rem;
|
||||
font-size: 0.625rem;
|
||||
font-weight: bold;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
[dir="ltr"] .number {
|
||||
left: 0.15rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .number {
|
||||
right: 0.15rem;
|
||||
}
|
||||
@@ -68,8 +68,14 @@
|
||||
.add-button {
|
||||
position: absolute;
|
||||
bottom: 0.75rem;
|
||||
}
|
||||
|
||||
[dir="ltr"] .add-button {
|
||||
right: 1rem;
|
||||
z-index: $z-index-add-button;
|
||||
}
|
||||
|
||||
[dir="rtl"] .add-button {
|
||||
left: 1rem;
|
||||
}
|
||||
|
||||
.raised {
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -140,6 +140,7 @@ const SpriteSelectorComponent = function (props) {
|
||||
}
|
||||
]}
|
||||
title={intl.formatMessage(messages.addSpriteFromLibrary)}
|
||||
tooltipPlace={RtlLocales.indexOf(intl.locale) === -1 ? 'left' : 'right'}
|
||||
onClick={onNewSpriteClick}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -31,9 +31,16 @@
|
||||
|
||||
.stage-size-toggle-group {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
[dir="ltr"] .stage-size-toggle-group {
|
||||
margin-right: .2rem;
|
||||
}
|
||||
|
||||
[dir="rtl"] .stage-size-toggle-group {
|
||||
margin-left: .2rem;
|
||||
}
|
||||
|
||||
.stage-button {
|
||||
display: block;
|
||||
border: 1px solid $ui-black-transparent;
|
||||
@@ -51,13 +58,24 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.stage-button-right {
|
||||
[dir="ltr"] .stage-button-first {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
[dir="ltr"] .stage-button-last {
|
||||
border-left: none;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.stage-button-left {
|
||||
[dir="rtl"] .stage-button-first {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .stage-button-last {
|
||||
border-right: none;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ const StageHeaderComponent = function (props) {
|
||||
<Button
|
||||
className={classNames(
|
||||
styles.stageButton,
|
||||
styles.stageButtonLeft,
|
||||
styles.stageButtonFirst,
|
||||
(stageSizeMode === STAGE_SIZE_MODES.small) ? null : styles.stageButtonToggledOff
|
||||
)}
|
||||
onClick={onSetStageSmall}
|
||||
@@ -113,7 +113,7 @@ const StageHeaderComponent = function (props) {
|
||||
<Button
|
||||
className={classNames(
|
||||
styles.stageButton,
|
||||
styles.stageButtonRight,
|
||||
styles.stageButtonLast,
|
||||
(stageSizeMode === STAGE_SIZE_MODES.large) ? null : styles.stageButtonToggledOff
|
||||
)}
|
||||
onClick={onSetStageLarge}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
@import "../../css/units.css";
|
||||
@import "../../css/colors.css";
|
||||
@import "../../css/z-index.css";
|
||||
|
||||
$header-height: calc($stage-menu-height - 2px);
|
||||
|
||||
@@ -96,7 +95,6 @@ $header-height: calc($stage-menu-height - 2px);
|
||||
.add-button {
|
||||
position: absolute;
|
||||
bottom: 0.75rem;
|
||||
z-index: $z-index-add-button
|
||||
}
|
||||
|
||||
.raised, .raised .header {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
@@ -16,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);
|
||||
@@ -43,6 +39,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 +69,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 +81,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 (
|
||||
|
||||
@@ -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: (
|
||||
|
||||
+1
-1
@@ -8,8 +8,8 @@ $z-index-extension-button: 50; /* Force extension button above the ScratchBlocks
|
||||
$z-index-menu-bar: 50; /* blocklyToolboxDiv is 40 */
|
||||
|
||||
$z-index-monitor: 100;
|
||||
$z-index-coming-soon: 110;
|
||||
$z-index-add-button: 120;
|
||||
$z-index-tooltip: 130; /* tooltips should go over add buttons if they overlap */
|
||||
|
||||
$z-index-card: 490;
|
||||
$z-index-loader: 500;
|
||||
|
||||
@@ -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'];
|
||||
@@ -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);
|
||||
|
||||
@@ -9,6 +10,7 @@ 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
|
||||
@@ -19,12 +21,14 @@ const reducer = function (state, action) {
|
||||
switch (action.type) {
|
||||
case SELECT_LOCALE:
|
||||
return Object.assign({}, state, {
|
||||
isRtl: RtlLocales.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 +57,7 @@ const initLocale = function (currentState, locale) {
|
||||
{},
|
||||
currentState,
|
||||
{
|
||||
isRtl: RtlLocales.indexOf(locale) !== -1,
|
||||
locale: locale,
|
||||
messagesByLocale: currentState.messagesByLocale,
|
||||
messages: currentState.messagesByLocale[locale]
|
||||
|
||||
@@ -39,6 +39,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
title="Undo"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
draggable={false}
|
||||
src="test-file-stub"
|
||||
/>
|
||||
@@ -50,6 +51,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
title="Redo"
|
||||
>
|
||||
<img
|
||||
className={undefined}
|
||||
draggable={false}
|
||||
src="test-file-stub"
|
||||
/>
|
||||
@@ -334,7 +336,7 @@ exports[`Sound Editor Component matches snapshot 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={undefined}
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className={undefined}
|
||||
|
||||
Reference in new issue
Block a user