webamp/js/Marquee.jsx
Jordan Eldredge 2a02123890 Move marquee to offset by pixels
In anticipation of supporting the ability to drag the marquee contents, we're
moving to offsetting by pixels rather than actually modifying the text.
2016-07-28 17:54:36 -07:00

120 lines
3.1 KiB
JavaScript

// Single line text display that can animate and hold multiple registers
import React from 'react';
import {connect} from 'react-redux';
import {getTimeStr} from './utils';
const getBalanceText = (balance) => {
if (balance === 0) {
return 'Balance: Center';
}
const direction = balance > 0 ? 'Right' : 'Left';
return `Balance: ${Math.abs(balance)}% ${direction}`;
};
const getVolumeText = (volume) => `Volume: ${volume}%`;
const getPositionText = (duration, seekToPercent) => {
const newElapsedStr = getTimeStr(duration * seekToPercent / 100);
const durationStr = getTimeStr(duration);
return `Seek to: ${newElapsedStr}/${durationStr} (${seekToPercent}%)`;
};
const getMediaText = (name, duration) => {
return `${name} (${getTimeStr(duration)}) *** `;
};
const getDoubleSizeModeText = (enabled) => {
return `${enabled ? 'Disable' : 'Enable'} doublesize mode`;
};
const isLong = (text) => text.length > 30;
// Given text and step, how many pixels should it be shifted?
const stepOffset = (text, step) => {
if (!isLong(text)) {
return 0;
}
return (step % text.length) * 5;
};
// Format an int as negative pixels
const negativePixels = (pixels) => `-${pixels}px`;
// If text is wider than the marquee, it needs to loop
const loopText = (text) => isLong(text) ? text + text : text;
import CharacterString from './CharacterString.jsx';
class Marquee extends React.Component {
constructor(props) {
super(props);
this.state = {stepping: true};
this.handleMouseDown = this.handleMouseDown.bind(this);
this.getText = this.getText.bind(this);
}
componentDidMount() {
const step = () => {
setTimeout(() => {
if (this.state.stepping) {
this.props.dispatch({type: 'STEP_MARQUEE'});
}
step();
}, 220);
};
step();
}
getText() {
switch (this.props.userInput.focus) {
case 'balance':
return getBalanceText(this.props.media.balance);
case 'volume':
return getVolumeText(this.props.media.volume);
case 'position':
return getPositionText(this.props.media.length, this.props.userInput.scrubPosition);
case 'double':
return getDoubleSizeModeText(this.props.display.doubled);
default:
break;
}
if (this.props.media.name) {
return getMediaText(this.props.media.name, this.props.media.length);
}
return 'Winamp 2.91';
}
handleMouseDown() {
this.setState({stepping: false});
document.addEventListener('mouseup', () => {
// TODO: Remove this listener
setTimeout(() => {
this.setState({stepping: true});
}, 1000);
});
}
render() {
const text = this.getText();
const offset = stepOffset(text, this.props.display.marqueeStep);
return <div id='marquee' className='text' onMouseDown={this.handleMouseDown}>
<CharacterString style={{marginLeft: negativePixels(offset)}} >
{loopText(text)}
</CharacterString>
</div>;
}
}
export {
getBalanceText,
getVolumeText,
getPositionText,
getMediaText,
getDoubleSizeModeText,
negativePixels,
stepOffset,
loopText,
Marquee
};
export default connect(state => state)(Marquee);