Skip to content

Commit 8502347

Browse files
committed
refactor(devti): refactor file action handling in AutoDevInputSection #358
- Extract file action logic into FileListViewModel - Implement handleFileAction and determineFileAction methods - Simplify file action handling in AutoDevInputSection- Improve code readability and maintainability
1 parent ccc3c3d commit 8502347

File tree

2 files changed

+91
-25
lines changed

2 files changed

+91
-25
lines changed

core/src/main/kotlin/cc/unitmesh/devti/gui/chat/ui/AutoDevInputSection.kt

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -246,32 +246,23 @@ class AutoDevInputSection(private val project: Project, val disposable: Disposab
246246

247247
val wrapper = fileListViewModel.getListModel().getElementAt(index)
248248
val cellBounds = list.getCellBounds(index, index)
249-
wrapper.panel?.components?.firstOrNull { it.contains(e.x - cellBounds.x - it.x, it.height - 1) }
250-
?.let { component ->
251-
when {
252-
component is JPanel -> {
253-
fileListViewModel.removeFile(wrapper)
254-
val vfile = wrapper.virtualFile
255-
val relativePath = vfile.path.substringAfter(project.basePath!!).removePrefix("/")
256-
fileListViewModel.addFileIfAbsent(vfile)
257-
258-
input.appendText("\n/" + "file" + ":${relativePath}")
259-
fileListViewModel.removeFileByVirtualFile(wrapper.virtualFile)
260-
261-
ApplicationManager.getApplication().invokeLater {
262-
if (!vfile.isValid) return@invokeLater
263-
val psiFile = PsiManager.getInstance(project).findFile(vfile) ?: return@invokeLater
264-
val relatedElements =
265-
RelatedClassesProvider.provide(psiFile.language)?.lookupIO(psiFile)
266-
updateElements(relatedElements)
267-
}
268-
}
269-
270-
component is JLabel && component.icon == AllIcons.Actions.Close -> fileListViewModel.removeFile(wrapper)
271-
272-
else -> list.clearSelection()
249+
250+
val actionType = fileListViewModel.determineFileAction(wrapper, e.point, cellBounds)
251+
val actionPerformed = fileListViewModel.handleFileAction(wrapper, actionType) { vfile, relativePath ->
252+
if (relativePath != null) {
253+
input.appendText("\n/" + "file" + ":${relativePath}")
254+
ApplicationManager.getApplication().invokeLater {
255+
if (!vfile.isValid) return@invokeLater
256+
val psiFile = PsiManager.getInstance(project).findFile(vfile) ?: return@invokeLater
257+
val relatedElements = RelatedClassesProvider.provide(psiFile.language)?.lookupIO(psiFile)
258+
updateElements(relatedElements)
273259
}
274-
} ?: list.clearSelection()
260+
}
261+
}
262+
263+
if (!actionPerformed) {
264+
list.clearSelection()
265+
}
275266
}
276267

277268
private fun updateElements(elements: List<PsiElement>?) {
@@ -405,3 +396,4 @@ fun JComponent.mediumFontFunction() {
405396
}
406397
putClientProperty(FONT_KEY, f)
407398
}
399+

core/src/main/kotlin/cc/unitmesh/devti/gui/chat/ui/viewmodel/FileListViewModel.kt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.intellij.openapi.project.Project
99
import com.intellij.openapi.vfs.VirtualFile
1010
import java.util.EventListener
1111
import javax.swing.DefaultListModel
12+
import java.awt.Point
1213

1314
/**
1415
* ViewModel for managing the list of file presentations.
@@ -22,6 +23,12 @@ class FileListViewModel(private val project: Project) : Disposable {
2223
fun onListCleared()
2324
}
2425

26+
enum class FileActionType {
27+
INSERT,
28+
REMOVE,
29+
NONE
30+
}
31+
2532
private val listeners = mutableListOf<FileListChangeListener>()
2633

2734
fun addChangeListener(listener: FileListChangeListener) {
@@ -91,6 +98,73 @@ class FileListViewModel(private val project: Project) : Disposable {
9198
}
9299
}
93100

101+
/**
102+
* Handles file operations based on the action type.
103+
*
104+
* @param filePresentation The file presentation to operate on
105+
* @param actionType The type of action to perform
106+
* @param callback Callback to handle UI-specific operations
107+
* @return True if an action was performed, false otherwise
108+
*/
109+
fun handleFileAction(filePresentation: FilePresentation,
110+
actionType: FileActionType,
111+
callback: (VirtualFile, String?) -> Unit): Boolean {
112+
when (actionType) {
113+
FileActionType.INSERT -> {
114+
val vfile = filePresentation.virtualFile
115+
if (!vfile.isValid) return false
116+
117+
// Get relative path for display
118+
val relativePath = try {
119+
project.basePath?.let { basePath ->
120+
vfile.path.substringAfter(basePath).removePrefix("/")
121+
} ?: vfile.path
122+
} catch (e: Exception) {
123+
vfile.path
124+
}
125+
126+
// Remove and re-add to prioritize
127+
removeFile(filePresentation)
128+
addFileIfAbsent(vfile)
129+
130+
// Call back to UI with file and path
131+
callback(vfile, relativePath)
132+
133+
// Remove from list after processing
134+
removeFileByVirtualFile(vfile)
135+
return true
136+
}
137+
FileActionType.REMOVE -> {
138+
removeFile(filePresentation)
139+
return true
140+
}
141+
FileActionType.NONE -> return false
142+
}
143+
}
144+
145+
/**
146+
* Determines the appropriate action for a file based on component coordinates.
147+
*
148+
* @param filePresentation The file presentation
149+
* @param componentPoint The local point in the component
150+
* @param componentBounds The bounds of the component cell
151+
* @return The appropriate action type
152+
*/
153+
fun determineFileAction(filePresentation: FilePresentation, componentPoint: Point,
154+
componentBounds: java.awt.Rectangle): FileActionType {
155+
// Extract component hit detection logic
156+
val hitComponent = filePresentation.panel?.components?.firstOrNull {
157+
it.contains(componentPoint.x - componentBounds.x - it.x, it.height - 1)
158+
}
159+
160+
return when {
161+
hitComponent is javax.swing.JPanel -> FileActionType.INSERT
162+
hitComponent is javax.swing.JLabel &&
163+
hitComponent.icon == com.intellij.icons.AllIcons.Actions.Close -> FileActionType.REMOVE
164+
else -> FileActionType.NONE
165+
}
166+
}
167+
94168
override fun dispose() {
95169
listeners.clear()
96170
}

0 commit comments

Comments
 (0)