Spaces:
Runtime error
Runtime error
| import classNames from "classnames"; | |
| import { connect } from "react-redux"; | |
| import { FormattedMessage, injectIntl } from "react-intl"; | |
| import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; | |
| import PropTypes from "prop-types"; | |
| import React from "react"; | |
| import Box from "../box/box.jsx"; | |
| import bindAll from "lodash.bindall"; | |
| import styles from "./gui.css"; | |
| import tabStyles from "react-tabs/style/react-tabs.css"; | |
| import addExtensionIcon from "./icon--extensions.svg"; | |
| import codeIcon from "./icon--code.svg"; | |
| import costumesIcon from "./icon--costumes.svg"; | |
| import soundsIcon from "./icon--sounds.svg"; | |
| import filesIcon from "./icon--files.svg"; | |
| import Blocks from "../../containers/blocks.jsx"; | |
| import CostumeTab from "../../containers/costume-tab.jsx"; | |
| import SoundTab from "../../containers/sound-tab.jsx"; | |
| import FilesTab from "../../containers/files-tab.jsx"; | |
| import Watermark from "../../containers/watermark.jsx"; | |
| const safeJSONParse = (json, defaul, mustBeArray) => { | |
| try { | |
| const parsed = JSON.parse(json); | |
| if (mustBeArray && !Array.isArray(parsed)) throw "Not array"; | |
| return parsed; | |
| } catch { | |
| return defaul; | |
| } | |
| }; | |
| class OrganizedTabs extends React.Component { | |
| constructor(props) { | |
| super(props); | |
| // bindAll(this, [ | |
| // 'handleMessageEvent', | |
| // 'wrapperEventHandler', | |
| // 'onUploadProject' | |
| // ]); | |
| } | |
| componentDidMount() { | |
| window.addEventListener("message", this.wrapperEventHandler); | |
| } | |
| componentWillUnmount() { | |
| window.removeEventListener("message", this.wrapperEventHandler); | |
| } | |
| shouldComponentUpdate(nextProps, nextState) { | |
| return this.props.stageSize !== nextProps.stageSize; | |
| } | |
| render() { | |
| const { | |
| activeTabIndex, | |
| onActivateTab, | |
| targetIsStage, | |
| canUseCloud, | |
| basePath, | |
| stageSize, | |
| vm, | |
| intl, | |
| messages, | |
| isDark, | |
| onActivateCostumesTab, | |
| onActivateSoundsTab, | |
| onExtensionButtonClick, | |
| blocksTabVisible, | |
| costumesTabVisible, | |
| soundsTabVisible, | |
| } = this.props; | |
| const tabClassNames = { | |
| tabs: styles.tabs, | |
| tab: classNames(tabStyles.reactTabsTab, styles.tab), | |
| tabList: classNames(tabStyles.reactTabsTabList, styles.tabList), | |
| tabPanel: classNames(tabStyles.reactTabsTabPanel, styles.tabPanel), | |
| tabPanelSelected: classNames( | |
| tabStyles.reactTabsTabPanelSelected, | |
| styles.isSelected | |
| ), | |
| tabSelected: classNames( | |
| tabStyles.reactTabsTabSelected, | |
| styles.isSelected | |
| ), | |
| }; | |
| const organizedTabs = (() => { | |
| const tabOrderStr = | |
| localStorage.getItem("pm:taborder") || | |
| '["code", "costume", "sound"]'; | |
| const tabOrder = safeJSONParse(tabOrderStr, [], true); | |
| const codeTab = ( | |
| <Tab className={tabClassNames.tab}> | |
| <img draggable={false} src={codeIcon} /> | |
| <FormattedMessage | |
| defaultMessage="Code" | |
| description="Button to get to the code panel" | |
| id="gui.gui.codeTab" | |
| /> | |
| </Tab> | |
| ); | |
| const costumesTab = ( | |
| <Tab | |
| className={tabClassNames.tab} | |
| onClick={onActivateCostumesTab} | |
| > | |
| <img draggable={false} src={costumesIcon} /> | |
| {targetIsStage ? ( | |
| <FormattedMessage | |
| defaultMessage="Backdrops" | |
| description="Button to get to the backdrops panel" | |
| id="gui.gui.backdropsTab" | |
| /> | |
| ) : ( | |
| <FormattedMessage | |
| defaultMessage="Costumes" | |
| description="Button to get to the costumes panel" | |
| id="gui.gui.costumesTab" | |
| /> | |
| )} | |
| </Tab> | |
| ); | |
| const soundsTab = ( | |
| <Tab | |
| className={tabClassNames.tab} | |
| onClick={onActivateSoundsTab} | |
| > | |
| <img draggable={false} src={soundsIcon} /> | |
| <FormattedMessage | |
| defaultMessage="Sounds" | |
| description="Button to get to the sounds panel" | |
| id="gui.gui.soundsTab" | |
| /> | |
| </Tab> | |
| ); | |
| const tabPairs = { | |
| code: codeTab, | |
| costume: costumesTab, | |
| sound: soundsTab, | |
| }; | |
| const enabledTabs = []; | |
| for (const tabId of tabOrder) { | |
| enabledTabs.push(tabPairs[tabId] || codeTab); | |
| } | |
| return enabledTabs; | |
| })(); | |
| return ( | |
| <Tabs | |
| forceRenderTabPanel | |
| className={tabClassNames.tabs} | |
| selectedIndex={activeTabIndex} | |
| selectedTabClassName={tabClassNames.tabSelected} | |
| selectedTabPanelClassName={tabClassNames.tabPanelSelected} | |
| onSelect={onActivateTab} | |
| > | |
| <TabList className={tabClassNames.tabList}> | |
| {organizedTabs} | |
| </TabList> | |
| <TabPanel className={tabClassNames.tabPanel}> | |
| <Box className={styles.blocksWrapper}> | |
| <Blocks | |
| canUseCloud={canUseCloud} | |
| grow={1} | |
| isVisible={blocksTabVisible} | |
| options={{ | |
| media: `${basePath}static/blocks-media/`, | |
| }} | |
| stageSize={stageSize} | |
| vm={vm} | |
| /> | |
| </Box> | |
| <Box className={styles.extensionButtonContainer}> | |
| <button | |
| className={styles.extensionButton} | |
| title={intl.formatMessage(messages.addExtension)} | |
| onClick={onExtensionButtonClick} | |
| > | |
| <img | |
| className={styles.extensionButtonIcon} | |
| draggable={false} | |
| src={addExtensionIcon} | |
| /> | |
| </button> | |
| </Box> | |
| <Box className={styles.watermark}> | |
| <Watermark /> | |
| </Box> | |
| </TabPanel> | |
| <TabPanel className={tabClassNames.tabPanel}> | |
| {costumesTabVisible ? ( | |
| <CostumeTab vm={vm} isDark={isDark} /> | |
| ) : null} | |
| </TabPanel> | |
| <TabPanel className={tabClassNames.tabPanel}> | |
| {soundsTabVisible ? <SoundTab vm={vm} /> : null} | |
| </TabPanel> | |
| </Tabs> | |
| ); | |
| } | |
| } | |
| OrganizedTabs.propTypes = { | |
| activeTabIndex: PropTypes.any, | |
| onActivateTab: PropTypes.any, | |
| targetIsStage: PropTypes.any, | |
| canUseCloud: PropTypes.any, | |
| basePath: PropTypes.any, | |
| stageSize: PropTypes.any, | |
| vm: PropTypes.any, | |
| intl: PropTypes.any, | |
| messages: PropTypes.any, | |
| isDark: PropTypes.any, | |
| onActivateCostumesTab: PropTypes.any, | |
| onActivateSoundsTab: PropTypes.any, | |
| onExtensionButtonClick: PropTypes.any, | |
| blocksTabVisible: PropTypes.any, | |
| costumesTabVisible: PropTypes.any, | |
| soundsTabVisible: PropTypes.any, | |
| }; | |
| export default injectIntl(OrganizedTabs); | |