generated from VLADIMIR/template_frontend
up
This commit is contained in:
Binary file not shown.
+20
-19
@@ -44,6 +44,7 @@ import type {
|
|||||||
TeamResult,
|
TeamResult,
|
||||||
Ticket,
|
Ticket,
|
||||||
} from '@/api/generated/crabs/evening_detective_server'
|
} from '@/api/generated/crabs/evening_detective_server'
|
||||||
|
import notificationSoundURL from '@/assets/icq-uh-oh.wav'
|
||||||
import GameMapPanel from '@/components/GameMapPanel.vue'
|
import GameMapPanel from '@/components/GameMapPanel.vue'
|
||||||
import GameScreensPanel from '@/components/GameScreensPanel.vue'
|
import GameScreensPanel from '@/components/GameScreensPanel.vue'
|
||||||
import GameStatePanel from '@/components/GameStatePanel.vue'
|
import GameStatePanel from '@/components/GameStatePanel.vue'
|
||||||
@@ -134,6 +135,7 @@ let appliedGameRequestVersion = 0
|
|||||||
let hasLoadedGame = false
|
let hasLoadedGame = false
|
||||||
let isDisposed = false
|
let isDisposed = false
|
||||||
let notificationAudio: AudioContext | undefined
|
let notificationAudio: AudioContext | undefined
|
||||||
|
let notificationSound: Promise<AudioBuffer> | undefined
|
||||||
let hasReportedSoundError = false
|
let hasReportedSoundError = false
|
||||||
const canViewState = computed(
|
const canViewState = computed(
|
||||||
() =>
|
() =>
|
||||||
@@ -239,30 +241,29 @@ async function enableNotificationSound() {
|
|||||||
try {
|
try {
|
||||||
notificationAudio ??= new AudioContext()
|
notificationAudio ??= new AudioContext()
|
||||||
if (notificationAudio.state === 'suspended') await notificationAudio.resume()
|
if (notificationAudio.state === 'suspended') await notificationAudio.resume()
|
||||||
|
const audio = notificationAudio
|
||||||
|
notificationSound ??= fetch(notificationSoundURL).then(async (response) => {
|
||||||
|
if (!response.ok) throw new Error('Не удалось загрузить звук уведомления')
|
||||||
|
return audio.decodeAudioData(await response.arrayBuffer())
|
||||||
|
})
|
||||||
|
await notificationSound
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
notificationSound = undefined
|
||||||
reportSoundError(error)
|
reportSoundError(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playApplicationNotification() {
|
async function playApplicationNotification() {
|
||||||
// До первого взаимодействия браузер блокирует звук; пропущенные сигналы не накапливаем.
|
// До первого взаимодействия браузер блокирует звук; пропущенные сигналы не накапливаем.
|
||||||
if (!notificationAudio || notificationAudio.state !== 'running') return
|
if (!notificationAudio || notificationAudio.state !== 'running' || !notificationSound) return
|
||||||
try {
|
try {
|
||||||
const oscillator = notificationAudio.createOscillator()
|
const buffer = await notificationSound
|
||||||
const gain = notificationAudio.createGain()
|
if (isDisposed || notificationAudio.state !== 'running') return
|
||||||
const now = notificationAudio.currentTime
|
const source = notificationAudio.createBufferSource()
|
||||||
oscillator.frequency.value = 880
|
source.buffer = buffer
|
||||||
gain.gain.setValueAtTime(0, now)
|
source.connect(notificationAudio.destination)
|
||||||
gain.gain.linearRampToValueAtTime(0.1, now + 0.02)
|
source.onended = () => source.disconnect()
|
||||||
gain.gain.linearRampToValueAtTime(0, now + 0.3)
|
source.start()
|
||||||
oscillator.connect(gain)
|
|
||||||
gain.connect(notificationAudio.destination)
|
|
||||||
oscillator.onended = () => {
|
|
||||||
oscillator.disconnect()
|
|
||||||
gain.disconnect()
|
|
||||||
}
|
|
||||||
oscillator.start(now)
|
|
||||||
oscillator.stop(now + 0.3)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reportSoundError(error)
|
reportSoundError(error)
|
||||||
}
|
}
|
||||||
@@ -270,7 +271,7 @@ function playApplicationNotification() {
|
|||||||
|
|
||||||
async function testNotificationSound() {
|
async function testNotificationSound() {
|
||||||
await enableNotificationSound()
|
await enableNotificationSound()
|
||||||
playApplicationNotification()
|
await playApplicationNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -303,7 +304,7 @@ async function getGame(id: number) {
|
|||||||
hasLoadedGame &&
|
hasLoadedGame &&
|
||||||
hasNewTeamApplications(game.value.teams || [], res.game?.teams || [])
|
hasNewTeamApplications(game.value.teams || [], res.game?.teams || [])
|
||||||
) {
|
) {
|
||||||
playApplicationNotification()
|
void playApplicationNotification()
|
||||||
}
|
}
|
||||||
hasLoadedGame = true
|
hasLoadedGame = true
|
||||||
game.value = res.game!
|
game.value = res.game!
|
||||||
|
|||||||
Reference in New Issue
Block a user