Skip to content

Commit

Permalink
⚡️ perf: improve setting page performance (#5218)
Browse files Browse the repository at this point in the history
* ⚡️ perf: improve setting page performance

* fix tests
  • Loading branch information
arvinxx authored Dec 28, 2024
1 parent 95153a4 commit 44ee25c
Show file tree
Hide file tree
Showing 10 changed files with 21 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import { Button, Dropdown } from 'antd';
import { createStyles } from 'antd-style';
import { ChevronDownIcon, SquareArrowOutUpRight } from 'lucide-react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { FlexboxProps } from 'react-layout-kit';

import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
import { SettingsTabs } from '@/store/global/initialState';
import { DiscoverProviderItem } from '@/types/discover';

const useStyles = createStyles(({ css }) => ({
Expand All @@ -29,7 +28,11 @@ interface ProviderConfigProps extends FlexboxProps {
const ProviderConfig = memo<ProviderConfigProps>(({ data }) => {
const { styles } = useStyles();
const { t } = useTranslation('discover');
const openSettings = useOpenSettings(SettingsTabs.LLM);

const router = useRouter();
const openSettings = () => {
router.push('/settings/llm');
};

const icon = <Icon icon={SquareArrowOutUpRight} size={{ fontSize: 16 }} />;

Expand All @@ -56,7 +59,7 @@ const ProviderConfig = memo<ProviderConfigProps>(({ data }) => {

if (!items || items?.length === 0)
return (
<Button onClick={openSettings} size={'large'} style={{ flex: 1 }} type={'primary'}>
<Button size={'large'} style={{ flex: 1 }} type={'primary'}>
{t('providers.config')}
</Button>
);
Expand Down
45 changes: 0 additions & 45 deletions src/app/@modal/(.)settings/modal/index.tsx

This file was deleted.

47 changes: 0 additions & 47 deletions src/app/@modal/(.)settings/modal/layout.tsx

This file was deleted.

5 changes: 0 additions & 5 deletions src/app/@modal/(.)settings/modal/loading.tsx

This file was deleted.

19 changes: 0 additions & 19 deletions src/app/@modal/(.)settings/modal/page.tsx

This file was deleted.

5 changes: 3 additions & 2 deletions src/features/MobileTabBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { rgba } from 'polished';
import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';

import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
import { SidebarTabKey } from '@/store/global/initialState';
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';

Expand All @@ -26,8 +25,10 @@ interface Props {
export default memo<Props>(({ className, tabBarKey }) => {
const { t } = useTranslation('common');
const { styles } = useStyles();
const openSettings = useOpenSettings();
const router = useRouter();
const openSettings = () => {
router.push('/settings/llm');
};
const { showMarket } = useServerConfigStore(featureFlagsSelectors);

const items: MobileTabBarProps['items'] = useMemo(
Expand Down
4 changes: 2 additions & 2 deletions src/features/User/UserAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ const UserAvatar = forwardRef<HTMLDivElement, UserAvatarProps>(

return (
<Avatar
alt={isSignedIn ? (username as string) : BRANDING_NAME}
avatar={isSignedIn ? avatar || DEFAULT_USER_AVATAR_URL : DEFAULT_USER_AVATAR_URL}
alt={isSignedIn && !!username ? username : BRANDING_NAME}
avatar={isSignedIn && !!avatar ? avatar : DEFAULT_USER_AVATAR_URL}
background={isSignedIn && avatar ? background : undefined}
className={cx(clickable && styles.clickable, className)}
ref={ref}
Expand Down
25 changes: 5 additions & 20 deletions src/features/User/UserPanel/useMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ActionIcon, DiscordIcon, Icon } from '@lobehub/ui';
import { DiscordIcon, Icon } from '@lobehub/ui';
import { Badge } from 'antd';
import { ItemType } from 'antd/es/menu/interface';
import {
Expand All @@ -13,14 +13,12 @@ import {
LifeBuoy,
LogOut,
Mail,
Maximize,
Settings2,
} from 'lucide-react';
import Link from 'next/link';
import { PropsWithChildren, memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import urlJoin from 'url-join';

import type { MenuProps } from '@/components/Menu';
import { LOBE_CHAT_CLOUD } from '@/const/branding';
Expand All @@ -35,11 +33,8 @@ import {
} from '@/const/url';
import { isServerMode } from '@/const/version';
import DataImporter from '@/features/DataImporter';
import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
import { usePWAInstall } from '@/hooks/usePWAInstall';
import { useQueryRoute } from '@/hooks/useQueryRoute';
import { configService } from '@/services/config';
import { SettingsTabs } from '@/store/global/initialState';
import { featureFlagsSelectors, useServerConfigStore } from '@/store/serverConfig';
import { useUserStore } from '@/store/user';
import { authSelectors } from '@/store/user/selectors';
Expand All @@ -51,7 +46,7 @@ const NewVersionBadge = memo(
children,
showBadge,
onClick,
}: PropsWithChildren & { onClick: () => void; showBadge?: boolean }) => {
}: PropsWithChildren & { onClick?: () => void; showBadge?: boolean }) => {
const { t } = useTranslation('common');
if (!showBadge)
return (
Expand All @@ -69,10 +64,8 @@ const NewVersionBadge = memo(
);

export const useMenu = () => {
const router = useQueryRoute();
const { canInstall, install } = usePWAInstall();
const hasNewVersion = useNewVersion();
const openSettings = useOpenSettings();
const { t } = useTranslation(['common', 'setting', 'auth']);
const { showCloudPromotion, hideDocs } = useServerConfigStore(featureFlagsSelectors);
const [isLogin, isLoginWithAuth, isLoginWithClerk, openUserProfile] = useUserStore((s) => [
Expand All @@ -93,20 +86,12 @@ export const useMenu = () => {

const settings: MenuProps['items'] = [
{
extra: (
<ActionIcon
icon={Maximize}
onClick={() => router.push(urlJoin('/settings', SettingsTabs.Common))}
size={'small'}
title={t('fullscreen')}
/>
),
icon: <Icon icon={Settings2} />,
key: 'setting',
label: (
<NewVersionBadge onClick={openSettings} showBadge={hasNewVersion}>
{t('userPanel.setting')}
</NewVersionBadge>
<Link href={'/settings/common'}>
<NewVersionBadge showBadge={hasNewVersion}>{t('userPanel.setting')}</NewVersionBadge>
</Link>
),
},
{
Expand Down
18 changes: 2 additions & 16 deletions src/hooks/useInterceptingRoutes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useGlobalStore } from '@/store/global';
import { ChatSettingsTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
import { useSessionStore } from '@/store/session';

import { useOpenChatSettings, useOpenSettings } from './useInterceptingRoutes';
import { useOpenChatSettings } from './useInterceptingRoutes';

// Mocks
vi.mock('next/navigation', () => ({
Expand All @@ -32,26 +32,12 @@ vi.mock('@/store/global', () => ({
},
}));

describe('useOpenSettings', () => {
it('should handle mobile route correctly', () => {
vi.mocked(useIsMobile).mockReturnValue(true);
const { result } = renderHook(() => useOpenSettings(SettingsTabs.Common));
expect(result.current()).toBe('/settings/common');
});

it('should handle desktop route correctly', () => {
vi.mocked(useIsMobile).mockReturnValue(false);
const { result } = renderHook(() => useOpenSettings(SettingsTabs.Agent));
expect(result.current()).toBe('/settings/modal?tab=agent');
});
});

describe('useOpenChatSettings', () => {
it('should handle inbox session id correctly', () => {
vi.mocked(useSessionStore).mockReturnValue(INBOX_SESSION_ID);
const { result } = renderHook(() => useOpenChatSettings());

expect(result.current()).toBe('/settings/modal?session=inbox&tab=agent'); // Assuming openSettings returns a function
expect(result.current()).toBe('/settings/agent'); // Assuming openSettings returns a function
});

it('should handle mobile route for chat settings', () => {
Expand Down
20 changes: 2 additions & 18 deletions src/hooks/useInterceptingRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,8 @@ import { useGlobalStore } from '@/store/global';
import { ChatSettingsTabs, SettingsTabs, SidebarTabKey } from '@/store/global/initialState';
import { useSessionStore } from '@/store/session';

export const useOpenSettings = (tab: SettingsTabs = SettingsTabs.Common) => {
const activeId = useSessionStore((s) => s.activeId);
const router = useQueryRoute();
const mobile = useIsMobile();

return useMemo(() => {
if (mobile) {
return () => router.push(urlJoin('/settings', tab));
} else {
// use Intercepting Routes on Desktop
return () => router.push('/settings/modal', { query: { session: activeId, tab } });
}
}, [mobile, tab, activeId, router]);
};

export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Meta) => {
const activeId = useSessionStore((s) => s.activeId);
const openSettings = useOpenSettings(SettingsTabs.Agent);
const router = useQueryRoute();
const mobile = useIsMobile();

Expand All @@ -34,13 +18,13 @@ export const useOpenChatSettings = (tab: ChatSettingsTabs = ChatSettingsTabs.Met
useGlobalStore.setState({
sidebarKey: SidebarTabKey.Setting,
});
return openSettings;
return () => router.push(urlJoin('/settings', SettingsTabs.Agent));
}
if (mobile) {
return () => router.push('/chat/settings');
} else {
// use Intercepting Routes on Desktop
return () => router.push('/chat/settings/modal', { query: { session: activeId, tab } });
}
}, [openSettings, mobile, activeId, router, tab]);
}, [mobile, activeId, router, tab]);
};

0 comments on commit 44ee25c

Please sign in to comment.