diff --git a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/sw.ts b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/sw.ts index e40c8e972b4..e51c0f57df4 100644 --- a/flow-server/src/main/resources/com/vaadin/flow/server/frontend/sw.ts +++ b/flow-server/src/main/resources/com/vaadin/flow/server/frontend/sw.ts @@ -149,9 +149,7 @@ self.addEventListener('message', (event) => { self.addEventListener('push', (e) => { const data = e.data?.json(); if (data) { - self.registration.showNotification(data.title, { - body: data.body, - }); + self.registration.showNotification(data.title, data.options); } }); diff --git a/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushAction.java b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushAction.java new file mode 100644 index 00000000000..4849a8eff27 --- /dev/null +++ b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushAction.java @@ -0,0 +1,6 @@ +package com.vaadin.flow.webpush; + +import java.io.Serializable; + +public record WebPushAction(String action, String title, String icon) implements Serializable { +} diff --git a/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushOptions.java b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushOptions.java new file mode 100644 index 00000000000..fdc0597eafd --- /dev/null +++ b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushOptions.java @@ -0,0 +1,20 @@ +package com.vaadin.flow.webpush; + +import java.io.Serializable; +import java.util.List; + +public record WebPushOptions(List actions, + String badge, + String body, + Serializable data, + String dir, + String icon, + String image, + String lang, + boolean renotify, + boolean requireInteraction, + boolean silent, + String tag, + long timestamp, + List vibrate) implements Serializable { +} diff --git a/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushView.java b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushView.java index bb72be89f9f..c9ae1667276 100644 --- a/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushView.java +++ b/flow-tests/test-webpush/src/main/java/com/vaadin/flow/webpush/WebPushView.java @@ -16,6 +16,8 @@ package com.vaadin.flow.webpush; +import java.util.List; + import nl.martijndwars.webpush.Subscription; import com.vaadin.flow.component.Text; @@ -44,6 +46,12 @@ public class WebPushView extends Div { WebPush webPush; private final Div log; + private final WebPushAction webPushAction = new WebPushAction( + "dashboard", + "Open Dashboard", + "https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png" + ); + private Subscription subscription; public WebPushView() { @@ -73,8 +81,25 @@ public WebPushView() { notify = new NativeButton("Notify", event -> { if (subscription != null) { + WebPushOptions webPushOptions = new WebPushOptions( + List.of(webPushAction), + "https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png", + "Testing notification", + "This is my data!", + "rtl", + "https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png", + "https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png", + "de-DE", + true, + true, + false, + "My Notification", + System.currentTimeMillis(), + List.of(500, 500, 500) + ); + webPush.sendNotification(subscription, - new WebPushMessage(TEST_TITLE, "Testing notification")); + new WebPushMessage(TEST_TITLE, webPushOptions)); addLogEntry("Sent notification"); } else { addLogEntry("No notification sent due to missing subscription"); diff --git a/flow-tests/test-webpush/src/test/java/com/vaadin/flow/webpush/WebPushIT.java b/flow-tests/test-webpush/src/test/java/com/vaadin/flow/webpush/WebPushIT.java index feedcfc4768..03aeeb4bd24 100644 --- a/flow-tests/test-webpush/src/test/java/com/vaadin/flow/webpush/WebPushIT.java +++ b/flow-tests/test-webpush/src/test/java/com/vaadin/flow/webpush/WebPushIT.java @@ -153,7 +153,18 @@ public boolean isNotificationPresent(WebDriver driver) { .then( (notifications) => { return notifications.length == 1 && notifications[0].title === 'Test title' && - notifications[0].body === 'Testing notification'; + notifications[0].body === 'Testing notification' && + notifications[0].badge === 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png' && + notifications[0].data === 'This is my data!' && + notifications[0].dir === 'rtl' && + notifications[0].icon === 'https://upload.wikimedia.org/wikipedia/commons/0/0e/Message-icon-blue-symbol-double.png' && + notifications[0].lang === 'de-DE' && + notifications[0].renotify === true && + notifications[0].requireInteraction === true && + notifications[0].silent === false && + notifications[0].tag === 'My Notification' && + Array.isArray(notifications[0].actions) && notifications[0].actions.length > 0 && notifications[0].actions[0].action === 'dashboard' && + Array.isArray(notifications[0].vibrate) && notifications[0].vibrate.length > 0 && notifications[0].vibrate[0] === 500; }); """); } diff --git a/flow-webpush/src/main/java/com/vaadin/flow/server/webpush/WebPushMessage.java b/flow-webpush/src/main/java/com/vaadin/flow/server/webpush/WebPushMessage.java index 42ffbf2712a..01474ead43a 100644 --- a/flow-webpush/src/main/java/com/vaadin/flow/server/webpush/WebPushMessage.java +++ b/flow-webpush/src/main/java/com/vaadin/flow/server/webpush/WebPushMessage.java @@ -17,8 +17,8 @@ import java.io.Serializable; -import elemental.json.Json; -import elemental.json.JsonObject; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; /** * Web Push message object containing an information to be shown in the @@ -26,15 +26,40 @@ * * @since 24.2 */ -public record WebPushMessage(String title, String body) implements Serializable { +public record WebPushMessage(String title, ObjectNode options) implements Serializable { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Creates a new Web Push notification message with the specified title and various options + * fetched from a given Java object. + * + * @param title the notification title + * @param options any {@code Serializable} Java object representing custom settings to apply to the notification + * @see + * showNotification parameters + */ + public WebPushMessage(String title, Serializable options) { + this(title, objectMapper.convertValue(options, ObjectNode.class)); + } + + /** + * Creates a new Web Push notification message with just a title and body. + * + * @param title notification title + * @param body notification body + */ + public WebPushMessage(String title, String body) { + this(title, getBodyOption(body)); + } /** - * Creates a new Web Push notification message with title and body. + * Creates a new Web Push notification message with just a title. * * @param title notification title - * @param body notification body */ - public WebPushMessage { + public WebPushMessage(String title) { + this(title, (ObjectNode) null); } @Override @@ -48,9 +73,19 @@ public String toString() { * @return JSON representation of this message */ public String toJson() { - JsonObject json = Json.createObject(); + ObjectNode json = objectMapper.createObjectNode(); json.put("title", title); - json.put("body", body); - return json.toJson(); + if (options != null) { + json.set("options", options); + } + return json.toString(); + } + + private static ObjectNode getBodyOption(String body) { + ObjectNode objectNode = objectMapper.createObjectNode(); + if (body != null) { + objectNode.put("body", body); + } + return objectNode; } }