Add progress effect to playback waveform
This commit is contained in:
parent
c2d37af1cb
commit
c4d85c457b
5 changed files with 38 additions and 4 deletions
|
@ -36,7 +36,13 @@ limitations under the License.
|
||||||
height: 28px; // default is 30px, so we're subtracting the 2px border off the bars
|
height: 28px; // default is 30px, so we're subtracting the 2px border off the bars
|
||||||
|
|
||||||
.mx_Waveform_bar {
|
.mx_Waveform_bar {
|
||||||
background-color: $voice-record-waveform-fg-color;
|
background-color: $voice-record-waveform-incomplete-fg-color;
|
||||||
|
|
||||||
|
&.mx_Waveform_bar_100pct {
|
||||||
|
// Small animation to remove the mechanical feel of progress
|
||||||
|
transition: background-color 250ms ease;
|
||||||
|
background-color: $voice-record-waveform-fg-color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -196,6 +196,7 @@ $voice-record-stop-border-color: #E3E8F0;
|
||||||
$voice-record-stop-symbol-color: #ff4b55;
|
$voice-record-stop-symbol-color: #ff4b55;
|
||||||
$voice-record-waveform-bg-color: #E3E8F0;
|
$voice-record-waveform-bg-color: #E3E8F0;
|
||||||
$voice-record-waveform-fg-color: $muted-fg-color;
|
$voice-record-waveform-fg-color: $muted-fg-color;
|
||||||
|
$voice-record-waveform-incomplete-fg-color: #C1C6CD;
|
||||||
$voice-record-live-circle-color: #ff4b55;
|
$voice-record-live-circle-color: #ff4b55;
|
||||||
|
|
||||||
$roomtile-preview-color: #9e9e9e;
|
$roomtile-preview-color: #9e9e9e;
|
||||||
|
|
|
@ -186,6 +186,7 @@ $voice-record-stop-border-color: #E3E8F0;
|
||||||
$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes
|
$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes
|
||||||
$voice-record-waveform-bg-color: #E3E8F0;
|
$voice-record-waveform-bg-color: #E3E8F0;
|
||||||
$voice-record-waveform-fg-color: $muted-fg-color;
|
$voice-record-waveform-fg-color: $muted-fg-color;
|
||||||
|
$voice-record-waveform-incomplete-fg-color: #C1C6CD;
|
||||||
$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes
|
$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes
|
||||||
|
|
||||||
$roomtile-preview-color: $secondary-fg-color;
|
$roomtile-preview-color: $secondary-fg-color;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
import {arraySeed, arrayTrimFill} from "../../../utils/arrays";
|
import {arraySeed, arrayTrimFill} from "../../../utils/arrays";
|
||||||
import Waveform from "./Waveform";
|
import Waveform from "./Waveform";
|
||||||
import {Playback, PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback";
|
import {Playback, PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback";
|
||||||
|
import {percentageOf} from "../../../utils/numbers";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
playback: Playback;
|
playback: Playback;
|
||||||
|
@ -26,6 +27,7 @@ interface IProps {
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
heights: number[];
|
heights: number[];
|
||||||
|
progress: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,9 +38,13 @@ export default class PlaybackWaveform extends React.PureComponent<IProps, IState
|
||||||
public constructor(props) {
|
public constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {heights: this.toHeights(this.props.playback.waveform)};
|
this.state = {
|
||||||
|
heights: this.toHeights(this.props.playback.waveform),
|
||||||
|
progress: 0, // default no progress
|
||||||
|
};
|
||||||
|
|
||||||
this.props.playback.waveformData.onUpdate(this.onWaveformUpdate);
|
this.props.playback.waveformData.onUpdate(this.onWaveformUpdate);
|
||||||
|
this.props.playback.clockInfo.liveData.onUpdate(this.onTimeUpdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private toHeights(waveform: number[]) {
|
private toHeights(waveform: number[]) {
|
||||||
|
@ -50,7 +56,12 @@ export default class PlaybackWaveform extends React.PureComponent<IProps, IState
|
||||||
this.setState({heights: this.toHeights(waveform)});
|
this.setState({heights: this.toHeights(waveform)});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private onTimeUpdate = (time: number[]) => {
|
||||||
|
const progress = percentageOf(time[0], 0, time[1]);
|
||||||
|
this.setState({progress});
|
||||||
|
};
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
return <Waveform relHeights={this.state.heights} />;
|
return <Waveform relHeights={this.state.heights} progress={this.state.progress} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,11 @@ limitations under the License.
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
||||||
|
import classNames from "classnames";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
relHeights: number[]; // relative heights (0-1)
|
relHeights: number[]; // relative heights (0-1)
|
||||||
|
progress: number; // percent complete, 0-1, default 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
|
@ -28,9 +30,16 @@ interface IState {
|
||||||
* A simple waveform component. This renders bars (centered vertically) for each
|
* A simple waveform component. This renders bars (centered vertically) for each
|
||||||
* height provided in the component properties. Updating the properties will update
|
* height provided in the component properties. Updating the properties will update
|
||||||
* the rendered waveform.
|
* the rendered waveform.
|
||||||
|
*
|
||||||
|
* For CSS purposes, a mx_Waveform_bar_100pct class is added when the bar should be
|
||||||
|
* "filled", as a demonstration of the progress property.
|
||||||
*/
|
*/
|
||||||
@replaceableComponent("views.voice_messages.Waveform")
|
@replaceableComponent("views.voice_messages.Waveform")
|
||||||
export default class Waveform extends React.PureComponent<IProps, IState> {
|
export default class Waveform extends React.PureComponent<IProps, IState> {
|
||||||
|
public static defaultProps = {
|
||||||
|
progress: 1,
|
||||||
|
};
|
||||||
|
|
||||||
public constructor(props) {
|
public constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
@ -38,7 +47,13 @@ export default class Waveform extends React.PureComponent<IProps, IState> {
|
||||||
public render() {
|
public render() {
|
||||||
return <div className='mx_Waveform'>
|
return <div className='mx_Waveform'>
|
||||||
{this.props.relHeights.map((h, i) => {
|
{this.props.relHeights.map((h, i) => {
|
||||||
return <span key={i} style={{height: (h * 100) + '%'}} className='mx_Waveform_bar' />;
|
const progress = this.props.progress;
|
||||||
|
const isCompleteBar = (i / this.props.relHeights.length) <= progress && progress > 0;
|
||||||
|
const classes = classNames({
|
||||||
|
'mx_Waveform_bar': true,
|
||||||
|
'mx_Waveform_bar_100pct': isCompleteBar,
|
||||||
|
});
|
||||||
|
return <span key={i} style={{height: (h * 100) + '%'}} className={classes} />;
|
||||||
})}
|
})}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue