diff --git a/src/components/post-attachment-video.jsx b/src/components/post-attachment-video.jsx
new file mode 100644
index 000000000..7ef3d98b3
--- /dev/null
+++ b/src/components/post-attachment-video.jsx
@@ -0,0 +1,74 @@
+import { PureComponent } from 'react';
+import { faFileVideo, faPlayCircle } from '@fortawesome/free-regular-svg-icons';
+import { faTimes } from '@fortawesome/free-solid-svg-icons';
+
+import { formatFileSize } from '../utils';
+import { ButtonLink } from './button-link';
+import { Icon } from './fontawesome-icons';
+
+class VideoAttachment extends PureComponent {
+ state = {
+ isOpen: false,
+ };
+
+ handleClickOnRemoveAttachment = () => {
+ this.props.removeAttachment(this.props.id);
+ };
+
+ toggleOpen = () => {
+ this.setState({ isOpen: true });
+ };
+
+ render() {
+ const { props } = this;
+ const { isOpen } = this.state;
+ const formattedFileSize = formatFileSize(props.fileSize);
+
+ const title = `${props.fileName} (${formattedFileSize})`;
+
+ const thumbnailStyle = {
+ width: props.imageSizes.t?.w,
+ height: props.imageSizes.t?.h,
+ backgroundImage: `url(${props.imageSizes.t?.url})`,
+ };
+
+ return (
+
+ {isOpen ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+ );
+ }
+}
+
+export default VideoAttachment;
diff --git a/src/components/post-attachments.jsx b/src/components/post-attachments.jsx
index a99fa8638..b7e6888f8 100644
--- a/src/components/post-attachments.jsx
+++ b/src/components/post-attachments.jsx
@@ -1,12 +1,29 @@
import ImageAttachmentsContainer from './post-attachment-image-container';
import AudioAttachment from './post-attachment-audio';
import GeneralAttachment from './post-attachment-general';
+import VideoAttachment from './post-attachment-video';
import ErrorBoundary from './error-boundary';
export default (props) => {
const attachments = props.attachments || [];
- const imageAttachments = attachments.filter((attachment) => attachment.mediaType === 'image');
+ const imageAttachments = [];
+ const audioAttachments = [];
+ const videoAttachments = [];
+ const generalAttachments = [];
+
+ attachments.forEach((attachment) => {
+ if (attachment.mediaType === 'image') {
+ imageAttachments.push(attachment);
+ } else if (attachment.mediaType === 'audio') {
+ audioAttachments.push(attachment);
+ } else if (attachment.mediaType === 'video') {
+ videoAttachments.push(attachment);
+ } else {
+ generalAttachments.push(attachment);
+ }
+ });
+
const imageAttachmentsContainer =
imageAttachments.length > 0 ? (
{
false
);
- const audioAttachments = attachments.filter((attachment) => attachment.mediaType === 'audio');
const audioAttachmentsNodes = audioAttachments.map((attachment) => (
{
false
);
- const generalAttachments = attachments.filter((attachment) => attachment.mediaType === 'general');
+ const videoAttachmentsNodes = videoAttachments.map((attachment) => (
+
+ ));
+ const videoAttachmentsContainer =
+ videoAttachments.length > 0 ? (
+ {videoAttachmentsNodes}
+ ) : (
+ false
+ );
+
const generalAttachmentsNodes = generalAttachments.map((attachment) => (
{
{imageAttachmentsContainer}
{audioAttachmentsContainer}
+ {videoAttachmentsContainer}
{generalAttachmentsContainer}
diff --git a/styles/shared/attachments-edit.scss b/styles/shared/attachments-edit.scss
index 928f213eb..5585706d9 100644
--- a/styles/shared/attachments-edit.scss
+++ b/styles/shared/attachments-edit.scss
@@ -74,6 +74,7 @@
}
.audio-attachments,
+.video-attachments,
.general-attachments {
.attachment:hover .remove-attachment {
display: block;
diff --git a/styles/shared/attachments.scss b/styles/shared/attachments.scss
index 0020ea60f..f990b9145 100644
--- a/styles/shared/attachments.scss
+++ b/styles/shared/attachments.scss
@@ -132,6 +132,7 @@
}
.audio-attachments,
+.video-attachments,
.general-attachments {
.attachment {
position: relative;
@@ -149,3 +150,33 @@
}
}
}
+
+.video-attachments {
+ .video-attachment-thumb {
+ display: flex;
+ width: 80px;
+ height: 80px;
+ justify-content: center;
+ align-items: center;
+ border-radius: 2px;
+ background-color: #000;
+ background-position: center;
+ background-repeat: no-repeat;
+ font-size: 2em;
+
+ &:hover {
+ font-size: 2.5em;
+ }
+ }
+
+ .video-attachment-click-to-play {
+ filter: drop-shadow(0px 0px 3px #000);
+ color: #fff;
+ }
+
+ video {
+ max-width: 100%;
+ max-height: 400px;
+ background-color: #eee;
+ }
+}
diff --git a/styles/shared/media-viewer.scss b/styles/shared/media-viewer.scss
index b189f7ad8..fecdfca1d 100644
--- a/styles/shared/media-viewer.scss
+++ b/styles/shared/media-viewer.scss
@@ -34,10 +34,11 @@
width: 100%;
height: 100%;
}
-}
-video {
- width: 100% !important;
- height: auto !important;
+
+ video {
+ width: 100% !important;
+ height: auto !important;
+ }
}
.media-link {
.icon-bond {
diff --git a/test/jest-setup.js b/test/jest-setup.js
index c85715e93..59daf3b48 100644
--- a/test/jest-setup.js
+++ b/test/jest-setup.js
@@ -1 +1,6 @@
require('../config/lib/loader-node');
+
+// https://github.com/testing-library/react-testing-library/issues/470
+Object.defineProperty(HTMLMediaElement.prototype, 'muted', {
+ set: () => {},
+});
diff --git a/test/jest/__snapshots__/post-attachments.test.js.snap b/test/jest/__snapshots__/post-attachments.test.js.snap
new file mode 100644
index 000000000..474d3b68e
--- /dev/null
+++ b/test/jest/__snapshots__/post-attachments.test.js.snap
@@ -0,0 +1,211 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PostAttachments Displays all post attachment types 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`PostAttachments Renders an empty attachments container 1`] = ``;
diff --git a/test/jest/post-attachments.test.js b/test/jest/post-attachments.test.js
new file mode 100644
index 000000000..a829b8dca
--- /dev/null
+++ b/test/jest/post-attachments.test.js
@@ -0,0 +1,82 @@
+/* global describe, it, expect */
+import { render } from '@testing-library/react';
+
+import PostAttachments from '../../src/components/post-attachments';
+
+const renderPostAttachments = (props = {}) => {
+ return render();
+};
+
+describe('PostAttachments', () => {
+ it('Renders an empty attachments container', () => {
+ const { asFragment } = renderPostAttachments();
+ expect(asFragment()).toMatchSnapshot();
+ });
+
+ it('Displays all post attachment types', () => {
+ const image1 = {
+ id: 'im1',
+ mediaType: 'image',
+ fileName: 'CAT.JPG',
+ fileSize: 200000,
+ thumbnailUrl: 'https://thumbnail/CAT.JPG',
+ url: 'https://media/CAT.JPG',
+ imageSizes: {
+ t: {
+ w: 400,
+ h: 300,
+ },
+ o: {
+ w: 2000,
+ h: 1500,
+ },
+ },
+ };
+
+ const image2 = {
+ id: 'im2',
+ mediaType: 'image',
+ fileName: 'food.jpg',
+ fileSize: 2000,
+ thumbnailUrl: 'https://thumbnail/food.jpg',
+ url: 'https://media/food.jpg',
+ imageSizes: {
+ o: {
+ w: 2000,
+ h: 1500,
+ },
+ },
+ };
+
+ const video1 = {
+ id: 'vi1',
+ mediaType: 'general',
+ fileName: 'sunrise.mp4',
+ fileSize: 123456789,
+ url: 'https://media/sunrise.mp4',
+ };
+
+ const audio1 = {
+ id: 'au1',
+ mediaType: 'audio',
+ fileName: 'wonderwall.mp3',
+ artist: 'Oasis',
+ title: 'Wonderwall',
+ fileSize: 1234567,
+ url: 'https://media/wonderwall.mp3',
+ };
+
+ const general1 = {
+ id: 'ge1',
+ mediaType: 'general',
+ fileName: 'rfc.pdf',
+ fileSize: 50000,
+ url: 'https://media/rfc.pdf',
+ };
+
+ const { asFragment } = renderPostAttachments({
+ attachments: [video1, image1, general1, image2, audio1],
+ });
+ expect(asFragment()).toMatchSnapshot();
+ });
+});