mirror of
https://github.com/element-hq/element-web.git
synced 2024-12-16 09:31:31 +03:00
103 lines
3.7 KiB
TypeScript
103 lines
3.7 KiB
TypeScript
/*
|
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
import React from "react";
|
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
|
import { Playback } from "../../../audio/Playback";
|
|
import InlineSpinner from '../elements/InlineSpinner';
|
|
import { _t } from "../../../languageHandler";
|
|
import AudioPlayer from "../audio_messages/AudioPlayer";
|
|
import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent";
|
|
import MFileBody from "./MFileBody";
|
|
import { IBodyProps } from "./IBodyProps";
|
|
import { PlaybackManager } from "../../../audio/PlaybackManager";
|
|
|
|
interface IState {
|
|
error?: Error;
|
|
playback?: Playback;
|
|
}
|
|
|
|
@replaceableComponent("views.messages.MAudioBody")
|
|
export default class MAudioBody extends React.PureComponent<IBodyProps, IState> {
|
|
constructor(props: IBodyProps) {
|
|
super(props);
|
|
|
|
this.state = {};
|
|
}
|
|
|
|
public async componentDidMount() {
|
|
let buffer: ArrayBuffer;
|
|
|
|
try {
|
|
try {
|
|
const blob = await this.props.mediaEventHelper.sourceBlob.value;
|
|
buffer = await blob.arrayBuffer();
|
|
} catch (e) {
|
|
this.setState({ error: e });
|
|
console.warn("Unable to decrypt audio message", e);
|
|
return; // stop processing the audio file
|
|
}
|
|
} catch (e) {
|
|
this.setState({ error: e });
|
|
console.warn("Unable to decrypt/download audio message", e);
|
|
return; // stop processing the audio file
|
|
}
|
|
|
|
// We should have a buffer to work with now: let's set it up
|
|
|
|
// Note: we don't actually need a waveform to render an audio event, but voice messages do.
|
|
const content = this.props.mxEvent.getContent<IMediaEventContent>();
|
|
const waveform = content?.["org.matrix.msc1767.audio"]?.waveform?.map(p => p / 1024);
|
|
|
|
// We should have a buffer to work with now: let's set it up
|
|
const playback = PlaybackManager.instance.createPlaybackInstance(buffer, waveform);
|
|
playback.clockInfo.populatePlaceholdersFrom(this.props.mxEvent);
|
|
this.setState({ playback });
|
|
|
|
// Note: the components later on will handle preparing the Playback class for us.
|
|
}
|
|
|
|
public componentWillUnmount() {
|
|
this.state.playback?.destroy();
|
|
}
|
|
|
|
public render() {
|
|
if (this.state.error) {
|
|
return (
|
|
<span className="mx_MAudioBody">
|
|
<img src={require("../../../../res/img/warning.svg")} width="16" height="16" />
|
|
{ _t("Error processing audio message") }
|
|
</span>
|
|
);
|
|
}
|
|
|
|
if (!this.state.playback) {
|
|
return (
|
|
<span className="mx_MAudioBody">
|
|
<InlineSpinner />
|
|
</span>
|
|
);
|
|
}
|
|
|
|
// At this point we should have a playable state
|
|
return (
|
|
<span className="mx_MAudioBody">
|
|
<AudioPlayer playback={this.state.playback} mediaName={this.props.mxEvent.getContent().body} />
|
|
{ this.props.tileShape && <MFileBody {...this.props} showGenericPlaceholder={false} /> }
|
|
</span>
|
|
);
|
|
}
|
|
}
|