From c57cb79cb3b8b8c00fdf4baf5cca64a53f1ce3c9 Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Tue, 15 Jul 2025 14:46:06 -0700 Subject: [PATCH 1/3] fix(amazonq): render drag&drop overlay and fix the issue that images added to pinned context from drag&drop --- .../amazonq/toolwindow/AmazonQPanel.kt | 47 +++++++++++++++++++ .../services/amazonq/webview/Browser.kt | 9 ++++ 2 files changed, 56 insertions(+) diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt index 7fb75af2198..b452940f332 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt @@ -49,7 +49,9 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.utils.isCodeTrans import software.aws.toolkits.resources.message import java.awt.datatransfer.DataFlavor import java.awt.dnd.DropTarget +import java.awt.dnd.DropTargetDragEvent import java.awt.dnd.DropTargetDropEvent +import java.awt.dnd.DropTargetEvent import java.io.File import java.util.concurrent.CompletableFuture import javax.imageio.ImageIO.read @@ -138,6 +140,39 @@ class AmazonQPanel(val project: Project, private val scope: CoroutineScope) : Di // As an alternative, enabling the native drag in JCEF, // and let the native handling the drop event, and update the UI through JS bridge. val dropTarget = object : DropTarget() { + override fun dragEnter(dtde: DropTargetDragEvent) { + try { + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + "window.setDragAndDropVisible('true')", + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + } catch (e: Exception) { + LOG.error { "Failed to handle dragEnter: ${e.message}" } + } + } + override fun dragOver(dtde: DropTargetDragEvent) { + try { + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + "window.setDragAndDropVisible('true')", + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + } catch (e: Exception) { + LOG.error { "Failed to handle dragOver: ${e.message}" } + } + } + override fun dragExit(dte: DropTargetEvent) { + try { + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + "window.setDragAndDropVisible('false')", + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + } catch (e: Exception) { + LOG.error { "Failed to handle dragExit: ${e.message}" } + } + } override fun drop(dtde: DropTargetDropEvent) { try { dtde.acceptDrop(dtde.dropAction) @@ -166,6 +201,18 @@ class AmazonQPanel(val project: Project, private val scope: CoroutineScope) : Di validImages.subList(20, validImages.size).clear() } + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + "window.resetTopBarClicked()", + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + "window.setDragAndDropVisible('false')", + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + val json = OBJECT_MAPPER.writeValueAsString(validImages) browserInstance.jcefBrowser.cefBrowser.executeJavaScript( "window.handleNativeDrop('$json')", diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt index c092e1bf2f8..50684b427df 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/webview/Browser.kt @@ -181,6 +181,15 @@ class Browser(parent: Disposable, private val webUri: URI, val project: Project) }) }); }; + + window.setDragAndDropVisible = function(visibility) { + const parsedVisibility = JSON.parse(visibility); + qChat.setDragOverlayVisible(qChat.getSelectedTabId(), parsedVisibility) + }; + + window.resetTopBarClicked = function() { + qChat.resetTopBarClicked(qChat.getSelectedTabId()) + }; } """.trimIndent() From 0c89d77c1278d73c89d5592bb3ab45a56178426d Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Tue, 15 Jul 2025 15:22:57 -0700 Subject: [PATCH 2/3] fix(amazonq): add changelog --- .../bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json diff --git a/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json b/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json new file mode 100644 index 00000000000..5c34b22ce45 --- /dev/null +++ b/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json @@ -0,0 +1,4 @@ +{ + "type" : "bugfix", + "description" : "Fix the issue that sometime image added via drag & drop are incorrectly routing to pinned contexts and drag overlay is not rendered" +} \ No newline at end of file From 7bd3254e9482ef8a61647a54ee644488b1b405db Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Thu, 24 Jul 2025 15:13:07 -0700 Subject: [PATCH 3/3] fix(amazonq): comments --- ...-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json | 2 +- .../amazonq/toolwindow/AmazonQPanel.kt | 70 ++++++------------- 2 files changed, 24 insertions(+), 48 deletions(-) diff --git a/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json b/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json index 5c34b22ce45..dad10a96c13 100644 --- a/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json +++ b/.changes/next-release/bugfix-bf74f9c0-2d61-420d-854d-a5b0daa5861a.json @@ -1,4 +1,4 @@ { "type" : "bugfix", - "description" : "Fix the issue that sometime image added via drag & drop are incorrectly routing to pinned contexts and drag overlay is not rendered" + "description" : "Fix the issue that sometime images added via drag & drop are incorrectly routed to pinned context" } \ No newline at end of file diff --git a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt index cc6bea281aa..4ea60b26c6e 100644 --- a/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt +++ b/plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQPanel.kt @@ -141,37 +141,13 @@ class AmazonQPanel(val project: Project, private val scope: CoroutineScope) : Di // and let the native handling the drop event, and update the UI through JS bridge. val dropTarget = object : DropTarget() { override fun dragEnter(dtde: DropTargetDragEvent) { - try { - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.setDragAndDropVisible('true')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) - } catch (e: Exception) { - LOG.error { "Failed to handle dragEnter: ${e.message}" } - } + setDragAndDropOverlayVisible(browserInstance, true) } override fun dragOver(dtde: DropTargetDragEvent) { - try { - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.setDragAndDropVisible('true')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) - } catch (e: Exception) { - LOG.error { "Failed to handle dragOver: ${e.message}" } - } + setDragAndDropOverlayVisible(browserInstance, true) } override fun dragExit(dte: DropTargetEvent) { - try { - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.setDragAndDropVisible('false')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) - } catch (e: Exception) { - LOG.error { "Failed to handle dragExit: ${e.message}" } - } + setDragAndDropOverlayVisible(browserInstance, false) } override fun drop(dtde: DropTargetDropEvent) { try { @@ -201,32 +177,16 @@ class AmazonQPanel(val project: Project, private val scope: CoroutineScope) : Di validImages.subList(20, validImages.size).clear() } - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.resetTopBarClicked()", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) + executeJavaScript(browserInstance, "window.resetTopBarClicked()") - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.setDragAndDropVisible('false')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) + setDragAndDropOverlayVisible(browserInstance, false) val json = OBJECT_MAPPER.writeValueAsString(validImages) - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.handleNativeDrop('$json')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) + executeJavaScript(browserInstance, "window.handleNativeDrop('$json')") if (errorMessages.isNotEmpty()) { val errorJson = OBJECT_MAPPER.writeValueAsString(errorMessages) - browserInstance.jcefBrowser.cefBrowser.executeJavaScript( - "window.handleNativeNotify('$errorJson')", - browserInstance.jcefBrowser.cefBrowser.url, - 0 - ) + executeJavaScript(browserInstance, "window.handleNativeNotify('$errorJson')") } dtde.dropComplete(true) @@ -333,6 +293,22 @@ class AmazonQPanel(val project: Project, private val scope: CoroutineScope) : Di } } + private fun executeJavaScript(browserInstance: Browser, jsCommand: String) { + try { + browserInstance.jcefBrowser.cefBrowser.executeJavaScript( + jsCommand, + browserInstance.jcefBrowser.cefBrowser.url, + 0 + ) + } catch (e: Exception) { + LOG.error { "Failed to execute JavaScript: $jsCommand - ${e.message}" } + } + } + + private fun setDragAndDropOverlayVisible(browserInstance: Browser, visible: Boolean) { + executeJavaScript(browserInstance, "window.setDragAndDropVisible('$visible')") + } + private fun validateImageFile(file: File, allowedTypes: Set, maxFileSize: Double, maxDimension: Int): String? { val fileName = file.name val ext = fileName.substringAfterLast('.', "").lowercase()