Skip to content

Commit a5126d1

Browse files
committed
show notifications when panel is opened
1 parent 57fb2ef commit a5126d1

File tree

10 files changed

+124
-51
lines changed

10 files changed

+124
-51
lines changed

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/AmazonQToolWindowFactory.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class AmazonQToolWindowFactory : ToolWindowFactory, DumbAware {
4444
mainPanel.addToTop(notificationPanel)
4545
mainPanel.add(qPanel)
4646
val notifListener = ProcessNotificationsBase.getInstance(project)
47-
notifListener.addListenerForNotification { title, message, followupActions ->
47+
notifListener.addListenerForNotification { bannerContent ->
4848
runInEdt {
49-
notificationPanel.updateNotificationPanel(title, message, followupActions)
49+
notificationPanel.updateNotificationPanel(bannerContent)
5050
}
5151
}
5252

plugins/amazonq/chat/jetbrains-community/src/software/aws/toolkits/jetbrains/services/amazonq/toolwindow/NotificationPanel.kt

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ import com.intellij.openapi.project.Project
1111
import com.intellij.ui.EditorNotificationPanel
1212
import com.intellij.ui.components.panels.Wrapper
1313
import com.intellij.util.ui.components.BorderLayoutPanel
14-
import software.aws.toolkits.jetbrains.core.notifications.NotificationActionList
14+
import software.aws.toolkits.jetbrains.core.notifications.BannerContent
1515
import software.aws.toolkits.jetbrains.core.notifications.NotificationManager
16+
import software.aws.toolkits.jetbrains.core.notifications.ProcessNotificationsBase
1617
import software.aws.toolkits.resources.AwsCoreBundle
1718

1819
@Service(Service.Level.PROJECT)
@@ -21,19 +22,23 @@ class NotificationPanel : BorderLayoutPanel() {
2122
init {
2223
isOpaque = false
2324
addToCenter(wrapper)
25+
ProcessNotificationsBase.showBannerNotification.forEach {
26+
updateNotificationPanel(it.value)
27+
}
2428
}
2529

26-
private fun removeNotificationPanel() = runInEdt {
30+
private fun removeNotificationPanel(notificationId: String) = runInEdt {
31+
ProcessNotificationsBase.showBannerNotification.remove(notificationId) // TODO: add id to dismissed notification list
2732
wrapper.removeAll()
2833
}
2934

30-
fun updateNotificationPanel(title: String, message: String, notificationActionList: List<NotificationActionList>) {
35+
fun updateNotificationPanel(bannerContent: BannerContent) {
3136
val panel = EditorNotificationPanel()
32-
panel.text = title
37+
panel.text = bannerContent.title
3338
panel.icon(AllIcons.General.Error)
34-
val panelWithActions = NotificationManager.buildBannerPanel(panel, notificationActionList)
39+
val panelWithActions = NotificationManager.buildBannerPanel(panel, bannerContent.actions)
3540
panelWithActions.createActionLabel(AwsCoreBundle.message("general.dismiss")) {
36-
removeNotificationPanel()
41+
removeNotificationPanel(bannerContent.id)
3742
}
3843

3944
wrapper.setContent(panelWithActions)

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/CustomizeNotificationsUi.kt

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.intellij.icons.AllIcons
77
import com.intellij.ide.BrowserUtil
88
import com.intellij.openapi.actionSystem.AnAction
99
import com.intellij.openapi.actionSystem.AnActionEvent
10+
import com.intellij.openapi.project.Project
1011
import com.intellij.openapi.ui.Messages
1112
import com.intellij.ui.EditorNotificationPanel
1213
import software.aws.toolkits.jetbrains.AwsToolkit
@@ -21,31 +22,16 @@ fun checkSeverity(notificationSeverity: String): NotificationSeverity = when (no
2122

2223
object NotificationManager {
2324
fun createActions(
25+
project: Project,
2426
followupActions: List<NotificationFollowupActions>?,
2527
message: String,
2628
title: String,
2729

2830
): List<NotificationActionList> = buildList {
29-
add(
30-
NotificationActionList(AwsCoreBundle.message("notification.expand")) {
31-
Messages.showYesNoDialog(
32-
null,
33-
message,
34-
title,
35-
AwsCoreBundle.message("general.ok"),
36-
AwsCoreBundle.message("general.cancel"),
37-
AllIcons.General.Error
38-
)
39-
}
40-
)
41-
31+
var url: String? = null
4232
followupActions?.forEach { action ->
4333
if (action.type == "ShowUrl") {
44-
add(
45-
NotificationActionList(AwsCoreBundle.message("notification.learn_more")) {
46-
action.content.locale.url?.let { url -> BrowserUtil.browse(url) }
47-
}
48-
)
34+
url = action.content.locale.url
4935
}
5036

5137
if (action.type == "UpdateExtension") {
@@ -64,6 +50,32 @@ object NotificationManager {
6450
)
6551
}
6652
}
53+
add(
54+
NotificationActionList(AwsCoreBundle.message("general.more_dialog")) {
55+
if (url == null) {
56+
Messages.showYesNoDialog(
57+
project,
58+
message,
59+
title,
60+
AwsCoreBundle.message("general.acknowledge"),
61+
AwsCoreBundle.message("general.cancel"),
62+
AllIcons.General.Error
63+
)
64+
} else {
65+
val openLink = Messages.showYesNoDialog(
66+
project,
67+
message,
68+
title,
69+
AwsCoreBundle.message(AwsCoreBundle.message("notification.learn_more")),
70+
AwsCoreBundle.message("general.cancel"),
71+
AllIcons.General.Error
72+
)
73+
if (openLink == 0) {
74+
BrowserUtil.browse(url!!)
75+
}
76+
}
77+
}
78+
)
6779
}
6880

6981
fun buildNotificationActions(actions: List<NotificationActionList>): List<AnAction> = actions.map { (title, block) ->
@@ -89,3 +101,10 @@ data class NotificationActionList(
89101
val title: String,
90102
val blockToExecute: () -> Unit,
91103
)
104+
105+
data class BannerContent(
106+
val title: String,
107+
val message: String,
108+
val actions: List<NotificationActionList>,
109+
val id: String,
110+
)

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/DummyNotificationAction.kt

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,50 @@ import com.intellij.openapi.util.registry.Registry
99

1010
class DummyNotificationAction : AnAction("Show notif") {
1111
override fun actionPerformed(e: AnActionEvent) {
12+
// TODO: Delete before release
1213
if (!Registry.`is`("aws.toolkit.developerMode")) return
13-
// ShowCriticalNotificationBannerListener.showBanner(
14-
// "hello hello",
15-
// "This is a bug",
16-
// NotificationManager.createActions(emptyList(), "This is a bug", "hello hello")
17-
// )
18-
val a = e.project?.let { ProcessNotificationsBase.getInstance(it) } ?: return
19-
a.notifyListenerForNotification(
20-
"hello hello",
21-
"This is a bug",
22-
NotificationManager.createActions(emptyList(), "This is a bug", "hello hello")
2314

15+
val notificationWithValidConnectionData = NotificationData(
16+
id = "example_id_12344",
17+
schedule = NotificationSchedule(type = "StartUp"),
18+
severity = "Critical",
19+
condition = NotificationDisplayCondition(
20+
compute = null,
21+
os = null,
22+
ide = null,
23+
extension = null,
24+
authx = listOf(
25+
AuthxType(
26+
feature = "q",
27+
type = NotificationExpression.AnyOfCondition(listOf("Idc", "BuilderId")),
28+
region = NotificationExpression.ComparisonCondition("us-east-1"),
29+
connectionState = NotificationExpression.ComparisonCondition("Connected"),
30+
ssoScopes = null
31+
)
32+
)
33+
),
34+
actions = emptyList(),
35+
content = NotificationContentDescriptionLocale(
36+
NotificationContentDescription(
37+
title = "Look at this!",
38+
description = "Some bug is there"
39+
)
40+
)
2441
)
42+
43+
val project = e.project ?: return
44+
// val notificationFollowupActions = NotificationFollowupActions(
45+
// type = "ShowUrl",
46+
// content = NotificationFollowupActionsContent(
47+
// NotificationActionDescription(
48+
// title = "Learn more",
49+
// url = "https://github.com/aws/aws-toolkit-jetbrains"
50+
// )
51+
// )
52+
// )
53+
54+
val a = ProcessNotificationsBase.getInstance(project)
55+
a.processNotification(project, notificationWithValidConnectionData)
2556
}
2657

2758
override fun update(e: AnActionEvent) {

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/core/notifications/ProcessNotificationsBase.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ class ProcessNotificationsBase {
3131
if (shouldShow) {
3232
val notificationContent = notificationData.content.locale
3333
val severity = notificationData.severity
34-
val followupActions = NotificationManager.createActions(notificationData.actions, notificationContent.description, notificationContent.title)
34+
val followupActions = NotificationManager.createActions(
35+
project,
36+
notificationData.actions,
37+
notificationContent.description,
38+
notificationContent.title
39+
)
3540
showToast(
3641
notificationContent.title,
3742
notificationContent.description,
@@ -40,7 +45,9 @@ class ProcessNotificationsBase {
4045
notificationData.id
4146
)
4247
if (severity == "Critical") {
43-
notifyListenerForNotification(notificationContent.title, notificationContent.description, followupActions)
48+
val bannerContent = BannerContent(notificationContent.title, notificationContent.description, followupActions, notificationData.id)
49+
showBannerNotification[notificationData.id] = bannerContent
50+
notifyListenerForNotification(bannerContent)
4451
}
4552
}
4653
}
@@ -54,15 +61,17 @@ class ProcessNotificationsBase {
5461
notifyStickyWithData(notifyType, title, message, null, action, notificationId)
5562
}
5663

57-
fun notifyListenerForNotification(title: String, description: String, followUpActions: List<NotificationActionList>) =
58-
notifListener.forEach { it(title, description, followUpActions) }
64+
fun notifyListenerForNotification(bannerContent: BannerContent) =
65+
notifListener.forEach { it(bannerContent) }
5966

6067
fun addListenerForNotification(newNotifListener: NotifListener) =
6168
notifListener.add(newNotifListener)
6269

6370
companion object {
6471
fun getInstance(project: Project): ProcessNotificationsBase = project.service()
72+
73+
val showBannerNotification = mutableMapOf<String, BannerContent>()
6574
}
6675
}
6776

68-
typealias NotifListener = (title: String, message: String, followupActions: List<NotificationActionList>) -> Unit
77+
typealias NotifListener = (bannerContent: BannerContent) -> Unit

plugins/core/jetbrains-community/src/software/aws/toolkits/jetbrains/utils/NotificationUtils.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import com.intellij.ui.ScrollPaneFactory
1717
import org.slf4j.LoggerFactory
1818
import software.aws.toolkits.core.utils.warn
1919
import software.aws.toolkits.jetbrains.core.help.HelpIds
20+
import software.aws.toolkits.jetbrains.core.notifications.ProcessNotificationsBase
2021
import software.aws.toolkits.resources.AwsCoreBundle
2122
import javax.swing.JLabel
2223
import javax.swing.JTextArea
@@ -65,7 +66,7 @@ fun notifyStickyWithData(
6566
createNotificationExpiringAction(
6667
object : AnAction("Dismiss") {
6768
override fun actionPerformed(e: AnActionEvent) {
68-
id
69+
ProcessNotificationsBase.showBannerNotification.remove(id)
6970
// TODO: add id to dismissed notification list
7071
}
7172
}

plugins/core/jetbrains-community/tst/software/aws/toolkits/jetbrains/core/notifications/NotificationFormatUtilsTestCases.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ val notificationWithValidConnectionData = NotificationData(
301301
AuthxType(
302302
feature = "q",
303303
type = NotificationExpression.AnyOfCondition(listOf("Idc", "BuilderId")),
304-
region = NotificationExpression.ComparisonCondition("us-west-2"),
304+
region = NotificationExpression.ComparisonCondition("us-east-1"),
305305
connectionState = NotificationExpression.ComparisonCondition("Connected"),
306306
ssoScopes = null
307307
)

plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,7 @@ gateway.connection.workflow.start_ide=Start IDE
12571257
gateway.connection.workflow.step_failed=\nStep failed exceptionally\n
12581258
gateway.connection.workflow.step_skipped=Step skipped
12591259
gateway.connection.workflow.step_successful=\nStep completed successfully\n
1260+
general.acknowledge=Acknowledge
12601261
general.add.another=Add another
12611262
general.auth.reauthenticate=Reauthenticate
12621263
general.cancel=Cancel
@@ -1285,6 +1286,7 @@ general.in_progress_button=In progress
12851286
general.logs=Logs
12861287
general.message=Message
12871288
general.more=More
1289+
general.more_dialog=More...
12881290
general.name.label=Name:
12891291
general.no_changes=No changes were provided
12901292
general.notification.action.hide_forever=Don't show again

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/explorer/AwsToolkitExplorerFactory.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ class AwsToolkitExplorerFactory : ToolWindowFactory, DumbAware {
5555
mainPanel.addToTop(notificationPanel)
5656
mainPanel.add(toolkitPanel)
5757
val notifListener = ProcessNotificationsBase.getInstance(project)
58-
notifListener.addListenerForNotification { title, message, followupActions ->
58+
notifListener.addListenerForNotification { bannerContent ->
5959
runInEdt {
60-
notificationPanel.updateNotificationPanel(title, message, followupActions)
60+
notificationPanel.updateNotificationPanel(bannerContent)
6161
}
6262
}
6363
toolWindow.helpId = HelpIds.EXPLORER_WINDOW.id

plugins/toolkit/jetbrains-core/src/software/aws/toolkits/jetbrains/core/explorer/webview/NotificationPanel.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import com.intellij.openapi.components.service
1010
import com.intellij.ui.EditorNotificationPanel
1111
import com.intellij.ui.components.panels.Wrapper
1212
import com.intellij.util.ui.components.BorderLayoutPanel
13-
import software.aws.toolkits.jetbrains.core.notifications.NotificationActionList
13+
import software.aws.toolkits.jetbrains.core.notifications.BannerContent
1414
import software.aws.toolkits.jetbrains.core.notifications.NotificationManager
15+
import software.aws.toolkits.jetbrains.core.notifications.ProcessNotificationsBase
1516
import software.aws.toolkits.resources.AwsCoreBundle
1617

1718
@Service(Service.Level.PROJECT)
@@ -20,20 +21,25 @@ class NotificationPanel : BorderLayoutPanel() {
2021
init {
2122
isOpaque = false
2223
addToCenter(wrapper)
24+
// will show only 1 critical notification
25+
ProcessNotificationsBase.showBannerNotification.forEach {
26+
updateNotificationPanel(it.value)
27+
}
2328
}
2429

25-
private fun removeNotificationPanel() = runInEdt {
30+
private fun removeNotificationPanel(notificationId: String) = runInEdt {
31+
ProcessNotificationsBase.showBannerNotification.remove(notificationId) // TODO: add id to dismissed notification list
2632
wrapper.removeAll()
2733
}
2834

29-
fun updateNotificationPanel(title: String, message: String, notificationActionList: List<NotificationActionList>) {
35+
fun updateNotificationPanel(bannerContent: BannerContent) {
3036
val panel = EditorNotificationPanel()
31-
panel.text = title
37+
panel.text = bannerContent.title
3238
panel.icon(AllIcons.General.Error)
33-
val panelWithActions = NotificationManager.buildBannerPanel(panel, notificationActionList)
39+
val panelWithActions = NotificationManager.buildBannerPanel(panel, bannerContent.actions)
3440

3541
panelWithActions.createActionLabel(AwsCoreBundle.message("general.dismiss")) {
36-
removeNotificationPanel()
42+
removeNotificationPanel(bannerContent.id)
3743
}
3844

3945
wrapper.setContent(panelWithActions)

0 commit comments

Comments
 (0)