Skip to content

Commit

Permalink
feat: add audio and video support to file displayer
Browse files Browse the repository at this point in the history
  • Loading branch information
davidlougheed committed Oct 12, 2023
1 parent 33f5934 commit 6410ba2
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 16 deletions.
19 changes: 19 additions & 0 deletions src/components/display/AudioDisplay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useEffect, useRef } from "react";
import PropTypes from "prop-types";

const AudioDisplay = ({blob}) => {
const audioRef = useRef(null);

useEffect(() => {
if (audioRef.current && blob) {
audioRef.current.src = URL.createObjectURL(blob);
}
}, [audioRef, blob]);

return <audio style={{ width: "100%" }} ref={audioRef} controls={true} />;
};
AudioDisplay.propTypes = {
blob: PropTypes.instanceOf(Blob),
};

export default AudioDisplay;
56 changes: 40 additions & 16 deletions src/components/display/FileDisplay.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useAuthorizationHeader } from "../../lib/auth/utils";
import PropTypes from "prop-types";
import { Alert, Spin } from "antd";

import fetch from "cross-fetch";
Expand All @@ -20,13 +20,16 @@ import {
xml,
} from "react-syntax-highlighter/dist/cjs/languages/hljs";

import JsonDisplay from "./JsonDisplay";

import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";
import PropTypes from "prop-types";

import { useAuthorizationHeader } from "../../lib/auth/utils";

import AudioDisplay from "./AudioDisplay";
import CsvDisplay from "./CsvDisplay";
import ImageBlobDisplay from "./ImageBlobDisplay";
import JsonDisplay from "./JsonDisplay";
import VideoDisplay from "./VideoDisplay";

SyntaxHighlighter.registerLanguage("bash", bash);
SyntaxHighlighter.registerLanguage("dockerfile", dockerfile);
Expand Down Expand Up @@ -60,8 +63,16 @@ const LANGUAGE_HIGHLIGHTERS = {
"CHANGELOG": "plaintext",
};

// TODO: ".bed",
// .bed files are basically TSVs, but they can have instructions and can be whitespace-delimited instead
const AUDIO_FILE_EXTENSIONS = [
"3gp",
"aac",
"flac",
"m4a",
"mp3",
"ogg",
"wav",
];

const IMAGE_FILE_EXTENSIONS = [
"apng",
"avif",
Expand All @@ -73,14 +84,27 @@ const IMAGE_FILE_EXTENSIONS = [
"svg",
"webp",
];

const VIDEO_FILE_EXTENSIONS = [
"mp4",
];

// TODO: ".bed",
// .bed files are basically TSVs, but they can have instructions and can be whitespace-delimited instead
export const VIEWABLE_FILE_EXTENSIONS = [
// Tabular data
"csv",
"tsv",

// Audio
...AUDIO_FILE_EXTENSIONS,

// Images
...IMAGE_FILE_EXTENSIONS,

// Videos
...VIDEO_FILE_EXTENSIONS,

// Documents
"pdf",

Expand All @@ -89,7 +113,7 @@ export const VIEWABLE_FILE_EXTENSIONS = [
];

const DEFER_LOADING_FILE_EXTENSIONS = ["pdf"]; // Don't use a fetch() for these extensions
const BINARY_FILE_EXTENSIONS = [...IMAGE_FILE_EXTENSIONS, "pdf"];
const BINARY_FILE_EXTENSIONS = [...AUDIO_FILE_EXTENSIONS, ...IMAGE_FILE_EXTENSIONS, ...VIDEO_FILE_EXTENSIONS, "pdf"];

const FileDisplay = ({ uri, fileName, loading }) => {
const authHeader = useAuthorizationHeader();
Expand Down Expand Up @@ -192,22 +216,22 @@ const FileDisplay = ({ uri, fileName, loading }) => {
</Document>
);
} else if (["csv", "tsv"].includes(fileExt)) {
if (loadingFileContents) {
return <div />;
}
if (loadingFileContents) return <div />;
return (
<CsvDisplay contents={fileContents[uri]} />
);
} else if (AUDIO_FILE_EXTENSIONS.includes(fileExt)) {
if (loadingFileContents) return <div />;
return <AudioDisplay blob={fileContents[uri]} />;
} else if (IMAGE_FILE_EXTENSIONS.includes(fileExt)) {
if (loadingFileContents) {
return <div />;
}
if (loadingFileContents) return <div />;
return <ImageBlobDisplay alt={fileName} blob={fileContents[uri]} />;
} else if (VIDEO_FILE_EXTENSIONS.includes(fileExt)) {
if (loadingFileContents) return <div />;
return <VideoDisplay blob={fileContents[uri]} />;
} else if (fileExt === "json") {
const jsonSrc = fileContents[uri];
if (loadingFileContents || !jsonSrc) {
return <div/>;
}
if (loadingFileContents || !jsonSrc) return <div/>;
return (
<JsonDisplay jsonSrc={jsonSrc}/>
);
Expand Down
19 changes: 19 additions & 0 deletions src/components/display/VideoDisplay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React, { useEffect, useRef } from "react";
import PropTypes from "prop-types";

const VideoDisplay = ({blob}) => {
const videoRef = useRef(null);

useEffect(() => {
if (videoRef.current && blob) {
videoRef.current.src = URL.createObjectURL(blob);
}
}, [videoRef, blob]);

return <video style={{ width: "100%" }} ref={videoRef} controls={true} />;
};
VideoDisplay.propTypes = {
blob: PropTypes.instanceOf(Blob),
};

export default VideoDisplay;

0 comments on commit 6410ba2

Please sign in to comment.