1 import PropTypes from 'prop-types';
2 import React from 'react';
4 import SettingsDialog from '../components/snes/SettingsDialog';
5 import SNESSocket from '../helpers/SNESSocket';
7 const context = React.createContext({});
9 export const useSNES = () => React.useContext(context);
11 export const SNESProvider = ({ children }) => {
12 const [enabled, setEnabled] = React.useState(false);
13 const [showSettingsDialog, setShowSettingsDialog] = React.useState(false);
15 const sock = React.useRef(null);
17 const [settings, setSettings] = React.useState({
24 const [status, setStatus] = React.useState({
31 React.useEffect(() => {
37 const tryAttach = () => {
38 const { deviceList } = sock.current;
40 if (deviceList.includes(settings.device)) {
41 device = settings.device;
42 } else if (deviceList.length > 0) {
43 device = deviceList[0];
45 setStatus(s => ({ ...s, device, deviceList }));
47 sock.current.attachDevice(device);
50 sock.current = new SNESSocket(`${settings.proto}://${settings.host}:${settings.port}`);
51 sock.current.onclose = () => {
59 sock.current.onerror = (e) => {
67 sock.current.onopen = () => {
74 sock.current.requestDeviceList(() => {
78 const watchdog = setInterval(() => {
79 if (!sock.current.isOpen()) {
83 if (!sock.current.device) {
84 sock.current.requestDeviceList(() => {
90 clearInterval(watchdog);
93 }, [enabled, settings]);
95 const enable = React.useCallback(() => {
96 setEnabled(prevEnabled => {
97 if (prevEnabled) return true;
102 const disable = React.useCallback(() => {
103 setEnabled(prevEnabled => {
104 if (!prevEnabled) return false;
109 const openSettings = React.useCallback(() => {
110 setShowSettingsDialog(true);
113 const closeSettings = React.useCallback(() => {
114 setShowSettingsDialog(false);
117 const saveSettings = React.useCallback((values) => {
119 const newSettings = { ...s, ...values };
120 localStorage.setItem('snes.settings', JSON.stringify(newSettings));
123 setShowSettingsDialog(false);
126 React.useEffect(() => {
127 const savedSettings = localStorage.getItem('snes.settings');
129 setSettings(JSON.parse(savedSettings));
133 const value = React.useMemo(() => {
134 return { disable, enable, enabled, openSettings, settings, sock, status };
135 }, [disable, enable, enabled, openSettings, settings, sock, status]);
137 return <context.Provider value={value}>
140 deviceList={status.deviceList}
141 onHide={closeSettings}
142 onSubmit={saveSettings}
144 show={showSettingsDialog}
149 SNESProvider.propTypes = {
150 children: PropTypes.node,