about summary refs log tree commit diff
path: root/src/lib/hooks/useCleanError.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/hooks/useCleanError.ts')
-rw-r--r--src/lib/hooks/useCleanError.ts91
1 files changed, 91 insertions, 0 deletions
diff --git a/src/lib/hooks/useCleanError.ts b/src/lib/hooks/useCleanError.ts
new file mode 100644
index 000000000..dc9284e90
--- /dev/null
+++ b/src/lib/hooks/useCleanError.ts
@@ -0,0 +1,91 @@
+import {useCallback} from 'react'
+import {msg} from '@lingui/macro'
+import {useLingui} from '@lingui/react'
+
+type CleanedError = {
+  raw: string | undefined
+  clean: string | undefined
+}
+
+export function useCleanError() {
+  const {_} = useLingui()
+
+  return useCallback<(error?: any) => CleanedError>(
+    error => {
+      if (!error)
+        return {
+          raw: undefined,
+          clean: undefined,
+        }
+
+      let raw = error.toString()
+
+      if (isNetworkError(raw)) {
+        return {
+          raw,
+          clean: _(
+            msg`Unable to connect. Please check your internet connection and try again.`,
+          ),
+        }
+      }
+
+      if (
+        raw.includes('Upstream Failure') ||
+        raw.includes('NotEnoughResources') ||
+        raw.includes('pipethrough network error')
+      ) {
+        return {
+          raw,
+          clean: _(
+            msg`The server appears to be experiencing issues. Please try again in a few moments.`,
+          ),
+        }
+      }
+
+      if (raw.includes('Bad token scope')) {
+        return {
+          raw,
+          clean: _(
+            msg`This feature is not available while using an app password. Please sign in with your main password.`,
+          ),
+        }
+      }
+
+      if (raw.includes('Rate Limit Exceeded')) {
+        return {
+          raw,
+          clean: _(
+            msg`You've reached the maximum number of requests allowed. Please try again later.`,
+          ),
+        }
+      }
+
+      if (raw.startsWith('Error: ')) {
+        raw = raw.slice('Error: '.length)
+      }
+
+      return {
+        raw,
+        clean: undefined,
+      }
+    },
+    [_],
+  )
+}
+
+const NETWORK_ERRORS = [
+  'Abort',
+  'Network request failed',
+  'Failed to fetch',
+  'Load failed',
+]
+
+export function isNetworkError(e: unknown) {
+  const str = String(e)
+  for (const err of NETWORK_ERRORS) {
+    if (str.includes(err)) {
+      return true
+    }
+  }
+  return false
+}