import bindAll from 'lodash.bindall'; import PropTypes from 'prop-types'; import React from 'react'; import localforage from 'localforage'; import {injectIntl, intlShape, defineMessages} from 'react-intl'; import LibraryItemComponent from '../components/library-item/library-item.jsx'; class LibraryItem extends React.PureComponent { constructor (props) { super(props); bindAll(this, [ 'handleBlur', 'handleClick', 'handleFavoriteClick', 'handleFocus', 'handleKeyPress', 'handleMouseEnter', 'handleMouseLeave', 'handlePlay', 'handleStop', 'processFavoriteClick', 'handleDeleteClick', 'rotateIcon', 'startRotatingIcons', 'stopRotatingIcons' ]); this.state = { iconIndex: 0, isRotatingIcon: false }; } componentWillUnmount () { clearInterval(this.intervalId); } handleBlur (id) { this.handleMouseLeave(id); } handleClick (e) { if (e.target.dataset && e.target.dataset.clearclick === 'true') { return; } if (e.target.parentElement.dataset && e.target.parentElement.dataset.clearclick === 'true') { return; } if (e.target.closest('a')) { // Allow clicking on links inside the item return; } if (!this.props.disabled) { if (this.props.href) { window.open(this.props.href); } else { this.props.onSelect(this.props.id, e); } } e.preventDefault(); } handleFavoriteClick (...args) { this.processFavoriteClick(...args); } async handleDeleteClick () { const id = this.props._id; const db = "pm:favorited_extensions"; let favorites = []; const _saved = await localforage.getItem(db); if (_saved) { favorites = _saved; } // remove from favorites favorites = favorites.filter(item => { // console.log(item._id, id); return item._id !== id; }); await localforage.setItem(db, favorites); // update on library.jsx this.props.onFavoriteUpdated(); } handleFocus (id) { if (!this.props.showPlayButton) { this.handleMouseEnter(id); } } handleKeyPress (e) { if (e.key === ' ' || e.key === 'Enter') { e.preventDefault(); this.props.onSelect(this.props.id); } } handleMouseEnter () { // only show hover effects on the item if not showing a play button if (!this.props.showPlayButton) { this.props.onMouseEnter(this.props.id); if (this.props.icons && this.props.icons.length) { this.stopRotatingIcons(); this.setState({ isRotatingIcon: true }, this.startRotatingIcons); } } } handleMouseLeave () { // only show hover effects on the item if not showing a play button if (!this.props.showPlayButton) { this.props.onMouseLeave(this.props.id); if (this.props.icons && this.props.icons.length) { this.setState({ isRotatingIcon: false }, this.stopRotatingIcons); } } } handlePlay () { this.props.onMouseEnter(this.props.id); } handleStop () { this.props.onMouseLeave(this.props.id); } async processFavoriteClick (alreadyFavorite) { const id = "pm:favorited_extensions"; let favorites = []; const _saved = await localforage.getItem(id); if (_saved) { favorites = _saved; } if (!alreadyFavorite) { // add to favorites favorites.push(this.props.extensionId); } else { // remove from favorites favorites = favorites.filter(item => { return item !== this.props.extensionId; }); } await localforage.setItem(id, favorites); // update on library.jsx this.props.onFavoriteUpdated(); } startRotatingIcons () { this.rotateIcon(); this.intervalId = setInterval(this.rotateIcon, 300); } stopRotatingIcons () { if (this.intervalId) { this.intervalId = clearInterval(this.intervalId); } } rotateIcon () { const nextIconIndex = (this.state.iconIndex + 1) % this.props.icons.length; this.setState({iconIndex: nextIconIndex}); } curIconMd5 () { const iconMd5Prop = this.props.iconMd5; if (this.props.icons && this.state.isRotatingIcon && this.state.iconIndex < this.props.icons.length) { const icon = this.props.icons[this.state.iconIndex] || {}; return icon.md5ext || // 3.0 library format icon.baseLayerMD5 || // 2.0 library format, TODO GH-5084 iconMd5Prop; } return iconMd5Prop; } render () { const iconMd5 = this.curIconMd5(); const iconURL = iconMd5 ? `https://cdn.assets.scratch.mit.edu/internalapi/asset/${iconMd5}/get/` : this.props.iconRawURL; return (