Add repeatable admin notification sounds
This commit is contained in:
@@ -159,8 +159,11 @@
|
|||||||
<option value="soft">Jemny</option>
|
<option value="soft">Jemny</option>
|
||||||
<option value="chime">Cinknuti</option>
|
<option value="chime">Cinknuti</option>
|
||||||
<option value="urgent">Vyrazny</option>
|
<option value="urgent">Vyrazny</option>
|
||||||
|
<option value="tap">Kratke tuknuti</option>
|
||||||
|
<option value="double">Dvojite upozorneni</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
<label class="setting-switch">Opakovat do otevreni chatu <input id="adminSoundRepeat" type="checkbox"></label>
|
||||||
<button id="adminSoundTest" type="button">Otestovat zvuk</button>
|
<button id="adminSoundTest" type="button">Otestovat zvuk</button>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -12,8 +12,10 @@ const state = {
|
|||||||
soundMuted: localStorage.getItem("mf_admin_sound_muted") === "1",
|
soundMuted: localStorage.getItem("mf_admin_sound_muted") === "1",
|
||||||
soundVolume: Number(localStorage.getItem("mf_admin_sound_volume") || 70),
|
soundVolume: Number(localStorage.getItem("mf_admin_sound_volume") || 70),
|
||||||
soundStyle: localStorage.getItem("mf_admin_sound_style") || "bright",
|
soundStyle: localStorage.getItem("mf_admin_sound_style") || "bright",
|
||||||
|
soundRepeat: localStorage.getItem("mf_admin_sound_repeat") === "1",
|
||||||
replyFiles: [],
|
replyFiles: [],
|
||||||
attentionTimer: null,
|
attentionTimer: null,
|
||||||
|
soundRepeatTimer: null,
|
||||||
attentionOn: false,
|
attentionOn: false,
|
||||||
originalTitle: document.title,
|
originalTitle: document.title,
|
||||||
originalFavicon: document.querySelector("link[rel='icon']")?.href || "/favicon.svg"
|
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);
|
localStorage.setItem("mf_admin_sound_style", state.soundStyle);
|
||||||
renderAdminSoundControls();
|
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", () => {
|
$("#adminSoundTest").addEventListener("click", () => {
|
||||||
playNotifySound({ ignoreMuted: true });
|
playNotifySound({ ignoreMuted: true });
|
||||||
});
|
});
|
||||||
@@ -804,6 +812,7 @@ async function saveSite(patch) {
|
|||||||
function notify() {
|
function notify() {
|
||||||
startAttention();
|
startAttention();
|
||||||
playNotifySound();
|
playNotifySound();
|
||||||
|
startRepeatingSound();
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderAdminSoundControls() {
|
function renderAdminSoundControls() {
|
||||||
@@ -812,6 +821,7 @@ function renderAdminSoundControls() {
|
|||||||
const settingsToggle = $("#adminSoundToggleSettings");
|
const settingsToggle = $("#adminSoundToggleSettings");
|
||||||
const settingsVolume = $("#adminSoundVolumeSettings");
|
const settingsVolume = $("#adminSoundVolumeSettings");
|
||||||
const settingsStyle = $("#adminSoundStyle");
|
const settingsStyle = $("#adminSoundStyle");
|
||||||
|
const settingsRepeat = $("#adminSoundRepeat");
|
||||||
const safeVolume = clamp(state.soundVolume, 0, 100);
|
const safeVolume = clamp(state.soundVolume, 0, 100);
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
toggle.classList.toggle("muted", state.soundMuted || safeVolume <= 0);
|
toggle.classList.toggle("muted", state.soundMuted || safeVolume <= 0);
|
||||||
@@ -825,6 +835,7 @@ function renderAdminSoundControls() {
|
|||||||
if (settingsToggle) settingsToggle.checked = !state.soundMuted;
|
if (settingsToggle) settingsToggle.checked = !state.soundMuted;
|
||||||
if (settingsVolume) settingsVolume.value = String(safeVolume);
|
if (settingsVolume) settingsVolume.value = String(safeVolume);
|
||||||
if (settingsStyle) settingsStyle.value = state.soundStyle;
|
if (settingsStyle) settingsStyle.value = state.soundStyle;
|
||||||
|
if (settingsRepeat) settingsRepeat.checked = state.soundRepeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setAdminSoundMuted(isMuted) {
|
function setAdminSoundMuted(isMuted) {
|
||||||
@@ -832,6 +843,7 @@ function setAdminSoundMuted(isMuted) {
|
|||||||
if (!state.soundMuted && state.soundVolume <= 0) state.soundVolume = 70;
|
if (!state.soundMuted && state.soundVolume <= 0) state.soundVolume = 70;
|
||||||
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
||||||
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
||||||
|
if (state.soundMuted) stopRepeatingSound();
|
||||||
renderAdminSoundControls();
|
renderAdminSoundControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,6 +852,7 @@ function setAdminSoundVolume(value) {
|
|||||||
state.soundMuted = state.soundVolume <= 0;
|
state.soundMuted = state.soundVolume <= 0;
|
||||||
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
||||||
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
||||||
|
if (state.soundMuted) stopRepeatingSound();
|
||||||
renderAdminSoundControls();
|
renderAdminSoundControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -863,8 +876,28 @@ function playNotifySound(options = {}) {
|
|||||||
setTimeout(() => audio.close().catch(() => {}), 720);
|
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) {
|
function soundPattern(style) {
|
||||||
const patterns = {
|
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: [
|
soft: [
|
||||||
{ offset: 0, duration: 0.13, frequency: 520, type: "sine" },
|
{ offset: 0, duration: 0.13, frequency: 520, type: "sine" },
|
||||||
{ offset: 0.16, duration: 0.12, frequency: 680, type: "sine" }
|
{ offset: 0.16, duration: 0.12, frequency: 680, type: "sine" }
|
||||||
@@ -905,6 +938,7 @@ function startAttention() {
|
|||||||
function stopAttention() {
|
function stopAttention() {
|
||||||
if (state.attentionTimer) clearInterval(state.attentionTimer);
|
if (state.attentionTimer) clearInterval(state.attentionTimer);
|
||||||
state.attentionTimer = null;
|
state.attentionTimer = null;
|
||||||
|
stopRepeatingSound();
|
||||||
state.attentionOn = false;
|
state.attentionOn = false;
|
||||||
document.title = state.originalTitle;
|
document.title = state.originalTitle;
|
||||||
const favicon = document.querySelector("link[rel='icon']");
|
const favicon = document.querySelector("link[rel='icon']");
|
||||||
|
|||||||
Reference in New Issue
Block a user