Compare commits
23
Commits
develop
...
desktop-0.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dd83af71fd | ||
|
|
e795bdc0cb | ||
|
|
dc68458634 | ||
|
|
5c25b07e1e | ||
|
|
dcd5ac11b1 | ||
|
|
17630e0812 | ||
|
|
7db75dbf6d | ||
|
|
edadc3ac7f | ||
|
|
d2e7c4fdaf | ||
|
|
d573691288 | ||
|
|
5df9370307 | ||
|
|
172df1b808 | ||
|
|
cfc01bc136 | ||
|
|
3084d2489e | ||
|
|
aa1e099570 | ||
|
|
63f4707fc6 | ||
|
|
5a238b3459 | ||
|
|
6900b2b64e | ||
|
|
544b2bae83 | ||
|
|
d192466784 | ||
|
|
fa3f030d1c | ||
|
|
629d832304 | ||
|
|
0f3ab023b0 |
No files matched your search
@@ -5,9 +5,6 @@
|
|||||||
/node_modules
|
/node_modules
|
||||||
npm-*
|
npm-*
|
||||||
|
|
||||||
# Double copies of all the static assets and tutorial gifs
|
|
||||||
/src
|
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
/.nyc_output
|
/.nyc_output
|
||||||
/coverage
|
/coverage
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "scratch-gui",
|
"name": "scratch-gui",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "GraphicaL User Interface for creating and running Scratch 3.0 projects",
|
"description": "GraphicaL User Interface for creating and running Scratch 3.0 projects",
|
||||||
"main": "./dist/scratch-gui.js",
|
"main": "./dist/js/scratch-gui.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npm run clean && webpack --colors --bail",
|
"build": "npm run clean && webpack --colors --bail",
|
||||||
"clean": "rimraf ./build && mkdirp build && rimraf ./dist && mkdirp dist",
|
"clean": "rimraf ./build && mkdirp build && rimraf ./dist && mkdirp dist",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
let loaded = false;
|
let loaded = false;
|
||||||
|
|
||||||
const load = () => {
|
const load = () => {
|
||||||
import(/* webpackChunkName: "addons" */ './index');
|
// import(/* webpackChunkName: "addons" */ './index');
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadAddons = () => {
|
const loadAddons = () => {
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import topBlock from './top-block.svg';
|
|||||||
import middleBlock from './middle-block.svg';
|
import middleBlock from './middle-block.svg';
|
||||||
import bottomBlock from './bottom-block.svg';
|
import bottomBlock from './bottom-block.svg';
|
||||||
|
|
||||||
import * as progressMonitor from './tw-progress-monitor';
|
|
||||||
|
|
||||||
// tw:
|
// tw:
|
||||||
// we make some rather large changes here:
|
// we make some rather large changes here:
|
||||||
// - remove random message, replaced with message dependent on what is actually being loaded
|
// - remove random message, replaced with message dependent on what is actually being loaded
|
||||||
@@ -19,6 +17,9 @@ import * as progressMonitor from './tw-progress-monitor';
|
|||||||
// The way of doing this is extremely unusual and weird compared to how things are typically done for performance.
|
// The way of doing this is extremely unusual and weird compared to how things are typically done for performance.
|
||||||
// This is because react updates are too performance crippling to handle the progress bar rapidly updating.
|
// This is because react updates are too performance crippling to handle the progress bar rapidly updating.
|
||||||
|
|
||||||
|
// tw:
|
||||||
|
// progress bar logic removed entirely as it is unneeded in desktop build
|
||||||
|
|
||||||
const mainMessages = {
|
const mainMessages = {
|
||||||
'gui.loader.headline': (
|
'gui.loader.headline': (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
@@ -63,41 +64,13 @@ class LoaderComponent extends React.Component {
|
|||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this._state = 0;
|
this._state = 0;
|
||||||
this.progress = 0;
|
|
||||||
this.complete = 0;
|
|
||||||
this.total = 0;
|
|
||||||
bindAll(this, [
|
bindAll(this, [
|
||||||
'barInnerRef',
|
|
||||||
'handleProgressChange',
|
|
||||||
'messageRef'
|
'messageRef'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
progressMonitor.setProgressHandler(this.handleProgressChange);
|
|
||||||
this.updateMessage();
|
this.updateMessage();
|
||||||
}
|
}
|
||||||
componentDidUpdate () {
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
componentWillUnmount () {
|
|
||||||
progressMonitor.setProgressHandler(() => {});
|
|
||||||
}
|
|
||||||
handleProgressChange (state, progress, complete, total) {
|
|
||||||
if (state !== this._state) {
|
|
||||||
this._state = state;
|
|
||||||
this.updateMessage();
|
|
||||||
}
|
|
||||||
this.progress = progress;
|
|
||||||
this.complete = complete;
|
|
||||||
this.total = total;
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
update () {
|
|
||||||
this.barInner.style.width = `${this.progress * 100}%`;
|
|
||||||
if (this._state === 2) {
|
|
||||||
this.updateMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateMessage () {
|
updateMessage () {
|
||||||
if (this._state === 0) {
|
if (this._state === 0) {
|
||||||
this.message.textContent = this.props.intl.formatMessage(messages.generic);
|
this.message.textContent = this.props.intl.formatMessage(messages.generic);
|
||||||
@@ -112,9 +85,6 @@ class LoaderComponent extends React.Component {
|
|||||||
this.message.textContent = this.props.intl.formatMessage(messages.assetsUnknown);
|
this.message.textContent = this.props.intl.formatMessage(messages.assetsUnknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
barInnerRef (element) {
|
|
||||||
this.barInner = element;
|
|
||||||
}
|
|
||||||
messageRef (element) {
|
messageRef (element) {
|
||||||
this.message = element;
|
this.message = element;
|
||||||
}
|
}
|
||||||
@@ -149,12 +119,6 @@ class LoaderComponent extends React.Component {
|
|||||||
ref={this.messageRef}
|
ref={this.messageRef}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.twProgressOuter}>
|
|
||||||
<div
|
|
||||||
className={styles.twProgressInner}
|
|
||||||
ref={this.barInnerRef}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -225,7 +225,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mystuff > a {
|
.mystuff > a {
|
||||||
background-image: url("/images/mystuff.png");
|
/* background-image: url("/images/mystuff.png"); */
|
||||||
}
|
}
|
||||||
|
|
||||||
.about-icon {
|
.about-icon {
|
||||||
|
|||||||
@@ -384,7 +384,7 @@ class MenuBar extends React.Component {
|
|||||||
>
|
>
|
||||||
<div className={styles.mainMenu}>
|
<div className={styles.mainMenu}>
|
||||||
<div className={styles.fileGroup}>
|
<div className={styles.fileGroup}>
|
||||||
{this.props.onClickLogo ? (
|
{false && this.props.onClickLogo ? (
|
||||||
<div className={classNames(styles.menuBarItem)}>
|
<div className={classNames(styles.menuBarItem)}>
|
||||||
<img
|
<img
|
||||||
alt="Scratch"
|
alt="Scratch"
|
||||||
@@ -552,30 +552,6 @@ class MenuBar extends React.Component {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
<MenuItem onClick={this.getSaveToComputerHandler(downloadProject)}>
|
|
||||||
{extended.available ? (
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="{saveToYourComputer} (legacy)"
|
|
||||||
description="Wrapper around 'Save to your computer' when a more modern API is available" // eslint-disable-line max-len
|
|
||||||
id="tw.menuBar.legacyDownloadToComputer"
|
|
||||||
values={{
|
|
||||||
saveToYourComputer: (
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Save to your computer"
|
|
||||||
description="Menu bar item for downloading a project to your computer" // eslint-disable-line max-len
|
|
||||||
id="gui.menuBar.downloadToComputer"
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Save to your computer"
|
|
||||||
description="Menu bar item for downloading a project to your computer" // eslint-disable-line max-len
|
|
||||||
id="gui.menuBar.downloadToComputer"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</MenuItem>
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}</SB3Downloader>
|
)}</SB3Downloader>
|
||||||
</MenuSection>
|
</MenuSection>
|
||||||
@@ -830,6 +806,13 @@ class MenuBar extends React.Component {
|
|||||||
onRequestClose={this.props.onRequestCloseHelp}
|
onRequestClose={this.props.onRequestCloseHelp}
|
||||||
>
|
>
|
||||||
<MenuSection>
|
<MenuSection>
|
||||||
|
<MenuItem onClick={this.props.onClickLogo}>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="About, credits, license"
|
||||||
|
description="Link to about in desktop"
|
||||||
|
id="tw.desktop.about"
|
||||||
|
/>
|
||||||
|
</MenuItem>
|
||||||
<MenuItemLink href="https://github.com/TurboWarp">
|
<MenuItemLink href="https://github.com/TurboWarp">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Source Code"
|
defaultMessage="Source Code"
|
||||||
@@ -837,18 +820,11 @@ class MenuBar extends React.Component {
|
|||||||
id="tw.code"
|
id="tw.code"
|
||||||
/>
|
/>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
<MenuItemLink href="/privacy.html">
|
<MenuItemLink href="https://desktop.turbowarp.org">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Privacy"
|
defaultMessage="Website"
|
||||||
description="Link to privacy policy"
|
description="Link to website in desktop"
|
||||||
id="tw.privacy"
|
id="tw.desktop.website"
|
||||||
/>
|
|
||||||
</MenuItemLink>
|
|
||||||
<MenuItemLink href="https://github.com/TurboWarp/scratch-gui/wiki/Embedding">
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="Embedding"
|
|
||||||
description="Menu bar item for embedding link"
|
|
||||||
id="tw.menuBar.embed"
|
|
||||||
/>
|
/>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
<MenuItemLink href="https://github.com/TurboWarp/scratch-gui/wiki/TurboWarp-blocks">
|
<MenuItemLink href="https://github.com/TurboWarp/scratch-gui/wiki/TurboWarp-blocks">
|
||||||
@@ -858,13 +834,6 @@ class MenuBar extends React.Component {
|
|||||||
id="tw.menuBar.blocks"
|
id="tw.menuBar.blocks"
|
||||||
/>
|
/>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
<MenuItemLink href="https://github.com/TurboWarp/scratch-gui/wiki/URL-Parameters">
|
|
||||||
<FormattedMessage
|
|
||||||
defaultMessage="URL Parameters"
|
|
||||||
description="Menu bar item for URL parameters link"
|
|
||||||
id="tw.menuBar.parameters"
|
|
||||||
/>
|
|
||||||
</MenuItemLink>
|
|
||||||
<MenuItemLink href="https://github.com/TurboWarp/translations/blob/master/CONTRIBUTING.md#readme">
|
<MenuItemLink href="https://github.com/TurboWarp/translations/blob/master/CONTRIBUTING.md#readme">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Help Translate TurboWarp"
|
defaultMessage="Help Translate TurboWarp"
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ class LibraryItem extends React.PureComponent {
|
|||||||
render () {
|
render () {
|
||||||
const iconMd5 = this.curIconMd5();
|
const iconMd5 = this.curIconMd5();
|
||||||
const iconURL = iconMd5 ?
|
const iconURL = iconMd5 ?
|
||||||
`https://cdn.assets.scratch.mit.edu/internalapi/asset/${iconMd5}/get/` :
|
`library-files/${iconMd5}` :
|
||||||
this.props.iconRawURL;
|
this.props.iconRawURL;
|
||||||
return (
|
return (
|
||||||
<LibraryItemComponent
|
<LibraryItemComponent
|
||||||
|
|||||||
@@ -167,12 +167,12 @@ class Monitor extends React.Component {
|
|||||||
this.element = monitorElt;
|
this.element = monitorElt;
|
||||||
}
|
}
|
||||||
handleImport () {
|
handleImport () {
|
||||||
importCSV().then(rows => {
|
importCSV().then(async rows => {
|
||||||
const numberOfColumns = rows[0].length;
|
const numberOfColumns = rows[0].length;
|
||||||
let columnNumber = 1;
|
let columnNumber = 1;
|
||||||
if (numberOfColumns > 1) {
|
if (numberOfColumns > 1) {
|
||||||
const msg = this.props.intl.formatMessage(messages.columnPrompt, {numberOfColumns});
|
const msg = this.props.intl.formatMessage(messages.columnPrompt, {numberOfColumns});
|
||||||
columnNumber = parseInt(prompt(msg), 10); // eslint-disable-line no-alert
|
columnNumber = parseInt(await prompt(msg), 10); // eslint-disable-line no-alert
|
||||||
}
|
}
|
||||||
const newListValue = rows.map(row => row[columnNumber - 1])
|
const newListValue = rows.map(row => row[columnNumber - 1])
|
||||||
.filter(item => typeof item === 'string'); // CSV importer can leave undefineds
|
.filter(item => typeof item === 'string'); // CSV importer can leave undefineds
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ class ChangeUsername extends React.Component {
|
|||||||
'changeUsername'
|
'changeUsername'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
changeUsername () {
|
async changeUsername () {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
const newUsername = prompt(this.props.intl.formatMessage(messages.usernamePrompt), this.props.username);
|
const newUsername = await prompt(this.props.intl.formatMessage(messages.usernamePrompt), this.props.username);
|
||||||
if (newUsername === null) {
|
if (newUsername === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,18 @@ import React from 'react';
|
|||||||
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
import {defineMessages, injectIntl, intlShape} from 'react-intl';
|
||||||
import {connect} from 'react-redux';
|
import {connect} from 'react-redux';
|
||||||
import {setCloud} from '../reducers/tw';
|
import {setCloud} from '../reducers/tw';
|
||||||
|
import {isScratchDesktop} from '../lib/isScratchDesktop';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
cloudUnavailableAlert: {
|
cloudUnavailableAlert: {
|
||||||
defaultMessage: 'Cannot use cloud variables, most likely because you opened the editor.',
|
defaultMessage: 'Cannot use cloud variables, most likely because you opened the editor.',
|
||||||
description: 'Message displayed when clicking on the option to toggle cloud variables when cloud variables are not available',
|
description: 'Message displayed when clicking on the option to toggle cloud variables when cloud variables are not available',
|
||||||
id: 'tw.menuBar.cloudUnavailableAlert'
|
id: 'tw.menuBar.cloudUnavailableAlert'
|
||||||
|
},
|
||||||
|
offlineEditorAlert: {
|
||||||
|
defaultMessage: 'Cannot use cloud variables in offline editor.',
|
||||||
|
description: 'Message displayed when clicking on the option to toggle cloud variables in offline editor',
|
||||||
|
id: 'tw.menuBar.cloudUnavailableOfflineEditorAlert'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -23,7 +29,7 @@ class CloudVariablesToggler extends React.Component {
|
|||||||
toggleCloudVariables () {
|
toggleCloudVariables () {
|
||||||
if (!this.props.canUseCloudVariables) {
|
if (!this.props.canUseCloudVariables) {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
alert(this.props.intl.formatMessage(messages.cloudUnavailableAlert));
|
alert(this.props.intl.formatMessage(isScratchDesktop() ? messages.offlineEditorAlert : messages.cloudUnavailableAlert));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.props.onCloudChange(!this.props.enabled);
|
this.props.onCloudChange(!this.props.enabled);
|
||||||
|
|||||||
@@ -20,10 +20,10 @@ class FramerateChanger extends React.Component {
|
|||||||
'changeFramerate'
|
'changeFramerate'
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
changeFramerate (e) {
|
async changeFramerate (e) {
|
||||||
if (e && (e.ctrlKey || e.shiftKey)) {
|
if (e && (e.ctrlKey || e.shiftKey)) {
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
const newFPS = prompt(this.props.intl.formatMessage(messages.newFramerate), this.props.framerate);
|
const newFPS = await prompt(this.props.intl.formatMessage(messages.newFramerate), this.props.framerate);
|
||||||
if (newFPS === null) {
|
if (newFPS === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* Utility functions for handling tutorial images in multiple languages
|
* Utility functions for handling tutorial images in multiple languages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {enImages as defaultImages} from './en-steps.js';
|
const defaultImages = {};
|
||||||
|
|
||||||
let savedImages = {};
|
let savedImages = {};
|
||||||
let savedLocale = '';
|
let savedLocale = '';
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
|||||||
if (typeof window === 'object') {
|
if (typeof window === 'object') {
|
||||||
// Note: it might be better to use a listener instead of assigning onbeforeunload;
|
// Note: it might be better to use a listener instead of assigning onbeforeunload;
|
||||||
// but then it'd be hard to turn this listening off in our tests
|
// but then it'd be hard to turn this listening off in our tests
|
||||||
window.onbeforeunload = e => this.leavePageConfirm(e);
|
// window.onbeforeunload = e => this.leavePageConfirm(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow the GUI consumer to pass in a function to receive a trigger
|
// Allow the GUI consumer to pass in a function to receive a trigger
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const TWEditorWarningHOC = function (WrappedComponent) {
|
|||||||
if (!this.props.isPlayerOnly) {
|
if (!this.props.isPlayerOnly) {
|
||||||
shownWarning = true;
|
shownWarning = true;
|
||||||
|
|
||||||
this.props.onShowWarning();
|
// this.props.onShowWarning();
|
||||||
this.props.vm.setCompilerOptions({
|
this.props.vm.setCompilerOptions({
|
||||||
warpTimer: true
|
warpTimer: true
|
||||||
});
|
});
|
||||||
|
|||||||
+3
-3
@@ -41,8 +41,8 @@ const base = {
|
|||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
library: 'GUI',
|
library: 'GUI',
|
||||||
filename: process.env.NODE_ENV === 'production' ? 'js/[name].[contenthash].js' : 'js/[name].js',
|
filename: process.env.NODE_ENV === 'production' ? 'js/[name].js' : 'js/[name].js',
|
||||||
chunkFilename: process.env.NODE_ENV === 'production' ? 'js/[name].[contenthash].js' : 'js/[name].js',
|
chunkFilename: process.env.NODE_ENV === 'production' ? 'js/[name].js' : 'js/[name].js',
|
||||||
publicPath: root
|
publicPath: root
|
||||||
},
|
},
|
||||||
externals: {
|
externals: {
|
||||||
@@ -220,7 +220,7 @@ module.exports = [
|
|||||||
output: {
|
output: {
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
path: path.resolve('dist'),
|
path: path.resolve('dist'),
|
||||||
publicPath: `${STATIC_PATH}/`
|
// publicPath: `${STATIC_PATH}/`
|
||||||
},
|
},
|
||||||
externals: {
|
externals: {
|
||||||
React: 'react',
|
React: 'react',
|
||||||
|
|||||||
Reference in new issue
Block a user