app/ItemView/PlayerContainer.tsx (229 lines of code) (raw):
import React, { useState, useEffect } from "react";
import { VidispineShape } from "../vidispine/shape/VidispineShape";
import {
Grid,
Typography,
Button,
Tooltip,
IconButton,
Dialog,
DialogActions,
DialogContent,
DialogContentText,
makeStyles,
} from "@material-ui/core";
import PreviewPlayer from "./PreviewPlayer";
import ShapeSelector from "./ShapeSelector";
import axios from "axios";
import HelpIcon from "@material-ui/icons/Help";
interface PlayerContainerProps {
shapes: VidispineShape[];
uriList: string[];
defaultShapes: string[];
originalFilename: string | undefined;
}
const useStyles = makeStyles({
infoIcon: {
display: "flex",
marginLeft: "auto",
marginBottom: "0.625rem",
},
});
const PlayerContainer: React.FC<PlayerContainerProps> = (props) => {
const classes = useStyles();
const [openDialog, setOpenDialog] = useState<boolean>(false);
/**
* checks to see if any of the shapes we have been given have tags that match the ones that are our "defaults".
* if so, return the first matching tag. this is used as the default value for the shapetag selector.
*/
const findInitialShapetag = () => {
const shapeMatches = props.shapes
.filter((shape) => shape.tag.length > 0)
.filter((shape) => props.defaultShapes.includes(shape.tag[0]));
return shapeMatches.length > 0 ? shapeMatches[0].tag[0] : "original";
};
const [selectedShapeTag, setSelectedShapeTag] = useState<string>(
findInitialShapetag()
);
//const [selectedShape, setSelectedShape] = useState<VidispineShape|null>(null);
const [playerUri, setPlayerUri] = useState<string>("");
const [mimeType, setMimeType] = useState<string>("");
const [targetUrl, setTargetUrl] = useState<string>("");
/**
* try to locate the file ID associated with the given shape
* @param currentShapeData
*/
const getFileId = (currentShapeData: VidispineShape) => {
if (currentShapeData.mimeType.length > 0) {
setMimeType(currentShapeData.mimeType[0]);
}
if (currentShapeData.containerComponent) {
return currentShapeData.containerComponent.file &&
currentShapeData.containerComponent.file.length > 0
? currentShapeData.containerComponent.file[0].id
: undefined;
}
if (currentShapeData.audioComponent) {
const potentialComponents = currentShapeData.audioComponent.filter(
(c) => c.file.length > 0
);
if (potentialComponents.length > 0) {
return potentialComponents[0].file[0].id;
} else {
return undefined;
}
}
if (currentShapeData.videoComponent) {
const potentialComponents = currentShapeData.videoComponent.filter(
(c) => c.file.length > 0
);
if (potentialComponents.length > 0) {
return potentialComponents[0].file[0].id;
} else {
return undefined;
}
}
if (currentShapeData.binaryComponent) {
const potentialComponents = currentShapeData.binaryComponent.filter(
(c) => c.file.length > 0
);
if (potentialComponents.length > 0) {
return potentialComponents[0].file[0].id;
} else {
return undefined;
}
}
return undefined;
};
/**
* when the selected shape tag changes, update the player url
*/
useEffect(() => {
const currentShapeData = findSelectedShape();
if (!currentShapeData) return;
const fileId = getFileId(currentShapeData);
if (!fileId) return;
console.log("fileId is ", fileId);
const matcher = new RegExp(`${fileId}\..*$`);
//uri.search returns the index in the string of a match, or -1 if there is no match
const matchingUris = props.uriList.filter((uri) => uri.search(matcher) > 0);
console.log("Matching Uris: ", matchingUris);
console.debug(`Found ${matchingUris.length} matching URIs`);
const originalFilename = props.originalFilename;
if (matchingUris.length > 0) {
setPlayerUri(matchingUris[0]);
} else {
setPlayerUri("");
}
}, [selectedShapeTag]);
useEffect(() => {
let baseUri = playerUri.replace(":8080", "");
if (props.originalFilename === undefined) {
setTargetUrl(baseUri);
} else {
let baseUrl = baseUri.slice(0, baseUri.lastIndexOf("/") + 1);
let newTargetUrl = baseUrl + props.originalFilename;
setTargetUrl(newTargetUrl);
}
}, [playerUri, props.originalFilename]);
/**
* returns the VidispineShape data structure associated with the shape matching the selected tag
*/
const findSelectedShape = () => {
if (selectedShapeTag === "") return null;
for (let i = 0; i < props.shapes.length; ++i) {
if (props.shapes[i].tag.includes(selectedShapeTag))
return props.shapes[i];
}
return null;
};
const closeDialog = () => {
setOpenDialog(false);
};
return (
<>
<Grid container alignItems="center" justify="center" direction="column">
<Grid item xs={12} spacing={1}>
{<PreviewPlayer proxyUri={playerUri} mediaType={mimeType} />}
{selectedShapeTag == "" ? (
<Typography variant="caption">
There is no shape currently selected
</Typography>
) : null}
{selectedShapeTag != "" && !playerUri ? (
<Typography variant="caption">
Could not find a uri for {mimeType}
</Typography>
) : null}
</Grid>
<Grid item xs={12}>
<Grid container spacing={3}>
<Grid item xs={4}>
<ShapeSelector
options={props.shapes.map((s) =>
s.tag.length > 0 ? s.tag[0] : ""
)}
onSelectionChanged={(newSelection) =>
setSelectedShapeTag(newSelection)
}
currentTag={selectedShapeTag}
/>
</Grid>
<Grid item xs={4}>
{playerUri != "" ? (
<div style={{ marginTop: "8px" }}>
<Button
variant="contained"
color="primary"
target="_blank"
href={targetUrl}
>
Download
</Button>
</div>
) : null}
</Grid>
<Grid item xs={4}>
{playerUri != "" ? (
<Tooltip
className={classes.infoIcon}
title="How do I download files?"
>
<IconButton
onClick={(event) => {
event.stopPropagation();
setOpenDialog(true);
}}
>
<HelpIcon />
</IconButton>
</Tooltip>
) : null}
</Grid>
</Grid>
</Grid>
</Grid>
<Dialog
open={openDialog}
onClose={closeDialog}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Select the file you want to download from the menu. To select the
original file, select 'Original'.
<br />
<br />
To save the file locally on Chrome and Firefox right click on the
DOWNLOAD button and select 'Save Link As...'.
<br />
<br />
To save the file locally on Safari right click on the DOWNLOAD
button and select 'Download Linked File As...'.
<br />
<br />
If right clicking does not work on your computer do the following: -
<br />
<br />
1. Open System Preferences.
<br />
2. Click on Mouse.
<br />
3. In the right hand menu select 'Secondary Button'.
<br />
4. Close System Preferences.
<br />
<br />
Right clicking should now work.
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={closeDialog}>Close</Button>
</DialogActions>
</Dialog>
</>
);
};
export default PlayerContainer;