diff --git a/docs/releases.md b/docs/releases.md index c9cc744b..08171bc3 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -30,6 +30,7 @@ to [@Joeharrison94](https://github.com/Joeharrison94) for the input. * `Upgrade` header check is now case in-sensitive ([#228](https://github.com/binwiederhier/ntfy/issues/228), thanks to [@wunter8](https://github.com/wunter8) for finding it) * Made web app sounds quieter ([#222](https://github.com/binwiederhier/ntfy/issues/222)) +* Add "private browsing"-specific error message for Firefox/Safari ([#208](https://github.com/binwiederhier/ntfy/issues/208), thanks to [@julianfoad](https://github.com/julianfoad) for reporting) **Additional translations:** diff --git a/web/public/static/langs/en.json b/web/public/static/langs/en.json index d668ce2c..ad05f57b 100644 --- a/web/public/static/langs/en.json +++ b/web/public/static/langs/en.json @@ -152,5 +152,7 @@ "error_boundary_description": "This should obviously not happen. Very sorry about this.
If you have a minute, please report this on GitHub, or let us know via Discord or Matrix.", "error_boundary_button_copy_stack_trace": "Copy stack trace", "error_boundary_stack_trace": "Stack trace", - "error_boundary_gathering_info": "Gather more info …" + "error_boundary_gathering_info": "Gather more info …", + "error_boundary_unsupported_indexeddb_title": "Private browsing not supported", + "error_boundary_unsupported_indexeddb_description": "The ntfy web app needs IndexedDB to function, and your browser does not support IndexedDB in private browsing mode.

While this is unfortunate, it also doesn't really make a lot of sense to use the ntfy web app in private browsing mode anyway, because everything is stored in the browser storage. You can read more about it in this GitHub issue, or talk to us on Discord or Matrix." } diff --git a/web/src/components/ErrorBoundary.js b/web/src/components/ErrorBoundary.js index 0a3393c5..c6d789a3 100644 --- a/web/src/components/ErrorBoundary.js +++ b/web/src/components/ErrorBoundary.js @@ -10,13 +10,28 @@ class ErrorBoundaryImpl extends React.Component { this.state = { error: false, originalStack: null, - niceStack: null + niceStack: null, + unsupportedIndexedDB: false }; } componentDidCatch(error, info) { console.error("[ErrorBoundary] Error caught", error, info); + // Special case for unsupported IndexedDB in Private Browsing mode (Firefox, Safari), see + // - https://github.com/dexie/Dexie.js/issues/312 + // - https://bugzilla.mozilla.org/show_bug.cgi?id=781982 + const isUnsupportedIndexedDB = error?.name === "InvalidStateError" || + (error?.name === "DatabaseClosedError" && error?.message?.indexOf("InvalidStateError") !== -1); + + if (isUnsupportedIndexedDB) { + this.handleUnsupportedIndexedDB(); + } else { + this.handleError(error, info); + } + } + + handleError(error, info) { // Immediately render original stack trace const prettierOriginalStack = info.componentStack .trim() @@ -36,6 +51,13 @@ class ErrorBoundaryImpl extends React.Component { }); } + handleUnsupportedIndexedDB() { + this.setState({ + error: true, + unsupportedIndexedDB: true + }); + } + copyStack() { let stack = ""; if (this.state.niceStack) { @@ -46,34 +68,61 @@ class ErrorBoundaryImpl extends React.Component { } render() { - const { t } = this.props; if (this.state.error) { - return ( -
-

{t("error_boundary_title")} 😮

-

- , - discordLink: , - matrixLink: - }} - /> -

-

- -

-

{t("error_boundary_stack_trace")}

- {this.state.niceStack - ?
{this.state.niceStack}
- : <> {t("error_boundary_gathering_info")}} -
{this.state.originalStack}
-
- ); + if (this.state.unsupportedIndexedDB) { + return this.renderUnsupportedIndexedDB(); + } else { + return this.renderError(); + } } return this.props.children; } + + renderUnsupportedIndexedDB() { + const { t } = this.props; + return ( +
+

{t("error_boundary_unsupported_indexeddb_title")} 😮

+

+ , + discordLink: , + matrixLink: + }} + /> +

+
+ ); + } + + renderError() { + const { t } = this.props; + return ( +
+

{t("error_boundary_title")} 😮

+

+ , + discordLink: , + matrixLink: + }} + /> +

+

+ +

+

{t("error_boundary_stack_trace")}

+ {this.state.niceStack + ?
{this.state.niceStack}
+ : <> {t("error_boundary_gathering_info")}} +
{this.state.originalStack}
+
+ ); + } } const ErrorBoundary = withTranslation()(ErrorBoundaryImpl); // Adds props.t