Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions packages/scratch-gui/src/components/gui/gui.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import TelemetryModal from '../telemetry-modal/telemetry-modal.jsx';

import layout, {STAGE_SIZE_MODES} from '../../lib/layout-constants';
import {resolveStageSize} from '../../lib/screen-utils';
import {themeMap} from '../../lib/themes';
import {colorModeMap} from '../../lib/settings/color-mode/index.js';
import {AccountMenuOptionsPropTypes} from '../../lib/account-menu-options';

import styles from './gui.css';
Expand Down Expand Up @@ -67,6 +67,7 @@ const GUIComponent = props => {
blocksTabVisible,
cardsVisible,
canChangeLanguage,
canChangeColorMode,
canChangeTheme,
canCreateNew,
canEditTitle,
Expand Down Expand Up @@ -129,6 +130,7 @@ const GUIComponent = props => {
stageSizeMode,
targetIsStage,
telemetryModalVisible,
colorMode,
theme,
tipsLibraryVisible,
useExternalPeripheralList,
Expand Down Expand Up @@ -258,6 +260,7 @@ const GUIComponent = props => {
authorThumbnailUrl={authorThumbnailUrl}
authorUsername={authorUsername}
canChangeLanguage={canChangeLanguage}
canChangeColorMode={canChangeColorMode}
canChangeTheme={canChangeTheme}
canCreateCopy={canCreateCopy}
canCreateNew={canCreateNew}
Expand Down Expand Up @@ -362,15 +365,15 @@ const GUIComponent = props => {
<TabPanel className={tabClassNames.tabPanel}>
<Box className={styles.blocksWrapper}>
<Blocks
key={`${blocksId}/${theme}`}
key={`${blocksId}/${colorMode}/${theme}`}
canUseCloud={canUseCloud}
grow={1}
isVisible={blocksTabVisible}
options={{
media: `${basePath}static/${themeMap[theme].blocksMediaFolder}/`
media: `${basePath}static/${colorModeMap[colorMode].blocksMediaFolder}/`
}}
stageSize={stageSize}
theme={theme}
colorMode={colorMode}
vm={vm}
showNewFeatureCallouts={showNewFeatureCallouts}
username={username}
Expand Down Expand Up @@ -442,6 +445,7 @@ GUIComponent.propTypes = {
blocksTabVisible: PropTypes.bool,
blocksId: PropTypes.string,
canChangeLanguage: PropTypes.bool,
canChangeColorMode: PropTypes.bool,
canChangeTheme: PropTypes.bool,
canCreateCopy: PropTypes.bool,
canCreateNew: PropTypes.bool,
Expand Down Expand Up @@ -503,6 +507,7 @@ GUIComponent.propTypes = {
setPlatform: PropTypes.func,
targetIsStage: PropTypes.bool,
telemetryModalVisible: PropTypes.bool,
colorMode: PropTypes.string,
theme: PropTypes.string,
tipsLibraryVisible: PropTypes.bool,
useExternalPeripheralList: PropTypes.bool, // true for CDM, false for normal Scratch Link
Expand All @@ -518,6 +523,8 @@ GUIComponent.defaultProps = {
basePath: './',
blocksId: 'original',
canChangeLanguage: true,
canChangeColorMode: true,
// TODO: Make this depend on membership status
canChangeTheme: true,
canCreateNew: false,
canEditTitle: false,
Expand All @@ -543,7 +550,8 @@ const mapStateToProps = state => ({
// This is the button's mode, as opposed to the actual current state
blocksId: state.scratchGui.timeTravel.year.toString(),
stageSizeMode: state.scratchGui.stageSize.stageSize,
theme: state.scratchGui.theme.theme
colorMode: state.scratchGui.settings.colorMode,
theme: state.scratchGui.settings.theme
});

const mapDispatchToProps = dispatch => ({
Expand Down
5 changes: 4 additions & 1 deletion packages/scratch-gui/src/components/menu-bar/menu-bar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,10 @@ class MenuBar extends React.Component {
onClick={this.props.onClickLogo}
/>
</div>
{(this.props.canChangeTheme || this.props.canChangeLanguage) && (<SettingsMenu
{(this.props.canChangeColorMode || this.props.canChangeLanguage || this.props.canChangeTheme) &&
(<SettingsMenu
canChangeLanguage={this.props.canChangeLanguage}
canChangeColorMode={this.props.canChangeColorMode}
canChangeTheme={this.props.canChangeTheme}
isRtl={this.props.isRtl}
onRequestClose={this.props.onRequestCloseSettings}
Expand Down Expand Up @@ -901,6 +903,7 @@ MenuBar.propTypes = {
authorUsername: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
autoUpdateProject: PropTypes.func,
canChangeLanguage: PropTypes.bool,
canChangeColorMode: PropTypes.bool,
canChangeTheme: PropTypes.bool,
canCreateCopy: PropTypes.bool,
canCreateNew: PropTypes.bool,
Expand Down
114 changes: 114 additions & 0 deletions packages/scratch-gui/src/components/menu-bar/preference-menu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React, {useState, useMemo, useCallback} from 'react';
import {FormattedMessage} from 'react-intl';
import {connect} from 'react-redux';

import check from './check.svg';
import {MenuItem, Submenu} from '../menu/menu.jsx';

import styles from './settings-menu.css';

import dropdownCaret from './dropdown-caret.svg';

const intlMessageShape = PropTypes.shape({
defaultMessage: PropTypes.string,
description: PropTypes.string,
id: PropTypes.string
});

const PreferenceItem = props => {
const item = props.item;

return (
<MenuItem onClick={props.onClick}>
<div className={styles.option}>
<img
className={classNames(styles.check, {[styles.selected]: props.isSelected})}
src={check}
/>
{item.icon && <img
className={styles.icon}
src={item.icon}
/>}
<FormattedMessage {...item.label} />
</div>
</MenuItem>);
};

PreferenceItem.propTypes = {
isSelected: PropTypes.bool,
onClick: PropTypes.func,
item: PropTypes.shape({
icon: PropTypes.string,
label: intlMessageShape.isRequired
})
};

const PreferenceMenu = ({
itemsMap,
onChange,
defaultMenuIconSrc,
submenuLabel,
selectedItemKey,
isRtl
}) => {
const [isOpen, setIsOpen] = useState(false);
const itemKeys = useMemo(() => Object.keys(itemsMap), [itemsMap]);
const selectedItem = useMemo(() => itemsMap[selectedItemKey], [itemsMap, selectedItemKey]);
const onClick = useCallback(() => {
setIsOpen(!isOpen);
}, [isOpen]);
return (
<MenuItem expanded={isOpen}>
<div
className={styles.option}
onClick={onClick}
>
<img
src={selectedItem.icon || defaultMenuIconSrc}
style={{width: 24}}
/>
<span className={styles.submenuLabel}>
<FormattedMessage {...submenuLabel} />
</span>
<img
className={styles.expandCaret}
src={dropdownCaret}
/>
</div>
<Submenu place={isRtl ? 'left' : 'right'}>
{itemKeys.map(itemKey => (
<PreferenceItem
key={itemKey}
isSelected={itemKey === selectedItemKey}
// eslint-disable-next-line react/jsx-no-bind
onClick={() => onChange(itemKey)}
item={itemsMap[itemKey]}
/>)
)}
</Submenu>
</MenuItem>
);
};

PreferenceMenu.propTypes = {
itemsMap: PropTypes.objectOf(PropTypes.shape({
icon: PropTypes.string,
label: intlMessageShape.isRequired
})).isRequired,
onChange: PropTypes.func,
defaultMenuIconSrc: PropTypes.string,
submenuLabel: intlMessageShape.isRequired,
selectedItemKey: PropTypes.string,
isRtl: PropTypes.bool,
onRequestCloseSettings: PropTypes.func
};

const mapStateToProps = state => ({
isRtl: state.locales.isRtl
});

export default connect(
mapStateToProps
)(PreferenceMenu);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
width: 1.5rem;
}

.theme-label {
/* Unused? */
.color-mode-label {
flex: 1;
}

Expand Down
Loading
Loading