import React, { SyntheticEvent, Component } from 'react'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel'; import AppBar from '@mui/material/AppBar'; import Toolbar from '@mui/material/Toolbar'; import Divider from '@mui/material/Divider'; import ArrowBackIcon from '@mui/icons-material/ArrowBack'; import JackHostStatus from './JackHostStatus'; import { PiPedalError } from './PiPedalError'; import DialogEx from './DialogEx'; import createStyles from '@mui/styles/createStyles'; import { Theme } from '@mui/material/styles'; import { withStyles, WithStyles } from '@mui/styles'; import Slide, { SlideProps } from '@mui/material/Slide'; interface AboutDialogProps extends WithStyles { open: boolean; onClose: () => void; }; interface AboutDialogState { jackStatus?: JackHostStatus; openSourceNotices: string; }; const styles = (theme: Theme) => createStyles({ dialogAppBar: { position: 'relative', top: 0, left: 0 }, dialogTitle: { marginLeft: theme.spacing(2), flex: 1, }, sectionHead: { marginLeft: 24, marginRight: 24, marginTop: 16, paddingBottom: 12 }, textBlock: { marginLeft: 24, marginRight: 24, marginTop: 16, paddingBottom: 0, opacity: 0.95 }, textBlockIndented: { marginLeft: 40, marginRight: 24, marginTop: 16, paddingBottom: 0, opacity: 0.95 }, setting: { minHeight: 64, width: "100%", textAlign: "left", paddingLeft: 22, paddingRight: 22 }, primaryItem: { }, secondaryItem: { }, can_select: { userSelect: "text", cursor: "text" }, no_select: { userSelect: "none", cursor: "text" } }); const Transition = React.forwardRef(function Transition( props: SlideProps, ref: React.Ref ) { return (); }); const AboutDialog = withStyles(styles, { withTheme: true })( class extends Component { model: PiPedalModel; refNotices: React.RefObject; constructor(props: AboutDialogProps) { super(props); this.model = PiPedalModelFactory.getInstance(); this.refNotices = React.createRef(); this.handleDialogClose = this.handleDialogClose.bind(this); this.state = { jackStatus: undefined, openSourceNotices: "" }; } mounted: boolean = false; subscribed: boolean = false; tick() { if (this.model.state.get() === State.Ready) { this.model.getJackStatus() .then(jackStatus => { this.setState({ jackStatus: jackStatus }); }) .catch(error => { /* ignore*/ }); } } timerHandle?: NodeJS.Timeout; updateNotifications() { let subscribed = this.mounted && this.props.open; if (subscribed !== this.subscribed) { if (subscribed) { this.timerHandle = setInterval(() => this.tick(), 1000); } else { if (this.timerHandle) { clearInterval(this.timerHandle); this.timerHandle = undefined; } } this.subscribed = subscribed; } } startFossRequest() { if (this.state.openSourceNotices === "") { fetch("var/notices.txt") .then((request) => { if (!request.ok) { throw new PiPedalError("notices request failed."); } return request.text(); }) .then((text) => { if (this.mounted) { this.setState({ openSourceNotices: text }); } }) .catch((err) => { // ok in debug builds. File doesn't get placed until install time. console.log("Failed to fetch open-source notices. " + err.toString()); }); } } componentDidMount() { super.componentDidMount?.(); this.mounted = true; this.updateNotifications(); this.startFossRequest(); } componentWillUnmount() { super.componentWillUnmount?.(); this.mounted = false; this.updateNotifications(); } componentDidUpdate(prevProps: Readonly, prevState: Readonly, snapshot: any): void { super.componentDidUpdate?.(prevProps, prevState, snapshot); this.updateNotifications(); } handleDialogClose(e: SyntheticEvent) { this.props.onClose(); } render() { let classes = this.props.classes; let addressKey = 0; let serverVersion = this.model.serverVersion?.serverVersion ?? ""; let nPos = serverVersion.indexOf(' '); if (nPos !== -1) { serverVersion = serverVersion.substring(nPos + 1); } return ( { this.props.onClose() }} TransitionComponent={Transition} onEnterKey={() => { this.props.onClose() }} style={{ userSelect: "none" }} >
About
PiPedal {serverVersion + (this.model.serverVersion?.debug ? " (Debug)" : "")}
Copyright © 2022-2024 Robin Davies. {this.model.isAndroidHosted() && ( {this.model.getAndroidHostVersion()} )} {this.model.isAndroidHosted() && ( Copyright © 2022-2024 Robin Davies. )} ADDRESSES
{ this.model.serverVersion?.webAddresses.map((address) => ( {address} )) }
SERVER OS
{this.model.serverVersion?.osVersion ?? ""}
LEGAL NOTICES
); } } ); export default AboutDialog;