Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,9 @@
"react-layout-kit": "^2.0.0",
"react-lazy-load": "^4.0.1",
"react-pdf": "^9.2.1",
"react-responsive": "^10.0.1",
"react-rnd": "^10.5.2",
"react-router-dom": "^7.9.4",
"react-scan": "^0.4.3",
"react-virtuoso": "^4.14.1",
"react-wrap-balancer": "^1.1.1",
Expand Down
2 changes: 1 addition & 1 deletion packages/utils/src/server/responsive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { UAParser } from 'ua-parser-js';
/**
* check mobile device in server
*/
const isMobileDevice = async () => {
export const isMobileDevice = async () => {
if (typeof process === 'undefined') {
throw new Error('[Server method] you are importing a server-only module outside of server');
}
Expand Down
26 changes: 0 additions & 26 deletions src/app/(backend)/trpc/desktop/[trpc]/route.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import { PropsWithChildren, memo } from 'react';

import Desktop from './Desktop';
import Mobile from './Mobile';

interface DetailLayoutProps extends PropsWithChildren {
mobile?: boolean;
}

const DetailLayout = memo<DetailLayoutProps>(({ children, mobile }) => {
if (mobile) {
return <Mobile>{children}</Mobile>;
}

return <Desktop>{children}</Desktop>;
});

DetailLayout.displayName = 'DetailLayout';

export default DetailLayout;
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
'use client';

import { ChatHeader } from '@lobehub/ui/mobile';
import { usePathname } from 'next/navigation';
import { useRouter } from 'nextjs-toploader/app';
import { memo } from 'react';
import urlJoin from 'url-join';
import { useLocation, useNavigate } from 'react-router-dom';

import { mobileHeaderSticky } from '@/styles/mobileHeader';

const Header = memo(() => {
const pathname = usePathname();
const router = useRouter();
const location = useLocation();
const navigate = useNavigate();

const path = pathname.split('/').filter(Boolean)[1];
// Extract the path segment (assistant, model, provider, mcp)
const path = location.pathname.split('/').find(Boolean);

return (
<ChatHeader
onBackClick={() => router.push(urlJoin('/discover', path))}
onBackClick={() => navigate(`/${path}`)}
showBackButton
style={mobileHeaderSticky}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
'use client';

import { memo } from 'react';
import { useParams } from 'react-router-dom';
import { Flexbox } from 'react-layout-kit';

import { withSuspense } from '@/components/withSuspense';
import { useDiscoverStore } from '@/store/discover';
import { DiscoverTab } from '@/types/discover';

import Breadcrumb from '../features/Breadcrumb';
import { TocProvider } from '../features/Toc/useToc';
import NotFound from '../components/NotFound';
import { DetailProvider } from './[...slugs]/features/DetailProvider';
import Details from './[...slugs]/features/Details';
import Header from './[...slugs]/features/Header';
import Loading from './[...slugs]/loading';

interface AssistantDetailPageProps {
mobile?: boolean;
}

const AssistantDetailPage = memo<AssistantDetailPageProps>(({ mobile }) => {
const params = useParams();
const slugs = params['*']?.split('/') || [];
const identifier = decodeURIComponent(slugs.join('/'));

const useAssistantDetail = useDiscoverStore((s) => s.useAssistantDetail);
const { data, isLoading } = useAssistantDetail({ identifier });

if (isLoading) return <Loading />;
if (!data) return <NotFound />;

return (
<TocProvider>
<DetailProvider config={data}>
{!mobile && <Breadcrumb identifier={identifier} tab={DiscoverTab.Assistants} />}
<Flexbox gap={16}>
<Header mobile={mobile} />
<Details mobile={mobile} />
</Flexbox>
</DetailProvider>
</TocProvider>
);
});

export default withSuspense(AssistantDetailPage);

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client';

import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

const NotFound = memo(() => {
const { t } = useTranslation('error', { keyPrefix: 'notFound' });

return (
<Flexbox
align="center"
height="100%"
justify="center"
style={{ minHeight: 400 }}
width="100%"
>
<h2>{t('title')}</h2>
</Flexbox>
);
});

export default NotFound;
4 changes: 2 additions & 2 deletions src/app/[variants]/(main)/discover/(detail)/features/Back.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import { Icon } from '@lobehub/ui';
import { createStyles } from 'antd-style';
import { ArrowLeft } from 'lucide-react';
import Link from 'next/link';
import { CSSProperties, memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';
import { Link } from 'react-router-dom';

const useStyles = createStyles(({ css, token }) => {
return {
Expand All @@ -25,7 +25,7 @@ const Back = memo<{ href: string; style?: CSSProperties }>(({ href, style }) =>
const { styles } = useStyles();

return (
<Link className={styles.back} href={href} style={{ marginBottom: 8, ...style }}>
<Link className={styles.back} style={{ marginBottom: 8, ...style }} to={href}>
<Flexbox align={'center'} gap={8} horizontal>
<Icon icon={ArrowLeft} />
{t(`back`)}
Expand Down
12 changes: 0 additions & 12 deletions src/app/[variants]/(main)/discover/(detail)/layout.tsx

This file was deleted.

51 changes: 51 additions & 0 deletions src/app/[variants]/(main)/discover/(detail)/mcp/McpDetailPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use client';

import { memo } from 'react';
import { useParams } from 'react-router-dom';
import { Flexbox } from 'react-layout-kit';

import { withSuspense } from '@/components/withSuspense';
import { DetailProvider } from '@/features/MCPPluginDetail/DetailProvider';
import Header from '@/features/MCPPluginDetail/Header';
import { useFetchInstalledPlugins } from '@/hooks/useFetchInstalledPlugins';
import { useQuery } from '@/hooks/useQuery';
import { useDiscoverStore } from '@/store/discover';
import { DiscoverTab } from '@/types/discover';

import Breadcrumb from '../features/Breadcrumb';
import { TocProvider } from '../features/Toc/useToc';
import NotFound from '../components/NotFound';
import Details from './[slug]/features/Details';
import Loading from './[slug]/loading';

interface McpDetailPageProps {
mobile?: boolean;
}

const McpDetailPage = memo<McpDetailPageProps>(({ mobile }) => {
const params = useParams();
const identifier = params['*'] || params.slug || '';

const { version } = useQuery() as { version?: string };
const useMcpDetail = useDiscoverStore((s) => s.useFetchMcpDetail);
const { data, isLoading } = useMcpDetail({ identifier, version });

useFetchInstalledPlugins();

if (isLoading) return <Loading />;
if (!data) return <NotFound />;

return (
<TocProvider>
<DetailProvider config={data}>
{!mobile && <Breadcrumb identifier={identifier} tab={DiscoverTab.Mcp} />}
<Flexbox gap={16}>
<Header mobile={mobile} />
<Details mobile={mobile} />
</Flexbox>
</DetailProvider>
</TocProvider>
);
});

export default withSuspense(McpDetailPage);
Loading
Loading