Enable support for image, video and audio files

This commit is contained in:
Jaiwanth 2021-05-31 21:01:19 +05:30
parent 409213ceb4
commit 59c1b67b7d
8 changed files with 86 additions and 21 deletions

View file

@ -34,6 +34,7 @@ export default class MAudioBody extends React.Component {
error: null,
};
}
onPlayToggle() {
this.setState({
playing: !this.state.playing,
@ -41,6 +42,7 @@ export default class MAudioBody extends React.Component {
}
_getContentUrl() {
if (this.props.mediaSrc) return this.props.mediaSrc;
const media = mediaFromContent(this.props.mxEvent.getContent());
if (media.isEncrypted) {
return this.state.decryptedUrl;
@ -49,6 +51,11 @@ export default class MAudioBody extends React.Component {
}
}
getFileBody() {
if (this.props.mediaSrc) return null;
return <MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />;
}
componentDidMount() {
const content = this.props.mxEvent.getContent();
if (content.file !== undefined && this.state.decryptedUrl === null) {
@ -101,11 +108,11 @@ export default class MAudioBody extends React.Component {
}
const contentUrl = this._getContentUrl();
const fileBody = this.getFileBody();
return (
<span className="mx_MAudioBody">
<audio src={contentUrl} controls />
<MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />
{ fileBody }
</span>
);
}

View file

@ -242,7 +242,7 @@ export default class MFileBody extends React.Component {
<span className="mx_MFileBody">
{placeholder}
<div className="mx_MFileBody_download">
<div style={{display: "none"}}>
<div style={{ display: "none" }}>
{ /*
* Add dummy copy of the "a" tag
* We'll use it to learn how the download link
@ -309,7 +309,7 @@ export default class MFileBody extends React.Component {
if (this.props.tileShape === "file_grid") {
return (
<span className="mx_MFileBody">
{placeholder}
{ placeholder }
<div className="mx_MFileBody_download">
<a className="mx_MFileBody_downloadLink" {...downloadProps}>
{ fileName }
@ -323,7 +323,7 @@ export default class MFileBody extends React.Component {
} else {
return (
<span className="mx_MFileBody">
{placeholder}
{ placeholder }
<div className="mx_MFileBody_download">
<a {...downloadProps}>
<span className="mx_MFileBody_download_icon" />
@ -336,7 +336,7 @@ export default class MFileBody extends React.Component {
} else {
const extra = text ? (': ' + text) : '';
return <span className="mx_MFileBody">
{placeholder}
{ placeholder }
{ _t("Invalid file%(extra)s", { extra: extra }) }
</span>;
}

View file

@ -90,7 +90,7 @@ export default class MImageBody extends React.Component {
showImage() {
localStorage.setItem("mx_ShowImage_" + this.props.mxEvent.getId(), "true");
this.setState({showImage: true});
this.setState({ showImage: true });
this._downloadImage();
}
@ -172,6 +172,7 @@ export default class MImageBody extends React.Component {
}
_getContentUrl() {
if (this.props.mediaSrc) return this.props.mediaSrc;
const media = mediaFromContent(this.props.mxEvent.getContent());
if (media.isEncrypted) {
return this.state.decryptedUrl;
@ -296,7 +297,7 @@ export default class MImageBody extends React.Component {
if (showImage) {
// Don't download anything becaue we don't want to display anything.
this._downloadImage();
this.setState({showImage: true});
this.setState({ showImage: true });
}
this._afterComponentDidMount();
@ -345,7 +346,7 @@ export default class MImageBody extends React.Component {
imageElement = <HiddenImagePlaceholder />;
} else {
imageElement = (
<img style={{display: 'none'}} src={thumbUrl} ref={this._image}
<img style={{ display: 'none' }} src={thumbUrl} ref={this._image}
alt={content.body}
onError={this.onImageError}
onLoad={this.onImageLoad}
@ -449,6 +450,7 @@ export default class MImageBody extends React.Component {
// Overidden by MStickerBody
getFileBody() {
if (this.props.mediaSrc) return null;
return <MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />;
}
@ -466,7 +468,7 @@ export default class MImageBody extends React.Component {
const contentUrl = this._getContentUrl();
let thumbUrl;
if (this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) {
if ((this._isGif() && SettingsStore.getValue("autoplayGifsAndVideos")) || this.props.mediaSrc) {
thumbUrl = contentUrl;
} else {
thumbUrl = this._getThumbUrl();

View file

@ -29,6 +29,8 @@ interface IProps {
mxEvent: any;
/* called when the video has loaded */
onHeightChanged: () => void;
/* used to refer to the local file while exporting */
mediaSrc?: string;
}
interface IState {
@ -76,6 +78,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
private getContentUrl(): string|null {
if (this.props.mediaSrc) return this.props.mediaSrc;
const media = mediaFromContent(this.props.mxEvent.getContent());
if (media.isEncrypted) {
return this.state.decryptedUrl;
@ -90,6 +93,9 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
}
private getThumbUrl(): string|null {
// there's no need of thumbnail when the content is local
if (this.props.mediaSrc) return null;
const content = this.props.mxEvent.getContent();
const media = mediaFromContent(content);
if (media.isEncrypted) {
@ -184,6 +190,11 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
this.props.onHeightChanged();
}
private getFileBody = () => {
if (this.props.mediaSrc) return null;
return <MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />;
}
render() {
const content = this.props.mxEvent.getContent();
const autoplay = SettingsStore.getValue("autoplayGifsAndVideos");
@ -197,7 +208,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
);
}
// Important: If we aren't autoplaying and we haven't decrypred it yet, show a video with a poster.
// Important: If we aren't autoplaying and we haven't decrypted it yet, show a video with a poster.
if (content.file !== undefined && this.state.decryptedUrl === null && autoplay) {
// Need to decrypt the attachment
// The attachment is decrypted in componentDidMount.
@ -229,6 +240,8 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
preload = "none";
}
}
const fileBody = this.getFileBody();
return (
<span className="mx_MVideoBody">
<video
@ -246,7 +259,7 @@ export default class MVideoBody extends React.PureComponent<IProps, IState> {
onPlay={this.videoOnPlay}
>
</video>
<MFileBody {...this.props} decryptedBlob={this.state.decryptedBlob} showGenericPlaceholder={false} />
{ fileBody }
</span>
);
}

View file

@ -23,6 +23,7 @@ import MVoiceMessageBody from "./MVoiceMessageBody";
interface IProps {
mxEvent: MatrixEvent;
mediaSrc?: string;
}
@replaceableComponent("views.messages.MVoiceOrAudioBody")
@ -30,7 +31,7 @@ export default class MVoiceOrAudioBody extends React.PureComponent<IProps> {
public render() {
const isVoiceMessage = !!this.props.mxEvent.getContent()['org.matrix.msc2516.voice'];
const voiceMessagesEnabled = SettingsStore.getValue("feature_voice_messages");
if (isVoiceMessage && voiceMessagesEnabled) {
if (isVoiceMessage && voiceMessagesEnabled && !this.props.mediaSrc) {
return <MVoiceMessageBody {...this.props} />;
} else {
return <MAudioBody {...this.props} />;

View file

@ -44,6 +44,9 @@ export default class MessageEvent extends React.Component {
/* the shape of the tile, used */
tileShape: PropTypes.string,
/* to set source to local file path during export */
mediaSrc: PropTypes.string,
/* the maximum image height to use, if the event is an image */
maxImageHeight: PropTypes.number,
@ -120,6 +123,7 @@ export default class MessageEvent extends React.Component {
highlightLink={this.props.highlightLink}
showUrlPreview={this.props.showUrlPreview}
tileShape={this.props.tileShape}
mediaSrc={this.props.mediaSrc}
maxImageHeight={this.props.maxImageHeight}
replacingEventId={this.props.replacingEventId}
editState={this.props.editState}