Add repeatable admin notification sounds

This commit is contained in:
rajchales-monito
2026-07-24 14:57:03 +02:00
parent 3f709f3a4e
commit 8c81e5d405
2 changed files with 37 additions and 0 deletions
+3
View File
@@ -159,8 +159,11 @@
<option value="soft">Jemny</option>
<option value="chime">Cinknuti</option>
<option value="urgent">Vyrazny</option>
<option value="tap">Kratke tuknuti</option>
<option value="double">Dvojite upozorneni</option>
</select>
</label>
<label class="setting-switch">Opakovat do otevreni chatu <input id="adminSoundRepeat" type="checkbox"></label>
<button id="adminSoundTest" type="button">Otestovat zvuk</button>
</div>
</section>
+34
View File
@@ -12,8 +12,10 @@ const state = {
soundMuted: localStorage.getItem("mf_admin_sound_muted") === "1",
soundVolume: Number(localStorage.getItem("mf_admin_sound_volume") || 70),
soundStyle: localStorage.getItem("mf_admin_sound_style") || "bright",
soundRepeat: localStorage.getItem("mf_admin_sound_repeat") === "1",
replyFiles: [],
attentionTimer: null,
soundRepeatTimer: null,
attentionOn: false,
originalTitle: document.title,
originalFavicon: document.querySelector("link[rel='icon']")?.href || "/favicon.svg"
@@ -68,6 +70,12 @@ $("#adminSoundStyle").addEventListener("change", (event) => {
localStorage.setItem("mf_admin_sound_style", state.soundStyle);
renderAdminSoundControls();
});
$("#adminSoundRepeat").addEventListener("change", (event) => {
state.soundRepeat = event.target.checked;
localStorage.setItem("mf_admin_sound_repeat", state.soundRepeat ? "1" : "0");
if (!state.soundRepeat) stopRepeatingSound();
renderAdminSoundControls();
});
$("#adminSoundTest").addEventListener("click", () => {
playNotifySound({ ignoreMuted: true });
});
@@ -804,6 +812,7 @@ async function saveSite(patch) {
function notify() {
startAttention();
playNotifySound();
startRepeatingSound();
}
function renderAdminSoundControls() {
@@ -812,6 +821,7 @@ function renderAdminSoundControls() {
const settingsToggle = $("#adminSoundToggleSettings");
const settingsVolume = $("#adminSoundVolumeSettings");
const settingsStyle = $("#adminSoundStyle");
const settingsRepeat = $("#adminSoundRepeat");
const safeVolume = clamp(state.soundVolume, 0, 100);
if (toggle) {
toggle.classList.toggle("muted", state.soundMuted || safeVolume <= 0);
@@ -825,6 +835,7 @@ function renderAdminSoundControls() {
if (settingsToggle) settingsToggle.checked = !state.soundMuted;
if (settingsVolume) settingsVolume.value = String(safeVolume);
if (settingsStyle) settingsStyle.value = state.soundStyle;
if (settingsRepeat) settingsRepeat.checked = state.soundRepeat;
}
function setAdminSoundMuted(isMuted) {
@@ -832,6 +843,7 @@ function setAdminSoundMuted(isMuted) {
if (!state.soundMuted && state.soundVolume <= 0) state.soundVolume = 70;
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
if (state.soundMuted) stopRepeatingSound();
renderAdminSoundControls();
}
@@ -840,6 +852,7 @@ function setAdminSoundVolume(value) {
state.soundMuted = state.soundVolume <= 0;
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
if (state.soundMuted) stopRepeatingSound();
renderAdminSoundControls();
}
@@ -863,8 +876,28 @@ function playNotifySound(options = {}) {
setTimeout(() => audio.close().catch(() => {}), 720);
}
function startRepeatingSound() {
if (!state.soundRepeat || state.soundRepeatTimer || state.soundMuted || clamp(state.soundVolume, 0, 100) <= 0) return;
state.soundRepeatTimer = setInterval(() => {
playNotifySound();
}, 5500);
}
function stopRepeatingSound() {
if (state.soundRepeatTimer) clearInterval(state.soundRepeatTimer);
state.soundRepeatTimer = null;
}
function soundPattern(style) {
const patterns = {
tap: [
{ offset: 0, duration: 0.08, frequency: 720, type: "sine" }
],
double: [
{ offset: 0, duration: 0.09, frequency: 760, type: "sine" },
{ offset: 0.12, duration: 0.09, frequency: 760, type: "sine" },
{ offset: 0.28, duration: 0.1, frequency: 980, type: "triangle" }
],
soft: [
{ offset: 0, duration: 0.13, frequency: 520, type: "sine" },
{ offset: 0.16, duration: 0.12, frequency: 680, type: "sine" }
@@ -905,6 +938,7 @@ function startAttention() {
function stopAttention() {
if (state.attentionTimer) clearInterval(state.attentionTimer);
state.attentionTimer = null;
stopRepeatingSound();
state.attentionOn = false;
document.title = state.originalTitle;
const favicon = document.querySelector("link[rel='icon']");