mirror of
https://github.com/Yidadaa/ChatGPT-Next-Web.git
synced 2025-10-22 15:59:23 +08:00
refactor: init switching to nextjs router
This commit is contained in:
102
app/(app)/chat/layout.tsx
Normal file
102
app/(app)/chat/layout.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
"use client";
|
||||
import {
|
||||
DEFAULT_SIDEBAR_WIDTH,
|
||||
MAX_SIDEBAR_WIDTH,
|
||||
MIN_SIDEBAR_WIDTH,
|
||||
Path,
|
||||
} from "@/app/constant";
|
||||
import useDrag from "@/app/hooks/useDrag";
|
||||
import useMobileScreen from "@/app/hooks/useMobileScreen";
|
||||
import { updateGlobalCSSVars } from "@/app/utils/client";
|
||||
import { useRef, useState } from "react";
|
||||
import { useAppConfig } from "@/app/store/config";
|
||||
import React from "react";
|
||||
import { AuthPage } from "@/app/components/auth";
|
||||
import { SideBar } from "@/app/containers/Sidebar";
|
||||
import Screen from "@/app/components/Screen";
|
||||
import { useSwitchTheme } from "@/app/hooks/useSwitchTheme";
|
||||
import Chat from "@/app/containers/Chat/ChatPanel";
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
const [showPanel, setShowPanel] = useState(false);
|
||||
const [externalProps, setExternalProps] = useState({});
|
||||
const config = useAppConfig();
|
||||
useSwitchTheme();
|
||||
const isMobileScreen = useMobileScreen();
|
||||
|
||||
const startDragWidth = useRef(config.sidebarWidth ?? DEFAULT_SIDEBAR_WIDTH);
|
||||
// drag side bar
|
||||
const { onDragStart } = useDrag({
|
||||
customToggle: () => {
|
||||
config.update((config) => {
|
||||
config.sidebarWidth = DEFAULT_SIDEBAR_WIDTH;
|
||||
});
|
||||
},
|
||||
customDragMove: (nextWidth: number) => {
|
||||
const { menuWidth } = updateGlobalCSSVars(nextWidth);
|
||||
|
||||
document.documentElement.style.setProperty(
|
||||
"--menu-width",
|
||||
`${menuWidth}px`,
|
||||
);
|
||||
config.update((config) => {
|
||||
config.sidebarWidth = nextWidth;
|
||||
});
|
||||
},
|
||||
customLimit: (x: number) =>
|
||||
Math.max(
|
||||
MIN_SIDEBAR_WIDTH,
|
||||
Math.min(MAX_SIDEBAR_WIDTH, startDragWidth.current + x),
|
||||
),
|
||||
});
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
w-[100%] relative bg-center
|
||||
max-md:h-[100%]
|
||||
md:flex md:my-2.5
|
||||
`}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
flex flex-col px-6
|
||||
h-[100%]
|
||||
max-md:w-[100%] max-md:px-4 max-md:pb-4 max-md:flex-1
|
||||
md:relative md:basis-sidebar md:pb-6 md:rounded-md md:bg-menu
|
||||
`}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
{!isMobileScreen && (
|
||||
<div
|
||||
className={`group/menu-dragger cursor-col-resize w-[0.25rem] flex items-center justify-center`}
|
||||
onPointerDown={(e) => {
|
||||
startDragWidth.current = config.sidebarWidth;
|
||||
onDragStart(e as any);
|
||||
}}
|
||||
>
|
||||
<div className="w-[2px] opacity-0 group-hover/menu-dragger:opacity-100 bg-menu-dragger h-[100%] rounded-[2px]">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={`
|
||||
md:flex-1 md:h-[100%] md:w-page
|
||||
max-md:transition-all max-md:duration-300 max-md:absolute max-md:top-0 max-md:max-h-[100vh] max-md:w-[100%] ${
|
||||
showPanel ? "max-md:left-0" : "max-md:left-[101%]"
|
||||
} max-md:z-10
|
||||
`}
|
||||
>
|
||||
{/* <PanelComponent
|
||||
{...props}
|
||||
{...externalProps}
|
||||
setShowPanel={setShowPanel}
|
||||
setExternalProps={setExternalProps}
|
||||
showPanel={showPanel}
|
||||
/> */}
|
||||
{/* {children} */}
|
||||
<Chat></Chat>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
137
app/(app)/chat/page.tsx
Normal file
137
app/(app)/chat/page.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
"use client";
|
||||
import {
|
||||
DragDropContext,
|
||||
Droppable,
|
||||
OnDragEndResponder,
|
||||
} from "@hello-pangea/dnd";
|
||||
|
||||
import { useAppConfig, useChatStore } from "@/app/store";
|
||||
|
||||
import Locale from "@/app/locales";
|
||||
// import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { useRouter, usePathname } from "next/navigation";
|
||||
|
||||
import AddIcon from "@/app/icons/addIcon.svg";
|
||||
import NextChatTitle from "@/app/icons/nextchatTitle.svg";
|
||||
|
||||
import Modal from "@/app/components/Modal";
|
||||
import SessionItem from "@/app/containers/Chat/components/SessionItem";
|
||||
|
||||
export default function Page() {
|
||||
const [sessions, selectedIndex, selectSession, moveSession] = useChatStore(
|
||||
(state) => [
|
||||
state.sessions,
|
||||
state.currentSessionIndex,
|
||||
state.selectSession,
|
||||
state.moveSession,
|
||||
],
|
||||
);
|
||||
const config = useAppConfig();
|
||||
|
||||
const { isMobileScreen } = config;
|
||||
|
||||
const chatStore = useChatStore();
|
||||
|
||||
const pathname = usePathname();
|
||||
const onDragEnd: OnDragEndResponder = (result) => {
|
||||
const { destination, source } = result;
|
||||
if (!destination) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
destination.droppableId === source.droppableId &&
|
||||
destination.index === source.index
|
||||
) {
|
||||
return;
|
||||
}
|
||||
moveSession(source.index, destination.index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
h-[100%] flex flex-col
|
||||
md:px-0
|
||||
`}
|
||||
>
|
||||
<div data-tauri-drag-region>
|
||||
<div
|
||||
className={`
|
||||
flex items-center justify-between
|
||||
py-6 max-md:box-content max-md:h-0
|
||||
md:py-7
|
||||
`}
|
||||
data-tauri-drag-region
|
||||
>
|
||||
<div className="">
|
||||
<NextChatTitle />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer "
|
||||
onClick={() => {
|
||||
// if (config.dontShowMaskSplashScreen) {
|
||||
// chatStore.newSession();
|
||||
// navigate(Path.Chat);
|
||||
// } else {
|
||||
// navigate(Path.NewChat);
|
||||
// }
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={`pb-3 text-sm sm:text-sm-mobile text-text-chat-header-subtitle`}
|
||||
>
|
||||
Build your own AI assistant.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`flex-1 overflow-y-auto max-md:pb-chat-panel-mobile `}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<Droppable droppableId="chat-list">
|
||||
{(provided) => (
|
||||
<div
|
||||
ref={provided.innerRef}
|
||||
{...provided.droppableProps}
|
||||
className={`w-[100%]`}
|
||||
>
|
||||
{sessions.map((item, i) => (
|
||||
<SessionItem
|
||||
title={item.topic}
|
||||
time={new Date(item.lastUpdate).toLocaleString()}
|
||||
count={item.messages.length}
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
index={i}
|
||||
selected={i === selectedIndex}
|
||||
onClick={() => {
|
||||
// navigate(Path.Chat);
|
||||
// selectSession(i);
|
||||
}}
|
||||
onDelete={async () => {
|
||||
if (
|
||||
await Modal.warn({
|
||||
okText: Locale.ChatItem.DeleteOkBtn,
|
||||
cancelText: Locale.ChatItem.DeleteCancelBtn,
|
||||
title: Locale.ChatItem.DeleteTitle,
|
||||
content: Locale.ChatItem.DeleteContent,
|
||||
})
|
||||
) {
|
||||
chatStore.deleteSession(i);
|
||||
}
|
||||
}}
|
||||
mask={item.mask}
|
||||
isMobileScreen={isMobileScreen}
|
||||
/>
|
||||
))}
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</DragDropContext>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
21
app/(app)/layout.tsx
Normal file
21
app/(app)/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { AuthPage } from "@/app/components/auth";
|
||||
import { SideBar } from "@/app/containers/Sidebar";
|
||||
import Screen from "@/app/components/Screen";
|
||||
|
||||
export interface MenuWrapperInspectProps {
|
||||
setExternalProps?: (v: Record<string, any>) => void;
|
||||
setShowPanel?: (v: boolean) => void;
|
||||
showPanel?: boolean;
|
||||
[k: string]: any;
|
||||
}
|
||||
|
||||
export default function AppLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<Screen noAuth={<AuthPage />} sidebar={<SideBar />}>
|
||||
{children}
|
||||
</Screen>
|
||||
);
|
||||
}
|
4
app/(app)/settings/layout.tsx
Normal file
4
app/(app)/settings/layout.tsx
Normal file
@@ -0,0 +1,4 @@
|
||||
import React from "react";
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
return <>{children}</>;
|
||||
}
|
3
app/(app)/settings/page.tsx
Normal file
3
app/(app)/settings/page.tsx
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function Page() {
|
||||
return <></>;
|
||||
}
|
Reference in New Issue
Block a user