Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 错误处理 & 配置优化 #58

Merged
merged 11 commits into from
May 24, 2024
3 changes: 1 addition & 2 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ const nextConfig = {
compress: isProd,
pageExtensions: ['tsx', 'ts'],
experimental: {
optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki'],
webVitalsAttribution: ['CLS', 'LCP'],
optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki', '@icons-pack/react-simple-icons','gpt-tokenizer'],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space after the comma for consistent formatting.

- '@icons-pack/react-simple-icons','gpt-tokenizer'
+ '@icons-pack/react-simple-icons', 'gpt-tokenizer'

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki', '@icons-pack/react-simple-icons','gpt-tokenizer'],
optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki', '@icons-pack/react-simple-icons', 'gpt-tokenizer'],

},
reactStrictMode: true,
webpack(config) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/utilities": "^3.2.2",
"@gltf-transform/core": "^3.10.1",
"@icons-pack/react-simple-icons": "^9.5.0",
"@lobehub/tts": "^1.24.1",
"@lobehub/ui": "^1.138.17",
"@pixiv/three-vrm": "^2.1.1",
Expand Down
4 changes: 2 additions & 2 deletions src/app/chat/Apps.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DancePanel, MarketPanel } from '@/panels';
import { useConfigStore } from '@/store/config';
import { useGlobalStore } from '@/store/global';
import { PanelKey } from '@/types/config';

export const apps = [
Expand All @@ -16,7 +16,7 @@ export const apps = [
];

export default () => {
const [panel] = useConfigStore((s) => [s.panel]);
const [panel] = useGlobalStore((s) => [s.panel]);

return (
<>
Expand Down
5 changes: 5 additions & 0 deletions src/app/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
'use client';

import dynamic from 'next/dynamic';

export default dynamic(() => import('@/components/Error'));
22 changes: 22 additions & 0 deletions src/app/global-error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import Error from 'next/error';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename the imported Error to avoid shadowing the global JavaScript Error object.

- import Error from 'next/error';
+ import NextError from 'next/error';

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
import Error from 'next/error';
import NextError from 'next/error';

import { useEffect } from 'react';

export default function GlobalError({
error,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
console.log('error', error);
}, [error]);
return (
<html>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a lang attribute to the html element to improve accessibility.

- <html>
+ <html lang="en">

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
<html>
<html lang="en">

<body>
<Error statusCode={undefined as any} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using undefined as any. Specify a valid status code or handle the undefined case appropriately.

- <Error statusCode={undefined as any} />
+ <NextError statusCode={500} />  // Example: Use a specific status code

Committable suggestion was skipped due low confidence.

</body>
</html>
);
}
6 changes: 1 addition & 5 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
import { Analytics } from '@vercel/analytics/react';
import { cookies } from 'next/headers';
import { PropsWithChildren } from 'react';

import { VIDOL_THEME_APPEARANCE } from '@/constants/theme';
import Layout from '@/layout';

import StyleRegistry from './StyleRegistry';

const RootLayout = ({ children }: PropsWithChildren) => {
// get default theme config to use with ssr
const cookieStore = cookies();
const appearance = cookieStore.get(VIDOL_THEME_APPEARANCE);

return (
<html lang="cn" suppressHydrationWarning>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide a valid value for the lang attribute, such as "zh-CN" for Chinese.

- <html lang="cn" suppressHydrationWarning>
+ <html lang="zh-CN" suppressHydrationWarning>

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
<html lang="cn" suppressHydrationWarning>
<html lang="zh-CN" suppressHydrationWarning>

<body>
<StyleRegistry>
<Layout defaultAppearance={appearance?.value}>{children}</Layout>
<Layout>{children}</Layout>
</StyleRegistry>
<Analytics />
</body>
Expand Down
2 changes: 1 addition & 1 deletion src/app/role/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const useStyles = createStyles(({ css }) => ({
preview: css`
overflow: auto;
width: 80rem;
margin: 32px auto;
margin: 0 auto;
`,
edit: css`
padding: 0 24px;
Expand Down
43 changes: 43 additions & 0 deletions src/components/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { createStyles } from 'antd-style';
import NextImage from 'next/image';

import { AVATAR_IMAGE_SIZE, DEFAULT_USER_AVATAR_URL } from '@/constants/common';

const useStyle = createStyles(
({ css, token }) => css`
cursor: pointer;
overflow: hidden;
border-radius: 50%;
transition:
scale 400ms ${token.motionEaseOut},
box-shadow 100ms ${token.motionEaseOut};

&:hover {
box-shadow: 0 0 0 3px ${token.colorText};
}

&:active {
scale: 0.8;
}
`,
);

interface Props {
avatar?: string;
size?: number;
}

export default (props: Props) => {
const { size = AVATAR_IMAGE_SIZE, avatar } = props;
const { styles } = useStyle();
return (
<NextImage
className={styles}
alt={avatar ? 'userAvatar' : 'LobeVidol'}
height={size}
src={!!avatar ? avatar : DEFAULT_USER_AVATAR_URL}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Simplify the conditional expression for clarity.

- src={!!avatar ? avatar : DEFAULT_USER_AVATAR_URL}
+ src={avatar ? avatar : DEFAULT_USER_AVATAR_URL}

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
src={!!avatar ? avatar : DEFAULT_USER_AVATAR_URL}
src={avatar ? avatar : DEFAULT_USER_AVATAR_URL}

unoptimized
width={size}
/>
);
};
61 changes: 61 additions & 0 deletions src/components/Error/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
'use client';

import { FluentEmoji } from '@lobehub/ui';
import { Button } from 'antd';
import Link from 'next/link';
import { memo, useEffect } from 'react';
import { Flexbox } from 'react-layout-kit';

import { MAX_WIDTH } from '@/constants/common';
import ResetConfig from '@/features/Actions/ClearSession';
import ClearChat from '@/features/Actions/ResetConfig';

interface ErrorCaptureProps {
error: Error & { digest?: string };
reset: () => void;
}

const ErrorCapture = memo<ErrorCaptureProps>(({ reset, error }) => {
useEffect(() => {
// Log the error to an error reporting service
console.error(error);
}, [error]);

return (
<Flexbox align={'center'} justify={'center'} style={{ minHeight: '100%', width: '100%' }}>
<h1
style={{
filter: 'blur(8px)',
fontSize: `min(${MAX_WIDTH / 6}px, 25vw)`,
fontWeight: 900,
margin: 0,
opacity: 0.12,
position: 'absolute',
zIndex: 0,
}}
>
ERROR
</h1>
<FluentEmoji emoji={'🤧'} size={64} />
<h2 style={{ fontWeight: 'bold', marginTop: '1em', textAlign: 'center' }}>
页面遇到一点问题...
</h2>
<p style={{ marginBottom: '2em' }}>
项目当前正在施工中,不保证数据稳定性,如果遇到问题可以尝试
<ClearChat text="清除会话消息" type={'link'} />
或 <ResetConfig text="重置系统设置" type={'link'} />
,造成地不便敬请谅解
</p>
<Flexbox gap={12} horizontal style={{ marginBottom: '1em' }}>
<Button onClick={() => reset()}>重新加载</Button>
<Link href="/">
<Button type={'primary'}>返回首页</Button>
</Link>
</Flexbox>
</Flexbox>
);
});

ErrorCapture.displayName = 'ErrorCapture';

export default ErrorCapture;
97 changes: 97 additions & 0 deletions src/components/Menu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { Menu as AntdMenu, MenuProps as AntdMenuProps, ConfigProvider } from 'antd';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using these imports only for type annotations to clean up the import statements.

- import { Menu as AntdMenu, MenuProps as AntdMenuProps, ConfigProvider } from 'antd';
+ import type { MenuProps as AntdMenuProps } from 'antd';
+ import { Menu as AntdMenu, ConfigProvider } from 'antd';

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
import { Menu as AntdMenu, MenuProps as AntdMenuProps, ConfigProvider } from 'antd';
import type { MenuProps as AntdMenuProps } from 'antd';
import { Menu as AntdMenu, ConfigProvider } from 'antd';

import { createStyles } from 'antd-style';
import { memo } from 'react';

const useStyles = createStyles(({ css, token, prefixCls }) => ({
compact: css`
display: flex;
flex-direction: column;
gap: 0.125rem;
`,
menu: css`
flex: 1;
background: transparent;
border: none !important;

.${prefixCls}-menu-item-divider {
margin-block: 0.125rem;
border-color: ${token.colorFillTertiary};

&:first-child {
margin-top: 0;
}

&:last-child {
margin-bottom: 0;
}
}

.${prefixCls}-menu-item, .${prefixCls}-menu-submenu-title {
display: flex;
gap: 0.75rem;
align-items: center;

height: unset;
min-height: 2rem;
padding: 0.375rem 0.75rem;

line-height: 2;

.anticon + .${prefixCls}-menu-title-content {
margin-inline-start: 0;
}
}

.${prefixCls}-menu-item-selected {
.${prefixCls}-menu-item-icon svg {
color: ${token.colorText};
}
}

.${prefixCls}-menu-item-icon svg {
color: ${token.colorTextSecondary};
}

.${prefixCls}-menu-title-content {
flex: 1;
}
`,
}));

export interface MenuProps extends AntdMenuProps {
variant?: 'default' | 'compact';
}

const Menu = memo<MenuProps>(({ className, selectable = false, variant, ...rest }) => {
const isCompact = variant === 'compact';
const { cx, styles, theme } = useStyles();
return (
<ConfigProvider
theme={{
components: {
Menu: {
controlHeightLG: 36,
iconMarginInlineEnd: 8,
iconSize: 16,
itemBorderRadius: theme.borderRadius,
itemColor: selectable ? theme.colorTextSecondary : theme.colorText,
itemHoverBg: theme.colorFillTertiary,
itemMarginBlock: isCompact ? 0 : 4,
itemMarginInline: isCompact ? 0 : 4,
itemSelectedBg: theme.colorFillSecondary,
paddingXS: -8,
},
},
}}
>
<AntdMenu
className={cx(styles.menu, isCompact && styles.compact, className)}
mode="vertical"
selectable={selectable}
{...rest}
/>
</ConfigProvider>
);
});

export default Menu;
4 changes: 3 additions & 1 deletion src/components/PageLoading/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { Center, Flexbox } from 'react-layout-kit';

interface PageLoadingProps {
className?: string;
description?: string;
style?: React.CSSProperties;
title: string;
}

const PageLoading = (props: PageLoadingProps) => {
const { title, className, style } = props;
const { title, className, style, description } = props;
return (
<Flexbox height={'100%'} width={'100%'} className={className} style={style}>
<Center flex={1} gap={12} width={'100%'}>
Expand All @@ -19,6 +20,7 @@ const PageLoading = (props: PageLoadingProps) => {
<Icon icon={Loader2} spin />
{title}
</Center>
{description && <Center>{description}</Center>}
</Center>
</Flexbox>
);
Expand Down
2 changes: 2 additions & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const LOADING_FLAG = '...';
export const DEFAULT_USER_AVATAR = '😀';

export const MAX_NAME_LENGTH = 20;

export const MAX_WIDTH = 1024;
export const MAX_DESCRIPTION_LENGTH = 100;
export const MAX_GREETING_LENGTH = 200;
export const MAX_README_LENGTH = 800;
Expand Down
17 changes: 0 additions & 17 deletions src/constants/settings.ts

This file was deleted.

41 changes: 41 additions & 0 deletions src/features/Actions/ClearSession.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { App, Button } from 'antd';
import { ButtonType } from 'antd/es/button';
Comment on lines +1 to +2
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optimize imports by using import type for type-only imports.

- import { App, Button } from 'antd';
- import { ButtonType } from 'antd/es/button';
+ import type { App, Button } from 'antd';
+ import type { ButtonType } from 'antd/es/button';

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
import { App, Button } from 'antd';
import { ButtonType } from 'antd/es/button';
import type { App, Button } from 'antd';
import type { ButtonType } from 'antd/es/button';

import React from 'react';

import { useAgentStore } from '@/store/agent';
import { useSessionStore } from '@/store/session';

interface Props {
text?: string;
type?: ButtonType;
}
export default (props: Props) => {
const { text = '立即清除', type = 'primary' } = props;
const clearAgentStorage = useAgentStore((s) => s.clearAgentStorage);
const clearSessions = useSessionStore((s) => s.clearSessions);
const { message, modal } = App.useApp();

const handleClear = () => {
modal.confirm({
cancelText: '取消',
centered: true,
content: '操作无法撤销,清除后数据将无法恢复,请慎重操作',
okButtonProps: {
danger: true,
},
okText: '确定',
onOk: () => {
clearSessions();
clearAgentStorage();
message.success('清除成功');
},
title: '确认清除所有会话消息?',
});
};

return (
<Button danger onClick={handleClear} type={type}>
{text}
</Button>
);
};
Loading
Loading