keepsafe rework & alert ajustments
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s

This commit is contained in:
Shinuwa 2026-07-26 17:48:14 +02:00
parent 68005ef918
commit 2e6d8a2c0c
11 changed files with 129 additions and 45 deletions

View file

@ -11,6 +11,7 @@ import {
getDailyTargetMs,
getNowMs,
getTimePatternTargetMs,
getTimePatternRecurrenceMs,
timePartsToDurationMs,
timePartsToString
} from "./timerUtils.js";
@ -27,6 +28,17 @@ const ALERT_MODES = [
{ mode: "site", icon: "sound-max" }
];
const ALERT_MIN_DELAY_MS = 5 * 60 * 1000;
const AUTO_REFRESH_COUNTDOWN_TYPES = new Set(["time_pattern", "interval"]);
function isAlertGuarded(countdown) {
if (countdown?.type === "interval") return Number(countdown.intervalMs) < ALERT_MIN_DELAY_MS;
if (countdown?.type === "time_pattern") return getTimePatternRecurrenceMs(countdown.pattern) < ALERT_MIN_DELAY_MS;
return false;
}
function getAlertGuardMessage(textContent) {
return textContent.alertTooSoonTitle || "Alerte indisponible pour une répétition inférieure à 5 minutes";
}
function TimerValue({ ms, compact = false, showCentiseconds = true }) {
if (!showCentiseconds) return <span className="timer-value">{formatDuration(ms)}</span>;
@ -204,9 +216,8 @@ export function TimerModule({ toolboxId, moduleId, context }) {
function setCountdownAlertMode(countdownId, alertMode) {
const countdown = data.countdowns.find((item) => item.id === countdownId);
const targetMs = countdown ? getCountdownTargetMs(countdown, nowMs) : 0;
if (alertMode !== "off" && targetMs && targetMs - nowMs < ALERT_MIN_DELAY_MS) {
context.notify?.(textContent.alertTooSoonTitle || "Alerte indisponible à moins de 5 minutes");
if (alertMode !== "off" && AUTO_REFRESH_COUNTDOWN_TYPES.has(countdown?.type) && isAlertGuarded(countdown)) {
context.notify?.(getAlertGuardMessage(textContent));
return;
}
save({
@ -303,7 +314,7 @@ function TimerAlertModeSwitch({ mode, blocked, textContent, onChange }) {
visible: textContent.alertVisibleTitle || "Alerte quand la toolbox est affichée",
site: textContent.alertSiteTitle || "Alerte sur tout le site"
};
const blockedTitle = textContent.alertTooSoonTitle || "Alerte indisponible à moins de 5 minutes";
const blockedTitle = getAlertGuardMessage(textContent);
return (
<div
@ -316,11 +327,11 @@ function TimerAlertModeSwitch({ mode, blocked, textContent, onChange }) {
>
{ALERT_MODES.map((option) => {
const label = labels[option.mode];
const disabled = blocked && option.mode !== "off";
const disabled = Boolean(blocked);
return (
<button
key={option.mode}
className={`timer-alert-mode-button ${mode === option.mode ? "active" : ""}`}
className={`timer-alert-mode-button ${!blocked && mode === option.mode ? "active" : ""}`}
type="button"
onClick={() => onChange(option.mode)}
disabled={disabled}
@ -368,31 +379,31 @@ function CountdownControls({ textContent, form, onChange, onSubmit }) {
<select value={form.type} onChange={(event) => onChange({ type: event.target.value })}>
<option value="duration">{textContent.durationType || "Durée"}</option>
<option value="daily_time">{textContent.dailyTimeType || "Heure précise"}</option>
<option value="time_pattern">{textContent.timePatternType || "Horaire spécifique"}</option>
<option value="time_pattern">{textContent.timePatternType || "Pattern horaire"}</option>
<option value="interval">{textContent.intervalType || "Intervalle"}</option>
</select>
</label>
{form.type === "duration" && (
<label>
<span>{textContent.durationLabel || "Durée"}</span>
<span className="sr-only">{textContent.durationLabel || "Durée"}</span>
<TimePartsInput value={form.duration} onChange={(duration) => onChange({ duration })} />
</label>
)}
{form.type === "daily_time" && (
<label>
<span>{textContent.dailyTimeLabel || "Heure"}</span>
<span className="sr-only">{textContent.dailyTimeLabel || "Heure"}</span>
<TimePartsInput value={form.time} onChange={(time) => onChange({ time })} />
</label>
)}
{form.type === "time_pattern" && (
<label>
<span>{textContent.timePatternLabel || "Heure / minute / seconde"}</span>
<span className="sr-only">{textContent.timePatternLabel || "Heure / minute / seconde"}</span>
<TimePartsInput value={form.pattern} onChange={(pattern) => onChange({ pattern })} allowWildcard />
</label>
)}
{form.type === "interval" && (
<label>
<span>{textContent.intervalLabel || "Toutes les"}</span>
<span className="sr-only">{textContent.intervalLabel || "Toutes les"}</span>
<TimePartsInput value={form.interval} onChange={(interval) => onChange({ interval })} />
</label>
)}
@ -512,7 +523,7 @@ function CountdownList({ countdowns, nowMs, textContent, onRename, onAlertModeCh
)}
<TimerAlertModeSwitch
mode={countdown.alertMode}
blocked={countdown.targetMs && countdown.targetMs - nowMs < ALERT_MIN_DELAY_MS}
blocked={AUTO_REFRESH_COUNTDOWN_TYPES.has(countdown.type) && isAlertGuarded(countdown)}
textContent={textContent}
onChange={(alertMode) => onAlertModeChange(countdown.id, alertMode)}
/>