Skip to content

Commit

Permalink
Fix state and props usage
Browse files Browse the repository at this point in the history
  • Loading branch information
aemandine committed Aug 19, 2024
1 parent 81a8989 commit b2f4049
Showing 1 changed file with 47 additions and 43 deletions.
90 changes: 47 additions & 43 deletions packages/perseus/src/widgets/phet-sim.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import Banner from "@khanacademy/wonder-blocks-banner";
import {View} from "@khanacademy/wonder-blocks-core";
import IconButton from "@khanacademy/wonder-blocks-icon-button";
import cornersOutIcon from "@phosphor-icons/core/regular/corners-out.svg";
import PropTypes from "prop-types";
import * as React from "react";

import {PerseusI18nContext} from "../components/i18n-context";
Expand All @@ -28,12 +27,6 @@ type State = {

/* This renders the PhET sim */
class PhetSim extends React.Component<Props, State> {
static propTypes = {
...Changeable.propTypes,
url: PropTypes.string,
description: PropTypes.string,
};

static contextType = PerseusI18nContext;
declare context: React.ContextType<typeof PerseusI18nContext>;
private readonly iframeRef: React.RefObject<HTMLIFrameElement>;
Expand All @@ -48,32 +41,20 @@ class PhetSim extends React.Component<Props, State> {
super(props);
this.locale = this.getPhetCompatibleLocale(getDependencies().kaLocale);
this.iframeRef = React.createRef<HTMLIFrameElement>();
this.state.url = new URL(this.props.url);
this.state.url.searchParams.set("locale", this.locale);
if (this.state.url.origin !== "https://phet.colorado.edu") {
this.state.url = null;
}
}

getUserInput: () => any = () => {
return null;
};

async componentDidMount() {
// Display an error if we fail to load the resource
if (this.state.url) {
const validLink = await fetch(this.state.url).then(
(response: Response) => response.ok,
);
if (!validLink) {
this.setState({url: null});
}
}
// Display a warning if the simulation doesn't have our locale
if (await this.showLocaleWarning(this.locale)) {
this.setState({
errMessage: this.context.strings.simulationLocaleWarning,
});
await this.updateSimState(this.props.url);
}

async componentDidUpdate(prevProps) {
// If the URL has changed, update our state
if (prevProps.url !== this.props.url) {
await this.updateSimState(this.props.url);
}
}

Expand All @@ -93,28 +74,20 @@ class PhetSim extends React.Component<Props, State> {
text={this.state.errMessage}
/>
)}
<View
style={{
position: "relative",
width: "100%",
paddingBottom: "100%",
height: 0,
}}
>
<View>
<iframe
ref={this.iframeRef}
title={this.props.description}
sandbox={sandboxProperties}
style={{
width: "100%",
height: "100%",
position: "absolute",
width: 400,
height: 400,
}}
src={this.state.url?.toString()}
srcDoc={
this.state.url
? undefined
: this.context.strings.simulationLocaleWarning
: this.context.strings.simulationLoadFail
}
allow="fullscreen"
/>
Expand Down Expand Up @@ -165,17 +138,48 @@ class PhetSim extends React.Component<Props, State> {
}
};

async showLocaleWarning(locale: string): Promise<boolean> {
makeSafeUrl(urlString: string): URL | null {
let url: URL | null = null;
if (URL.canParse(urlString)) {
url = new URL(urlString);
url.searchParams.set("locale", this.locale);
if (url.origin !== "https://phet.colorado.edu") {
url = null;
}
}
return url;
}

async updateSimState(urlString: string) {
const url = this.makeSafeUrl(urlString);
if (url) {
// Display an error if we fail to load the resource
const validLink = await fetch(url)
.then((response: Response) => response.ok)
.catch(() => false);
if (validLink) {
const showLocaleWarning = await this.showLocaleWarning(url);
this.setState({
url: url,
errMessage: showLocaleWarning
? this.context.strings.simulationLocaleWarning
: null,
});
return;
}
}
this.setState({url: null, errMessage: null});
}

async showLocaleWarning(url: URL): Promise<boolean> {
// Do not show a locale warning on an invalid URL
if (!this.state.url) {
if (!url) {
return false;
}
// Grab the simulation name
const phetRegex: RegExp =
/https:\/\/phet\.colorado\.edu\/sims\/html\/([a-zA-Z0-9-]+)\/.*/g;
const match: RegExpExecArray | null = phetRegex.exec(
this.state.url.toString(),
);
const match: RegExpExecArray | null = phetRegex.exec(url.toString());
// Do not show a locale warning on a non-simulation URL
if (!match) {
return false;
Expand Down

0 comments on commit b2f4049

Please sign in to comment.