Skip to content

Commit

Permalink
feat: close ChatGPTNextWeb#380 collapse side bar
Browse files Browse the repository at this point in the history
  • Loading branch information
Yidadaa committed Apr 20, 2023
1 parent 5185166 commit 82ad057
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 35 deletions.
31 changes: 22 additions & 9 deletions app/components/chat-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function ChatItem(props: {
selected: boolean;
id: number;
index: number;
narrow?: boolean;
}) {
return (
<Draggable draggableId={`${props.id}`} index={props.index}>
Expand All @@ -35,13 +36,20 @@ export function ChatItem(props: {
{...provided.draggableProps}
{...provided.dragHandleProps}
>
<div className={styles["chat-item-title"]}>{props.title}</div>
<div className={styles["chat-item-info"]}>
<div className={styles["chat-item-count"]}>
{Locale.ChatItem.ChatItemCount(props.count)}
</div>
<div className={styles["chat-item-date"]}>{props.time}</div>
</div>
{props.narrow ? (
<div className={styles["chat-item-narrow"]}>{props.count}</div>
) : (
<>
<div className={styles["chat-item-title"]}>{props.title}</div>
<div className={styles["chat-item-info"]}>
<div className={styles["chat-item-count"]}>
{Locale.ChatItem.ChatItemCount(props.count)}
</div>
<div className={styles["chat-item-date"]}>{props.time}</div>
</div>
</>
)}

<div className={styles["chat-item-delete"]} onClick={props.onDelete}>
<DeleteIcon />
</div>
Expand All @@ -51,7 +59,7 @@ export function ChatItem(props: {
);
}

export function ChatList() {
export function ChatList(props: { narrow?: boolean }) {
const [sessions, selectedIndex, selectSession, removeSession, moveSession] =
useChatStore((state) => [
state.sessions,
Expand Down Expand Up @@ -101,7 +109,12 @@ export function ChatList() {
navigate(Path.Chat);
selectSession(i);
}}
onDelete={() => chatStore.deleteSession(i)}
onDelete={() => {
if (!props.narrow || confirm(Locale.Home.DeleteChat)) {
chatStore.deleteSession(i);
}
}}
narrow={props.narrow}
/>
))}
{provided.placeholder}
Expand Down
69 changes: 68 additions & 1 deletion app/components/home.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
flex-direction: column;
box-shadow: inset -2px 0px 2px 0px rgb(0, 0, 0, 0.05);
position: relative;
transition: width ease 0.1s;
transition: width ease 0.05s;
}

.sidebar-drag {
Expand Down Expand Up @@ -126,11 +126,13 @@
.sidebar-title {
font-size: 20px;
font-weight: bold;
animation: slide-in ease 0.3s;
}

.sidebar-sub-title {
font-size: 12px;
font-weight: 400px;
animation: slide-in ease 0.3s;
}

.sidebar-body {
Expand Down Expand Up @@ -171,6 +173,7 @@
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
animation: slide-in ease 0.3s;
}

.chat-item-delete {
Expand All @@ -197,6 +200,7 @@
color: rgb(166, 166, 166);
font-size: 12px;
margin-top: 8px;
animation: slide-in ease 0.3s;
}

.chat-item-count,
Expand All @@ -206,6 +210,69 @@
white-space: nowrap;
}

.narrow-sidebar {
.sidebar-title,
.sidebar-sub-title {
display: none;
}
.sidebar-logo {
position: relative;
display: flex;
justify-content: center;
}

.chat-item {
padding: 0;
min-height: 50px;
display: flex;
justify-content: center;
align-items: center;
transition: all ease 0.3s;

&:hover {
.chat-item-narrow {
transform: scale(0.7) translateX(-50%);
}
}
}

.chat-item-narrow {
font-weight: bolder;
font-size: 24px;
line-height: 0;
font-weight: lighter;
color: var(--black);
transform: translateX(0);
transition: all ease 0.3s;
opacity: 0.1;
padding: 4px;
}

.chat-item-delete {
top: 15px;
}

.chat-item:hover > .chat-item-delete {
opacity: 0.5;
right: 5px;
}

.sidebar-tail {
flex-direction: column;
align-items: center;

.sidebar-actions {
flex-direction: column;
align-items: center;

.sidebar-action {
margin-right: 0;
margin-bottom: 15px;
}
}
}
}

.sidebar-tail {
display: flex;
justify-content: space-between;
Expand Down
13 changes: 4 additions & 9 deletions app/components/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const SideBar = dynamic(async () => (await import("./sidebar")).SideBar, {
loading: () => <Loading noLogo />,
});

function useSwitchTheme() {
export function useSwitchTheme() {
const config = useChatStore((state) => state.config);

useEffect(() => {
Expand Down Expand Up @@ -83,7 +83,6 @@ const useHasHydrated = () => {
};

function WideScreen() {
// setting
const config = useChatStore((state) => state.config);

return (
Expand All @@ -92,9 +91,7 @@ function WideScreen() {
config.tightBorder ? styles["tight-container"] : styles.container
}`}
>
<div className={styles.sidebar}>
<SideBar></SideBar>
</div>
<SideBar />

<div className={styles["window-content"]}>
<Routes>
Expand All @@ -113,9 +110,7 @@ function MobileScreen() {

return (
<div className={styles.container}>
<div className={`${styles.sidebar} ${isHome && styles["sidebar-show"]}`}>
<SideBar />
</div>
<SideBar className={isHome ? styles["sidebar-show"] : ""} />

<div className={styles["window-content"]}>
<Routes>
Expand All @@ -129,8 +124,8 @@ function MobileScreen() {
}

export function Home() {
useSwitchTheme();
const isMobileScreen = useMobileScreen();
useSwitchTheme();

if (!useHasHydrated()) {
return <Loading />;
Expand Down
43 changes: 27 additions & 16 deletions app/components/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,28 @@ import Locale from "../locales";

import { useChatStore } from "../store";

import { Path, REPO_URL } from "../constant";
import {
MAX_SIDEBAR_WIDTH,
MIN_SIDEBAR_WIDTH,
NARROW_SIDEBAR_WIDTH,
Path,
REPO_URL,
} from "../constant";

import { HashRouter as Router, Link, useNavigate } from "react-router-dom";
import { useMobileScreen } from "../utils";
import { ChatList } from "./chat-list";

function useDragSideBar() {
const limit = (x: number) => Math.min(500, Math.max(220, x));
const limit = (x: number) => Math.min(MAX_SIDEBAR_WIDTH, x);

const chatStore = useChatStore();
const startX = useRef(0);
const startDragWidth = useRef(chatStore.config.sidebarWidth ?? 300);
const lastUpdateTime = useRef(Date.now());

const handleMouseMove = useRef((e: MouseEvent) => {
if (Date.now() < lastUpdateTime.current + 100) {
if (Date.now() < lastUpdateTime.current + 50) {
return;
}
lastUpdateTime.current = Date.now();
Expand All @@ -49,29 +55,36 @@ function useDragSideBar() {
window.addEventListener("mouseup", handleMouseUp.current);
};
const isMobileScreen = useMobileScreen();
const shouldNarrow =
!isMobileScreen && chatStore.config.sidebarWidth < MIN_SIDEBAR_WIDTH;

useEffect(() => {
const sideBarWidth = isMobileScreen
? "100vw"
: `${limit(chatStore.config.sidebarWidth ?? 300)}px`;
const barWidth = shouldNarrow
? NARROW_SIDEBAR_WIDTH
: limit(chatStore.config.sidebarWidth ?? 300);
const sideBarWidth = isMobileScreen ? "100vw" : `${barWidth}px`;
document.documentElement.style.setProperty("--sidebar-width", sideBarWidth);
}, [chatStore.config.sidebarWidth, isMobileScreen]);
}, [chatStore.config.sidebarWidth, isMobileScreen, shouldNarrow]);

return {
onDragMouseDown,
shouldNarrow,
};
}

export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) {
export function SideBar(props: { className?: string }) {
const chatStore = useChatStore();

// drag side bar
const { onDragMouseDown } = useDragSideBar();
const { onDragMouseDown, shouldNarrow } = useDragSideBar();
const navigate = useNavigate();
const isMobileScreen = useMobileScreen();

return (
<>
<div
className={`${styles.sidebar} ${props.className} ${
shouldNarrow && styles["narrow-sidebar"]
}`}
>
<div className={styles["sidebar-header"]}>
<div className={styles["sidebar-title"]}>ChatGPT Next</div>
<div className={styles["sidebar-sub-title"]}>
Expand All @@ -88,10 +101,9 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) {
if (e.target === e.currentTarget) {
navigate(Path.Home);
}
props.setShowSideBar?.(false);
}}
>
<ChatList />
<ChatList narrow={shouldNarrow} />
</div>

<div className={styles["sidebar-tail"]}>
Expand All @@ -116,10 +128,9 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) {
<div>
<IconButton
icon={<AddIcon />}
text={Locale.Home.NewChat}
text={shouldNarrow ? undefined : Locale.Home.NewChat}
onClick={() => {
chatStore.newSession();
props.setShowSideBar?.(false);
}}
shadow
/>
Expand All @@ -130,6 +141,6 @@ export function SideBar(props: { setShowSideBar?: (_: boolean) => void }) {
className={styles["sidebar-drag"]}
onMouseDown={(e) => onDragMouseDown(e as any)}
></div>
</>
</div>
);
}
4 changes: 4 additions & 0 deletions app/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ export enum Path {
Chat = "/chat",
Settings = "/settings",
}

export const MAX_SIDEBAR_WIDTH = 500;
export const MIN_SIDEBAR_WIDTH = 230;
export const NARROW_SIDEBAR_WIDTH = 100;

0 comments on commit 82ad057

Please sign in to comment.