@@ -12,11 +12,23 @@ import com.intellij.openapi.actionSystem.ActionUpdateThread
12
12
import com.intellij.openapi.actionSystem.AnAction
13
13
import com.intellij.openapi.actionSystem.AnActionEvent
14
14
import com.intellij.openapi.project.Project
15
+ import com.intellij.openapi.ui.Messages
15
16
import com.intellij.openapi.ui.popup.JBPopupFactory
17
+ import com.intellij.openapi.ui.popup.PopupStep
18
+ import com.intellij.openapi.ui.popup.util.BaseListPopupStep
16
19
import com.intellij.openapi.wm.ToolWindowManager
20
+ import com.intellij.ui.ColoredListCellRenderer
21
+ import com.intellij.ui.SimpleTextAttributes
17
22
import com.intellij.ui.components.JBList
18
- import java.text.SimpleDateFormat
23
+ import com.intellij.util.ui.JBUI
19
24
import java.util.*
25
+ import java.awt.BorderLayout
26
+ import java.awt.Component
27
+ import java.awt.event.MouseAdapter
28
+ import java.awt.event.MouseEvent
29
+ import javax.swing.JButton
30
+ import javax.swing.JPanel
31
+ import javax.swing.JLabel
20
32
import javax.swing.ListSelectionModel
21
33
22
34
class ViewHistoryAction : AnAction (
@@ -26,39 +38,173 @@ class ViewHistoryAction : AnAction(
26
38
) {
27
39
override fun getActionUpdateThread (): ActionUpdateThread = ActionUpdateThread .BGT
28
40
41
+ private fun formatRelativeTime (timestamp : Long ): String {
42
+ val now = System .currentTimeMillis()
43
+ val diff = now - timestamp
44
+
45
+ val seconds = diff / 1000
46
+ val minutes = seconds / 60
47
+ val hours = minutes / 60
48
+ val days = hours / 24
49
+ val weeks = days / 7
50
+ val months = days / 30
51
+ val years = days / 365
52
+
53
+ return when {
54
+ years > 0 -> " ${years} 年前"
55
+ months > 0 -> " ${months} 个月前"
56
+ weeks > 0 -> " ${weeks} 周前"
57
+ days > 0 -> " ${days} 天前"
58
+ hours > 0 -> " ${hours} 小时前"
59
+ minutes > 0 -> " ${minutes} 分钟前"
60
+ else -> " 刚刚"
61
+ }
62
+ }
63
+
64
+ private inner class SessionListItem (
65
+ val session : ChatSessionHistory ,
66
+ val relativeTime : String
67
+ )
68
+
69
+ private inner class SessionListCellRenderer (
70
+ private val project : Project ,
71
+ private val onDelete : (ChatSessionHistory ) -> Unit
72
+ ) : ColoredListCellRenderer<SessionListItem>() {
73
+
74
+ override fun customizeCellRenderer (
75
+ list : javax.swing.JList <out SessionListItem >,
76
+ value : SessionListItem ? ,
77
+ index : Int ,
78
+ selected : Boolean ,
79
+ hasFocus : Boolean
80
+ ) {
81
+ if (value == null ) return
82
+
83
+ // 创建主面板
84
+ val panel = JPanel (BorderLayout ())
85
+ panel.border = JBUI .Borders .empty(4 , 8 )
86
+
87
+ // 左侧标题
88
+ val titleLabel = JLabel (value.session.name)
89
+ titleLabel.font = titleLabel.font.deriveFont(14f )
90
+
91
+ // 右侧时间和删除按钮的面板
92
+ val rightPanel = JPanel (BorderLayout ())
93
+
94
+ // 时间标签
95
+ val timeLabel = JLabel (value.relativeTime)
96
+ timeLabel.font = timeLabel.font.deriveFont(12f )
97
+ timeLabel.foreground = if (selected) list.selectionForeground else list.foreground.darker()
98
+
99
+ // 删除按钮
100
+ val deleteButton = JButton (AllIcons .Actions .Close )
101
+ deleteButton.isOpaque = false
102
+ deleteButton.isBorderPainted = false
103
+ deleteButton.preferredSize = JBUI .size(16 , 16 )
104
+ deleteButton.addActionListener {
105
+ onDelete(value.session)
106
+ }
107
+
108
+ rightPanel.add(timeLabel, BorderLayout .CENTER )
109
+ rightPanel.add(deleteButton, BorderLayout .EAST )
110
+
111
+ panel.add(titleLabel, BorderLayout .WEST )
112
+ panel.add(rightPanel, BorderLayout .EAST )
113
+
114
+ // 设置简单的文本渲染
115
+ append(value.session.name, SimpleTextAttributes .REGULAR_ATTRIBUTES )
116
+ append(" - ${value.relativeTime} " , SimpleTextAttributes .GRAYED_ATTRIBUTES )
117
+ }
118
+ }
119
+
120
+ private inner class SessionPopupStep (
121
+ private val project : Project ,
122
+ private val sessions : List <ChatSessionHistory >
123
+ ) : BaseListPopupStep<SessionListItem>(
124
+ AutoDevBundle .message("popup.title.session.history"),
125
+ sessions.map { SessionListItem (it, formatRelativeTime(it.createdAt)) }
126
+ ) {
127
+
128
+ override fun getTextFor (value : SessionListItem ): String {
129
+ return value.session.name
130
+ }
131
+
132
+ override fun onChosen (selectedValue : SessionListItem , finalChoice : Boolean ): PopupStep <* >? {
133
+ if (finalChoice) {
134
+ loadSessionIntoSketch(project, selectedValue.session)
135
+ }
136
+ return PopupStep .FINAL_CHOICE
137
+ }
138
+
139
+ override fun hasSubstep (selectedValue : SessionListItem ): Boolean = false
140
+
141
+ override fun isSelectable (value : SessionListItem ): Boolean = true
142
+ }
143
+
29
144
override fun actionPerformed (e : AnActionEvent ) {
30
145
val project = e.project ? : return
31
146
val historyService = project.getService(ChatHistoryService ::class .java)
32
- val sessions = historyService.getAllSessions().sortedByDescending { it.createdAt }
147
+ var sessions = historyService.getAllSessions().sortedByDescending { it.createdAt }
33
148
34
149
if (sessions.isEmpty()) {
35
- // Optionally show a message if no history is available
36
150
return
37
151
}
38
152
39
- val listModel = sessions.map {
40
- val date = SimpleDateFormat (" yyyy-MM-dd HH:mm:ss" ).format(Date (it.createdAt))
41
- " ${it.name} - $date "
42
- }
43
-
44
- val jbList = JBList (listModel)
45
- jbList.selectionMode = ListSelectionModel .SINGLE_SELECTION
46
-
47
- JBPopupFactory .getInstance()
48
- .createListPopupBuilder(jbList)
49
- .setTitle(AutoDevBundle .message(" popup.title.session.history" ))
50
- .setMovable(true )
51
- .setResizable(true )
52
- .setRequestFocus(true )
53
- .setItemChoosenCallback {
54
- val selectedIndex = jbList.selectedIndex
55
- if (selectedIndex != - 1 ) {
56
- val selectedSession = sessions[selectedIndex]
57
- loadSessionIntoSketch(project, selectedSession)
153
+ fun createAndShowPopup () {
154
+ val listItems = sessions.map { SessionListItem (it, formatRelativeTime(it.createdAt)) }
155
+ val jbList = JBList (listItems)
156
+ jbList.selectionMode = ListSelectionModel .SINGLE_SELECTION
157
+
158
+ val onDeleteSession = { session: ChatSessionHistory ->
159
+ val result = Messages .showYesNoDialog(
160
+ project,
161
+ " 确定要删除会话 \" ${session.name} \" 吗?" ,
162
+ " 删除会话" ,
163
+ Messages .getQuestionIcon()
164
+ )
165
+
166
+ if (result == Messages .YES ) {
167
+ historyService.deleteSession(session.id)
168
+ sessions = historyService.getAllSessions().sortedByDescending { it.createdAt }
169
+ // 关闭当前popup并重新创建
170
+ createAndShowPopup()
58
171
}
59
172
}
60
- .createPopup()
61
- .showInBestPositionFor(e.dataContext)
173
+
174
+ jbList.cellRenderer = SessionListCellRenderer (project, onDeleteSession)
175
+
176
+ // 添加右键菜单支持
177
+ jbList.addMouseListener(object : MouseAdapter () {
178
+ override fun mouseClicked (e : MouseEvent ) {
179
+ if (e.button == MouseEvent .BUTTON3 ) { // 右键
180
+ val index = jbList.locationToIndex(e.point)
181
+ if (index >= 0 ) {
182
+ jbList.selectedIndex = index
183
+ val selectedSession = listItems[index].session
184
+ onDeleteSession(selectedSession)
185
+ }
186
+ }
187
+ }
188
+ })
189
+
190
+ JBPopupFactory .getInstance()
191
+ .createListPopupBuilder(jbList)
192
+ .setTitle(AutoDevBundle .message(" popup.title.session.history" ))
193
+ .setMovable(true )
194
+ .setResizable(true )
195
+ .setRequestFocus(true )
196
+ .setItemChoosenCallback {
197
+ val selectedIndex = jbList.selectedIndex
198
+ if (selectedIndex != - 1 ) {
199
+ val selectedSession = listItems[selectedIndex].session
200
+ loadSessionIntoSketch(project, selectedSession)
201
+ }
202
+ }
203
+ .createPopup()
204
+ .showInBestPositionFor(e.dataContext)
205
+ }
206
+
207
+ createAndShowPopup()
62
208
}
63
209
64
210
private fun loadSessionIntoSketch (project : Project , session : ChatSessionHistory ) {
0 commit comments