Skip to content

Commit 528518f

Browse files
feat: add possibilty to use the new DownloadHandler (#7342)
* feat: add possibilty to use the new DownloadHandler Add methods/constructors for using the new DownloadHandler instead of AbstractStreamResource. Part of vaadin/flow#21255 * chore: cleanup --------- Co-authored-by: ugur-vaadin <[email protected]>
1 parent 58ab766 commit 528518f

File tree

12 files changed

+256
-14
lines changed

12 files changed

+256
-14
lines changed

vaadin-avatar-flow-parent/vaadin-avatar-flow-integration-tests/src/main/java/com/vaadin/flow/component/avatar/tests/AvatarGroupPage.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.vaadin.flow.component.html.Div;
2424
import com.vaadin.flow.component.html.NativeButton;
2525
import com.vaadin.flow.router.Route;
26+
import com.vaadin.flow.server.DownloadHandler;
2627
import com.vaadin.flow.server.StreamResource;
2728

2829
@Route("vaadin-avatar/avatar-group-test")
@@ -60,6 +61,19 @@ public AvatarGroupPage() {
6061
});
6162
setItemsWithResource.setId("set-items-with-resource");
6263

64+
NativeButton setItemsWithDownloadHandler = new NativeButton(
65+
"Set new item with download resource image", e -> {
66+
DownloadHandler download = DownloadHandler.forClassResource(
67+
getClass(),
68+
"/META-INF/resources/frontend/images/user.png",
69+
"avatar-group-img");
70+
AvatarGroupItem newItem = new AvatarGroupItem();
71+
newItem.setImageHandler(download);
72+
73+
avatarGroup.setItems(newItem);
74+
});
75+
setItemsWithDownloadHandler.setId("set-items-with-download-resource");
76+
6377
NativeButton addClassNames = new NativeButton("Add class name", e -> {
6478
items.get(0).addClassNames("red");
6579
});
@@ -72,6 +86,6 @@ public AvatarGroupPage() {
7286
removeClassNames.setId("remove-class-names");
7387

7488
add(avatarGroup, updateItems, setItemsWithResource, addClassNames,
75-
removeClassNames);
89+
removeClassNames, setItemsWithDownloadHandler);
7690
}
7791
}

vaadin-avatar-flow-parent/vaadin-avatar-flow-integration-tests/src/main/java/com/vaadin/flow/component/avatar/tests/AvatarPage.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.vaadin.flow.component.html.Div;
2020
import com.vaadin.flow.component.html.NativeButton;
2121
import com.vaadin.flow.router.Route;
22+
import com.vaadin.flow.server.DownloadHandler;
2223
import com.vaadin.flow.server.StreamResource;
2324

2425
@Route("vaadin-avatar/avatar-test")
@@ -69,6 +70,20 @@ public AvatarPage() {
6970
});
7071
toggleImgResource.setId("toggle-res");
7172

73+
NativeButton toggleImgHandler = new NativeButton("Toggle image handler",
74+
e -> {
75+
if (avatar.getImageResource() == null) {
76+
DownloadHandler download = DownloadHandler
77+
.forClassResource(getClass(),
78+
"/META-INF/resources/frontend/images/user.png",
79+
"user+.png");
80+
avatar.setImageHandler(download);
81+
} else {
82+
avatar.setImageHandler(null);
83+
}
84+
});
85+
toggleImgHandler.setId("toggle-res-handler");
86+
7287
Div dataImg = new Div();
7388
dataImg.setId("data-block-img");
7489

@@ -92,6 +107,7 @@ public AvatarPage() {
92107
getPropertyValues.setId("get-props");
93108

94109
add(avatar, toggleImage, toggleAbbr, toggleName, toggleImgResource,
95-
dataImg, dataAbbr, dataName, dataResource, getPropertyValues);
110+
toggleImgHandler, dataImg, dataAbbr, dataName, dataResource,
111+
getPropertyValues);
96112
}
97113
}

vaadin-avatar-flow-parent/vaadin-avatar-flow-integration-tests/src/test/java/com/vaadin/flow/component/avatar/tests/AvatarGroupIT.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ public void avatarGroupAttached_setItemsWithImageResource_imageLoaded() {
6262
checkLogsForErrors(); // would fail if the image wasn't hosted
6363
}
6464

65+
@Test
66+
public void avatarGroupAttached_setItemsWithDownloadHandler_imageLoaded() {
67+
clickElementWithJs("set-items-with-download-resource");
68+
String imageUrl = $(AvatarGroupElement.class).first()
69+
.getAvatarElement(0).getPropertyString("img");
70+
Assert.assertTrue(imageUrl.startsWith("VAADIN/dynamic"));
71+
checkLogsForErrors(); // would fail if the image wasn't hosted
72+
}
73+
6574
@Test
6675
public void addClassNames_removeClassNames_avatarsUpdated() {
6776
findElement(By.id("add-class-names")).click();

vaadin-avatar-flow-parent/vaadin-avatar-flow-integration-tests/src/test/java/com/vaadin/flow/component/avatar/tests/AvatarIT.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public void propertiesAreSet() {
4646
WebElement toggleAbbr = findElement(By.id("toggle-abbr"));
4747
WebElement toggleName = findElement(By.id("toggle-name"));
4848
WebElement toggleResource = findElement(By.id("toggle-res"));
49+
WebElement toggleResourceHandler = findElement(
50+
By.id("toggle-res-handler"));
4951

5052
WebElement imgBlock = findElement(By.id("data-block-img"));
5153
WebElement abbrBlock = findElement(By.id("data-block-abbr"));
@@ -56,6 +58,12 @@ public void propertiesAreSet() {
5658
getPropsBtn.click();
5759
Assert.assertEquals("https://vaadin.com/", imgBlock.getText());
5860

61+
toggleResourceHandler.click();
62+
getPropsBtn.click();
63+
Assert.assertTrue("img url contains file name",
64+
resourceBlock.getText().contains("user%2B.png"));
65+
toggleResourceHandler.click();
66+
5967
toggleAbbr.click();
6068
getPropsBtn.click();
6169
Assert.assertEquals("BB", abbrBlock.getText());
@@ -78,6 +86,8 @@ public void propertiesAreUnset() {
7886
WebElement toggleAbbr = findElement(By.id("toggle-abbr"));
7987
WebElement toggleName = findElement(By.id("toggle-name"));
8088
WebElement toggleResource = findElement(By.id("toggle-res"));
89+
WebElement toggleResourceHandler = findElement(
90+
By.id("toggle-res-handler"));
8191

8292
WebElement imgBlock = findElement(By.id("data-block-img"));
8393
WebElement abbrBlock = findElement(By.id("data-block-abbr"));
@@ -105,5 +115,10 @@ public void propertiesAreUnset() {
105115
toggleResource.click();
106116
getPropsBtn.click();
107117
Assert.assertEquals("", resourceBlock.getText());
118+
119+
toggleResourceHandler.click();
120+
toggleResourceHandler.click();
121+
getPropsBtn.click();
122+
Assert.assertEquals("", resourceBlock.getText());
108123
}
109124
}

vaadin-avatar-flow-parent/vaadin-avatar-flow/src/main/java/com/vaadin/flow/component/avatar/Avatar.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import com.vaadin.flow.component.shared.HasThemeVariant;
2828
import com.vaadin.flow.internal.JsonSerializer;
2929
import com.vaadin.flow.server.AbstractStreamResource;
30+
import com.vaadin.flow.server.DownloadHandler;
31+
import com.vaadin.flow.server.StreamResourceRegistry;
3032

3133
import elemental.json.JsonObject;
3234

@@ -263,6 +265,28 @@ public void setImageResource(AbstractStreamResource resource) {
263265
getElement().setAttribute("img", resource);
264266
}
265267

268+
/**
269+
* Sets the image for the avatar.
270+
* <p>
271+
* Setting the image as a resource with this method resets the image URL
272+
* that was set with {@link Avatar#setImage(String)}
273+
*
274+
* @see Avatar#setImage(String)
275+
* @param downloadHandler
276+
* the download resource or {@code null} to remove the resource
277+
*/
278+
public void setImageHandler(DownloadHandler downloadHandler) {
279+
if (downloadHandler == null) {
280+
imageResource = null;
281+
getElement().removeAttribute("img");
282+
return;
283+
}
284+
imageResource = new StreamResourceRegistry.ElementStreamResource(
285+
downloadHandler, getElement());
286+
287+
getElement().setAttribute("img", imageResource);
288+
}
289+
266290
/**
267291
* Gets the color index for the avatar.
268292
*

vaadin-avatar-flow-parent/vaadin-avatar-flow/src/main/java/com/vaadin/flow/component/avatar/AvatarGroup.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.vaadin.flow.component.HasSize;
3535
import com.vaadin.flow.component.HasStyle;
3636
import com.vaadin.flow.component.Tag;
37+
import com.vaadin.flow.component.UI;
3738
import com.vaadin.flow.component.dependency.JsModule;
3839
import com.vaadin.flow.component.dependency.NpmPackage;
3940
import com.vaadin.flow.component.shared.HasOverlayClassName;
@@ -43,6 +44,7 @@
4344
import com.vaadin.flow.internal.StateTree;
4445
import com.vaadin.flow.server.AbstractStreamResource;
4546
import com.vaadin.flow.server.Command;
47+
import com.vaadin.flow.server.DownloadHandler;
4648
import com.vaadin.flow.server.StreamRegistration;
4749
import com.vaadin.flow.server.StreamResourceRegistry;
4850
import com.vaadin.flow.server.VaadinSession;
@@ -219,6 +221,28 @@ public void setImage(String url) {
219221
}
220222
}
221223

224+
/**
225+
* Sets the image for the avatar.
226+
* <p>
227+
* Setting the image as a resource with this method resets the image URL
228+
* that was set with {@link AvatarGroupItem#setImage(String)}
229+
*
230+
* @see AvatarGroupItem#setImage(String)
231+
* @param downloadHandler
232+
* the download resource or {@code null} to remove the
233+
* resource
234+
*/
235+
public void setImageHandler(DownloadHandler downloadHandler) {
236+
if (downloadHandler == null) {
237+
unsetResource();
238+
return;
239+
}
240+
241+
setImageResource(new StreamResourceRegistry.ElementStreamResource(
242+
downloadHandler, getHost() != null ? getHost().getElement()
243+
: UI.getCurrent().getElement()));
244+
}
245+
222246
/**
223247
* Sets the image for the avatar.
224248
* <p>

vaadin-icons-flow-parent/vaadin-icons-flow/src/main/java/com/vaadin/flow/component/icon/SvgIcon.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
package com.vaadin.flow.component.icon;
1717

1818
import com.vaadin.flow.server.AbstractStreamResource;
19+
import com.vaadin.flow.server.DownloadHandler;
1920
import com.vaadin.flow.server.StreamResource;
21+
import com.vaadin.flow.server.StreamResourceRegistry;
2022

2123
/**
2224
* Component for displaying an icon from a SVG file.
@@ -84,6 +86,33 @@ public SvgIcon(AbstractStreamResource src, String symbol) {
8486
setSymbol(symbol);
8587
}
8688

89+
/**
90+
* Creates an SVG icon with the given download handler resource
91+
*
92+
* @param src
93+
* the download handler resource
94+
* @see #setSrc(AbstractStreamResource)
95+
*/
96+
public SvgIcon(DownloadHandler src) {
97+
setSrc(new StreamResourceRegistry.ElementStreamResource(src,
98+
getElement()));
99+
}
100+
101+
/**
102+
* Creates an SVG icon with the given download handler resource
103+
*
104+
* @param src
105+
* the download handler resource
106+
* @param symbol
107+
* the symbol reference of the icon
108+
* @see #setSrc(AbstractStreamResource)
109+
* @see #setSymbol(String)
110+
*/
111+
public SvgIcon(DownloadHandler src, String symbol) {
112+
this(src);
113+
setSymbol(symbol);
114+
}
115+
87116
/**
88117
* Sets the URL of the SVG file to be used as the icon. The value can be:
89118
* <ul>

vaadin-icons-flow-parent/vaadin-icons-flow/src/test/java/com/vaadin/flow/component/icon/tests/SvgIconTest.java

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.vaadin.flow.component.icon.tests;
1717

1818
import java.io.ByteArrayInputStream;
19+
import java.io.IOException;
1920
import java.nio.charset.StandardCharsets;
2021

2122
import org.junit.After;
@@ -24,6 +25,8 @@
2425

2526
import com.vaadin.flow.component.UI;
2627
import com.vaadin.flow.component.icon.SvgIcon;
28+
import com.vaadin.flow.server.DownloadHandler;
29+
import com.vaadin.flow.server.DownloadRequest;
2730
import com.vaadin.flow.server.StreamResource;
2831

2932
public class SvgIconTest {
@@ -61,9 +64,7 @@ public void sourceWithSymbolConstructor_hasSrcAndSymbol() {
6164
@Test
6265
public void streamResourceConstructor_hasSrc() {
6366
UI.setCurrent(new UI());
64-
var resource = new StreamResource("image.svg",
65-
() -> new ByteArrayInputStream(
66-
"<svg></svg>".getBytes(StandardCharsets.UTF_8)));
67+
var resource = getStreamResource();
6768
var icon = new SvgIcon(resource);
6869
Assert.assertTrue(icon.getSrc().contains("image.svg"));
6970
Assert.assertTrue(
@@ -73,9 +74,30 @@ public void streamResourceConstructor_hasSrc() {
7374
@Test
7475
public void streamResourceConstructorWithSymbol_hasSrcAndSymbol() {
7576
UI.setCurrent(new UI());
76-
var resource = new StreamResource("image.svg",
77-
() -> new ByteArrayInputStream(
78-
"<svg></svg>".getBytes(StandardCharsets.UTF_8)));
77+
var resource = getStreamResource();
78+
var symbol = "symbol";
79+
var icon = new SvgIcon(resource, symbol);
80+
Assert.assertTrue(icon.getSrc().contains("image.svg"));
81+
Assert.assertTrue(
82+
icon.getElement().getAttribute("src").contains("image.svg"));
83+
Assert.assertEquals(symbol, icon.getSymbol());
84+
Assert.assertEquals(symbol, icon.getElement().getProperty("symbol"));
85+
}
86+
87+
@Test
88+
public void downloadHandlerConstructor_hasSrc() {
89+
UI.setCurrent(new UI());
90+
var resource = getDownloadHandler();
91+
var icon = new SvgIcon(resource);
92+
Assert.assertTrue(icon.getSrc().contains("image.svg"));
93+
Assert.assertTrue(
94+
icon.getElement().getAttribute("src").contains("image.svg"));
95+
}
96+
97+
@Test
98+
public void downloadHandlerConstructorWithSymbol_hasSrcAndSymbol() {
99+
UI.setCurrent(new UI());
100+
var resource = getDownloadHandler();
79101
var symbol = "symbol";
80102
var icon = new SvgIcon(resource, symbol);
81103
Assert.assertTrue(icon.getSrc().contains("image.svg"));
@@ -110,9 +132,7 @@ public void setSrcWithSymbol_hasSrcAndSymbol() {
110132
@Test
111133
public void hasStreamResource_setSrcWithSymbol_hasSrcAndSymbol() {
112134
UI.setCurrent(new UI());
113-
var resource = new StreamResource("image.svg",
114-
() -> new ByteArrayInputStream(
115-
"<svg></svg>".getBytes(StandardCharsets.UTF_8)));
135+
var resource = getStreamResource();
116136
var symbol = "symbol";
117137
var icon = new SvgIcon();
118138
icon.setSrc(resource, symbol);
@@ -147,9 +167,7 @@ public void modifySrc_hasModifiedSrc() {
147167
public void withStreamResource_setSrc_hasSrc() {
148168
UI.setCurrent(new UI());
149169
var icon = new SvgIcon();
150-
var resource = new StreamResource("image.svg",
151-
() -> new ByteArrayInputStream(
152-
"<svg></svg>".getBytes(StandardCharsets.UTF_8)));
170+
var resource = getStreamResource();
153171
icon.setSrc(resource);
154172
Assert.assertTrue(icon.getSrc().contains("image.svg"));
155173
}
@@ -170,4 +188,28 @@ public void removeColor_hasNoColor() {
170188
Assert.assertNull(icon.getColor());
171189
Assert.assertNull(icon.getStyle().get("fill"));
172190
}
191+
192+
private static StreamResource getStreamResource() {
193+
return new StreamResource("image.svg", () -> new ByteArrayInputStream(
194+
"<svg></svg>".getBytes(StandardCharsets.UTF_8)));
195+
}
196+
197+
private static DownloadHandler getDownloadHandler() {
198+
return new DownloadHandler() {
199+
@Override
200+
public void handleDownloadRequest(DownloadRequest downloadRequest) {
201+
try {
202+
downloadRequest.getOutputStream().write(
203+
"<svg></svg>".getBytes(StandardCharsets.UTF_8));
204+
} catch (IOException e) {
205+
throw new RuntimeException(e);
206+
}
207+
}
208+
209+
@Override
210+
public String getUrlPostfix() {
211+
return "image.svg";
212+
}
213+
};
214+
}
173215
}

vaadin-messages-flow-parent/vaadin-messages-flow-integration-tests/src/main/java/com/vaadin/flow/component/messages/tests/MessageListPage.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.vaadin.flow.component.messages.MessageListItem;
2626
import com.vaadin.flow.router.Route;
2727
import com.vaadin.flow.server.Command;
28+
import com.vaadin.flow.server.DownloadHandler;
2829
import com.vaadin.flow.server.StreamResource;
2930

3031
@Route("vaadin-messages/message-list-test")
@@ -72,6 +73,14 @@ public MessageListPage() {
7273
foo.setUserImageResource(resource);
7374
});
7475

76+
addButton("setImageAsDownloadHandler", () -> {
77+
DownloadHandler resource = DownloadHandler.forClassResource(
78+
getClass(),
79+
"/META-INF/resources/frontend/images/avatar.png",
80+
"message-list-img");
81+
foo.setUserImageHandler(resource);
82+
});
83+
7584
}
7685

7786
private void addButton(String id, Command action) {

0 commit comments

Comments
 (0)