Merge branch 'develop' into greenkeeper/scratch-paint-0.2.0-prerelease.20180803171604

This commit is contained in:
Paul Kaplan authored and GitHub committed 2018-08-06 09:07:10 -04:00
commit e86512bcae
25 files changed
+233 -54

No files matched your search

+2 -2
View File
@@ -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",
+8 -2
View File
@@ -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;
+6 -4
View File
@@ -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;
+1
View File
@@ -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%;
+1 -1
View File
@@ -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 {
+8 -1
View File
@@ -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;
}
+31 -4
View File
@@ -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;
}
+3
View File
@@ -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,
+59 -13
View File
@@ -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;
}
+3 -1
View File
@@ -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
+22 -4
View File
@@ -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;
}
+2 -2
View File
@@ -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>
+20 -2
View File
@@ -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;
}
+2 -2
View File
@@ -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 {
+4 -1
View File
@@ -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,
+23 -7
View File
@@ -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 (
+1
View File
@@ -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
View File
@@ -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;
+3
View File
@@ -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'];
+5
View File
@@ -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}