Skip to content

Commit 984153c

Browse files
authored
Flex message update 3 (#744)
* Add Video component * Add max width and height of a box component * Add line spacing in a text component
1 parent caa197d commit 984153c

File tree

8 files changed

+223
-5
lines changed

8 files changed

+223
-5
lines changed

line-bot-model/src/main/java/com/linecorp/bot/model/message/flex/component/Box.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,26 @@ public class Box implements FlexComponent {
7878

7979
String width;
8080

81+
/**
82+
* Max width of the box.
83+
*
84+
* <p>The value should be given in pixels or as a percentage of the width of the parent element.
85+
*
86+
* @see <a href="https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-width">Max width of a box</a>
87+
*/
88+
String maxWidth;
89+
8190
String height;
8291

92+
/**
93+
* Max height of the box.
94+
*
95+
* <p>The value should be given in pixels or as a percentage of the height of the parent element.
96+
*
97+
* @see <a href="https://developers.line.biz/en/docs/messaging-api/flex-message-layout/#box-height">Max height of a box</a>
98+
*/
99+
String maxHeight;
100+
83101
String paddingAll;
84102

85103
String paddingTop;

line-bot-model/src/main/java/com/linecorp/bot/model/message/flex/component/FlexComponent.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
@JsonSubTypes.Type(Button.class),
3131
@JsonSubTypes.Type(Icon.class),
3232
@JsonSubTypes.Type(Spacer.class),
33+
@JsonSubTypes.Type(Video.class),
3334
})
3435
@JsonTypeInfo(
3536
use = JsonTypeInfo.Id.NAME,

line-bot-model/src/main/java/com/linecorp/bot/model/message/flex/component/Text.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ public enum TextDecoration {
8686

8787
Boolean wrap;
8888

89+
/**
90+
* Line spacing in a wrapping text.
91+
*
92+
* <p>Specify a positive integer or decimal number that ends in px. The lineSpacing property doesn't apply
93+
* to the top of the start line and the bottom of the last line.
94+
* @see <a href="https://developers.line.biz/en/docs/messaging-api/flex-message-elements/#text-line-spacing">Increase the line spacing in a text</a>
95+
*/
96+
String lineSpacing;
97+
8998
String margin;
9099

91100
FlexPosition position;
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
/*
2+
* Copyright 2022 LINE Corporation
3+
*
4+
* LINE Corporation licenses this file to you under the Apache License,
5+
* version 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. You may obtain a copy of the License at:
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations
14+
* under the License.
15+
*/
16+
17+
package com.linecorp.bot.model.message.flex.component;
18+
19+
import java.net.URI;
20+
import java.text.DecimalFormat;
21+
import java.util.function.Supplier;
22+
23+
import javax.annotation.Nullable;
24+
25+
import com.fasterxml.jackson.annotation.JsonInclude;
26+
import com.fasterxml.jackson.annotation.JsonInclude.Include;
27+
import com.fasterxml.jackson.annotation.JsonTypeName;
28+
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
29+
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
30+
31+
import com.linecorp.bot.model.action.Action;
32+
33+
import lombok.AllArgsConstructor;
34+
import lombok.Builder;
35+
import lombok.Getter;
36+
import lombok.NonNull;
37+
import lombok.Value;
38+
39+
/**
40+
* The following conditions must be met to use the video component.
41+
*
42+
* <ul>
43+
* <li>The video component is specified directly under the hero block</li>
44+
* <li>kilo, mega or giga is specified as the value of the size property of the bubble</li>
45+
* <li>The bubble is not the child element of a carousel</li>
46+
* </ul>
47+
*/
48+
@JsonTypeName("video")
49+
@JsonInclude(Include.NON_NULL)
50+
@Value
51+
@Builder(toBuilder = true)
52+
@JsonDeserialize(builder = Video.VideoBuilder.class)
53+
public class Video implements FlexComponent {
54+
@AllArgsConstructor
55+
@Getter
56+
public enum VideoAspectRatio {
57+
R1TO1("1:1"),
58+
R20TO13("20:13"),
59+
R1_91TO1("1.91:1"),
60+
R4TO3("4:3"),
61+
R16TO9("16:9"),
62+
R2TO1("2:1"),
63+
R3TO1("3:1"),
64+
R3TO4("3:4"),
65+
R9TO16("9:16"),
66+
R1TO2("1:2"),
67+
R1TO3("1:3"),
68+
R1_51TO1("1.51:1");
69+
70+
private final String ratio;
71+
}
72+
73+
/**
74+
* Video file URL. (Max character limit: 2000)
75+
*
76+
* <ul>
77+
* <li>Protocol: HTTPS (TLS 1.2 or later)</li>
78+
* <li>Video format: mp4</li>
79+
* <li>Max file size: 200 MB</li>
80+
* </ul>
81+
*/
82+
@NonNull
83+
URI url;
84+
85+
/**
86+
* Preview image URL. (Max character limit: 2000)
87+
*
88+
* <ul>
89+
* <li>Protocol: HTTPS (TLS 1.2 or later)</li>
90+
* <li>Image format: JPEG or PNG</li>
91+
* <li>Maximum file size: 1 MB</li>
92+
* </ul>
93+
*/
94+
@NonNull
95+
URI previewUrl;
96+
97+
/**
98+
* Alternative content.
99+
*
100+
* <p>The alternative content will be displayed on the screen of a user device that is using a
101+
* version of LINE that doesn't support the video component. Specify a {@link Box} or an {@link Image}.
102+
*/
103+
@NonNull
104+
FlexComponent altContent;
105+
106+
/**
107+
* Aspect ratio of the video.
108+
*
109+
* <p>{@code width:height} format. Specify the value of {@code width} and {@code height} in the range from
110+
* 1 to 100000. However, you can't set {@code height} to a value that is more than three times the value of
111+
* {@code width}. The default value is {@code 1:1}.
112+
*/
113+
@Nullable
114+
String aspectRatio;
115+
116+
/**
117+
* URI {@link Action}.
118+
*/
119+
@Nullable
120+
Action action;
121+
122+
@JsonPOJOBuilder(withPrefix = "")
123+
public static class VideoBuilder {
124+
private static final Supplier<DecimalFormat> RATIO_FORMAT = () -> new DecimalFormat("0.#####");
125+
126+
/**
127+
* Specify aspect ratio by keyword.
128+
*/
129+
public VideoBuilder aspectRatio(VideoAspectRatio aspectRatio) {
130+
this.aspectRatio = aspectRatio.getRatio();
131+
return this;
132+
}
133+
134+
/**
135+
* Specify custom aspect ratio.
136+
*/
137+
public VideoBuilder aspectRatio(String aspectRatio) {
138+
this.aspectRatio = aspectRatio;
139+
return this;
140+
}
141+
142+
/**
143+
* Specify custom aspect ratio. The width and height are rounded up to 5 decimal places.
144+
*/
145+
public VideoBuilder aspectRatio(double width, double height) {
146+
final DecimalFormat fmt = RATIO_FORMAT.get();
147+
aspectRatio = fmt.format(width) + ':' + fmt.format(height);
148+
return this;
149+
}
150+
}
151+
}

line-bot-model/src/test/java/com/linecorp/bot/model/message/flex/component/AspectRatioFormatTest.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.assertj.core.api.Assertions.assertThat;
2020
import static org.junit.jupiter.params.provider.Arguments.arguments;
2121

22+
import java.net.URI;
2223
import java.util.stream.Stream;
2324

2425
import org.junit.jupiter.params.ParameterizedTest;
@@ -51,14 +52,32 @@ public void test(double width, double height, String result) {
5152
assertThat(image.getAspectRatio()).isEqualTo(result);
5253
}
5354

55+
@ParameterizedTest
56+
@MethodSource("testSource")
57+
public void video_aspectRatio(double width, double height, String result) throws Exception {
58+
final Image altImage =
59+
new ImageBuilder()
60+
.aspectRatio(width, height)
61+
.build();
62+
63+
final Video video =
64+
new Video.VideoBuilder()
65+
.aspectRatio(width, height)
66+
.url(new URI("https://example.com/video.mp4"))
67+
.previewUrl(new URI("https://example.com/picture.png"))
68+
.altContent(altImage)
69+
.build();
70+
assertThat(video.getAspectRatio()).isEqualTo(result);
71+
}
72+
5473
@ParameterizedTest
5574
@MethodSource("testSource")
5675
public void icon(double width, double height, String result) {
57-
final Icon image =
76+
final Icon icon =
5877
new IconBuilder()
5978
.aspectRatio(width, height)
6079
.build();
61-
assertThat(image.getAspectRatio()).isEqualTo(result);
80+
assertThat(icon.getAspectRatio()).isEqualTo(result);
6281
}
6382

6483
public static Stream<Arguments> testSource() {

line-bot-model/src/test/resources/flex/reconstruction/TODOapp.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@
223223
"text": "Buy milk and lettuce before class",
224224
"color": "#8C8C8C",
225225
"size": "sm",
226-
"wrap": true
226+
"wrap": true,
227+
"lineSpacing": "20px"
227228
}
228229
],
229230
"flex": 1

line-bot-model/src/test/resources/flex/reconstruction/Transit.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@
5050
"backgroundColor": "#0367D3",
5151
"spacing": "md",
5252
"height": "154px",
53-
"paddingTop": "22px"
53+
"paddingTop": "22px",
54+
"maxWidth": "100%"
5455
},
5556
"body": {
5657
"type": "box",
@@ -91,7 +92,8 @@
9192
"height": "12px",
9293
"width": "12px",
9394
"borderColor": "#EF454D",
94-
"borderWidth": "2px"
95+
"borderWidth": "2px",
96+
"maxHeight": "11px"
9597
},
9698
{
9799
"type": "filler"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"type": "bubble",
3+
"size": "kilo",
4+
"hero": {
5+
"type": "video",
6+
"url": "https://example.com/video.mp4",
7+
"previewUrl": "https://example.com/video_preview.jpg",
8+
"altContent": {
9+
"type": "image",
10+
"size": "full",
11+
"aspectRatio": "20:13",
12+
"aspectMode": "cover",
13+
"url": "https://example.com/image.jpg"
14+
},
15+
"aspectRatio": "20:13"
16+
}
17+
}

0 commit comments

Comments
 (0)