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 InlineSVG from 'react-inlinesvg'; import classNames from 'classnames'; import * as IDEActions from '../modules/IDE/actions/ide'; import * as projectActions from '../modules/IDE/actions/project'; import { setAllAccessibleOutput } from '../modules/IDE/actions/preferences'; import { logoutUser } from '../modules/User/actions'; import { metaKeyName, } from '../utils/metaKey'; const triangleUrl = require('../images/down-filled-triangle.svg'); const logoUrl = require('../images/p5js-logo-small.svg'); const __process = (typeof global !== 'undefined' ? global : window).process; 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.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() { if (!this.props.unsavedChanges) { this.props.newProject(); } else if (this.props.warnIfUnsavedChanges()) { 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.setDropdown('none'); } handleAddFolder() { this.props.newFolder(); 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'); } handleLogout() { this.props.logoutUser(); this.setDropdown('none'); } handleDownload() { this.props.autosaveProject(); this.props.exportProjectAsZip(this.props.project.id); this.setDropdown('none'); } handleDuplicate() { this.props.cloneProject(); this.setDropdown('none'); } handleShare() { this.props.showShareModal(); 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 (