restreamer-ui-v2/src/misc/Changelog.js
2022-11-08 00:17:35 +01:00

145 lines
3.1 KiB
JavaScript

import React from 'react';
import { Trans } from '@lingui/macro';
import makeStyles from '@mui/styles/makeStyles';
import Button from '@mui/material/Button';
import Grid from '@mui/material/Grid';
import ReactMarkdown from 'react-markdown';
import SemverGt from 'semver/functions/gt';
import SemverLte from 'semver/functions/lte';
import SemverValid from 'semver/functions/valid';
import BoxText from './BoxText';
import Dialog from './modals/Dialog';
const useStyles = makeStyles((theme) => ({
h1: theme.typography.h1,
h2: theme.typography.h2,
h3: theme.typography.h3,
h4: theme.typography.h4,
a: {
color: theme.palette.secondary.main,
},
}));
export default function Changelog(props) {
const [$data, setData] = React.useState('');
const classes = useStyles();
React.useEffect(() => {
(async () => {
await onMount();
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onMount = async () => {
let data = await loadData();
data = filter(data, props.current, props.previous);
setData(data);
};
const loadData = async () => {
let response = null;
try {
response = await fetch('CHANGELOG.md', {
method: 'GET',
});
} catch (err) {
return '';
}
if (response.ok === false) {
return '';
}
return await response.text();
};
const filter = (data, current, previous) => {
let lines = data.split('\n');
let filteredLines = [];
let copy = true;
for (let i = 0; i < lines.length; i++) {
if (lines[i].startsWith('### ')) {
let version = lines[i].replace('### ', '');
if (SemverValid(version) === null) {
if (copy === true) {
filteredLines.push(lines[i]);
}
continue;
}
if (current.length === 0) {
current = version;
}
if (previous.length === 0) {
previous = version;
}
if (SemverLte(version, current) && SemverGt(version, previous)) {
copy = true;
} else {
copy = false;
}
}
if (copy === true) {
filteredLines.push(lines[i]);
}
}
return filteredLines.join('\n');
};
if ($data.length === 0 || $data.startsWith('<!DOCTYPE')) {
return null;
}
const renderers = {
h1: (props) => <h1 className={classes.h1} {...props}>{props.children}</h1>,
h2: (props) => <h2 className={classes.h2} {...props}>{props.children}</h2>,
h3: (props) => <h3 className={classes.h3} {...props}>{props.children}</h3>,
h4: (props) => <h4 className={classes.h4} {...props}>{props.children}</h4>,
a: (props) => <a className={classes.a} target="_blank" {...props}>{props.children}</a>,
}
return (
<Dialog
open={props.open}
onClose={props.onClose}
title={<Trans>Changelog</Trans>}
maxWidth={600}
buttonsRight={
<Button variant="outlined" color="primary" onClick={props.onClose}>
<Trans>Dismiss</Trans>
</Button>
}
>
<Grid container spacing={2}>
<Grid item xs={12}>
<BoxText alignItems="left">
<ReactMarkdown
components={renderers}
>{$data}</ReactMarkdown>
</BoxText>
</Grid>
</Grid>
</Dialog>
);
}
Changelog.defaultProps = {
open: false,
current: '',
previous: '',
onClose: () => {},
};