frontend/app/ItemView/FlexMetadata.tsx (125 lines of code) (raw):
import React, {useEffect, useState} from "react";
import {ArchiveEntry} from "../types";
import {Grid, makeStyles, Paper} from "@material-ui/core";
import FlexMetadataEntry from "./FlexMetadataEntry";
import PathDisplayComponent from "../browse/PathDisplayComponent";
import {Storage} from "@material-ui/icons";
import {extractFileInfo} from "../common/Fileinfo";
import Chip from '@material-ui/core/Chip';
import MediaDurationComponent from "../common/MediaDurationComponent";
import FileSizeView from "../Entry/FileSizeView";
interface FlexMetadataProps {
entry: ArchiveEntry
jumpToPath?: ()=>void;
}
const useStyles = makeStyles((theme)=>({
metadataEntry: {
margin: "1em"
},
chip: {
margin: theme.spacing(0.5)
},
chipContainer: {
margin: 0,
padding: 0
}
}));
const FlexMetadata:React.FC<FlexMetadataProps> = (props) => {
const [firstVideoStream, setFirstVideoStream] = useState<any|undefined>(undefined);
const [firstAudioStream, setFirstAudioStream] = useState<any|undefined>(undefined);
const [videoStreamCount, setVideoStreamCount] = useState(0);
const [audioStreamCount, setAudioStreamCount] = useState(0);
const classes = useStyles();
const fileInfo = extractFileInfo(props.entry.path);
/**
* cache some information that is more expensive to obtain
*/
useEffect(()=>{
if(props.entry.mediaMetadata ) {
const vStreams = props.entry.mediaMetadata.streams.filter(entry => entry.codec_type === "video");
const aStreams = props.entry.mediaMetadata.streams.filter(entry => entry.codec_type === "audio");
setFirstVideoStream(vStreams.length > 0 ? vStreams[0] : undefined);
setFirstAudioStream(aStreams.length > 0 ? aStreams[0] : undefined);
setVideoStreamCount(vStreams.length);
setAudioStreamCount(aStreams.length);
} else {
setFirstAudioStream(undefined);
setFirstAudioStream(undefined);
setVideoStreamCount(0);
setAudioStreamCount(0);
}
}, [props.entry]);
return <>
<Grid container>
{
//FIXME: should put functionality on browse to open a specific set of paths
}
<FlexMetadataEntry className={classes.metadataEntry}
label="Path"
value={<PathDisplayComponent path={fileInfo.filepath}/>}
callout={props.jumpToPath}
/>
<FlexMetadataEntry className={classes.metadataEntry} label="Collection" value={props.entry.bucket} icon={<Storage/>}/>
<FlexMetadataEntry className={classes.metadataEntry} label="Storage class" value={props.entry.storageClass}/>
<FlexMetadataEntry className={classes.metadataEntry} label="Region" value={props.entry.region ?? "(not set)"}/>
{
props.entry.mediaMetadata ? <>
<FlexMetadataEntry className={classes.metadataEntry}
label="Duration"
value={<MediaDurationComponent value={props.entry.mediaMetadata.format.duration}/>}
/>
<FlexMetadataEntry className={classes.metadataEntry}
label="Bit rate"
value={<FileSizeView rawSize={props.entry.mediaMetadata.format.bit_rate} rateUnits={true}/>}
/>
<FlexMetadataEntry className={classes.metadataEntry} label="Format" value={props.entry.mediaMetadata.format.format_long_name}/>
<FlexMetadataEntry className={classes.metadataEntry}
label="File size"
value={<FileSizeView rawSize={props.entry.mediaMetadata.format.size}/>}
/>
</> : undefined
}
<FlexMetadataEntry className={classes.metadataEntry}
label="Channels"
value={<span>{videoStreamCount} video, {audioStreamCount} audio</span>}
/>
{ firstVideoStream || firstAudioStream ?
<FlexMetadataEntry className={classes.metadataEntry}
label="Codecs"
value={<span>{firstVideoStream ? firstVideoStream.codec_name : "(none)"} / {firstAudioStream ? firstAudioStream.codec_name : "(none)"}</span>}
/> : undefined
}
{
firstVideoStream ?
<FlexMetadataEntry className={classes.metadataEntry}
label="Resolution"
value={<span>{firstVideoStream.width} x {firstVideoStream.height}</span> }/>
: undefined
}
{
firstVideoStream && firstVideoStream.display_aspect_ratio ?
<FlexMetadataEntry className={classes.metadataEntry}
label="Aspect ratio"
value={firstVideoStream.display_aspect_ratio}
/> : undefined
}
{
firstAudioStream && firstAudioStream.channel_layout ?
<FlexMetadataEntry className={classes.metadataEntry}
label="Audio"
value={firstAudioStream.channel_layout}/> : undefined
}
{
props.entry.mediaMetadata ? <FlexMetadataEntry className={classes.metadataEntry} label="Format tags" value={
<Grid container className={classes.chipContainer}>
{
Object.keys(props.entry.mediaMetadata.format.tags)
.map(k=><Grid item>
<Chip
label={`${k}: ${props.entry.mediaMetadata?.format.tags[k]}`}
key={k}
className={classes.chip}
/>
</Grid>)
}
</Grid>
}/> : undefined
}
</Grid>
</>
}
export default FlexMetadata;