Improve graphql errors display in toast
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import { ApolloError } from '@apollo/client/errors';
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export const jsonSaveParse = <T = any>(...args: Parameters<typeof JSON.parse>): T | null => {
|
||||
try {
|
||||
@@ -41,3 +42,30 @@ export const getValueFromObject = <T>(obj: Record<string, any>, 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,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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<Theme>;
|
||||
}
|
||||
|
||||
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<EmptyViewProps, 'messageExtra'>) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -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(
|
||||
>
|
||||
<TitleComponent>{message}</TitleComponent>
|
||||
{actualDescription}
|
||||
{isDescriptionTooLong ? (
|
||||
{isDescriptionTooLong || (isGraphqlException && graphqlStackTrace) ? (
|
||||
<Button
|
||||
onClick={() => {
|
||||
awaitConfirmation({
|
||||
|
||||
Reference in New Issue
Block a user