Skip to content

Commit

Permalink
Enable player for video attachments. Add a playback time limit for it
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmz committed Oct 8, 2024
1 parent 6f6b49c commit 9d07ce9
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 63 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.135.0] - Not released
### Changed
- Enable player for video attachments. Add a playback time limit for it.

## [1.134.4] - 2024-08-26
### Changed
Expand Down
127 changes: 76 additions & 51 deletions src/components/post/post-attachment-video.jsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,92 @@
import { PureComponent } from 'react';
import { useEffect, useRef, useState } from 'react';
import { faFileVideo, faPlayCircle } from '@fortawesome/free-regular-svg-icons';
import { faTimes } from '@fortawesome/free-solid-svg-icons';

import { useEvent } from 'react-use-event-hook';
import { formatFileSize } from '../../utils';
import { ButtonLink } from '../button-link';
import { Icon } from '../fontawesome-icons';

class VideoAttachment extends PureComponent {
state = {
isOpen: false,
};
export default function VideoAttachment({
id,
url,
fileName,
fileSize,
removeAttachment,
isEditing,
}) {
const [isOpen, setIsOpen] = useState(false);

handleClickOnRemoveAttachment = () => {
this.props.removeAttachment(this.props.id);
};
const handleClickOnRemoveAttachment = useEvent(() => removeAttachment(id));
const toggleOpen = useEvent(() => setIsOpen(true));

toggleOpen = () => {
this.setState({ isOpen: true });
};
const formattedFileSize = formatFileSize(fileSize);
const title = `${fileName} (${formattedFileSize})`;

render() {
const { props } = this;
const { isOpen } = this.state;
const formattedFileSize = formatFileSize(props.fileSize);
const videoRef = useRef(null);

const title = `${props.fileName} (${formattedFileSize})`;
// Prevent video from playing infinitely (we has this situation once and don't
// want it to happen again)
useEffect(() => {
if (!isOpen || !videoRef.current) {
return;
}
const videoEl = videoRef.current;

return (
<div className="attachment" role="figure" aria-label={`Video attachment ${title}`}>
{isOpen ? (
<div>
<video title={title} autoPlay controls>
<source src={props.url} />
Your browser does not support HTML5 video tag.
</video>
</div>
) : (
<ButtonLink
onClick={this.toggleOpen}
className="video-attachment-click-to-play"
title="Click to play video"
>
<Icon icon={faPlayCircle} />
</ButtonLink>
)}
<div>
<a href={props.url} title={title} target="_blank">
<Icon icon={faFileVideo} className="attachment-icon" />
<span>{title}</span>
</a>
// By default, the video playback should be paused after 5 minutes
let maxPlayTime = 300 * 1000;
let playTimer = 0;
const onPlay = () => {
clearTimeout(playTimer);
playTimer = setTimeout(() => videoEl.pause(), maxPlayTime);
};
const onPause = () => clearTimeout(playTimer);
const onDurationChange = () => {
// Video in playback mode should not be longer than 10 times of the video duration
maxPlayTime = videoEl.duration * 10 * 1000;
};
const { signal, abort } = new AbortController();

{props.isEditing && (
<Icon
icon={faTimes}
className="remove-attachment"
title="Remove video file"
onClick={this.handleClickOnRemoveAttachment}
/>
)}
videoEl.addEventListener('durationchange', onDurationChange, { once: true, signal });
videoEl.addEventListener('play', onPlay, { signal });
videoEl.addEventListener('pause', onPause, { signal });
signal.addEventListener('abort', onPause);
return () => abort();
}, [isOpen]);

return (
<div className="attachment" role="figure" aria-label={`Video attachment ${title}`}>
{isOpen ? (
<div>
<video title={title} autoPlay controls ref={videoRef}>
<source src={url} />
Your browser does not support HTML5 video tag.
</video>
</div>
) : (
<ButtonLink
onClick={toggleOpen}
className="video-attachment-click-to-play"
title="Click to play video"
>
<Icon icon={faPlayCircle} />
</ButtonLink>
)}
<div>
<a href={url} title={title} target="_blank">
<Icon icon={faFileVideo} className="attachment-icon" />
<span>{title}</span>
</a>

{isEditing && (
<Icon
icon={faTimes}
className="remove-attachment"
title="Remove video file"
onClick={handleClickOnRemoveAttachment}
/>
)}
</div>
);
}
</div>
);
}

export default VideoAttachment;
15 changes: 3 additions & 12 deletions src/components/post/post-attachments.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import AudioAttachment from './post-attachment-audio';
import GeneralAttachment from './post-attachment-general';
import VideoAttachment from './post-attachment-video';

/*
const videoTypes = {
mov: 'video/quicktime',
mp4: 'video/mp4; codecs="avc1.42E01E"',
Expand All @@ -16,19 +15,11 @@ const videoTypes = {

// find video-types which browser supports
let video = document.createElement('video');
const supportedVideoTypes = [];
Object.keys(videoTypes).forEach((extension) => {
const mime = videoTypes[extension];
const supportedVideoTypes = Object.entries(videoTypes)
.filter(([, mime]) => video.canPlayType(mime) === 'probably')
.map(([extension]) => extension);

if (video.canPlayType(mime) !== '') {
supportedVideoTypes.push(extension);
}
});
video = null;
*/

// No video support for now
const supportedVideoTypes = [];

const looksLikeAVideoFile = (attachment) => {
const lowercaseFileName = attachment.fileName.toLowerCase();
Expand Down

0 comments on commit 9d07ce9

Please sign in to comment.