Add information to the recovery page

Adds error & environment information to the recovery page when
available. The info will be displayed when the error boundary catches an error only.

Otherwise, does a few minor tweaks to the UI of the page.

- Add DevPage button to throw an uncaught error to go into recovery
- Add "Delete Save" button in recovery from Game Options (refactored into its own
component)
- Use "Soft Reset" button from Game Options (refactored into its own
component)
- The "Soft Reset" & "Delete Save" buttons now have confirmations
- Add tooltip on "Disable Recovery Mode" button
- Add timestamp to the RECOVERY.json filename
- Add textarea containing markdown with the current error details, if
available
  - Error
  - Page
  - Version
  - Environment
  - Platform
  - UserAgent
  - Features
  - Source
  - Stack Trace
- Change GitHub new issue link to contain default body & title, if possible
- Change links to not take the full width (they were clickable by mistake)
- Fix "Disable Recovery Mode" not resetting the ErrorBoundary's state,
making going back to terminal impossible
This commit is contained in:
Martin Fournier
2022-01-10 11:29:58 -05:00
parent 8b69fd7faa
commit 65964c84b2
7 changed files with 325 additions and 74 deletions
+135
View File
@@ -0,0 +1,135 @@
import React from "react";
import { Page } from "../ui/Router";
import { hash } from "../hash/hash";
import { CONSTANTS } from "../Constants";
enum GameEnv {
Production,
Development,
}
enum Platform {
Browser,
Steam,
}
interface GameVersion {
version: string;
hash: string;
toDisplay: () => string;
}
interface BrowserFeatures {
userAgent: string;
language: string;
cookiesEnabled: boolean;
doNotTrack: string | null;
indexedDb: boolean;
}
interface IErrorMetadata {
error: Error;
errorInfo?: React.ErrorInfo;
page?: Page;
environment: GameEnv;
platform: Platform;
version: GameVersion;
features: BrowserFeatures;
}
export interface IErrorData {
metadata: IErrorMetadata;
title: string;
body: string;
features: string;
fileName?: string;
issueUrl: string;
}
export const newIssueUrl = `https://github.com/danielyxie/bitburner/issues/new`;
function getErrorMetadata(error: Error, errorInfo?: React.ErrorInfo, page?: Page): IErrorMetadata {
const isElectron = navigator.userAgent.toLowerCase().indexOf(" electron/") > -1;
const env = process.env.NODE_ENV === "development" ? GameEnv.Development : GameEnv.Production;
const version: GameVersion = {
version: CONSTANTS.VersionString,
hash: hash(),
toDisplay: () => `v${CONSTANTS.VersionString} (${hash()})`,
}
const features: BrowserFeatures = {
userAgent: navigator.userAgent,
language: navigator.language,
cookiesEnabled: navigator.cookieEnabled,
doNotTrack: navigator.doNotTrack,
indexedDb: (!!window.indexedDB),
}
const metadata: IErrorMetadata = {
platform: isElectron ? Platform.Steam : Platform.Browser,
environment: env,
version, features,
error, errorInfo, page,
}
return metadata;
}
export function getErrorForDisplay(error: Error, errorInfo?: React.ErrorInfo, page?: Page): IErrorData {
const metadata = getErrorMetadata(error, errorInfo, page);
const fileName = (metadata.error as any).fileName;
const features = `lang=${metadata.features.language} cookiesEnabled=${metadata.features.cookiesEnabled.toString()}` +
` doNotTrack=${metadata.features.doNotTrack} indexedDb=${metadata.features.indexedDb.toString()}`;
const title = `${metadata.error.name}: ${metadata.error.message}${metadata.page && ` (at "${Page[metadata.page]}")`}`;
const body = `
## ${title}
### How did this happen?
Please fill this information with details if relevant.
- [ ] Save file
- [ ] Minimal scripts to reproduce the issue
- [ ] Steps to reproduce
### Environment
* Error: ${metadata.error?.toString() ?? 'n/a'}
* Page: ${metadata.page ? Page[metadata.page] : 'n/a'}
* Version: ${metadata.version.toDisplay()}
* Environment: ${GameEnv[metadata.environment]}
* Platform: ${Platform[metadata.platform]}
* UserAgent: ${navigator.userAgent}
* Features: ${features}
* Source: ${fileName ?? 'n/a'}
${metadata.environment === GameEnv.Development ? `
### Stack Trace
\`\`\`
${metadata.errorInfo?.componentStack.toString().trim()}
\`\`\`
` : ''}
### Save
\`\`\`
Copy your save here if possible
\`\`\`
`.trim();
const issueUrl = `${newIssueUrl}?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}`;
const data: IErrorData = {
metadata,
fileName,
features,
title,
body,
issueUrl,
}
return data;
}