import { sleep } from '@decky/ui'; import { ErrorInfo, FunctionComponent, useReducer, useState } from 'react'; import { uninstallPlugin } from '../plugin'; import { doRestart, doShutdown } from '../updater'; interface ReactErrorInfo { error: Error; info: ErrorInfo; } interface DeckyErrorBoundaryProps { error: ReactErrorInfo; errorKey: string; reset: () => void; } declare global { interface Window { SystemNetworkStore?: any; } } const pluginErrorRegex = /\(http:\/\/localhost:1337\/plugins\/(.*)\//; const pluginSourceMapErrorRegex = /\(decky:\/\/decky\/plugin\/(.*)\//; const legacyPluginErrorRegex = /\(decky:\/\/decky\/legacy_plugin\/(.*)\/index.js/; function getLikelyErrorSource(error: ReactErrorInfo): [source: string, wasPlugin: boolean] { const pluginMatch = error.error.stack?.match(pluginErrorRegex); if (pluginMatch) { return [decodeURIComponent(pluginMatch[1]), true]; } const pluginMatchViaMap = error.error.stack?.match(pluginSourceMapErrorRegex); if (pluginMatchViaMap) { return [decodeURIComponent(pluginMatchViaMap[1]), true]; } const legacyPluginMatch = error.error.stack?.match(legacyPluginErrorRegex); if (legacyPluginMatch) { return [decodeURIComponent(legacyPluginMatch[1]), true]; } if (error.error.stack?.includes('http://localhost:1337/')) { return ['the Decky frontend', false]; } return ['Steam', false]; } export const startSSH = DeckyBackend.callable('utilities/start_ssh'); export const starrCEFForwarding = DeckyBackend.callable('utilities/allow_remote_debugging'); function ipToString(ip: number) { return [(ip >>> 24) & 255, (ip >>> 16) & 255, (ip >>> 8) & 255, (ip >>> 0) & 255].join('.'); } // Intentionally not localized since we can't really trust React here const DeckyErrorBoundary: FunctionComponent = ({ error, reset }) => { const [actionLog, addLogLine] = useReducer((log: string, line: string) => (log += '\n' + line), ''); const [actionsEnabled, setActionsEnabled] = useState(true); const [debugAllowed, setDebugAllowed] = useState(true); const [errorSource, wasCausedByPlugin] = getLikelyErrorSource(error); return (

⚠️ An error occured rendering this content.

This error likely occured in {getLikelyErrorSource(error)}.

{actionLog?.length > 0 && (
          
            Running actions...
            {actionLog}
          
        
)} {actionsEnabled && ( <>

Actions:

Use the touch screen.

{debugAllowed && (
)} {wasCausedByPlugin && (
{'\n'}
)} )}
        
          {error.error.stack}
          {'\n\n'}
          Component Stack:
          {error.info.componentStack}
        
      
); }; export default DeckyErrorBoundary;