feat(settings): reduce animations appearance flag
Build, Test & Push Auth Service / quality-check (push) Successful in 53s
Build, Test & Push Auth Service / docker (push) Successful in 1m31s

This commit is contained in:
lobo committed 2026-10-01 15:09:25 +02:00
1 parent a60011ce9f
commit 878ede914b
11 files changed
+30 -17

No files matched your search

@@ -13,7 +13,8 @@ public record AppearanceRequest(
Boolean wideLayout,
@Positive Long backgroundAppid,
@Positive Long bannerAppid,
Boolean showBanner) {
Boolean showBanner,
Boolean reduceMotion) {
public static final String ACCENTS = "violet|blue|green|orange|pink|red";
public static final String CORNERS = "sharp|default|round";
@@ -1,5 +1,5 @@
package auth_service.modules.user.api.dto.response;
public record AppearanceResponse(String accent, String corners, boolean wideLayout, Long backgroundAppid,
Long bannerAppid, boolean showBanner) {
Long bannerAppid, boolean showBanner, boolean reduceMotion) {
}
@@ -56,7 +56,8 @@ public abstract class ApiMapper {
private static AppearanceResponse toApi(Appearance appearance) {
return new AppearanceResponse(appearance.accent(), appearance.corners(), appearance.wideLayout(),
appearance.backgroundAppid(), appearance.bannerAppid(), appearance.showBanner());
appearance.backgroundAppid(), appearance.bannerAppid(), appearance.showBanner(),
appearance.reduceMotion());
}
private static ProfileStyleResponse toApi(ProfileStyle style) {
@@ -81,7 +82,8 @@ public abstract class ApiMapper {
public static Appearance toDomain(AppearanceRequest request) {
// A missing showBanner keeps the banner on, the default.
return new Appearance(request.accent(), request.corners(), Boolean.TRUE.equals(request.wideLayout()),
request.backgroundAppid(), request.bannerAppid(), !Boolean.FALSE.equals(request.showBanner()));
request.backgroundAppid(), request.bannerAppid(), !Boolean.FALSE.equals(request.showBanner()),
Boolean.TRUE.equals(request.reduceMotion()));
}
public static UserSettings toDomain(UserSettingsRequest request) {
@@ -4,9 +4,10 @@ package auth_service.modules.user.model;
* @param backgroundAppid the Steam app whose art fills the page background; null for none
* @param bannerAppid the Steam app whose art is the dashboard banner; null for the most played game of the last
* two weeks
* @param reduceMotion viewer setting: every animated look is static, also on other users' profiles
*/
public record Appearance(String accent, String corners, boolean wideLayout, Long backgroundAppid,
Long bannerAppid, boolean showBanner) {
Long bannerAppid, boolean showBanner, boolean reduceMotion) {
public static final Appearance DEFAULT = new Appearance("violet", "default", false, null, null, true);
public static final Appearance DEFAULT = new Appearance("violet", "default", false, null, null, true, false);
}
@@ -50,6 +50,9 @@ public class UserSettingsEntity {
@Column(name = "show_banner", nullable = false)
private boolean showBanner;
@Column(name = "reduce_motion", nullable = false)
private boolean reduceMotion;
@Column(name = "profile_accent", nullable = false)
private String profileAccent;
@@ -28,7 +28,8 @@ public abstract class EntityMapper {
.theme(settings.getTheme())
.publicProfile(settings.isPublicProfile())
.appearance(new Appearance(settings.getAccent(), settings.getCorners(), settings.isWideLayout(),
settings.getBackgroundAppid(), settings.getBannerAppid(), settings.isShowBanner()))
settings.getBackgroundAppid(), settings.getBannerAppid(), settings.isShowBanner(),
settings.isReduceMotion()))
.profileStyle(new ProfileStyle(settings.getProfileAccent(), settings.getProfileCorners(),
settings.getProfileBannerAppid(), settings.getProfileBackgroundAppid()))
.dashboardTiles(settings.getDashboardTiles() == null ? null
@@ -66,6 +67,7 @@ public abstract class EntityMapper {
target.setBackgroundAppid(appearance.backgroundAppid());
target.setBannerAppid(appearance.bannerAppid());
target.setShowBanner(appearance.showBanner());
target.setReduceMotion(appearance.reduceMotion());
ProfileStyle style = settings.getProfileStyle();
target.setProfileAccent(style.accent());
target.setProfileCorners(style.corners());
@@ -0,0 +1,3 @@
-- Viewer setting: every animated look is static, also on other users' profiles.
ALTER TABLE user_settings
ADD COLUMN reduce_motion BOOLEAN NOT NULL DEFAULT FALSE;
@@ -328,7 +328,7 @@ class UserControllerTest extends AbstractWebMvcTest {
void getCurrentUser_ShowsAppearance() throws Exception {
var email = "test@example.com";
var settings = UserSettings.builder().language("en").theme("dark")
.appearance(new Appearance("blue", "round", true, 620L, 1086940L, false)).build();
.appearance(new Appearance("blue", "round", true, 620L, 1086940L, false, true)).build();
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken(new UserPrincipal("1", null), null, Collections.emptyList())
);
@@ -341,7 +341,8 @@ class UserControllerTest extends AbstractWebMvcTest {
.andExpect(jsonPath("$.settings.appearance.wideLayout").value(true))
.andExpect(jsonPath("$.settings.appearance.backgroundAppid").value(620))
.andExpect(jsonPath("$.settings.appearance.bannerAppid").value(1086940))
.andExpect(jsonPath("$.settings.appearance.showBanner").value(false));
.andExpect(jsonPath("$.settings.appearance.showBanner").value(false))
.andExpect(jsonPath("$.settings.appearance.reduceMotion").value(true));
}
@Test
@@ -629,10 +630,10 @@ class UserControllerTest extends AbstractWebMvcTest {
mockMvc.perform(put("/api/users/settings/appearance")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"accent\":\"green\",\"corners\":\"sharp\",\"wideLayout\":true,\"backgroundAppid\":620,"
+ "\"bannerAppid\":1086940,\"showBanner\":false}"))
+ "\"bannerAppid\":1086940,\"showBanner\":false,\"reduceMotion\":true}"))
.andExpect(status().isNoContent());
verify(userService).updateAppearance(1L, new Appearance("green", "sharp", true, 620L, 1086940L, false));
verify(userService).updateAppearance(1L, new Appearance("green", "sharp", true, 620L, 1086940L, false, true));
}
@Test
@@ -645,7 +646,7 @@ class UserControllerTest extends AbstractWebMvcTest {
.content("{\"accent\":\"violet\",\"corners\":\"default\"}"))
.andExpect(status().isNoContent());
verify(userService).updateAppearance(1L, new Appearance("violet", "default", false, null, null, true));
verify(userService).updateAppearance(1L, new Appearance("violet", "default", false, null, null, true, false));
}
// Each body differs from a valid one in one field only, so the 400 comes from that field's constraint.
@@ -276,7 +276,7 @@ class UserRepositoryTest extends AbstractPersistenceTest {
.registrationDate(LocalDateTime.now())
.build());
userRepository.update(userEntity.getId(),
user -> user.getSettings().setAppearance(new Appearance("pink", "sharp", false, 220L, null, true)));
user -> user.getSettings().setAppearance(new Appearance("pink", "sharp", false, 220L, null, true, true)));
entityManager.flush();
updateSettings(userEntity.getId(), null,
@@ -285,7 +285,7 @@ class UserRepositoryTest extends AbstractPersistenceTest {
entityManager.clear();
var settings = findByEmail("keep@example.com").orElseThrow().getSettings();
assertEquals(new Appearance("pink", "sharp", false, 220L, null, true), settings.getAppearance());
assertEquals(new Appearance("pink", "sharp", false, 220L, null, true, true), settings.getAppearance());
}
@Test
@@ -180,7 +180,7 @@ class UserServiceTest extends AbstractUnitTest {
@Test
void updateAppearance_StoresItWithoutANewToken() {
var appearance = new Appearance("red", "round", false, null, null, true);
var appearance = new Appearance("red", "round", false, null, null, true, false);
userService.updateAppearance(1L, appearance);