diff --git a/src/lib/HelperFunctions.ts b/src/lib/HelperFunctions.ts index 3cac3606..5a4aa7c3 100644 --- a/src/lib/HelperFunctions.ts +++ b/src/lib/HelperFunctions.ts @@ -7,6 +7,7 @@ */ import { ApolloError } from '@apollo/client/errors'; +import { ReactNode } from 'react'; export const jsonSaveParse = (...args: Parameters): T | null => { try { @@ -41,3 +42,30 @@ export const getValueFromObject = (obj: Record, key: string): T export const coerceIn = (value: number, min: number, max: number): number => Math.max(Math.min(value, max), min); export const noOp = () => {}; + +const GRAPHQL_EXCEPTION_MESSAGE_REGEX = /(.*Exception while fetching data \(.*\) : .*)\r\n\r\n(.*)/s; +export const extractGraphqlExceptionInfo = ( + error: ReactNode | string, +): { + isGraphqlException: boolean; + graphqlError?: string; + graphqlStackTrace?: string; +} => { + if (typeof error !== 'string') { + return { isGraphqlException: false }; + } + + const regexMatch = error.match(GRAPHQL_EXCEPTION_MESSAGE_REGEX); + + const isGraphqlException = !!regexMatch; + if (!isGraphqlException) { + return { isGraphqlException: false }; + } + + const [, message, stackTrace] = regexMatch; + return { + isGraphqlException: true, + graphqlError: message, + graphqlStackTrace: stackTrace, + }; +}; diff --git a/src/modules/core/components/feedback/EmptyView.tsx b/src/modules/core/components/feedback/EmptyView.tsx index c90ff4ae..634a0a8e 100644 --- a/src/modules/core/components/feedback/EmptyView.tsx +++ b/src/modules/core/components/feedback/EmptyView.tsx @@ -8,13 +8,14 @@ // adopted from: https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/main/java/eu/kanade/tachiyomi/widget/EmptyView.kt -import { useMemo, useState, type JSX } from 'react'; +import { type JSX, useMemo, useState } from 'react'; import Typography from '@mui/material/Typography'; import { SxProps, Theme } from '@mui/material/styles'; import { useTranslation } from 'react-i18next'; import Button from '@mui/material/Button'; import Stack from '@mui/material/Stack'; import Collapse from '@mui/material/Collapse'; +import { extractGraphqlExceptionInfo } from '@/lib/HelperFunctions.ts'; const ERROR_FACES = ['(・o・;)', 'Σ(ಠ_ಠ)', 'ಥ_ಥ', '(˘・_・˘)', '(; ̄Д ̄)', '(・Д・。']; @@ -31,34 +32,6 @@ export interface EmptyViewProps { sx?: SxProps; } -const GRAPHQL_EXCEPTION_MESSAGE_REGEX = /(.*Exception while fetching data \(.*\) : .*)\r\n\r\n(.*)/s; - -const extractGraphqlExceptionInfo = ( - error: EmptyViewProps['messageExtra'], -): { - isGraphqlException: boolean; - graphqlError?: string; - graphqlStackTrace?: string; -} => { - if (typeof error !== 'string') { - return { isGraphqlException: false }; - } - - const regexMatch = error.match(GRAPHQL_EXCEPTION_MESSAGE_REGEX); - - const isGraphqlException = !!regexMatch; - if (!isGraphqlException) { - return { isGraphqlException: false }; - } - - const [, message, stackTrace] = regexMatch; - return { - isGraphqlException: true, - graphqlError: message, - graphqlStackTrace: stackTrace, - }; -}; - const ExtraMessage = ({ messageExtra }: Pick) => { const { t } = useTranslation(); diff --git a/src/modules/core/components/feedback/SnackbarWithDescription.tsx b/src/modules/core/components/feedback/SnackbarWithDescription.tsx index 397391fb..5cff412f 100644 --- a/src/modules/core/components/feedback/SnackbarWithDescription.tsx +++ b/src/modules/core/components/feedback/SnackbarWithDescription.tsx @@ -17,6 +17,7 @@ import { awaitConfirmation } from '@/modules/core/utils/AwaitableDialog.tsx'; import { TranslationKey } from '@/Base.types.ts'; import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts'; import { MediaQuery } from '@/modules/core/utils/MediaQuery.tsx'; +import { extractGraphqlExceptionInfo } from '@/lib/HelperFunctions.ts'; const MAX_DESCRIPTION_LENGTH = 200; @@ -49,10 +50,13 @@ export const SnackbarWithDescription = memo( const severity = variant === 'default' ? 'info' : variant; const finalAction = typeof action === 'function' ? action(id) : action; - const isDescriptionTooLong = (description?.length ?? 0) > MAX_DESCRIPTION_LENGTH; + const { isGraphqlException, graphqlError, graphqlStackTrace } = extractGraphqlExceptionInfo(description); + + const finalDescription = isGraphqlException ? graphqlError : description; + const isDescriptionTooLong = (finalDescription?.length ?? 0) > MAX_DESCRIPTION_LENGTH; const actualDescription = isDescriptionTooLong - ? description?.slice(0, MAX_DESCRIPTION_LENGTH) - : description; + ? finalDescription?.slice(0, MAX_DESCRIPTION_LENGTH) + : finalDescription; const TitleComponent = actualDescription?.length ? AlertTitle : Fragment; @@ -79,7 +83,7 @@ export const SnackbarWithDescription = memo( > {message} {actualDescription} - {isDescriptionTooLong ? ( + {isDescriptionTooLong || (isGraphqlException && graphqlStackTrace) ? (