Skip to content

Instantly share code, notes, and snippets.

@mseeley
Created March 2, 2020 21:05
Show Gist options
  • Save mseeley/195d27d4a7306fa005e4083c07618393 to your computer and use it in GitHub Desktop.
Save mseeley/195d27d4a7306fa005e4083c07618393 to your computer and use it in GitHub Desktop.
import PropTypes from 'prop-types';
import React, { Fragment, useCallback, useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
// This version is not transpiled. Requires recent Chrome.
import { Parsec } from 'common/js/libs/parsec-2.0-b2011ff';
import { endPlayback } from 'common/js/stores/actions/ui/player/playerLifecycleActions';
// This version will be transpiled.
// import { Parsec } from './parsec-2.0-b2011ff';
function GamePlayer(props) {
const { url } = props;
const dispatch = useDispatch();
const [client, setClient] = useState(null);
const [identifiers, setIdentifiers] = useState(null);
const [video, setVideo] = useState(null);
const onClick = useCallback(() => {
dispatch(endPlayback({ playerType: 'game' }));
}, [dispatch]);
useEffect(() => {
if (!url) {
return;
}
let xhr = new window.XMLHttpRequest();
const cleanup = () => {
if (xhr) {
xhr.removeEventListener('load', onLoad);
xhr.removeEventListener('abort', onAbort);
xhr.removeEventListener('error', onError);
xhr.removeEventListener('timeout', onTimeout);
xhr.abort();
xhr = null;
}
};
const onLoad = (event) => {
const responseText = event.target.responseText;
// Endpoint returned XML regardless of `Content-Type`.
const peerIDMatches = responseText.match(/peerID="([^"]+)"/);
const sessionIDMatches = responseText.match(/sessionID="([^"]+)"/);
const identifiers_ = {
peerID: peerIDMatches?.[1],
sessionID: sessionIDMatches?.[1],
};
cleanup();
console.log('[Game] Fetched identifiers', identifiers_);
setIdentifiers(identifiers_);
};
const onAbort = () => {
cleanup();
debugger;
};
const onError = () => {
cleanup();
debugger;
};
const onTimeout = () => {
cleanup();
debugger;
};
xhr.open('GET', url, true);
xhr.addEventListener('load', onLoad);
xhr.addEventListener('abort', onAbort);
xhr.addEventListener('error', onError);
xhr.addEventListener('timeout', onTimeout);
console.log('[Game] Fetching identifiers from:', url);
xhr.send();
return () => {
cleanup();
};
}, [url, setIdentifiers]);
useEffect(() => {
if (video) {
console.log('[Game] Video ready, creating client');
setClient(
new Parsec(video, (event) => {
console.log('[Game] Client event:', event);
})
);
} else {
setClient(null);
}
}, [video, setClient]);
useEffect(() => {
if (client && identifiers) {
console.log('[Game] Connecting client:', identifiers);
client.connect(identifiers.sessionID, identifiers.peerID);
}
return () => {
if (client && identifiers) {
try {
console.log('[Game] Destroying client');
client.destroy();
} catch (error) {
console.error('[Game] Destroy error', error);
}
}
};
}, [client, identifiers]);
return (
<Fragment>
<button onClick={onClick}>End</button>
<video key={url} ref={setVideo} />
</Fragment>
);
}
GamePlayer.propTypes = {
isMiniPlayer: PropTypes.bool.isRequired,
url: PropTypes.string.isRequired,
};
export default GamePlayer;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment