diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index e7964657874..dd30c9beced 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; -import {connect} from 'react-redux'; -import {compose} from 'redux'; -import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl'; +import { connect } from 'react-redux'; +import { compose } from 'redux'; +import { defineMessages, FormattedMessage, injectIntl, intlShape } from 'react-intl'; import PropTypes from 'prop-types'; import bindAll from 'lodash.bindall'; import bowser from 'bowser'; @@ -13,12 +13,12 @@ import Box from '../box/box.jsx'; import Button from '../button/button.jsx'; import CommunityButton from './community-button.jsx'; import ShareButton from './share-button.jsx'; -import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx'; +import { ComingSoonTooltip } from '../coming-soon/coming-soon.jsx'; import Divider from '../divider/divider.jsx'; import LanguageSelector from '../../containers/language-selector.jsx'; import ProjectWatcher from '../../containers/project-watcher.jsx'; import MenuBarMenu from './menu-bar-menu.jsx'; -import {MenuItem, MenuSection} from '../menu/menu.jsx'; +import { MenuItem, MenuSection } from '../menu/menu.jsx'; import ProjectTitleInput from './project-title-input.jsx'; import AuthorInfo from './author-info.jsx'; import SB3Downloader from '../../containers/sb3-downloader.jsx'; @@ -29,11 +29,10 @@ import MenuBarHOC from '../../containers/menu-bar-hoc.jsx'; import FramerateChanger from '../../containers/tw-framerate-changer.jsx'; import ChangeUsername from '../../containers/tw-change-username.jsx'; import CloudVariablesToggler from '../../containers/tw-cloud-toggler.jsx'; -import TWRestorePointLoader from '../../containers/tw-restore-point-loader.jsx'; import TWSaveStatus from './tw-save-status.jsx'; -import {openTipsLibrary, openSettingsModal} from '../../reducers/modals'; -import {setPlayer} from '../../reducers/mode'; +import { openTipsLibrary, openSettingsModal, openRestorePointModal } from '../../reducers/modals'; +import { setPlayer } from '../../reducers/mode'; import { autoUpdateProject, getIsUpdating, @@ -66,7 +65,7 @@ import { closeLoginMenu, loginMenuOpen } from '../../reducers/menus'; -import {setFileHandle} from '../../reducers/tw.js'; +import { setFileHandle } from '../../reducers/tw.js'; import collectMetadata from '../../lib/collect-metadata'; @@ -84,6 +83,7 @@ import scratchLogo from './scratch-logo.svg'; import sharedMessages from '../../lib/shared-messages'; import SeeInsideButton from './tw-see-inside.jsx'; +import { notScratchDesktop } from '../../lib/isScratchDesktop.js'; const ariaMessages = defineMessages({ language: { @@ -141,7 +141,7 @@ MenuBarItemTooltip.propTypes = { place: PropTypes.oneOf(['top', 'bottom', 'left', 'right']) }; -const MenuItemTooltip = ({id, isRtl, children, className}) => ( +const MenuItemTooltip = ({ id, isRtl, children, className }) => ( { restoreFun(); this.props.onRequestCloseEdit(); }; } - handleKeyPress (event) { + handleKeyPress(event) { const modifier = bowser.mac ? event.metaKey : event.ctrlKey; if (modifier && event.key.toLowerCase() === 's') { this.props.handleSaveProject(); event.preventDefault(); } } - getSaveToComputerHandler (downloadProjectCallback) { + getSaveToComputerHandler(downloadProjectCallback) { return () => { this.props.onRequestCloseFile(); downloadProjectCallback(); @@ -292,44 +302,44 @@ class MenuBar extends React.Component { } }; } - handleLanguageMouseUp (e) { + handleLanguageMouseUp(e) { if (!this.props.languageMenuOpen) { this.props.onClickLanguage(e); } } - restoreOptionMessage (deletedItem) { + restoreOptionMessage(deletedItem) { switch (deletedItem) { - case 'Sprite': - return (); - case 'Sound': - return (); - case 'Costume': - return (); - default: { - return (); - } + case 'Sprite': + return (); + case 'Sound': + return (); + case 'Costume': + return (); + default: { + return (); + } } } - handleClickSeeInside () { + handleClickSeeInside() { this.props.onClickSeeInside(); } - buildAboutMenu (onClickAbout) { + buildAboutMenu(onClickAbout) { if (!onClickAbout) { // hide the button return null; @@ -374,13 +384,13 @@ class MenuBar extends React.Component { ); } - wrapAboutMenuCallback (callback) { + wrapAboutMenuCallback(callback) { return () => { callback(); this.props.onRequestCloseAbout(); }; } - render () { + render() { const saveNowMessage = ( - + - + - {this.props.compileErrors.map(({id, sprite, error}) => ( + {this.props.compileErrors.map(({ id, sprite, error }) => ( {this.props.intl.formatMessage(twMessages.compileError, { sprite, @@ -558,6 +568,19 @@ class MenuBar extends React.Component { {newProjectMessage} + {this.props.onClickNewWindow && ( + + + + )} {(this.props.canSave || this.props.canCreateCopy || this.props.canRemix) && ( {this.props.canSave && ( @@ -588,9 +611,11 @@ class MenuBar extends React.Component { {extended.available && ( {extended.name !== null && ( + // eslint-disable-next-line max-len )} + {/* eslint-disable-next-line max-len */} )} - - {extended.available ? ( - - ) : ( - - )} - + {notScratchDesktop() && ( + + {extended.available ? ( + + ) : ( + + )} + + )} )} @@ -641,18 +671,13 @@ class MenuBar extends React.Component { )} - {(className, loadRestorePoint) => ( - - - - )} + + + @@ -677,9 +702,9 @@ class MenuBar extends React.Component { onRequestClose={this.props.onRequestCloseEdit} > {this.props.isPlayerOnly ? null : ( - {(handleRestore, {restorable, deletedItem}) => ( + {(handleRestore, { restorable, deletedItem }) => ( {this.restoreOptionMessage(deletedItem)} @@ -687,7 +712,7 @@ class MenuBar extends React.Component { )} )} - {(toggleTurboMode, {turboMode}) => ( + {(toggleTurboMode, { turboMode }) => ( {turboMode ? ( )} - {(changeFramerate, {framerate}) => ( + {(changeFramerate, { framerate }) => ( {framerate === 60 ? ( )} - {(toggleCloudVariables, {enabled, canUseCloudVariables}) => ( + {(toggleCloudVariables, { enabled, canUseCloudVariables }) => ( {canUseCloudVariables ? ( @@ -762,9 +787,9 @@ class MenuBar extends React.Component { @@ -791,14 +816,24 @@ class MenuBar extends React.Component { >
+ {/* {(this.props.authorUsername && this.props.authorUsername !== this.props.username) ? ( + + ) : null} */} {this.props.canEditTitle ? (
- ) : ((this.props.authorUsername && this.props.authorUsername !== this.props.username) ? ( - - ) : null)} + ) : null}
{this.props.canRemix ? remixButton : []}
@@ -852,9 +878,8 @@ class MenuBar extends React.Component { /> ) : []))} - {/* tw: add a feedback button */}
- {this.props.isShowingProject && this.props.canEditTitle && (!window.location.href.includes('#')) ? + {this.props.isShowingProject && this.props.canEditTitle ? ( - {/* todo: icon */} @@ -943,12 +967,14 @@ MenuBar.propTypes = { onClickAddonSettings: PropTypes.func, onClickTheme: PropTypes.func, onClickPackager: PropTypes.func, + onClickRestorePoints: PropTypes.func, onClickEdit: PropTypes.func, onClickFile: PropTypes.func, onClickLanguage: PropTypes.func, onClickLogin: PropTypes.func, onClickLogo: PropTypes.func, onClickNew: PropTypes.func, + onClickNewWindow: PropTypes.func, onClickRemix: PropTypes.func, onClickSave: PropTypes.func, onClickSaveAsCopy: PropTypes.func, @@ -1041,6 +1067,7 @@ const mapDispatchToProps = dispatch => ({ onClickRemix: () => dispatch(remixProject()), onClickSave: () => dispatch(manualUpdateProject()), onClickSaveAsCopy: () => dispatch(saveProjectAsCopy()), + onClickRestorePoints: () => dispatch(openRestorePointModal()), onClickSettings: () => { dispatch(openSettingsModal()); dispatch(closeEditMenu()); @@ -1055,4 +1082,4 @@ export default compose( mapStateToProps, mapDispatchToProps ) -)(MenuBar); +)(MenuBar); \ No newline at end of file diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx index 38ecccd3b95..bd71852c619 100644 --- a/src/components/stage-header/stage-header.jsx +++ b/src/components/stage-header/stage-header.jsx @@ -52,9 +52,9 @@ const messages = defineMessages({ id: 'gui.stageHeader.fullscreenControl' }, openSettingsMessage: { - defaultMessage: 'Open advanced settings', - description: 'Button to open advanced settings in embeds', - id: 'tw.openAdvanced' + defaultMessage: 'Open gameplay settings', + description: 'Button to open gameplay settings in embeds', + id: 'pm.openGameplay' } }); @@ -260,4 +260,4 @@ StageHeaderComponent.defaultProps = { export default injectIntl(connect( mapStateToProps -)(StageHeaderComponent)); +)(StageHeaderComponent)); \ No newline at end of file diff --git a/src/components/tw-settings-modal/settings-modal.css b/src/components/tw-settings-modal/settings-modal.css index e9188e43d09..f104971a59a 100644 --- a/src/components/tw-settings-modal/settings-modal.css +++ b/src/components/tw-settings-modal/settings-modal.css @@ -54,6 +54,9 @@ flex-direction: row; align-items: center; } +.label-unset-height { + height: initial; +} .setting table { border-collapse: collapse; @@ -84,11 +87,46 @@ background-image: url("./help-white.svg"); } +.custom-stage-size { + display: flex; + flex-direction: column; + align-items: flex-start; + height: initial; +} +.custom-stage-size-container { + display: flex; + align-items: center; +} .custom-stage-size > * { margin-right: 0.5rem; } +.custom-stage-size-button { + margin: 8px; + background: white; + border-radius: 10px; + font-size: 40px; + width: 168px; + height: 126px; + border: 4px solid rgba(0, 0, 0, 0.1); + outline: 4px white solid; +} +[theme="dark"] .custom-stage-size-button { + outline-color: $ui-primary; + background: $ui-primary; + border-color: rgba(255, 255, 255, 0.1); +} +.custom-stage-size-button[data-widescreen="true"] { + width: 224px; +} +.custom-stage-size-button[data-selected="true"] { + border-color: $motion-primary; +} +.custom-stage-size-button:active { + border-color: $motion-transparent; +} .custom-stage-size-input { width: 80px; + margin: 3px 8px; } .info { @@ -133,4 +171,4 @@ } [theme="dark"] .warning { background: rgb(114, 102, 0); -} +} \ No newline at end of file diff --git a/src/components/tw-settings-modal/settings-modal.jsx b/src/components/tw-settings-modal/settings-modal.jsx index ada0215d3c0..76ece8d0b78 100644 --- a/src/components/tw-settings-modal/settings-modal.jsx +++ b/src/components/tw-settings-modal/settings-modal.jsx @@ -17,9 +17,9 @@ const BufferedInput = BufferedInputHOC(Input); const messages = defineMessages({ title: { - defaultMessage: 'Advanced Settings', + defaultMessage: 'Settings', description: 'Title of settings modal', - id: 'tw.settingsModal.title' + id: 'pm.settingsModal.title' }, help: { defaultMessage: 'Click for help', @@ -70,7 +70,9 @@ class UnwrappedSetting extends React.Component { [styles.active]: this.props.active })} > -
+
{this.props.primary} + +
+
+ + + {'×'} + +
)} secondary={ @@ -362,7 +387,8 @@ CustomStageSize.propTypes = { stageWidth: PropTypes.number, onStageWidthChange: PropTypes.func, stageHeight: PropTypes.number, - onStageHeightChange: PropTypes.func + onStageHeightChange: PropTypes.func, + onStagePresetUsed: PropTypes.func }; const StoreProjectOptions = ({ onStoreProjectOptions }) => ( @@ -406,16 +432,21 @@ Header.propTypes = { const SettingsModalComponent = props => ( { + if (!props.isEmbedded) { + props.onStoreProjectOptions(); + } + props.onClose(...args) + }} contentLabel={props.intl.formatMessage(messages.title)} id="settingsModal" >
( value={props.interpolation} onChange={props.onInterpolationChange} /> - {/* - add back: nohqpen - */} ( />
{!props.isEmbedded && ( @@ -469,11 +497,11 @@ const SettingsModalComponent = props => ( {...props} /> )} - {!props.isEmbedded && ( + {/* {!props.isEmbedded && ( - )} + )} */}
); @@ -501,4 +529,4 @@ SettingsModalComponent.propTypes = { onDisableCompilerChange: PropTypes.func }; -export default injectIntl(SettingsModalComponent); +export default injectIntl(SettingsModalComponent); \ No newline at end of file diff --git a/src/containers/tw-settings-modal.jsx b/src/containers/tw-settings-modal.jsx index 8d9bd0a8f52..d84404eea4d 100644 --- a/src/containers/tw-settings-modal.jsx +++ b/src/containers/tw-settings-modal.jsx @@ -21,10 +21,7 @@ class UsernameModal extends React.Component { bindAll(this, [ 'handleFramerateChange', 'handleCustomizeFramerate', - /* - add back: nohqpen 'handleHighQualityPenChange', - */ 'handleInterpolationChange', 'handleInfiniteClonesChange', 'handleRemoveFencingChange', @@ -32,6 +29,7 @@ class UsernameModal extends React.Component { 'handleWarpTimerChange', 'handleStageWidthChange', 'handleStageHeightChange', + 'handleStagePresetUsed', 'handleDisableCompilerChange', 'handleStoreProjectOptions' ]); @@ -39,20 +37,18 @@ class UsernameModal extends React.Component { handleFramerateChange (e) { this.props.vm.setFramerate(e.target.checked ? 60 : 30); } - handleCustomizeFramerate () { + async handleCustomizeFramerate () { + // prompt() returns Promise in desktop app // eslint-disable-next-line no-alert - const newFramerate = prompt(this.props.intl.formatMessage(messages.newFramerate), this.props.framerate); + const newFramerate = await prompt(this.props.intl.formatMessage(messages.newFramerate), this.props.framerate); const parsed = parseFloat(newFramerate); if (isFinite(parsed)) { this.props.vm.setFramerate(parsed); } } - /* - add back: nohqpen handleHighQualityPenChange (e) { this.props.vm.renderer.setUseHighQualityRender(e.target.checked); } - */ handleInterpolationChange (e) { this.props.vm.setInterpolation(e.target.checked); } @@ -87,6 +83,13 @@ class UsernameModal extends React.Component { handleStageHeightChange (value) { this.props.vm.setStageSize(this.props.customStageSize.width, value); } + handleStagePresetUsed (widescreen) { + if (widescreen) { + this.props.vm.setStageSize(640, 360); + return; + } + this.props.vm.setStageSize(480, 360); + } handleStoreProjectOptions () { this.props.vm.storeProjectOptions(); } @@ -111,6 +114,7 @@ class UsernameModal extends React.Component { onWarpTimerChange={this.handleWarpTimerChange} onStageWidthChange={this.handleStageWidthChange} onStageHeightChange={this.handleStageHeightChange} + onStagePresetUsed={this.handleStagePresetUsed} onDisableCompilerChange={this.handleDisableCompilerChange} stageWidth={this.props.customStageSize.width} stageHeight={this.props.customStageSize.height} @@ -175,4 +179,4 @@ const mapDispatchToProps = dispatch => ({ export default injectIntl(connect( mapStateToProps, mapDispatchToProps -)(UsernameModal)); +)(UsernameModal)); \ No newline at end of file diff --git a/src/playground/render-interface.jsx b/src/playground/render-interface.jsx index 87c853842f7..88de875457f 100644 --- a/src/playground/render-interface.jsx +++ b/src/playground/render-interface.jsx @@ -205,13 +205,6 @@ const Footer = () => ( id="tw.examples" /> - - -