-
Notifications
You must be signed in to change notification settings - Fork 1
feat(vscode): improve renderer UI for better UX #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -217,48 +217,65 @@ private fun IdeaChangeSummaryHeader( | |
| } | ||
|
|
||
| /** | ||
| * Undo a file change by restoring the original content | ||
| * Undo a file change using IntelliJ's RollbackWorker for proper VCS integration. | ||
| * Falls back to manual revert if RollbackWorker fails. | ||
| */ | ||
| private fun undoChange(project: Project, change: FileChange) { | ||
| private fun undoChange(project: Project, fileChange: FileChange) { | ||
| ApplicationManager.getApplication().invokeLater { | ||
| runWriteAction { | ||
| try { | ||
| when (change.changeType) { | ||
| ChangeType.CREATE -> { | ||
| // For created files, delete or clear the content | ||
| try { | ||
| // Convert FileChange to IntelliJ Change and use RollbackWorker | ||
| val change = FileChangeConverter.toChange(project, fileChange) | ||
| val rollbackWorker = com.intellij.openapi.vcs.changes.ui.RollbackWorker(project) | ||
| rollbackWorker.doRollback(listOf(change), false) | ||
| } catch (e: Exception) { | ||
| logger.warn("RollbackWorker failed, falling back to manual revert", e) | ||
| // Fallback to manual revert | ||
| performManualUndo(project, fileChange) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Manual undo fallback when RollbackWorker fails. | ||
| */ | ||
| private fun performManualUndo(project: Project, change: FileChange) { | ||
| runWriteAction { | ||
| try { | ||
| when (change.changeType) { | ||
| ChangeType.CREATE -> { | ||
| // For created files, delete or clear the content | ||
| val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath) | ||
| virtualFile?.let { vf -> | ||
| val document = FileDocumentManager.getInstance().getDocument(vf) | ||
| document?.setText("") | ||
| } | ||
| } | ||
|
Comment on lines
+245
to
+252
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CREATE case should delete the file, not just clear content. For Apply this diff: ChangeType.CREATE -> {
- // For created files, delete or clear the content
+ // For created files, delete them
val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath)
- virtualFile?.let { vf ->
- val document = FileDocumentManager.getInstance().getDocument(vf)
- document?.setText("")
- }
+ virtualFile?.delete(project)
}🤖 Prompt for AI Agents |
||
| ChangeType.EDIT, ChangeType.RENAME -> { | ||
| // Restore original content | ||
| change.originalContent?.let { original -> | ||
| val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath) | ||
| virtualFile?.let { vf -> | ||
| val document = FileDocumentManager.getInstance().getDocument(vf) | ||
| document?.setText("") | ||
| } | ||
| } | ||
| ChangeType.EDIT, ChangeType.RENAME -> { | ||
| // Restore original content | ||
| change.originalContent?.let { original -> | ||
| val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath) | ||
| virtualFile?.let { vf -> | ||
| val document = FileDocumentManager.getInstance().getDocument(vf) | ||
| document?.setText(original) | ||
| } | ||
| document?.setText(original) | ||
| } | ||
| } | ||
| ChangeType.DELETE -> { | ||
| // For deleted files, we would need to recreate them | ||
| change.originalContent?.let { original -> | ||
| val parentPath = change.filePath.substringBeforeLast('/') | ||
| val fileName = change.filePath.substringAfterLast('/') | ||
| val parentDir = LocalFileSystem.getInstance().findFileByPath(parentPath) | ||
| parentDir?.let { dir -> | ||
| val newFile = dir.createChildData(project, fileName) | ||
| val document = FileDocumentManager.getInstance().getDocument(newFile) | ||
| document?.setText(original) | ||
| } | ||
| } | ||
| ChangeType.DELETE -> { | ||
| // For deleted files, we would need to recreate them | ||
| change.originalContent?.let { original -> | ||
| val parentPath = change.filePath.substringBeforeLast('/') | ||
| val fileName = change.filePath.substringAfterLast('/') | ||
| val parentDir = LocalFileSystem.getInstance().findFileByPath(parentPath) | ||
| parentDir?.let { dir -> | ||
| val newFile = dir.createChildData(project, fileName) | ||
| val document = FileDocumentManager.getInstance().getDocument(newFile) | ||
| document?.setText(original) | ||
| } | ||
| } | ||
| } | ||
| } catch (e: Exception) { | ||
| logger.error("Failed to undo change for ${change.filePath}", e) | ||
| } | ||
| } catch (e: Exception) { | ||
| logger.error("Failed to undo change for ${change.filePath}", e) | ||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+238
to
281
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Refactor duplicated performManualUndo logic into a shared utility. This function duplicates nearly identical logic from Consider creating a shared utility like this: object FileChangeUndoUtil {
fun performManualUndo(project: Project, change: FileChange, onSuccess: (() -> Unit)? = null) {
runWriteAction {
try {
when (change.changeType) {
ChangeType.CREATE -> {
val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath)
virtualFile?.delete(project)
}
ChangeType.EDIT, ChangeType.RENAME -> {
change.originalContent?.let { original ->
val virtualFile = LocalFileSystem.getInstance().findFileByPath(change.filePath)
virtualFile?.let { vf ->
val document = FileDocumentManager.getInstance().getDocument(vf)
document?.setText(original)
}
}
}
ChangeType.DELETE -> {
change.originalContent?.let { original ->
val parentPath = change.filePath.substringBeforeLast('/')
val fileName = change.filePath.substringAfterLast('/')
val parentDir = LocalFileSystem.getInstance().findFileByPath(parentPath)
parentDir?.let { dir ->
val newFile = dir.createChildData(project, fileName)
val document = FileDocumentManager.getInstance().getDocument(newFile)
document?.setText(original)
}
}
}
}
onSuccess?.invoke()
} catch (e: Exception) {
logger.error("Failed to undo change for ${change.filePath}", e)
}
}
}
}🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| .devin-renderer { | ||
| display: flex; | ||
| flex-direction: column; | ||
| gap: 8px; | ||
| } | ||
|
|
||
| .devin-tool-item { | ||
| border: 1px solid var(--vscode-panel-border); | ||
| border-radius: 4px; | ||
| overflow: hidden; | ||
| background-color: var(--vscode-editorWidget-background); | ||
| border-left: 3px solid var(--vscode-testing-iconPassed, #4caf50); | ||
| } | ||
|
|
||
| .devin-tool-header { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 8px; | ||
| padding: 8px 12px; | ||
| user-select: none; | ||
| transition: background-color 0.2s; | ||
| } | ||
|
|
||
| /* Only show pointer cursor when header is clickable (has params) */ | ||
| .devin-tool-header.clickable { | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| .devin-tool-header.clickable:hover { | ||
| background-color: var(--vscode-list-hoverBackground); | ||
| } | ||
|
|
||
| .devin-tool-icon { | ||
| font-size: 14px; | ||
| flex-shrink: 0; | ||
| } | ||
|
|
||
| .devin-tool-name { | ||
| font-weight: 600; | ||
| font-size: 12px; | ||
| color: var(--vscode-foreground); | ||
| } | ||
|
|
||
| .devin-tool-details { | ||
| font-size: 11px; | ||
| color: var(--vscode-descriptionForeground); | ||
| font-family: var(--vscode-editor-font-family, monospace); | ||
| overflow: hidden; | ||
| text-overflow: ellipsis; | ||
| white-space: nowrap; | ||
| flex: 1; | ||
| } | ||
|
|
||
| .devin-tool-actions { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 4px; | ||
| margin-left: auto; | ||
| flex-shrink: 0; | ||
| } | ||
|
|
||
| .devin-action-btn { | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| width: 24px; | ||
| height: 24px; | ||
| border: none; | ||
| border-radius: 4px; | ||
| background: transparent; | ||
| cursor: pointer; | ||
| font-size: 14px; | ||
| color: var(--vscode-descriptionForeground); | ||
| transition: background-color 0.2s; | ||
| } | ||
|
|
||
| .devin-action-btn:hover { | ||
| background-color: var(--vscode-list-hoverBackground); | ||
| } | ||
|
|
||
| .devin-action-btn.toggle { | ||
| font-size: 10px; | ||
| } | ||
|
|
||
| .devin-tool-params { | ||
| padding: 8px 12px; | ||
| border-top: 1px solid var(--vscode-panel-border); | ||
| background-color: var(--vscode-editor-background); | ||
| } | ||
|
|
||
| .devin-tool-params pre { | ||
| margin: 0; | ||
| font-family: var(--vscode-editor-font-family, monospace); | ||
| font-size: 11px; | ||
| line-height: 1.4; | ||
| white-space: pre-wrap; | ||
| word-break: break-word; | ||
| color: var(--vscode-editor-foreground); | ||
| } | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: phodal/auto-dev-sketch
Length of output: 2014
🏁 Script executed:
Repository: phodal/auto-dev-sketch
Length of output: 3757
🏁 Script executed:
Repository: phodal/auto-dev-sketch
Length of output: 2039
🏁 Script executed:
Repository: phodal/auto-dev-sketch
Length of output: 3448
Add missing imports for FileChangeConverter and RollbackWorker.
Line 227 uses
FileChangeConverter.toChange()but the import is missing. Addimport cc.unitmesh.devins.idea.toolwindow.changes.FileChangeConverterat the top of the file. Additionally, addimport com.intellij.openapi.vcs.changes.ui.RollbackWorkerand replace the fully qualified namecom.intellij.openapi.vcs.changes.ui.RollbackWorker(project)on line 228 with justRollbackWorker(project)for consistency with IdeaFileChangeDiffDialog.kt.🤖 Prompt for AI Agents