123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import React, { Component } from 'react';
- import '../css/CoverGridItem.scss'
- import LibraryIndicator from './LibraryIndicator'
- import Loader from '../assets/loading-dots2.png'
- import { connect } from 'react-redux'
- import PropTypes from 'prop-types'
- import { loadDetailsFromFile, loadDetailsFromKey } from '../actions/detailsActions'
- import { setScrollTop } from '../actions/songListActions'
- const getColors = window.require('get-image-colors')
- function Difficulties(props) {
- let difficulties = props.difficulties
- if (!difficulties) return null
- let badges = []
- if(difficulties.easy) {
- badges.push({
- text: 'Easy',
- backgroundColor: 'teal',
- color: 'white'
- })
- }
- if(difficulties.normal) {
- badges.push({
- text: 'Normal',
- backgroundColor: 'green',
- color: 'white'
- })
- }
- if(difficulties.hard) {
- badges.push({
- text: 'Hard',
- backgroundColor: 'orange',
- color: 'white'
- })
- }
- if(difficulties.expert) {
- badges.push({
- text: 'Expert',
- backgroundColor: 'darkred',
- color: 'white'
- })
- }
- if(difficulties.expertPlus) {
- badges.push({
- text: 'Expert+',
- backgroundColor: 'purple',
- color: 'white'
- })
- }
- return badges.map((badge, i) => {
- return <div key={ i } className='dot' title={ badge.text } style={ { backgroundColor: badge.backgroundColor, border: `1px solid ${props.textColor}` } }></div>
- })
- }
- function VoteRatio(props){
- var total = props.up + props.down;
- if(props.up > props.down){
- return <span>👍{(props.up / total * 100).toFixed(1) }/<CompactNumber value={ props.up + props.down }/></span>
- }else if (props.up < props.down){
- return <span>👎{(props.down / total * 100).toFixed(1)}/<CompactNumber value={ props.up + props.down }/></span>
- }else{
- return <span></span>
- }
- }
- function CompactNumber(props){
- var num = props.value, uni = 0;
- if( num >= 100 && num < 1000) return <span>{(num / 100).toFixed(0)}H</span>
- if( num >= 1000 && num < 10000) return <span>{(num / 1000).toFixed(0)}K</span>
- if( num >= 10000 && num < 1000000) return <span>{(num / 10000).toFixed(0)}万</span>
- if( num >= 1000000 && num < 10000000) return <span>{(num / 1000000).toFixed(0)}M</span>
- return <span>{num}</span>
- }
- class CoverGridItem extends Component {
- constructor() {
- super()
- this.state = {
- bgc: 'rgba(128, 128, 128)',
- textColor: 'black'
- }
- }
- componentWillReceiveProps(props) {
- getColors(this.props.imageSource.startsWith('file://') ? this.props.imageSource.substring(7, this.props.imageSource.length) : `https://beatsaver.com/${ this.props.imageSource }`)
- .then(colors => {
- this.setState({
- bgc: `rgb(${colors[0].rgb()[0]},${colors[0].rgb()[1]},${colors[0].rgb()[2]})`,
- textColor: (colors[0].rgb()[0] * 0.299 + colors[0].rgb()[1] * 0.587 + colors[0].rgb()[2] * 0.114) > 186 ? 'black' : 'white'
- })
- })
- .catch(() => {})
- }
- componentDidMount() {
- console.log( encodeURI(this.props.imageSource) )
- if(!this.props.imageSource) return
- getColors(this.props.imageSource.startsWith('file://') ? this.props.imageSource.substring(7, this.props.imageSource.length) : `https://beatsaver.com/${ this.props.imageSource }`)
- .then(colors => {
- this.setState({
- bgc: `rgb(${colors[0].rgb()[0]},${colors[0].rgb()[1]},${colors[0].rgb()[2]})`,
- textColor: (colors[0].rgb()[0] * 0.299 + colors[0].rgb()[1] * 0.587 + colors[0].rgb()[2] * 0.114) > 186 ? 'black' : 'white'
- })
- })
- .catch(() => {})
- }
- render() {
- if(this.props.loading) {
- return (
- <div className="cover-grid-item loading">
- <img className="cover-image" src={ Loader } alt={ this.props.key } />
- </div>
- )
- } else {
- return (
- <div key={ this.props.key } className='cover-grid-item' onClick={ () => { this.props.setScrollTop(document.getElementById('cover-grid-container').scrollTop); if(this.props.file) { this.props.loadDetailsFromFile(this.props.file) } else { this.props.loadDetailsFromKey(this.props.songKey) } } }>
- <img className="cover-image" src={ this.props.imageSource.startsWith('file://') ? this.props.imageSource : `https://beatsaver.com${ this.props.imageSource }` } alt=""/>
- {(!!this.props.file || this.props.downloadedSongs.some(dsong => dsong.hash === this.props.hash)) ? <LibraryIndicator /> : null}
- <div style={ { backgroundColor: this.state.bgc, color: this.state.textColor } } className="cover-grid-info-tab">
- <div className="cover-grid-title">{this.props.title}</div>
- <div className="cover-grid-artist">{this.props.artist}</div>
- <div>
- {/* 👍{ this.props.upvotes } 👎{ this.props.downvotes } */}
- <VoteRatio up={ this.props.upvotes } down={ this.props.downvotes } />
- 🏁{ ( 100 * this.props.plays / this.props.downloads).toFixed(1) }/<CompactNumber value={ this.props.downloads }/>
- </div>
- <div className="dots">
- <Difficulties difficulties={ this.props.difficulties } textColor={ this.state.textColor } />
- </div>
- </div>
- </div>
- )
- }
- }
- }
- CoverGridItem.propTypes = ({
- loadDetailsFromFile: PropTypes.func.isRequired,
- loadDetailsFromKey: PropTypes.func.isRequired
- })
- let mapStateToProps = state => ({
- downloadedSongs: state.songs.downloadedSongs
- })
- export default connect(mapStateToProps, { loadDetailsFromFile, loadDetailsFromKey, setScrollTop })(CoverGridItem)
|