diff --git a/app/components/chat-list.tsx b/app/components/chat-list.tsx
index 8ad2b7dc0..8d02805f7 100644
--- a/app/components/chat-list.tsx
+++ b/app/components/chat-list.tsx
@@ -1,14 +1,13 @@
-import { useState, useRef, useEffect, useLayoutEffect } from "react";
import DeleteIcon from "../icons/delete.svg";
import styles from "./home.module.scss";
-
import {
- Message,
- SubmitKey,
- useChatStore,
- ChatSession,
- BOT_HELLO,
-} from "../store";
+ DragDropContext,
+ Droppable,
+ Draggable,
+ OnDragEndResponder,
+} from "@hello-pangea/dnd";
+
+import { useChatStore } from "../store";
import Locale from "../locales";
import { isMobileScreen } from "../utils";
@@ -20,54 +19,92 @@ export function ChatItem(props: {
count: number;
time: string;
selected: boolean;
+ id: number;
+ index: number;
}) {
return (
-
-
{props.title}
-
-
- {Locale.ChatItem.ChatItemCount(props.count)}
+
+ {(provided) => (
+
+
{props.title}
+
+
+ {Locale.ChatItem.ChatItemCount(props.count)}
+
+
{props.time}
+
+
+
+
- {props.time}
-
-
-
-
-
+ )}
+
);
}
export function ChatList() {
- const [sessions, selectedIndex, selectSession, removeSession] = useChatStore(
- (state) => [
+ const [sessions, selectedIndex, selectSession, removeSession, moveSession] =
+ useChatStore((state) => [
state.sessions,
state.currentSessionIndex,
state.selectSession,
state.removeSession,
- ],
- );
+ state.moveSession,
+ ]);
+
+ 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 (
-
- {sessions.map((item, i) => (
- selectSession(i)}
- onDelete={() =>
- (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) &&
- removeSession(i)
- }
- />
- ))}
-
+
+
+ {(provided) => (
+
+ {sessions.map((item, i) => (
+ selectSession(i)}
+ onDelete={() =>
+ (!isMobileScreen() || confirm(Locale.Home.DeleteChat)) &&
+ removeSession(i)
+ }
+ />
+ ))}
+ {provided.placeholder}
+
+ )}
+
+
);
}
diff --git a/app/components/home.module.scss b/app/components/home.module.scss
index 64ac2363f..da954dc1d 100644
--- a/app/components/home.module.scss
+++ b/app/components/home.module.scss
@@ -125,7 +125,7 @@
border-radius: 10px;
margin-bottom: 10px;
box-shadow: var(--card-shadow);
- transition: all 0.3s ease;
+ transition: background-color 0.3s ease;
cursor: pointer;
user-select: none;
border: 2px solid transparent;
diff --git a/app/store/app.ts b/app/store/app.ts
index d01e3cdd5..0a4d487da 100644
--- a/app/store/app.ts
+++ b/app/store/app.ts
@@ -189,6 +189,7 @@ interface ChatStore {
currentSessionIndex: number;
clearSessions: () => void;
removeSession: (index: number) => void;
+ moveSession: (from: number, to: number) => void;
selectSession: (index: number) => void;
newSession: () => void;
currentSession: () => ChatSession;
@@ -278,6 +279,31 @@ export const useChatStore = create
()(
});
},
+ moveSession(from: number, to: number) {
+ set((state) => {
+ const { sessions, currentSessionIndex: oldIndex } = state;
+
+ // move the session
+ const newSessions = [...sessions];
+ const session = newSessions[from];
+ newSessions.splice(from, 1);
+ newSessions.splice(to, 0, session);
+
+ // modify current session id
+ let newIndex = oldIndex === from ? to : oldIndex;
+ if (oldIndex > from && oldIndex <= to) {
+ newIndex -= 1;
+ } else if (oldIndex < from && oldIndex >= to) {
+ newIndex += 1;
+ }
+
+ return {
+ currentSessionIndex: newIndex,
+ sessions: newSessions,
+ };
+ });
+ },
+
newSession() {
set((state) => ({
currentSessionIndex: 0,