mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 03:39:26 +00:00
Normalize settings on save
This commit is contained in:
@@ -2,9 +2,15 @@ package dev.kruhlmann.imgfloat.service;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import dev.kruhlmann.imgfloat.model.AudioAsset;
|
||||
import dev.kruhlmann.imgfloat.model.Settings;
|
||||
import dev.kruhlmann.imgfloat.model.VisualAsset;
|
||||
import dev.kruhlmann.imgfloat.repository.AudioAssetRepository;
|
||||
import dev.kruhlmann.imgfloat.repository.SettingsRepository;
|
||||
import dev.kruhlmann.imgfloat.repository.VisualAssetRepository;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -15,10 +21,19 @@ public class SettingsService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(SettingsService.class);
|
||||
|
||||
private final SettingsRepository repo;
|
||||
private final VisualAssetRepository visualAssetRepository;
|
||||
private final AudioAssetRepository audioAssetRepository;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public SettingsService(SettingsRepository repo, ObjectMapper objectMapper) {
|
||||
public SettingsService(
|
||||
SettingsRepository repo,
|
||||
VisualAssetRepository visualAssetRepository,
|
||||
AudioAssetRepository audioAssetRepository,
|
||||
ObjectMapper objectMapper
|
||||
) {
|
||||
this.repo = repo;
|
||||
this.visualAssetRepository = visualAssetRepository;
|
||||
this.audioAssetRepository = audioAssetRepository;
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
@@ -39,7 +54,9 @@ public class SettingsService {
|
||||
public Settings save(Settings settings) {
|
||||
settings.setId(1);
|
||||
logSettings("Saving settings", settings);
|
||||
return repo.save(settings);
|
||||
Settings savedSettings = repo.save(settings);
|
||||
clampAssetsToSettings(savedSettings);
|
||||
return savedSettings;
|
||||
}
|
||||
|
||||
public void logSettings(String msg, Settings settings) {
|
||||
@@ -49,4 +66,78 @@ public class SettingsService {
|
||||
logger.error("Failed to serialize settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void clampAssetsToSettings(Settings settings) {
|
||||
double minSpeed = settings.getMinAssetPlaybackSpeedFraction();
|
||||
double maxSpeed = settings.getMaxAssetPlaybackSpeedFraction();
|
||||
double minPitch = settings.getMinAssetAudioPitchFraction();
|
||||
double maxPitch = settings.getMaxAssetAudioPitchFraction();
|
||||
double minVolume = settings.getMinAssetVolumeFraction();
|
||||
double maxVolume = settings.getMaxAssetVolumeFraction();
|
||||
|
||||
List<VisualAsset> visualsToUpdate = new ArrayList<>();
|
||||
for (VisualAsset visual : visualAssetRepository.findAll()) {
|
||||
boolean changed = false;
|
||||
double speed = visual.getSpeed();
|
||||
double clampedSpeed = clamp(speed, minSpeed, maxSpeed);
|
||||
if (Double.compare(speed, clampedSpeed) != 0) {
|
||||
visual.setSpeed(clampedSpeed);
|
||||
changed = true;
|
||||
}
|
||||
double volume = visual.getAudioVolume();
|
||||
double clampedVolume = clamp(volume, minVolume, maxVolume);
|
||||
if (Double.compare(volume, clampedVolume) != 0) {
|
||||
visual.setAudioVolume(clampedVolume);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
visualsToUpdate.add(visual);
|
||||
}
|
||||
}
|
||||
|
||||
List<AudioAsset> audioToUpdate = new ArrayList<>();
|
||||
for (AudioAsset audio : audioAssetRepository.findAll()) {
|
||||
boolean changed = false;
|
||||
double speed = audio.getAudioSpeed();
|
||||
double clampedSpeed = clamp(speed, minSpeed, maxSpeed);
|
||||
if (Double.compare(speed, clampedSpeed) != 0) {
|
||||
audio.setAudioSpeed(clampedSpeed);
|
||||
changed = true;
|
||||
}
|
||||
double pitch = audio.getAudioPitch();
|
||||
double clampedPitch = clamp(pitch, minPitch, maxPitch);
|
||||
if (Double.compare(pitch, clampedPitch) != 0) {
|
||||
audio.setAudioPitch(clampedPitch);
|
||||
changed = true;
|
||||
}
|
||||
double volume = audio.getAudioVolume();
|
||||
double clampedVolume = clamp(volume, minVolume, maxVolume);
|
||||
if (Double.compare(volume, clampedVolume) != 0) {
|
||||
audio.setAudioVolume(clampedVolume);
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
audioToUpdate.add(audio);
|
||||
}
|
||||
}
|
||||
|
||||
if (!visualsToUpdate.isEmpty()) {
|
||||
visualAssetRepository.saveAll(visualsToUpdate);
|
||||
}
|
||||
if (!audioToUpdate.isEmpty()) {
|
||||
audioAssetRepository.saveAll(audioToUpdate);
|
||||
}
|
||||
|
||||
if (!visualsToUpdate.isEmpty() || !audioToUpdate.isEmpty()) {
|
||||
logger.info(
|
||||
"Normalized {} visual assets and {} audio assets to new settings ranges",
|
||||
visualsToUpdate.size(),
|
||||
audioToUpdate.size()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private double clamp(double value, double min, double max) {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,6 +318,82 @@ body.has-staging-banner {
|
||||
color: #fef3c7;
|
||||
}
|
||||
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 24px;
|
||||
right: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
z-index: 1200;
|
||||
}
|
||||
|
||||
.toast {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
min-width: 220px;
|
||||
max-width: 360px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 12px;
|
||||
border: 1px solid transparent;
|
||||
background: rgba(15, 23, 42, 0.96);
|
||||
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.45);
|
||||
color: #e2e8f0;
|
||||
font-size: 14px;
|
||||
animation: toast-enter 0.2s ease-out;
|
||||
}
|
||||
|
||||
.toast-exit {
|
||||
opacity: 0;
|
||||
transform: translateX(8px);
|
||||
transition:
|
||||
opacity 0.2s ease,
|
||||
transform 0.2s ease;
|
||||
}
|
||||
|
||||
.toast-indicator {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 999px;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.toast-success {
|
||||
border-color: rgba(34, 197, 94, 0.45);
|
||||
color: #86efac;
|
||||
}
|
||||
|
||||
.toast-error {
|
||||
border-color: rgba(248, 113, 113, 0.45);
|
||||
color: #fecaca;
|
||||
}
|
||||
|
||||
.toast-warning {
|
||||
border-color: rgba(251, 191, 36, 0.5);
|
||||
color: #fde68a;
|
||||
}
|
||||
|
||||
.toast-info {
|
||||
border-color: rgba(56, 189, 248, 0.45);
|
||||
color: #bae6fd;
|
||||
}
|
||||
|
||||
@keyframes toast-enter {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(8px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.info-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -624,6 +700,15 @@ button:disabled:hover {
|
||||
box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.25);
|
||||
}
|
||||
|
||||
.text-input:invalid {
|
||||
border-color: #f87171;
|
||||
}
|
||||
|
||||
.text-input:focus:invalid {
|
||||
border-color: #f87171;
|
||||
box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.25);
|
||||
}
|
||||
|
||||
.text-input:disabled,
|
||||
.text-input[aria-disabled="true"] {
|
||||
background: #020617;
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="0.5"
|
||||
/>
|
||||
</label>
|
||||
@@ -134,7 +134,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="1.0"
|
||||
/>
|
||||
</label>
|
||||
@@ -154,7 +154,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="0.8"
|
||||
/>
|
||||
</label>
|
||||
@@ -167,7 +167,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="1.0"
|
||||
/>
|
||||
</label>
|
||||
@@ -181,7 +181,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="0.2"
|
||||
/>
|
||||
</label>
|
||||
@@ -194,7 +194,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="decimal"
|
||||
pattern="^(0(\.\d+)?|1(\.0+)?)$"
|
||||
pattern="^(0|[1-9]\d*)(\.\d+)?$"
|
||||
placeholder="1.0"
|
||||
/>
|
||||
</label>
|
||||
@@ -214,7 +214,7 @@
|
||||
class="text-input"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
pattern="^[1-9]\\d*$"
|
||||
pattern="^[1-9]\d*$"
|
||||
placeholder="60"
|
||||
/>
|
||||
</label>
|
||||
|
||||
Reference in New Issue
Block a user