import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; import { withRouter } from 'react-router'; import { Link } from 'react-router'; import classNames from 'classnames'; import { withTranslation } from 'react-i18next'; import { languageKeyToLabel } from '../i18n'; import * as IDEActions from '../modules/IDE/actions/ide'; import * as toastActions from '../modules/IDE/actions/toast'; import * as projectActions from '../modules/IDE/actions/project'; import { setAllAccessibleOutput, setLanguage } from '../modules/IDE/actions/preferences'; import { logoutUser } from '../modules/User/actions'; import getConfig from '../utils/getConfig'; import { metaKeyName, } from '../utils/metaKey'; import CaretLeftIcon from '../images/left-arrow.svg'; import TriangleIcon from '../images/down-filled-triangle.svg'; import LogoIcon from '../images/p5js-logo-small.svg'; class Nav extends React.PureComponent { constructor(props) { super(props); this.state = { dropdownOpen: 'none' }; this.handleFocus = this.handleFocus.bind(this); this.handleBlur = this.handleBlur.bind(this); this.clearHideTimeout = this.clearHideTimeout.bind(this); this.handleClick = this.handleClick.bind(this); this.handleClickOutside = this.handleClickOutside.bind(this); this.handleSave = this.handleSave.bind(this); this.handleNew = this.handleNew.bind(this); this.handleDuplicate = this.handleDuplicate.bind(this); this.handleShare = this.handleShare.bind(this); this.handleDownload = this.handleDownload.bind(this); this.handleFind = this.handleFind.bind(this); this.handleAddFile = this.handleAddFile.bind(this); this.handleAddFolder = this.handleAddFolder.bind(this); this.handleFindNext = this.handleFindNext.bind(this); this.handleRun = this.handleRun.bind(this); this.handleFindPrevious = this.handleFindPrevious.bind(this); this.handleStop = this.handleStop.bind(this); this.handleStartAccessible = this.handleStartAccessible.bind(this); this.handleStopAccessible = this.handleStopAccessible.bind(this); this.handleKeyboardShortcuts = this.handleKeyboardShortcuts.bind(this); this.handleLogout = this.handleLogout.bind(this); this.toggleDropdownForFile = this.toggleDropdown.bind(this, 'file'); this.handleFocusForFile = this.handleFocus.bind(this, 'file'); this.setDropdownForNone = this.setDropdown.bind(this, 'none'); this.toggleDropdownForEdit = this.toggleDropdown.bind(this, 'edit'); this.handleFocusForEdit = this.handleFocus.bind(this, 'edit'); this.toggleDropdownForSketch = this.toggleDropdown.bind(this, 'sketch'); this.handleFocusForSketch = this.handleFocus.bind(this, 'sketch'); this.toggleDropdownForHelp = this.toggleDropdown.bind(this, 'help'); this.handleFocusForHelp = this.handleFocus.bind(this, 'help'); this.toggleDropdownForAccount = this.toggleDropdown.bind(this, 'account'); this.handleFocusForAccount = this.handleFocus.bind(this, 'account'); this.toggleDropdownForLang = this.toggleDropdown.bind(this, 'lang'); this.handleFocusForLang = this.handleFocus.bind(this, 'lang'); this.handleLangSelection = this.handleLangSelection.bind(this); this.closeDropDown = this.closeDropDown.bind(this); } componentDidMount() { document.addEventListener('mousedown', this.handleClick, false); document.addEventListener('keydown', this.closeDropDown, false); } componentWillUnmount() { document.removeEventListener('mousedown', this.handleClick, false); document.removeEventListener('keydown', this.closeDropDown, false); } setDropdown(dropdown) { this.setState({ dropdownOpen: dropdown }); } closeDropDown(e) { if (e.keyCode === 27) { this.setDropdown('none'); } } handleClick(e) { if (!this.node) { return; } if (this.node && this.node.contains(e.target)) { return; } this.handleClickOutside(); } handleNew() { const { unsavedChanges, warnIfUnsavedChanges } = this.props; if (!unsavedChanges) { this.props.showToast(1500); this.props.setToastText('Toast.OpenedNewSketch'); this.props.newProject(); } else if (warnIfUnsavedChanges && warnIfUnsavedChanges()) { this.props.showToast(1500); this.props.setToastText('Toast.OpenedNewSketch'); this.props.newProject(); } this.setDropdown('none'); } handleSave() { if (this.props.user.authenticated) { this.props.saveProject(this.props.cmController.getContent()); } else { this.props.showErrorModal('forceAuthentication'); } this.setDropdown('none'); } handleFind() { this.props.cmController.showFind(); this.setDropdown('none'); } handleFindNext() { this.props.cmController.findNext(); this.setDropdown('none'); } handleFindPrevious() { this.props.cmController.findPrev(); this.setDropdown('none'); } handleAddFile() { this.props.newFile(this.props.rootFile.id); this.setDropdown('none'); } handleAddFolder() { this.props.newFolder(this.props.rootFile.id); this.setDropdown('none'); } handleRun() { this.props.startSketch(); this.setDropdown('none'); } handleStop() { this.props.stopSketch(); this.setDropdown('none'); } handleStartAccessible() { this.props.setAllAccessibleOutput(true); this.setDropdown('none'); } handleStopAccessible() { this.props.setAllAccessibleOutput(false); this.setDropdown('none'); } handleKeyboardShortcuts() { this.props.showKeyboardShortcutModal(); this.setDropdown('none'); } handleLangSelection(event) { this.props.setLanguage(event.target.value); this.props.showToast(1500); this.props.setToastText('Toast.LangChange'); this.setDropdown('none'); } handleLogout() { this.props.logoutUser(); this.setDropdown('none'); } handleDownload() { this.props.autosaveProject(); projectActions.exportProjectAsZip(this.props.project.id); this.setDropdown('none'); } handleDuplicate() { this.props.cloneProject(); this.setDropdown('none'); } handleShare() { const { username } = this.props.params; this.props.showShareModal(this.props.project.id, this.props.project.name, username); this.setDropdown('none'); } handleClickOutside() { this.setState({ dropdownOpen: 'none' }); } toggleDropdown(dropdown) { if (this.state.dropdownOpen === 'none') { this.setState({ dropdownOpen: dropdown }); } else { this.setState({ dropdownOpen: 'none' }); } } isUserOwner() { return this.props.project.owner && this.props.project.owner.id === this.props.user.id; } handleFocus(dropdown) { this.clearHideTimeout(); this.setDropdown(dropdown); } clearHideTimeout() { if (this.timer) { clearTimeout(this.timer); this.timer = null; } } handleBlur() { this.timer = setTimeout(this.setDropdown.bind(this, 'none'), 10); } renderDashboardMenu(navDropdownState) { return (