Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
ca9deaa
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
2b4bf19
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
dc05bcb
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
9750c75
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
f996c1f
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
c98b8b2
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
0b2cc44
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 12, 2024
3f4cad0
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
a49f037
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
55692b3
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
9b54788
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
a7fc49c
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
61dfe59
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 13, 2024
51633da
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 14, 2024
35b059e
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 14, 2024
71997df
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 14, 2024
1981f4a
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 14, 2024
302595c
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 15, 2024
c02bc78
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 15, 2024
9da9389
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 16, 2024
0b4a5d9
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 18, 2024
26d1d25
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 18, 2024
b5be852
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 18, 2024
69b684f
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 19, 2024
6bec379
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 19, 2024
acd476e
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 19, 2024
e7bbcab
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 19, 2024
07c627c
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 19, 2024
2a6524e
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 20, 2024
d4eae94
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 20, 2024
b16b598
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 20, 2024
09930b0
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 20, 2024
794f006
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 20, 2024
5974403
Add framework for processing notifications (#5112)
manodnyab Nov 20, 2024
a235000
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 21, 2024
a1a5728
Add deserialization for notification messages retrieved from the noti…
manodnyab Nov 21, 2024
ae6d01a
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 21, 2024
bc31b59
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
6666e60
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
93af131
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
fcf7d38
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
dcb4204
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
87bbbce
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 22, 2024
dfe18e9
Show toasts for notifications and notification banner on critical not…
manodnyab Nov 22, 2024
b4950be
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 25, 2024
cbe7474
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
fe4788f
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
0cb5655
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
a987d25
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
038fffb
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
5bb683e
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
2fdb1d8
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 26, 2024
5f43277
Adding update/restart action to notifications (#5136)
bryceitoc9 Nov 27, 2024
33bfa44
Poll for new notifications (#5119)
samgst-amazon Nov 27, 2024
1eefd62
Merge main into feature/ideNotifs
aws-toolkit-automation Nov 27, 2024
b2e012a
Add logging info to IDE notification polling and processing (#5138)
samgst-amazon Nov 29, 2024
1c6f0d4
fix isFirstPoll not setting to false on first pass
samgst-amazon Nov 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import com.intellij.openapi.wm.ToolWindow
import com.intellij.openapi.wm.ToolWindowFactory
import com.intellij.openapi.wm.ex.ToolWindowEx
import com.intellij.ui.content.Content
import com.intellij.ui.content.ContentManager
import com.intellij.ui.components.panels.Wrapper
import com.intellij.util.ui.components.BorderLayoutPanel
import software.aws.toolkits.core.utils.debug
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.core.credentials.AwsBearerTokenConnection
Expand All @@ -22,6 +22,8 @@
import software.aws.toolkits.jetbrains.core.credentials.sono.Q_SCOPES
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState
import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenProviderListener
import software.aws.toolkits.jetbrains.core.notifications.NotificationPanel
import software.aws.toolkits.jetbrains.core.notifications.ProcessNotificationsBase
import software.aws.toolkits.jetbrains.core.webview.BrowserState
import software.aws.toolkits.jetbrains.services.amazonq.QWebviewPanel
import software.aws.toolkits.jetbrains.services.amazonq.RefreshQChatPanelButtonPressedListener
Expand All @@ -34,8 +36,22 @@
import java.awt.event.ComponentAdapter
import java.awt.event.ComponentEvent

class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {

Check warning on line 39 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Extension class should be final and non-public

Extension class should not be public

override fun createToolWindowContent(project: Project, toolWindow: ToolWindow) {
val mainPanel = BorderLayoutPanel()
val qPanel = Wrapper()
val notificationPanel = NotificationPanel()

mainPanel.addToTop(notificationPanel)
mainPanel.add(qPanel)
val notifListener = ProcessNotificationsBase.getInstance(project)
notifListener.addListenerForNotification { bannerContent ->
runInEdt {
notificationPanel.updateNotificationPanel(bannerContent)
}
}

if (toolWindow is ToolWindowEx) {
val actionManager = ActionManager.getInstance()
toolWindow.setTitleActions(listOf(actionManager.getAction("aws.q.toolwindow.titleBar")))
Expand All @@ -46,7 +62,7 @@
ToolkitConnectionManagerListener.TOPIC,
object : ToolkitConnectionManagerListener {
override fun activeConnectionChanged(newConnection: ToolkitConnection?) {
onConnectionChanged(project, newConnection, toolWindow)
onConnectionChanged(project, newConnection, qPanel)
}
}
)
Expand All @@ -56,8 +72,7 @@
object : RefreshQChatPanelButtonPressedListener {
override fun onRefresh() {
runInEdt {
contentManager.removeAllContents(true)
prepareChatContent(project, contentManager)
prepareChatContent(project, qPanel)
}
}
}
Expand All @@ -68,47 +83,41 @@
object : BearerTokenProviderListener {
override fun onChange(providerId: String, newScopes: List<String>?) {
if (ToolkitConnectionManager.getInstance(project).connectionStateForFeature(QConnection.getInstance()) == BearerTokenAuthState.AUTHORIZED) {
val content = contentManager.factory.createContent(AmazonQToolWindow.getInstance(project).component, null, false).also {
it.isCloseable = true
it.isPinnable = true
}
val qComponent = AmazonQToolWindow.getInstance(project).component

runInEdt {
contentManager.removeAllContents(true)
contentManager.addContent(content)
qPanel.setContent(qComponent)
}
}
}
}
)

val content = prepareChatContent(project, contentManager)
prepareChatContent(project, qPanel)

val content = contentManager.factory.createContent(mainPanel, null, false).also {
it.isCloseable = true
it.isPinnable = true
}
toolWindow.activate(null)
contentManager.setSelectedContent(content)
contentManager.addContent(content)
}

private fun prepareChatContent(
project: Project,
contentManager: ContentManager,
): Content {
qPanel: Wrapper,
) {
val component = if (isQConnected(project) && !isQExpired(project)) {
AmazonQToolWindow.getInstance(project).component
} else {
QWebviewPanel.getInstance(project).browser?.prepareBrowser(BrowserState(FeatureId.AmazonQ))
QWebviewPanel.getInstance(project).component
}

val content = contentManager.factory.createContent(component, null, false).also {
it.isCloseable = true
it.isPinnable = true
}
contentManager.addContent(content)
return content
qPanel.setContent(component)
}

override fun init(toolWindow: ToolWindow) {
toolWindow.stripeTitle = message("q.window.title")

Check warning on line 120 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Usage of redundant or deprecated syntax or deprecated symbols

'message(String, vararg Any): String' is deprecated. Use extension-specific localization bundle instead
toolWindow.component.addComponentListener(
object : ComponentAdapter() {
override fun componentResized(e: ComponentEvent) {
Expand All @@ -125,8 +134,7 @@

override fun shouldBeAvailable(project: Project): Boolean = isQWebviewsAvailable()

private fun onConnectionChanged(project: Project, newConnection: ToolkitConnection?, toolWindow: ToolWindow) {
val contentManager = toolWindow.contentManager
private fun onConnectionChanged(project: Project, newConnection: ToolkitConnection?, qPanel: Wrapper) {
val isNewConnectionForQ = newConnection?.let {
(it as? AwsBearerTokenConnection)?.let { conn ->
val scopeShouldHave = Q_SCOPES
Expand All @@ -151,19 +159,12 @@
LOG.debug { "returning login window; no Q connection found" }
QWebviewPanel.getInstance(project).component
}

val content = contentManager.factory.createContent(component, null, false).also {
it.isCloseable = true
it.isPinnable = true
}

runInEdt {
contentManager.removeAllContents(true)
contentManager.addContent(content)
qPanel.setContent(component)
}
}

companion object {

Check warning on line 167 in plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt

View workflow job for this annotation

GitHub Actions / Qodana Community for JVM

Companion object in extensions

Companion objects in IDE extension implementations may only contain a logger and constants
private val LOG = getLogger<AmazonQToolWindowFactory>()
const val WINDOW_ID = AMAZON_Q_WINDOW_ID
private const val MINIMUM_TOOLWINDOW_WIDTH = 325
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.services.amazonq.toolwindow

import com.intellij.openapi.project.Project
import com.intellij.ui.components.panels.Wrapper
import com.intellij.util.ui.components.BorderLayoutPanel
import software.aws.toolkits.core.utils.error
import software.aws.toolkits.core.utils.getLogger
import software.aws.toolkits.jetbrains.core.webview.BrowserState
import software.aws.toolkits.jetbrains.services.amazonq.QWebviewPanel
import software.aws.toolkits.jetbrains.utils.isQConnected
import software.aws.toolkits.jetbrains.utils.isQExpired
import software.aws.toolkits.telemetry.FeatureId
import javax.swing.JComponent

class OuterAmazonQPanel(val project: Project) : BorderLayoutPanel() {

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Class "OuterAmazonQPanel" is never used
private val wrapper = Wrapper()
init {
isOpaque = false
addToCenter(wrapper)
val component = if (isQConnected(project) && !isQExpired(project)) {
AmazonQToolWindow.getInstance(project).component
} else {
QWebviewPanel.getInstance(project).browser?.prepareBrowser(BrowserState(FeatureId.AmazonQ))
QWebviewPanel.getInstance(project).component
}
updateQPanel(component)
}

fun updateQPanel(content: JComponent) {

Check notice

Code scanning / QDJVMC

Class member can have 'private' visibility Note

Function 'updateQPanel' could be private
try {
wrapper.setContent(content)
} catch (e: Exception) {
getLogger<OuterAmazonQPanel>().error { "Error while creating window" }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ class DefaultRemoteResourceResolver(
private fun internalResolve(resource: RemoteResource): Path {
val expectedLocation = cacheBasePath.resolve(resource.name)
val current = expectedLocation.existsOrNull()
if (current != null && !isExpired(current, resource)) {
LOG.debug { "Existing file ($current) for ${resource.name} is present and not expired - using it." }
return current
if (resource.name != "notifications.json") {
if ((current != null && !isExpired(current, resource))) {
LOG.debug { "Existing file ($current) for ${resource.name} is present and not expired - using it." }
return current
}
}

LOG.debug { "Current file for ${resource.name} does not exist or is expired. Attempting to fetch from ${resource.urls}" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

<postStartupActivity implementation="software.aws.toolkits.jetbrains.core.plugin.PluginAutoUpdater"/>
<postStartupActivity implementation="software.aws.toolkits.jetbrains.core.AwsTelemetryPrompter"/>
<postStartupActivity implementation="software.aws.toolkits.jetbrains.services.telemetry.AwsToolkitStartupMetrics"/>

<registryKey key="aws.dev.useDAG" description="True if DAG should be used instead of authorization_grant with PKCE"
defaultValue="false" restartRequired="false"/>
Expand All @@ -77,6 +78,9 @@
restartRequired="true"/>
<registryKey key="aws.toolkit.developerMode" description="Enables features to facilitate development of the toolkit" restartRequired="false"
defaultValue="false"/>
<registryKey key="aws.toolkit.notification.endpoint" description="Endpoint for AWS Toolkit notifications"
defaultValue="https://idetoolkits-hostedfiles.amazonaws.com/Notifications/Jetbrains/emergency/1.x.json" restartRequired="true"/>


<notificationGroup id="aws.plugin.version.mismatch" displayType="STICKY_BALLOON" key="aws.settings.title"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ object AwsToolkit {

const val GITHUB_URL = "https://github.com/aws/aws-toolkit-jetbrains"
const val AWS_DOCS_URL = "https://docs.aws.amazon.com/console/toolkit-for-jetbrains"
const val GITHUB_CHANGELOG = "https://github.com/aws/aws-toolkit-jetbrains/blob/main/CHANGELOG.md"
}

data class PluginInfo(val id: String, val name: String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

import com.intellij.icons.AllIcons
import com.intellij.ide.BrowserUtil
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.Task
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.ui.EditorNotificationPanel
import software.aws.toolkits.jetbrains.AwsPlugin
import software.aws.toolkits.jetbrains.AwsToolkit
import software.aws.toolkits.jetbrains.core.plugin.PluginUpdateManager
import software.aws.toolkits.resources.AwsCoreBundle

fun checkSeverity(notificationSeverity: String): NotificationSeverity = when (notificationSeverity) {
"Critical" -> NotificationSeverity.CRITICAL
"Warning" -> NotificationSeverity.WARNING
"Info" -> NotificationSeverity.INFO
else -> NotificationSeverity.INFO
}

object NotificationManager {
fun createActions(
project: Project,
followupActions: List<NotificationFollowupActions>?,
message: String,
title: String,

): List<NotificationActionList> = buildList {
var url: String? = null
followupActions?.forEach { action ->
if (action.type == "ShowUrl") {
url = action.content.locale.url
}

if (action.type == "UpdateExtension") {
add(
NotificationActionList(AwsCoreBundle.message("notification.update")) {
updatePlugins()
}
)
}

if (action.type == "OpenChangelog") {
add(
NotificationActionList(AwsCoreBundle.message("notification.changelog")) {
BrowserUtil.browse(AwsToolkit.GITHUB_CHANGELOG)
}
)
}
}
add(
NotificationActionList(AwsCoreBundle.message("general.more_dialog")) {
if (url == null) {
Messages.showYesNoDialog(
project,
message,
title,
AwsCoreBundle.message("general.acknowledge"),
AwsCoreBundle.message("general.cancel"),
AllIcons.General.Error
)
} else {
val link = url ?: AwsToolkit.GITHUB_URL
val openLink = Messages.showYesNoDialog(
project,
message,
title,
AwsCoreBundle.message(AwsCoreBundle.message("notification.learn_more")),
AwsCoreBundle.message("general.cancel"),
AllIcons.General.Error
)
if (openLink == 0) {
BrowserUtil.browse(link)
}
}
}
)
}

fun buildNotificationActions(actions: List<NotificationActionList>): List<AnAction> = actions.map { (title, block) ->
object : AnAction(title) {
override fun actionPerformed(e: AnActionEvent) {
block()
}
}
}

fun buildBannerPanel(panel: EditorNotificationPanel, actions: List<NotificationActionList>): EditorNotificationPanel {
actions.forEach { (actionTitle, block) ->
panel.createActionLabel(actionTitle) {
block()
}
}

return panel
}
private fun updatePlugins() {
val pluginUpdateManager = PluginUpdateManager()
runInEdt {
ProgressManager.getInstance().run(object : Task.Backgroundable(
null,
AwsCoreBundle.message("aws.settings.auto_update.progress.message")
) {
override fun run(indicator: ProgressIndicator) {
pluginUpdateManager.checkForUpdates(indicator, AwsPlugin.CORE)
pluginUpdateManager.checkForUpdates(indicator, AwsPlugin.TOOLKIT)
pluginUpdateManager.checkForUpdates(indicator, AwsPlugin.Q)
}
})
}
}
}

data class NotificationActionList(
val title: String,
val blockToExecute: () -> Unit,
)

data class BannerContent(
val title: String,
val message: String,
val actions: List<NotificationActionList>,
val id: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package software.aws.toolkits.jetbrains.core.notifications

object DisplayToastNotifications

Check warning

Code scanning / QDJVMC

Unused symbol Warning

Object "DisplayToastNotifications" is never used
Loading
Loading