Add donate button and improve ux

This commit is contained in:
JKamsker 2024-02-19 17:54:45 +01:00
parent 10db1f235a
commit 0e636aa9ef

View file

@ -1,82 +1,78 @@
import React, { useState } from 'react'
import { withStyles } from '@material-ui/core/styles'
import Avatar from '@material-ui/core/Avatar'
import Button from '@material-ui/core/Button'
import CssBaseline from '@material-ui/core/CssBaseline'
import TextField from '@material-ui/core/TextField'
import React, { useState } from "react";
import { withStyles } from "@material-ui/core/styles";
import Avatar from "@material-ui/core/Avatar";
import Button from "@material-ui/core/Button";
import CssBaseline from "@material-ui/core/CssBaseline";
import TextField from "@material-ui/core/TextField";
import Link from '@material-ui/core/Link'
import Box from '@material-ui/core/Box'
import LockOutlinedIcon from '@material-ui/icons/LockOutlined'
import Typography from '@material-ui/core/Typography'
import Container from '@material-ui/core/Container'
import Link from "@material-ui/core/Link";
import Box from "@material-ui/core/Box";
import LockOutlinedIcon from "@material-ui/icons/LockOutlined";
import Typography from "@material-ui/core/Typography";
import Container from "@material-ui/core/Container";
import Dropzone from 'react-dropzone'
import IconButton from '@material-ui/core/IconButton'
import FileCopyOutlined from '@material-ui/icons/FileCopyOutlined'
import PublishOutlined from '@material-ui/icons/PublishOutlined'
import Dropzone from "react-dropzone";
import IconButton from "@material-ui/core/IconButton";
import FileCopyOutlined from "@material-ui/icons/FileCopyOutlined";
import PublishOutlined from "@material-ui/icons/PublishOutlined";
import { FilePicker } from '../src/Components'
import { FilePicker } from "../src/Components";
import { CopyToClipboard } from 'react-copy-to-clipboard'
import { CopyToClipboard } from "react-copy-to-clipboard";
import ControlledAccordions from './ControlledAccordions'
import OnlineConverter from './OnlineConverter'
import 'react-notifications-component/dist/theme.css'
import ControlledAccordions from "./ControlledAccordions";
import OnlineConverter from "./OnlineConverter";
import "react-notifications-component/dist/theme.css";
import ReactNotification from 'react-notifications-component'
import { store } from 'react-notifications-component'
import ReactNotification from "react-notifications-component";
import { store } from "react-notifications-component";
import AaxHashAlgorithm from './Utils/AaxHashAlgorithm'
import {
GoogleReCaptchaProvider,
withGoogleReCaptcha,
} from 'react-google-recaptcha-v3'
import AaxHashAlgorithm from "./Utils/AaxHashAlgorithm";
import { GoogleReCaptchaProvider, withGoogleReCaptcha } from "react-google-recaptcha-v3";
const useStyles = (theme) => ({
paper: {
marginTop: theme.spacing(8),
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
display: "flex",
flexDirection: "column",
alignItems: "center",
},
avatar: {
margin: theme.spacing(1),
backgroundColor: theme.palette.secondary.main,
},
form: {
width: '100%', // Fix IE 11 issue.
width: "100%", // Fix IE 11 issue.
marginTop: theme.spacing(1),
},
//Accordeon
heading: {
fontSize: theme.typography.pxToRem(15),
flexBasis: '33.33%',
flexBasis: "33.33%",
flexShrink: 0,
},
secondaryHeading: {
fontSize: theme.typography.pxToRem(15),
color: theme.palette.text.secondary,
},
})
});
class ChecksumResolver extends React.Component {
constructor(props) {
super(props)
super(props);
this.state = {
checksum: '',
fileName: 'input.aax',
activationBytes: '',
}
checksum: "",
fileName: "input.aax",
activationBytes: "",
};
}
componentDidMount() {
let path = window.location.pathname;
let checksumMatch = window.location.pathname.match(/([a-fA-F0-9]{40})/)
if(!checksumMatch) return;
let checksumMatch = window.location.pathname.match(/([a-fA-F0-9]{40})/);
if (!checksumMatch) return;
let checksum = checksumMatch[1];
// this.setState({});
this.setChecksum(checksum);
@ -90,151 +86,168 @@ class ChecksumResolver extends React.Component {
DarkerDisabledTextField = withStyles({
root: {
marginRight: 8,
'& .MuiInputBase-root.Mui-disabled': {
color: 'rgba(0, 0, 0, 0.6)',
"& .MuiInputBase-root.Mui-disabled": {
color: "rgba(0, 0, 0, 0.6)",
},
},
})(TextField)
})(TextField);
Copyright = function () {
return (
<Typography variant="body2" color="textSecondary" align="center">
{'Copyright © '}
{"Copyright © "}
<Link color="inherit" href="https://audible-tools.github.io/">
audible-tools
</Link>{' '}
</Link>{" "}
{new Date().getFullYear()}
{'. V 0.3'}
{". V 0.3"}
</Typography>
)
}
);
};
setChecksum = (value) => {
if (value.length > 40) {
return
return;
}
this.setState({ checksum: value })
}
this.setState({ checksum: value });
};
isChecksumValid = () => {
const { checksum } = this.state
const regex = RegExp('[a-f0-9]{40}')
const testResults = regex.test(checksum)
const { checksum } = this.state;
const regex = RegExp("[a-f0-9]{40}");
const testResults = regex.test(checksum);
return testResults
}
return testResults;
};
isInputInvalid = () => {
const { checksum } = this.state
if (!checksum || checksum === '') {
return false
const { checksum } = this.state;
if (!checksum || checksum === "") {
return false;
}
return !this.isChecksumValid()
}
return !this.isChecksumValid();
};
addNotification = function (text, success = true) {
store.addNotification({
message: text,
type: success ? 'success' : 'danger',
type: success ? "success" : "danger",
// type: "danger",
insert: 'bottom-left',
container: 'top-full',
animationIn: ['animate__animated', 'animate__fadeIn'],
animationOut: ['animate__animated', 'animate__fadeOut'],
insert: "bottom-left",
container: "top-full",
animationIn: ["animate__animated", "animate__fadeIn"],
animationOut: ["animate__animated", "animate__fadeOut"],
dismiss: {
duration: 3000,
onScreen: false,
},
})
}
});
};
requestActivationBytes = async (checksumX) => {
const checksum = checksumX ? checksumX : this.state.checksum
const checksum = checksumX ? checksumX : this.state.checksum;
window.history.pushState('page2', 'Title', '/' + checksum);
let executeRecaptcha = this.props.googleReCaptchaProps.executeRecaptcha
window.history.pushState("page2", "Title", "/" + checksum);
while(!executeRecaptcha) {
console.log('Recaptcha has not been loaded')
executeRecaptcha = this.props.googleReCaptchaProps?.executeRecaptcha
await new Promise(r => setTimeout(r, 100));
let executeRecaptcha = this.props.googleReCaptchaProps.executeRecaptcha;
while (!executeRecaptcha) {
console.log("Recaptcha has not been loaded");
executeRecaptcha = this.props.googleReCaptchaProps?.executeRecaptcha;
await new Promise((r) => setTimeout(r, 100));
}
const token = await executeRecaptcha('homepage')
console.log(`XToken: ${token}`)
const token = await executeRecaptcha("homepage");
console.log(`XToken: ${token}`);
try {
let request = await fetch(
`${process.env.REACT_APP_APISERVER}/api/v2/activation/${checksum}`,
{
headers: new Headers({ 'x-captcha-result': token }),
},
)
let result = await request.json()
const { success, activationBytes } = result
headers: new Headers({ "x-captcha-result": token }),
}
);
let result = await request.json();
const { success, activationBytes } = result;
if (success !== true) {
this.setState({ activationBytes: 'UNKNOWN' })
this.setState({ activationBytes: "UNKNOWN" });
this.addNotification(
'An error occured while resolving the activation bytes, please check your inputs',
false,
)
return
"An error occured while resolving the activation bytes, please check your inputs",
false
);
return;
}
if (success === true) {
const calculatedChecksum = await AaxHashAlgorithm.CalculateChecksum(
activationBytes,
)
activationBytes
);
if (calculatedChecksum == checksum) {
this.setState({ activationBytes: activationBytes })
this.addNotification('Successfully resolved the activation bytes')
return
this.setState({ activationBytes: activationBytes });
this.addNotification("Successfully resolved the activation bytes");
return;
}
this.setState({ activationBytes: 'API ERROR' })
this.setState({ activationBytes: "API ERROR" });
this.addNotification(
'An unexpected error occured while resolving the activation bytes, please try again',
false,
)
"An unexpected error occured while resolving the activation bytes, please try again",
false
);
}
} catch (error) {
this.setState({ activationBytes: error })
this.setState({ activationBytes: error });
this.addNotification(
'An error occured while resolving the activation bytes, please check your inputs',
false,
)
"An error occured while resolving the activation bytes, please check your inputs",
false
);
}
}
};
buf2hex(buffer) {
// buffer is an ArrayBuffer
return Array.prototype.map
.call(new Uint8Array(buffer), (x) => ('00' + x.toString(16)).slice(-2))
.join('')
.call(new Uint8Array(buffer), (x) => ("00" + x.toString(16)).slice(-2))
.join("");
}
acceptFiles = async (files) => {
const file = files[0]
await this.acceptFile(file)
}
const file = files[0];
await this.acceptFile(file);
};
acceptFile = async (file) => {
// if (!file.name.toLowerCase().endsWith(".aax")) {
// alert('FileType not supported!');
// return;
// }
if (!file.name.toLowerCase().endsWith(".aax")) {
// alert('FileType not supported!');
// return;
// notify user that the file type is not supported
// this.addNotification("FileType not supported!", false);
this.setState({ fileName: file.name, file: file })
const slic = file.slice(653, 653 + 20)
const results = this.buf2hex(await slic.arrayBuffer())
this.setChecksum(results)
this.requestActivationBytes()
}
// notify user that the file type is not supported with alert, ask if they want to continue
// Message if aaxc: "Only .aax files are supported, you have provided a .aaxc file. Renaming the file won't work, please provide a .aax file. You can download the .aax file from the Audible website. (eg: https://www.audible.de/library/titles)"
const fileExtension = file.name.includes(".") ? file.name.split(".").pop() : "unknown";
const message = file.name.toLowerCase().endsWith(".aaxc")
? "Only .aax files are supported, you have provided a .aaxc file. Renaming the file won't work, please provide a .aax file. You can download the .aax file from the Audible website. (eg: https://www.audible.de/library/titles) Do you want to continue anyway?"
: `.${fileExtension} files are not supported! Do you want to continue anyway?`;
const response = window.confirm(message);
if (!response) {
return;
}
}
this.setState({ fileName: file.name, file: file });
const slic = file.slice(653, 653 + 20);
const results = this.buf2hex(await slic.arrayBuffer());
this.setChecksum(results);
this.requestActivationBytes();
};
render() {
const { classes } = this.props
const { checksum, activationBytes, fileName, file } = this.state
const { classes } = this.props;
const { checksum, activationBytes, fileName, file } = this.state;
// const id = this.props.match.params.id;
// let { id } = useParams();
// console.log("IDDDDDD"+ id);
@ -254,8 +267,8 @@ class ChecksumResolver extends React.Component {
<Dropzone
noClick
onDrop={(acceptedFiles) => {
console.log(acceptedFiles)
this.acceptFiles(acceptedFiles)
console.log(acceptedFiles);
this.acceptFiles(acceptedFiles);
}}
>
{({ getRootProps, getInputProps }) => (
@ -280,7 +293,7 @@ class ChecksumResolver extends React.Component {
readOnly: false,
endAdornment: (
<FilePicker
extensions={['aax', 'AAX']}
extensions={["aax", "AAX"]}
maxSize={99999}
onChange={this.acceptFile}
onError={() => {}}
@ -297,16 +310,38 @@ class ChecksumResolver extends React.Component {
)}
</Dropzone>
<Button
fullWidth
variant="contained"
onClick={() => {
this.requestActivationBytes()
}}
disabled={!this.isChecksumValid()}
>
Request Activation Bytes
</Button>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<Button
fullWidth
variant="contained"
onClick={() => {
this.requestActivationBytes();
}}
disabled={!this.isChecksumValid()}
>
Request Activation Bytes
</Button>
{/* Paypal donate Button redirects to https://www.paypal.com/paypalme/jdawg1337*/}
<Button
style={{ marginLeft: 8, minWidth: 137 }}
variant="contained"
onClick={() => {
// window.location.href = "https://www.paypal.com/paypalme/jdawg1337";
// open in new tab
window.open("https://www.paypal.com/paypalme/jdawg1337", "_blank");
}}
>
{/* paypal icon */}
<a style={{ paddingLeft: 8, height: "100%" }}>Donate</a>
<img
style={{ marginLeft: -10, width: 50 }}
// src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png"
src="https://pngimg.com/uploads/paypal/paypal_PNG7.png"
alt="PayPal"
/>
</Button>
</div>
<this.DarkerDisabledTextField
value={activationBytes}
@ -315,7 +350,7 @@ class ChecksumResolver extends React.Component {
margin="normal"
fullWidth
id="activationBytes"
label={activationBytes ? '' : 'Activation Bytes'}
label={activationBytes ? "" : "Activation Bytes"}
name="activationBytes"
autoComplete="activationBytes"
aria-readonly
@ -341,9 +376,8 @@ class ChecksumResolver extends React.Component {
<this.Copyright />
</Box>
</Container>
)
);
}
}
export default withGoogleReCaptcha(withStyles(useStyles)(ChecksumResolver))
export default withGoogleReCaptcha(withStyles(useStyles)(ChecksumResolver));