diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx index cab8812c3..4490d637d 100644 --- a/app/components/chat-list.tsx +++ b/app/components/chat-list.tsx @@ -1,5 +1,6 @@ import DeleteIcon from "../icons/delete.svg"; import styles from "./home.module.scss"; +import BotIcon from "../icons/bot.svg"; import { DragDropContext, Droppable, @@ -22,7 +23,38 @@ export function ChatItem(props: { id: number; index: number; }) { - return ( + const [sidebarCollapse] = useChatStore((state) => [state.sidebarCollapse]); + return sidebarCollapse ? ( + + {(provided) => ( +
+
+ {Locale.ChatItem.ChatItemCount(props.count).replace(/[^0-9]/g, "") + .length <= 3 + ? Locale.ChatItem.ChatItemCount(props.count).replace( + /[^0-9]/g, + "", + ) + : ":)"} +
+
+ +
+
+ )} +
+ ) : ( {(provided) => (
[ - state.sessions, - state.currentSessionIndex, - state.selectSession, - state.removeSession, - state.moveSession, - ]); + const [ + sidebarCollapse, + sessions, + selectedIndex, + selectSession, + removeSession, + moveSession, + ] = useChatStore((state) => [ + state.sidebarCollapse, + state.sessions, + state.currentSessionIndex, + state.selectSession, + state.removeSession, + state.moveSession, + ]); const chatStore = useChatStore(); const onDragEnd: OnDragEndResponder = (result) => { @@ -78,31 +117,39 @@ export function ChatList() { }; return ( - - - {(provided) => ( -
- {sessions.map((item, i) => ( - selectSession(i)} - onDelete={() => chatStore.deleteSession(i)} - /> - ))} - {provided.placeholder} -
- )} -
-
+ <> + {sidebarCollapse && ( +
+ +
+ )} + + + {(provided: any) => ( +
+ {sessions.map((item, i) => ( + selectSession(i)} + onDelete={chatStore.deleteSession} + /> + ))} + + {provided.placeholder} +
+ )} +
+
+ ); } diff --git a/app/components/chat.tsx b/app/components/chat.tsx index f7b67b293..9e6923d5b 100644 --- a/app/components/chat.tsx +++ b/app/components/chat.tsx @@ -400,17 +400,17 @@ export function ChatActions(props: { ); } -export function Chat(props: { - showSideBar?: () => void; - sideBarShowing?: boolean; -}) { +export function Chat() { type RenderMessage = Message & { preview?: boolean }; const chatStore = useChatStore(); - const [session, sessionIndex] = useChatStore((state) => [ - state.currentSession(), - state.currentSessionIndex, - ]); + const [sidebarCollapse, setSideBarCollapse, session, sessionIndex] = + useChatStore((state) => [ + state.sidebarCollapse, + state.setSidebarCollapse, + state.currentSession(), + state.currentSessionIndex, + ]); const fontSize = useChatStore((state) => state.config.fontSize); const inputRef = useRef(null); @@ -599,7 +599,7 @@ export function Chat(props: { // Auto focus useEffect(() => { - if (props.sideBarShowing && isMobileScreen()) return; + if (isMobileScreen() && sidebarCollapse) return; inputRef.current?.focus(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -624,7 +624,9 @@ export function Chat(props: { icon={} bordered title={Locale.Chat.Actions.ChatList} - onClick={props?.showSideBar} + onClick={() => { + setSideBarCollapse(!sidebarCollapse); + }} />
@@ -775,7 +777,7 @@ export function Chat(props: { setAutoScroll(false); setTimeout(() => setPromptHints([]), 500); }} - autoFocus={!props?.sideBarShowing} + autoFocus={sidebarCollapse} rows={inputRows} /> .chat-item-delete { opacity: 0.5; right: 10px; } +.chat-item-collapse:hover > .chat-item-delete-collapse { + opacity: 0.5; + right: 0px; +} + .chat-item:hover > .chat-item-delete:hover { opacity: 1; } +.chat-item-collapse:hover > .chat-item-delete-collapse:hover { + opacity: 1; +} + .chat-item-info { display: flex; justify-content: space-between; @@ -199,6 +285,10 @@ margin-top: 8px; } +.chat-item-info-collapse { + color: rgb(166, 166, 166); +} + .chat-item-count, .chat-item-date { overflow: hidden; @@ -212,14 +302,45 @@ padding-top: 20px; } +.sidebar-tail-narrow { + display: flex; + flex-direction: column-reverse; + justify-content: space-between; + padding-top: 20px; +} + +.sidebar-tail-collapse { + display: flex; + justify-content: space-between; + //padding-top: 20px; + flex-direction: column-reverse; +} + .sidebar-actions { display: inline-flex; } -.sidebar-action:not(:last-child) { +.sidebar-actions-collapse { + display: flex; + flex-direction: column-reverse; +} + +//.sidebar-action:not(:last-child) { +// margin-right: 15px; +//} + +.sidebar-action { margin-right: 15px; } +.sidebar-action-collapse { + margin-top: 15px; +} + +.sidebar-addIcon-collapse { + margin-top: 15px; +} + .chat { display: flex; flex-direction: column; diff --git a/app/components/home.tsx b/app/components/home.tsx index 828b7576a..950419672 100644 --- a/app/components/home.tsx +++ b/app/components/home.tsx @@ -16,6 +16,9 @@ import AddIcon from "../icons/add.svg"; import LoadingIcon from "../icons/three-dots.svg"; import CloseIcon from "../icons/close.svg"; +import LeftIcon from "../icons/left.svg"; +import RightIcon from "../icons/right.svg"; + import { useChatStore } from "../store"; import { getCSSVar, isMobileScreen } from "../utils"; import Locale from "../locales"; @@ -131,17 +134,21 @@ const useHasHydrated = () => { }; function _Home() { - const [createNewSession, currentIndex, removeSession] = useChatStore( - (state) => [ - state.newSession, - state.currentSessionIndex, - state.removeSession, - ], - ); + const [ + sidebarCollapse, + setSideBarCollapse, + createNewSession, + currentIndex, + removeSession, + ] = useChatStore((state) => [ + state.sidebarCollapse, + state.setSidebarCollapse, + state.newSession, + state.currentSessionIndex, + state.removeSession, + ]); const chatStore = useChatStore(); const loading = !useHasHydrated(); - const [showSideBar, setShowSideBar] = useState(true); - // setting const [openSettings, setOpenSettings] = useState(false); const config = useChatStore((state) => state.config); @@ -164,85 +171,163 @@ function _Home() { }`} >
-
-
ChatGPT Next
-
- Build your own AI assistant. + {!sidebarCollapse && ( +
+
ChatGPT Next
+
+ Build your own AI assistant. +
+
+ +
-
- -
-
+ )}
{ setOpenSettings(false); - setShowSideBar(false); + if (window.innerWidth < 768) { + setSideBarCollapse(true); + } }} >
- -
-
-
- } - onClick={chatStore.deleteSession} - /> + {sidebarCollapse ? ( +
+
+
+ } + onClick={() => { + setSideBarCollapse(false); + }} + /> +
+
+ } + onClick={chatStore.deleteSession} + /> +
+
+ } + onClick={() => { + setOpenSettings(true); + setSideBarCollapse(true); + }} + shadow + /> +
+
-
+
} + className={styles["sidebar-addIcon-collapse"]} + icon={} + text={""} onClick={() => { - setOpenSettings(true); - setShowSideBar(false); + createNewSession(); + setSideBarCollapse(true); }} shadow />
- + ) : ( +
+
+
+ {sidebarCollapse ? ( + } + onClick={() => { + setSideBarCollapse(false); + }} + /> + ) : ( + } + onClick={() => { + setSideBarCollapse(true); + }} + /> + )} +
+
+ } + onClick={chatStore.deleteSession} + /> +
+
+ } + onClick={() => { + setOpenSettings(true); + setSideBarCollapse(true); + }} + shadow + /> +
+ +
+
+ } + // Auto hide Text 'Next Chat' when sidebar width shrinks + text={ + !isMobileScreen() + ? chatStore.config.sidebarWidth <= 340 + ? "" + : Locale.Home.NewChat + : Locale.Home.NewChat + } + onClick={() => { + createNewSession(); + setSideBarCollapse(true); + }} + shadow + />
-
- } - text={Locale.Home.NewChat} - onClick={() => { - createNewSession(); - setShowSideBar(false); - }} - shadow - /> -
-
+ )}
onDragMouseDown(e as any)} >
- -
+
{openSettings ? ( { setOpenSettings(false); - setShowSideBar(true); + setSideBarCollapse(false); }} /> ) : ( - setShowSideBar(true)} - sideBarShowing={showSideBar} - /> + )}
diff --git a/app/icons/left.svg b/app/icons/left.svg new file mode 100644 index 000000000..07952f6a5 --- /dev/null +++ b/app/icons/left.svg @@ -0,0 +1,14 @@ + + left + + + + + + + + + + \ No newline at end of file diff --git a/app/icons/right.svg b/app/icons/right.svg new file mode 100644 index 000000000..3fbf15291 --- /dev/null +++ b/app/icons/right.svg @@ -0,0 +1,14 @@ + + left + + + + + + + + + + \ No newline at end of file diff --git a/app/store/app.ts b/app/store/app.ts index 813668905..0e30b3eea 100644 --- a/app/store/app.ts +++ b/app/store/app.ts @@ -227,6 +227,8 @@ interface ChatStore { resetConfig: () => void; updateConfig: (updater: (config: ChatConfig) => void) => void; clearAllData: () => void; + sidebarCollapse: boolean; + setSidebarCollapse: (value: boolean) => void; } function countMessages(msgs: Message[]) { @@ -585,6 +587,13 @@ export const useChatStore = create()( location.reload(); } }, + + sidebarCollapse: false, + setSidebarCollapse(value) { + set({ + sidebarCollapse: value, + }); + }, }), { name: LOCAL_KEY, diff --git a/app/styles/globals.scss b/app/styles/globals.scss index cf36ee92b..c2f9d515c 100644 --- a/app/styles/globals.scss +++ b/app/styles/globals.scss @@ -59,8 +59,10 @@ --window-width: 90vw; --window-height: 90vh; --sidebar-width: 300px; + --sidebar-collapse-width: 75px; --window-content-width: calc(100% - var(--sidebar-width)); - --message-max-width: 80%; + --window-content-width-collapse: calc(100% - var(--sidebar-collapse-width)); + --message-max-width: 90%; --full-height: 100%; } @@ -103,6 +105,7 @@ body { @media only screen and (max-width: 600px) { background-color: var(--second); + --sidebar-width: 100vw; } }