1
- import { useState , useRef , useEffect , useLayoutEffect } from "react" ;
2
1
import DeleteIcon from "../icons/delete.svg" ;
3
2
import styles from "./home.module.scss" ;
4
-
5
3
import {
6
- Message ,
7
- SubmitKey ,
8
- useChatStore ,
9
- ChatSession ,
10
- BOT_HELLO ,
11
- } from "../store" ;
4
+ DragDropContext ,
5
+ Droppable ,
6
+ Draggable ,
7
+ OnDragEndResponder ,
8
+ } from "@hello-pangea/dnd" ;
9
+
10
+ import { useChatStore } from "../store" ;
12
11
13
12
import Locale from "../locales" ;
14
13
import { isMobileScreen } from "../utils" ;
@@ -20,54 +19,92 @@ export function ChatItem(props: {
20
19
count : number ;
21
20
time : string ;
22
21
selected : boolean ;
22
+ id : number ;
23
+ index : number ;
23
24
} ) {
24
25
return (
25
- < div
26
- className = { `${ styles [ "chat-item" ] } ${
27
- props . selected && styles [ "chat-item-selected" ]
28
- } `}
29
- onClick = { props . onClick }
30
- >
31
- < div className = { styles [ "chat-item-title" ] } > { props . title } </ div >
32
- < div className = { styles [ "chat-item-info" ] } >
33
- < div className = { styles [ "chat-item-count" ] } >
34
- { Locale . ChatItem . ChatItemCount ( props . count ) }
26
+ < Draggable draggableId = { `${ props . id } ` } index = { props . index } >
27
+ { ( provided ) => (
28
+ < div
29
+ className = { `${ styles [ "chat-item" ] } ${
30
+ props . selected && styles [ "chat-item-selected" ]
31
+ } `}
32
+ onClick = { props . onClick }
33
+ ref = { provided . innerRef }
34
+ { ...provided . draggableProps }
35
+ { ...provided . dragHandleProps }
36
+ >
37
+ < div className = { styles [ "chat-item-title" ] } > { props . title } </ div >
38
+ < div className = { styles [ "chat-item-info" ] } >
39
+ < div className = { styles [ "chat-item-count" ] } >
40
+ { Locale . ChatItem . ChatItemCount ( props . count ) }
41
+ </ div >
42
+ < div className = { styles [ "chat-item-date" ] } > { props . time } </ div >
43
+ </ div >
44
+ < div className = { styles [ "chat-item-delete" ] } onClick = { props . onDelete } >
45
+ < DeleteIcon />
46
+ </ div >
35
47
</ div >
36
- < div className = { styles [ "chat-item-date" ] } > { props . time } </ div >
37
- </ div >
38
- < div className = { styles [ "chat-item-delete" ] } onClick = { props . onDelete } >
39
- < DeleteIcon />
40
- </ div >
41
- </ div >
48
+ ) }
49
+ </ Draggable >
42
50
) ;
43
51
}
44
52
45
53
export function ChatList ( ) {
46
- const [ sessions , selectedIndex , selectSession , removeSession ] = useChatStore (
47
- ( state ) => [
54
+ const [ sessions , selectedIndex , selectSession , removeSession , moveSession ] =
55
+ useChatStore ( ( state ) => [
48
56
state . sessions ,
49
57
state . currentSessionIndex ,
50
58
state . selectSession ,
51
59
state . removeSession ,
52
- ] ,
53
- ) ;
60
+ state . moveSession ,
61
+ ] ) ;
62
+
63
+ const onDragEnd : OnDragEndResponder = ( result ) => {
64
+ const { destination, source } = result ;
65
+ if ( ! destination ) {
66
+ return ;
67
+ }
68
+
69
+ if (
70
+ destination . droppableId === source . droppableId &&
71
+ destination . index === source . index
72
+ ) {
73
+ return ;
74
+ }
75
+
76
+ moveSession ( source . index , destination . index ) ;
77
+ } ;
54
78
55
79
return (
56
- < div className = { styles [ "chat-list" ] } >
57
- { sessions . map ( ( item , i ) => (
58
- < ChatItem
59
- title = { item . topic }
60
- time = { item . lastUpdate }
61
- count = { item . messages . length }
62
- key = { i }
63
- selected = { i === selectedIndex }
64
- onClick = { ( ) => selectSession ( i ) }
65
- onDelete = { ( ) =>
66
- ( ! isMobileScreen ( ) || confirm ( Locale . Home . DeleteChat ) ) &&
67
- removeSession ( i )
68
- }
69
- />
70
- ) ) }
71
- </ div >
80
+ < DragDropContext onDragEnd = { onDragEnd } >
81
+ < Droppable droppableId = "chat-list" >
82
+ { ( provided ) => (
83
+ < div
84
+ className = { styles [ "chat-list" ] }
85
+ ref = { provided . innerRef }
86
+ { ...provided . droppableProps }
87
+ >
88
+ { sessions . map ( ( item , i ) => (
89
+ < ChatItem
90
+ title = { item . topic }
91
+ time = { item . lastUpdate }
92
+ count = { item . messages . length }
93
+ key = { item . id }
94
+ id = { item . id }
95
+ index = { i }
96
+ selected = { i === selectedIndex }
97
+ onClick = { ( ) => selectSession ( i ) }
98
+ onDelete = { ( ) =>
99
+ ( ! isMobileScreen ( ) || confirm ( Locale . Home . DeleteChat ) ) &&
100
+ removeSession ( i )
101
+ }
102
+ />
103
+ ) ) }
104
+ { provided . placeholder }
105
+ </ div >
106
+ ) }
107
+ </ Droppable >
108
+ </ DragDropContext >
72
109
) ;
73
110
}
0 commit comments