SHA256
Улучшить звуки входящих личных сообщений
This commit is contained in:
+106
-4
@@ -150,6 +150,8 @@ let uiUpdateReloadScheduled = false;
|
||||
let pwaUpdateCheckAttempted = false;
|
||||
let uiVersionCheckInFlight = false;
|
||||
let uiVersionPeriodicIntervalId = null;
|
||||
let hiddenDmAudioContext = null;
|
||||
let hiddenDmAudioUnlocked = false;
|
||||
const CALL_PUSH_PENDING_ACTION_KEY = 'shine-ui-call-push-pending-action-v1';
|
||||
const GUEST_ALLOWED_PAGES = new Set([
|
||||
'start-view',
|
||||
@@ -172,6 +174,94 @@ initPwaInstallPromptHandling();
|
||||
initCallUiOverlay();
|
||||
setCallDebugReporter((payload) => authService.reportClientDebug(payload));
|
||||
|
||||
async function unlockHiddenDmAudio() {
|
||||
try {
|
||||
const Ctx = window.AudioContext || window.webkitAudioContext;
|
||||
if (!Ctx) return false;
|
||||
if (!hiddenDmAudioContext) {
|
||||
hiddenDmAudioContext = new Ctx();
|
||||
}
|
||||
if (hiddenDmAudioContext.state === 'suspended') {
|
||||
await hiddenDmAudioContext.resume();
|
||||
}
|
||||
hiddenDmAudioUnlocked = hiddenDmAudioContext.state === 'running';
|
||||
return hiddenDmAudioUnlocked;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function playDmSignal({ extended = false } = {}) {
|
||||
try {
|
||||
if (!hiddenDmAudioUnlocked || !hiddenDmAudioContext) return false;
|
||||
if (hiddenDmAudioContext.state === 'suspended') {
|
||||
await hiddenDmAudioContext.resume();
|
||||
}
|
||||
if (hiddenDmAudioContext.state !== 'running') return false;
|
||||
|
||||
const now = hiddenDmAudioContext.currentTime;
|
||||
const gain = hiddenDmAudioContext.createGain();
|
||||
gain.connect(hiddenDmAudioContext.destination);
|
||||
gain.gain.setValueAtTime(0.0001, now);
|
||||
|
||||
const pulse = (offsetSec, freqHz, durationSec, peakGain) => {
|
||||
const osc = hiddenDmAudioContext.createOscillator();
|
||||
osc.type = 'sine';
|
||||
osc.frequency.setValueAtTime(freqHz, now + offsetSec);
|
||||
osc.connect(gain);
|
||||
gain.gain.exponentialRampToValueAtTime(peakGain, now + offsetSec + 0.01);
|
||||
gain.gain.exponentialRampToValueAtTime(0.0001, now + offsetSec + durationSec);
|
||||
osc.start(now + offsetSec);
|
||||
osc.stop(now + offsetSec + durationSec + 0.02);
|
||||
};
|
||||
|
||||
if (extended) {
|
||||
pulse(0, 880, 0.18, 0.032);
|
||||
pulse(0.24, 1174, 0.2, 0.026);
|
||||
pulse(0.52, 1567, 0.24, 0.02);
|
||||
} else {
|
||||
pulse(0, 1046, 0.12, 0.028);
|
||||
pulse(0.17, 1318, 0.14, 0.022);
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async function notifyHiddenIncomingMessage(fromLogin, text) {
|
||||
const body = String(text || '').trim() || `Вам пришло сообщение от ${fromLogin}`;
|
||||
const title = `Сообщение от ${fromLogin}`;
|
||||
try {
|
||||
const registration = await navigator.serviceWorker?.getRegistration?.();
|
||||
if (registration?.showNotification) {
|
||||
await registration.showNotification(title, {
|
||||
body,
|
||||
tag: `shine-hidden-dm-${String(fromLogin || '').trim().toLowerCase() || 'unknown'}`,
|
||||
renotify: true,
|
||||
data: {
|
||||
kind: 'new_message',
|
||||
fromLogin,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
new Notification(title, { body });
|
||||
}
|
||||
} catch {
|
||||
// ignore notification errors
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof navigator.vibrate === 'function') {
|
||||
navigator.vibrate([140, 80, 220, 90, 180]);
|
||||
}
|
||||
} catch {
|
||||
// ignore vibration errors
|
||||
}
|
||||
|
||||
void playDmSignal({ extended: true });
|
||||
}
|
||||
|
||||
function ensureConnectionIndicatorEl() {
|
||||
return document.getElementById('toolbar-connection-indicator');
|
||||
}
|
||||
@@ -960,10 +1050,16 @@ async function init() {
|
||||
if (added && isIncomingForCurrent) {
|
||||
shouldRefreshToolbarUnread = true;
|
||||
}
|
||||
if (added && isIncomingForCurrent && Notification.permission === 'granted' && !payload.backlog) {
|
||||
try {
|
||||
new Notification(`Сообщение от ${fromLogin}`, { body: text || '' });
|
||||
} catch {}
|
||||
if (added && isIncomingForCurrent && !payload.backlog) {
|
||||
if (document.visibilityState === 'visible') {
|
||||
void playDmSignal({ extended: false });
|
||||
} else if (Notification.permission === 'granted') {
|
||||
try {
|
||||
void notifyHiddenIncomingMessage(fromLogin, text || '');
|
||||
} catch {}
|
||||
} else {
|
||||
void playDmSignal({ extended: true });
|
||||
}
|
||||
}
|
||||
} else if (messageType === 3 || messageType === 4) {
|
||||
let refBaseKey = String(payload.receiptRefBaseKey || '').trim();
|
||||
@@ -1106,6 +1202,12 @@ async function init() {
|
||||
})();
|
||||
|
||||
window.addEventListener('popstate', renderApp);
|
||||
document.addEventListener('pointerdown', () => {
|
||||
void unlockHiddenDmAudio();
|
||||
}, { passive: true });
|
||||
document.addEventListener('keydown', () => {
|
||||
void unlockHiddenDmAudio();
|
||||
}, { passive: true });
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.visibilityState !== 'visible') return;
|
||||
void checkConnectionHealth();
|
||||
|
||||
Reference in New Issue
Block a user