diff --git a/web/public/locales/en/common.json b/web/public/locales/en/common.json index 2e16f84f1c..c5d9c4aca3 100644 --- a/web/public/locales/en/common.json +++ b/web/public/locales/en/common.json @@ -21,7 +21,7 @@ "1hour": "1 hour", "12hours": "12 hours", "24hours": "24 hours", - "custom": "Custom\u2026", + "custom": "Custom...", "pm": "pm", "am": "am", "yr": "{{time}}yr", diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index 8363cd13c3..3b2d6561f6 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -1083,20 +1083,14 @@ "1hour": "Suspend for 1 hour", "12hours": "Suspend for 12 hours", "24hours": "Suspend for 24 hours", - "custom": "Suspend for custom time\u2026", + "custom": "Suspend until...", "untilRestart": "Suspend until restart" }, "customSuspension": { "title": "Custom suspension time", - "description": "Choose how long notifications should stay suspended for this camera.", - "tabDuration": "Duration", - "tabUntilTime": "Until time", - "hours": "Hours", - "minutes": "Minutes", + "description": "Suspend notifications for this camera until the selected time.", "untilLabel": "Suspend until", - "invalidTime": "Pick a time in the future.", - "apply": "Apply", - "cancel": "Cancel" + "invalidTime": "Pick a time in the future." }, "cancelSuspension": "Cancel Suspension", "toast": { diff --git a/web/src/components/config-form/sectionExtras/NotificationsSettingsExtras.tsx b/web/src/components/config-form/sectionExtras/NotificationsSettingsExtras.tsx index 55b520b08b..a18667f326 100644 --- a/web/src/components/config-form/sectionExtras/NotificationsSettingsExtras.tsx +++ b/web/src/components/config-form/sectionExtras/NotificationsSettingsExtras.tsx @@ -740,16 +740,8 @@ export function CameraNotificationSwitch({ }, [notificationSuspendUntil, notificationState]); const [customDialogOpen, setCustomDialogOpen] = useState(false); - // Doesn't actually represent the state of the Select - // Workaround for CustomSuspensionDialog (explained below at setSelectValue call site). - const [selectValue, setSelectValue] = useState(""); const handleSuspend = (duration: string) => { - if (duration === "custom") { - setSelectValue("custom"); - setCustomDialogOpen(true); - return; - } setIsSuspended(true); if (duration == "off") { sendNotification("OFF"); @@ -822,37 +814,41 @@ export function CameraNotificationSwitch({ {!isSuspended ? ( - +
+ + +
) : ( - - - { - if (!day) return; - const next = new Date(day); - // If `until` is invalid, don't propagate - // NaN hours/minutes into the new date - fall back to now. - const carry = isValidDate(until) ? until : new Date(); - next.setHours( - carry.getHours(), - carry.getMinutes(), - carry.getSeconds(), - 0, - ); - setUntil(next); - setCalendarOpen(false); - }} - /> - - - { - // Ignore anything that doesn't parse to a real HH:MM pair. - const [h, m] = e.target.value.split(":"); - const hh = Number.parseInt(h ?? "", 10); - const mm = Number.parseInt(m ?? "", 10); - if (Number.isNaN(hh) || Number.isNaN(mm)) return; - const base = isValidDate(until) ? until : new Date(); - const next = new Date(base); - next.setHours(hh, mm, 0, 0); +
+ +
+ + + + + + + { + if (!day) return; + const next = new Date(day); + const carry = isValidDate(until) ? until : new Date(); + next.setHours( + carry.getHours(), + carry.getMinutes(), + carry.getSeconds(), + 0, + ); setUntil(next); + setCalendarOpen(false); }} /> -
- {!canApply && ( -

- {t("notification.customSuspension.invalidTime")} -

- )} -
- - + + + { + const [h, m] = e.target.value.split(":"); + const hh = Number.parseInt(h ?? "", 10); + const mm = Number.parseInt(m ?? "", 10); + if (Number.isNaN(hh) || Number.isNaN(mm)) return; + const base = isValidDate(until) ? until : new Date(); + const next = new Date(base); + next.setHours(hh, mm, 0, 0); + setUntil(next); + }} + /> + + {!isFuture && ( +

+ {t("notification.customSuspension.invalidTime")} +

+ )} +