Add admin sound preferences
This commit is contained in:
+88
-26
@@ -11,6 +11,7 @@ const state = {
|
||||
hideBots: localStorage.getItem("mf_admin_hide_bots") !== "0",
|
||||
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",
|
||||
replyFiles: [],
|
||||
attentionTimer: null,
|
||||
attentionOn: false,
|
||||
@@ -48,22 +49,35 @@ $("#logoutButton").addEventListener("click", async () => {
|
||||
location.reload();
|
||||
});
|
||||
|
||||
$("#settingsButton").addEventListener("click", () => $("#settingsPanel").classList.remove("hidden"));
|
||||
$("#settingsButton").addEventListener("click", () => $("#settingsPanel").classList.toggle("hidden"));
|
||||
$("#closeSettingsButton").addEventListener("click", () => $("#settingsPanel").classList.add("hidden"));
|
||||
$("#adminSoundToggle").addEventListener("click", () => {
|
||||
state.soundMuted = !state.soundMuted;
|
||||
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));
|
||||
renderAdminSoundControls();
|
||||
setAdminSoundMuted(!state.soundMuted);
|
||||
});
|
||||
$("#adminSoundVolume").addEventListener("input", (event) => {
|
||||
state.soundVolume = clamp(Number(event.target.value), 0, 100);
|
||||
state.soundMuted = state.soundVolume <= 0;
|
||||
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
||||
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
||||
setAdminSoundVolume(Number(event.target.value));
|
||||
});
|
||||
$("#adminSoundToggleSettings").addEventListener("change", (event) => {
|
||||
setAdminSoundMuted(!event.target.checked);
|
||||
});
|
||||
$("#adminSoundVolumeSettings").addEventListener("input", (event) => {
|
||||
setAdminSoundVolume(Number(event.target.value));
|
||||
});
|
||||
$("#adminSoundStyle").addEventListener("change", (event) => {
|
||||
state.soundStyle = event.target.value;
|
||||
localStorage.setItem("mf_admin_sound_style", state.soundStyle);
|
||||
renderAdminSoundControls();
|
||||
});
|
||||
$("#adminSoundTest").addEventListener("click", () => {
|
||||
playNotifySound({ ignoreMuted: true });
|
||||
});
|
||||
document.querySelectorAll("[data-settings-tab]").forEach((button) => {
|
||||
button.addEventListener("click", () => {
|
||||
const tab = button.dataset.settingsTab;
|
||||
document.querySelectorAll("[data-settings-tab]").forEach((item) => item.classList.toggle("active", item === button));
|
||||
document.querySelectorAll("[data-settings-panel]").forEach((panel) => panel.classList.toggle("active", panel.dataset.settingsPanel === tab));
|
||||
});
|
||||
});
|
||||
$("#settingsForm").brand.addEventListener("input", (event) => {
|
||||
$("#settingsForm").brandHex.value = normalizeHexColor(event.target.value) || event.target.value;
|
||||
});
|
||||
@@ -795,33 +809,81 @@ function notify() {
|
||||
function renderAdminSoundControls() {
|
||||
const toggle = $("#adminSoundToggle");
|
||||
const volume = $("#adminSoundVolume");
|
||||
if (!toggle || !volume) return;
|
||||
const settingsToggle = $("#adminSoundToggleSettings");
|
||||
const settingsVolume = $("#adminSoundVolumeSettings");
|
||||
const settingsStyle = $("#adminSoundStyle");
|
||||
const safeVolume = clamp(state.soundVolume, 0, 100);
|
||||
toggle.classList.toggle("muted", state.soundMuted || safeVolume <= 0);
|
||||
toggle.setAttribute("aria-label", state.soundMuted ? "Zapnout zvuk notifikaci" : "Vypnout zvuk notifikaci");
|
||||
toggle.title = state.soundMuted ? "Zapnout zvuk notifikaci" : "Vypnout zvuk notifikaci";
|
||||
volume.value = String(safeVolume);
|
||||
volume.title = `Hlasitost ${safeVolume}%`;
|
||||
if (toggle) {
|
||||
toggle.classList.toggle("muted", state.soundMuted || safeVolume <= 0);
|
||||
toggle.setAttribute("aria-label", state.soundMuted ? "Zapnout zvuk notifikaci" : "Vypnout zvuk notifikaci");
|
||||
toggle.title = state.soundMuted ? "Zapnout zvuk notifikaci" : "Vypnout zvuk notifikaci";
|
||||
}
|
||||
if (volume) {
|
||||
volume.value = String(safeVolume);
|
||||
volume.title = `Hlasitost ${safeVolume}%`;
|
||||
}
|
||||
if (settingsToggle) settingsToggle.checked = !state.soundMuted;
|
||||
if (settingsVolume) settingsVolume.value = String(safeVolume);
|
||||
if (settingsStyle) settingsStyle.value = state.soundStyle;
|
||||
}
|
||||
|
||||
function playNotifySound() {
|
||||
function setAdminSoundMuted(isMuted) {
|
||||
state.soundMuted = Boolean(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));
|
||||
renderAdminSoundControls();
|
||||
}
|
||||
|
||||
function setAdminSoundVolume(value) {
|
||||
state.soundVolume = clamp(value, 0, 100);
|
||||
state.soundMuted = state.soundVolume <= 0;
|
||||
localStorage.setItem("mf_admin_sound_volume", String(state.soundVolume));
|
||||
localStorage.setItem("mf_admin_sound_muted", state.soundMuted ? "1" : "0");
|
||||
renderAdminSoundControls();
|
||||
}
|
||||
|
||||
function playNotifySound(options = {}) {
|
||||
const volume = clamp(state.soundVolume, 0, 100);
|
||||
if (state.soundMuted || volume <= 0) return;
|
||||
if (!options.ignoreMuted && (state.soundMuted || volume <= 0)) return;
|
||||
const AudioCtor = window.AudioContext || window.webkitAudioContext;
|
||||
if (!AudioCtor) return;
|
||||
const audio = new AudioCtor();
|
||||
const gain = audio.createGain();
|
||||
gain.gain.value = 0.12 * (volume / 100);
|
||||
gain.gain.value = 0.12 * ((volume || 70) / 100);
|
||||
gain.connect(audio.destination);
|
||||
[0, 0.14].forEach((offset, index) => {
|
||||
for (const tone of soundPattern(state.soundStyle)) {
|
||||
const osc = audio.createOscillator();
|
||||
osc.type = "sine";
|
||||
osc.frequency.value = index ? 1040 : 820;
|
||||
osc.type = tone.type;
|
||||
osc.frequency.value = tone.frequency;
|
||||
osc.connect(gain);
|
||||
osc.start(audio.currentTime + offset);
|
||||
osc.stop(audio.currentTime + offset + 0.11);
|
||||
});
|
||||
setTimeout(() => audio.close().catch(() => {}), 520);
|
||||
osc.start(audio.currentTime + tone.offset);
|
||||
osc.stop(audio.currentTime + tone.offset + tone.duration);
|
||||
}
|
||||
setTimeout(() => audio.close().catch(() => {}), 720);
|
||||
}
|
||||
|
||||
function soundPattern(style) {
|
||||
const patterns = {
|
||||
soft: [
|
||||
{ offset: 0, duration: 0.13, frequency: 520, type: "sine" },
|
||||
{ offset: 0.16, duration: 0.12, frequency: 680, type: "sine" }
|
||||
],
|
||||
chime: [
|
||||
{ offset: 0, duration: 0.16, frequency: 880, type: "triangle" },
|
||||
{ offset: 0.18, duration: 0.18, frequency: 1320, type: "triangle" }
|
||||
],
|
||||
urgent: [
|
||||
{ offset: 0, duration: 0.1, frequency: 760, type: "square" },
|
||||
{ offset: 0.13, duration: 0.1, frequency: 760, type: "square" },
|
||||
{ offset: 0.26, duration: 0.12, frequency: 980, type: "square" }
|
||||
],
|
||||
bright: [
|
||||
{ offset: 0, duration: 0.11, frequency: 820, type: "sine" },
|
||||
{ offset: 0.14, duration: 0.11, frequency: 1040, type: "sine" }
|
||||
]
|
||||
};
|
||||
return patterns[style] || patterns.bright;
|
||||
}
|
||||
|
||||
function clamp(value, min, max) {
|
||||
|
||||
Reference in New Issue
Block a user