Expand definition of badge SVGs

This commit is contained in:
Ehren Kret 2021-10-25 10:28:02 -07:00
parent ae7077c643
commit 72b52965b9
9 changed files with 160 additions and 72 deletions

View File

@ -22,6 +22,7 @@ import javax.annotation.Nonnull;
import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration;
import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration;
import org.whispersystems.textsecuregcm.entities.Badge;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.entities.SelfBadge;
import org.whispersystems.textsecuregcm.storage.AccountBadge;
@ -66,6 +67,7 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter, B
resourceBundle.getString(configuration.getId() + "_name"),
resourceBundle.getString(configuration.getId() + "_description"),
configuration.getSprites(),
configuration.getSvg(),
configuration.getSvgs(),
null,
false);
@ -96,6 +98,7 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter, B
resourceBundle.getString(accountBadge.getId() + "_name"),
resourceBundle.getString(accountBadge.getId() + "_description"),
configuration.getSprites(),
configuration.getSvg(),
configuration.getSvgs(),
accountBadge.getExpiration(),
accountBadge.isVisible());
@ -110,6 +113,7 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter, B
resourceBundle.getString(id + "_name"),
resourceBundle.getString(id + "_description"),
configuration.getSprites(),
configuration.getSvg(),
configuration.getSvgs(),
now.plus(Duration.ofDays(1)),
true);
@ -158,13 +162,14 @@ public class ConfiguredProfileBadgeConverter implements ProfileBadgeConverter, B
final String name,
final String description,
final List<String> sprites,
final List<String> svgs,
final String svg,
final List<BadgeSvg> svgs,
final Instant expiration,
final boolean visible) {
if (isSelf) {
return new SelfBadge(id, category, name, description, sprites, svgs, expiration, visible);
return new SelfBadge(id, category, name, description, sprites, svg, svgs, expiration, visible);
} else {
return new Badge(id, category, name, description, sprites, svgs);
return new Badge(id, category, name, description, sprites, svg, svgs);
}
}
}

View File

@ -10,6 +10,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.util.ExactlySize;
public class BadgeConfiguration {
@ -18,17 +19,20 @@ public class BadgeConfiguration {
private final String id;
private final String category;
private final List<String> sprites;
private final List<String> svgs;
private final String svg;
private final List<BadgeSvg> svgs;
@JsonCreator
public BadgeConfiguration(
@JsonProperty("id") final String id,
@JsonProperty("category") final String category,
@JsonProperty("sprites") final List<String> sprites,
@JsonProperty("svgs") final List<String> svgs) {
@JsonProperty("svg") final String svg,
@JsonProperty("svgs") final List<BadgeSvg> svgs) {
this.id = id;
this.category = category;
this.sprites = sprites;
this.svg = svg;
this.svgs = svgs;
}
@ -48,9 +52,13 @@ public class BadgeConfiguration {
return sprites;
}
@NotEmpty
public String getSvg() {
return svg;
}
@NotNull
@ExactlySize(4)
public List<String> getSvgs() {
public List<BadgeSvg> getSvgs() {
return svgs;
}

View File

@ -7,6 +7,7 @@ package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import java.util.List;
import java.util.Objects;
@ -16,7 +17,8 @@ public class Badge {
private final String name;
private final String description;
private final List<String> sprites6;
private final List<String> svgs4;
private final String svg;
private final List<BadgeSvg> svgs;
@JsonCreator
public Badge(
@ -25,7 +27,8 @@ public class Badge {
@JsonProperty("name") final String name,
@JsonProperty("description") final String description,
@JsonProperty("sprites6") final List<String> sprites6,
@JsonProperty("svgs4") final List<String> svgs4) {
@JsonProperty("svg") final String svg,
@JsonProperty("svgs") final List<BadgeSvg> svgs) {
this.id = id;
this.category = category;
this.name = name;
@ -34,10 +37,11 @@ public class Badge {
if (sprites6.size() != 6) {
throw new IllegalArgumentException("sprites must have size 6");
}
this.svgs4 = Objects.requireNonNull(svgs4);
if (svgs4.size() != 4) {
throw new IllegalArgumentException("svgs must have size 4");
if (Strings.isNullOrEmpty(svg)) {
throw new IllegalArgumentException("svg cannot be empty");
}
this.svg = svg;
this.svgs = Objects.requireNonNull(svgs);
}
public String getId() {
@ -60,48 +64,12 @@ public class Badge {
return sprites6;
}
public List<String> getSvgs4() {
return svgs4;
public String getSvg() {
return svg;
}
@Deprecated
public String getLdpi() {
return sprites6.get(0);
}
@Deprecated
public String getMdpi() {
return sprites6.get(1);
}
@Deprecated
public String getHdpi() {
return sprites6.get(2);
}
@Deprecated
public String getXhdpi() {
return sprites6.get(3);
}
@Deprecated
public String getXxhdpi() {
return sprites6.get(4);
}
@Deprecated
public String getXxxhdpi() {
return sprites6.get(5);
}
@Deprecated
public String getLsvg() {
return svgs4.get(0);
}
@Deprecated
public String getHsvg() {
return svgs4.get(3);
public List<BadgeSvg> getSvgs() {
return svgs;
}
@Override
@ -118,11 +86,25 @@ public class Badge {
&& Objects.equals(name, badge.name)
&& Objects.equals(description, badge.description)
&& Objects.equals(sprites6, badge.sprites6)
&& Objects.equals(svgs4, badge.svgs4);
&& Objects.equals(svg, badge.svg)
&& Objects.equals(svgs, badge.svgs);
}
@Override
public int hashCode() {
return Objects.hash(id, category, name, description, sprites6, svgs4);
return Objects.hash(id, category, name, description, sprites6, svg, svgs);
}
@Override
public String toString() {
return "Badge{" +
"id='" + id + '\'' +
", category='" + category + '\'' +
", name='" + name + '\'' +
", description='" + description + '\'' +
", sprites6=" + sprites6 +
", svg='" + svg + '\'' +
", svgs=" + svgs +
'}';
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2021 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.whispersystems.textsecuregcm.entities;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Strings;
import java.util.Objects;
import javax.validation.constraints.NotEmpty;
public class BadgeSvg {
private final String light;
private final String dark;
private final String transparent;
@JsonCreator
public BadgeSvg(
@JsonProperty("light") final String light,
@JsonProperty("dark") final String dark,
@JsonProperty("transparent") final String transparent) {
if (Strings.isNullOrEmpty(light)) {
throw new IllegalArgumentException("light cannot be empty");
}
this.light = light;
if (Strings.isNullOrEmpty(dark)) {
throw new IllegalArgumentException("dark cannot be empty");
}
this.dark = dark;
if (Strings.isNullOrEmpty(transparent)) {
throw new IllegalArgumentException("transparent cannot be empty");
}
this.transparent = transparent;
}
@NotEmpty
public String getLight() {
return light;
}
@NotEmpty
public String getDark() {
return dark;
}
@NotEmpty
public String getTransparent() {
return transparent;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
BadgeSvg badgeSvg = (BadgeSvg) o;
return Objects.equals(light, badgeSvg.light)
&& Objects.equals(dark, badgeSvg.dark)
&& Objects.equals(transparent, badgeSvg.transparent);
}
@Override
public int hashCode() {
return Objects.hash(light, dark, transparent);
}
@Override
public String toString() {
return "BadgeSvg{" +
"light='" + light + '\'' +
", dark='" + dark + '\'' +
", transparent='" + transparent + '\'' +
'}';
}
}

View File

@ -23,10 +23,11 @@ public class SelfBadge extends Badge {
@JsonProperty("name") final String name,
@JsonProperty("description") final String description,
@JsonProperty("sprites6") final List<String> sprites6,
@JsonProperty("svgs4") final List<String> svgs4,
@JsonProperty("svg") final String svg,
@JsonProperty("svgs") final List<BadgeSvg> svgs,
@JsonProperty("expiration") final Instant expiration,
@JsonProperty("visible") final boolean visible) {
super(id, category, name, description, sprites6, svgs4);
super(id, category, name, description, sprites6, svg, svgs);
this.expiration = expiration;
this.visible = visible;
}
@ -58,4 +59,12 @@ public class SelfBadge extends Badge {
public int hashCode() {
return Objects.hash(super.hashCode(), expiration, visible);
}
@Override
public String toString() {
return "SelfBadge{" +
"expiration=" + expiration +
", visible=" + visible +
'}';
}
}

View File

@ -32,6 +32,7 @@ import org.mockito.ArgumentCaptor;
import org.whispersystems.textsecuregcm.configuration.BadgeConfiguration;
import org.whispersystems.textsecuregcm.configuration.BadgesConfiguration;
import org.whispersystems.textsecuregcm.entities.Badge;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.entities.SelfBadge;
import org.whispersystems.textsecuregcm.storage.AccountBadge;
@ -65,7 +66,7 @@ public class ConfiguredProfileBadgeConverterTest {
private static BadgeConfiguration newBadge(int i) {
return new BadgeConfiguration(
idFor(i), "other", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"));
idFor(i), "other", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")));
}
private BadgesConfiguration createBadges(int count) {
@ -135,15 +136,15 @@ public class ConfiguredProfileBadgeConverterTest {
arguments(idFor(0), expired, false, false, null),
arguments(idFor(0), notExpired, false, false, null),
arguments(idFor(0), expired, true, false, null),
arguments(idFor(0), notExpired, true, false, new Badge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))),
arguments(idFor(0), notExpired, true, false, new Badge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")))),
arguments(idFor(1), expired, false, false, null),
arguments(idFor(1), notExpired, false, false, null),
arguments(idFor(1), expired, true, false, null),
arguments(idFor(1), notExpired, true, false, null),
arguments(idFor(0), expired, false, true, null),
arguments(idFor(0), notExpired, false, true, new SelfBadge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"), notExpired, false)),
arguments(idFor(0), notExpired, false, true, new SelfBadge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")), notExpired, false)),
arguments(idFor(0), expired, true, true, null),
arguments(idFor(0), notExpired, true, true, new SelfBadge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"), notExpired, true)),
arguments(idFor(0), notExpired, true, true, new SelfBadge(idFor(0), "other", nameFor(0), desriptionFor(0), List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")), notExpired, true)),
arguments(idFor(1), expired, false, true, null),
arguments(idFor(1), notExpired, false, true, null),
arguments(idFor(1), expired, true, true, null),

View File

@ -35,6 +35,7 @@ import org.whispersystems.textsecuregcm.configuration.SubscriptionLevelConfigura
import org.whispersystems.textsecuregcm.configuration.SubscriptionPriceConfiguration;
import org.whispersystems.textsecuregcm.controllers.SubscriptionController.GetLevelsResponse;
import org.whispersystems.textsecuregcm.entities.Badge;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.storage.IssuedReceiptsManager;
import org.whispersystems.textsecuregcm.storage.SubscriptionManager;
import org.whispersystems.textsecuregcm.stripe.StripeManager;
@ -79,11 +80,11 @@ class SubscriptionControllerTest {
3L, new SubscriptionLevelConfiguration("B3", "P3", Map.of("USD", new SubscriptionPriceConfiguration("R3", BigDecimal.valueOf(300))))
));
when(BADGE_TRANSLATOR.translate(any(), eq("B1"))).thenReturn(new Badge("B1", "cat1", "name1", "desc1",
List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")));
List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))));
when(BADGE_TRANSLATOR.translate(any(), eq("B2"))).thenReturn(new Badge("B2", "cat2", "name2", "desc2",
List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")));
List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))));
when(BADGE_TRANSLATOR.translate(any(), eq("B3"))).thenReturn(new Badge("B3", "cat3", "name3", "desc3",
List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")));
List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))));
GetLevelsResponse response = RESOURCE_EXTENSION.target("/v1/subscription/levels")
.request()

View File

@ -53,6 +53,7 @@ import org.whispersystems.textsecuregcm.configuration.StripeConfiguration;
import org.whispersystems.textsecuregcm.controllers.DonationController;
import org.whispersystems.textsecuregcm.entities.ApplePayAuthorizationRequest;
import org.whispersystems.textsecuregcm.entities.ApplePayAuthorizationResponse;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.entities.RedeemReceiptRequest;
import org.whispersystems.textsecuregcm.storage.AccountBadge;
import org.whispersystems.textsecuregcm.storage.AccountsManager;
@ -89,10 +90,10 @@ class DonationControllerTest {
static BadgesConfiguration getBadgesConfiguration() {
return new BadgesConfiguration(
List.of(
new BadgeConfiguration("TEST", "other", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST1", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST2", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST3", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))),
new BadgeConfiguration("TEST", "other", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST1", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST2", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST3", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")))),
List.of("TEST"),
Map.of(1L, "TEST1", 2L, "TEST2", 3L, "TEST3"));
}

View File

@ -53,6 +53,7 @@ import org.whispersystems.textsecuregcm.configuration.dynamic.DynamicPaymentsCon
import org.whispersystems.textsecuregcm.controllers.ProfileController;
import org.whispersystems.textsecuregcm.controllers.RateLimitExceededException;
import org.whispersystems.textsecuregcm.entities.Badge;
import org.whispersystems.textsecuregcm.entities.BadgeSvg;
import org.whispersystems.textsecuregcm.entities.CreateProfileRequest;
import org.whispersystems.textsecuregcm.entities.Profile;
import org.whispersystems.textsecuregcm.entities.ProfileAvatarUploadAttributes;
@ -109,13 +110,13 @@ class ProfileControllerTest {
usernamesManager,
dynamicConfigurationManager,
(acceptableLanguages, accountBadges, isSelf) -> List.of(new Badge("TEST", "other", "Test Badge",
"This badge is in unit tests.", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))
"This badge is in unit tests.", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")))
),
new BadgesConfiguration(List.of(
new BadgeConfiguration("TEST", "other", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST1", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST2", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S")),
new BadgeConfiguration("TEST3", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), List.of("s", "m", "M", "S"))
new BadgeConfiguration("TEST", "other", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST1", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST2", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt"))),
new BadgeConfiguration("TEST3", "testing", List.of("l", "m", "h", "x", "xx", "xxx"), "SVG", List.of(new BadgeSvg("sl", "sd", "st"), new BadgeSvg("ml", "md", "mt"), new BadgeSvg("ll", "ld", "lt")))
), List.of("TEST1"), Map.of(1L, "TEST1", 2L, "TEST2", 3L, "TEST3")),
s3client,
postPolicyGenerator,