uberf-8485: fix sounds (#6944)

Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
Alexey Zinoviev 2024-10-15 21:31:49 +04:00 committed by GitHub
parent 171e1e88b7
commit 288c51aa0d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 36 deletions

View File

@ -3,10 +3,10 @@ import { type Asset, getMetadata, getResource } from '@hcengineering/platform'
import { getClient } from '.'
import notification from '@hcengineering/notification'
const sounds = new Map<Asset, AudioBufferSourceNode>()
const sounds = new Map<Asset, AudioBuffer>()
const context = new AudioContext()
export async function prepareSound (key: string, _class?: Ref<Class<Doc>>, loop = false, play = false): Promise<void> {
export async function prepareSound (key: string, _class?: Ref<Class<Doc>>): Promise<void> {
if (_class === undefined) return
const client = getClient()
@ -23,39 +23,45 @@ export async function prepareSound (key: string, _class?: Ref<Class<Doc>>, loop
try {
const soundUrl = getMetadata(key as Asset) as string
const audioBuffer = await fetch(soundUrl)
.then(async (res) => await res.arrayBuffer())
.then(async (ArrayBuffer) => await context.decodeAudioData(ArrayBuffer))
const rawAudio = await fetch(soundUrl)
const rawBuffer = await rawAudio.arrayBuffer()
const decodedBuffer = await context.decodeAudioData(rawBuffer)
sounds.set(key as Asset, decodedBuffer)
} catch (err) {
console.error('Sound not found', key)
}
}
export async function playSound (
soundKey: string,
_class?: Ref<Class<Doc>>,
loop = false
): Promise<(() => void) | null> {
const soundAssetKey = soundKey as Asset
if (!sounds.has(soundAssetKey)) {
await prepareSound(soundKey, _class)
}
const sound = sounds.get(soundKey as Asset)
if (sound === undefined) {
console.error('Cannot prepare audio buffer', soundKey)
return null
}
try {
const audio = context.createBufferSource()
audio.buffer = audioBuffer
audio.buffer = sound
audio.loop = loop
sounds.set(key as Asset, audio)
if (play) {
playSound(key)
audio.connect(context.destination)
audio.start()
return (): void => {
audio.stop()
audio.disconnect(context.destination)
}
} catch (err) {
console.error('sound not found', key)
}
}
export function playSound (soundKey: string, _class?: Ref<Class<Doc>>, loop = false): void {
const sound = sounds.get(soundKey as Asset)
if (sound !== undefined) {
try {
sound.connect(context.destination)
sound.start()
} catch (err) {
console.error('error happened during sound play', soundKey, err)
}
} else {
void prepareSound(soundKey, _class, loop, true)
}
}
export function stopSound (soundKey: string): void {
const sound = sounds.get(soundKey as Asset)
if (sound !== undefined && sound?.context.state === 'running') {
sound.stop()
sound.disconnect(context.destination)
console.error('Error when playing sound back', soundKey, err)
return null
}
}

View File

@ -16,7 +16,7 @@
import { PersonAccount, formatName } from '@hcengineering/contact'
import { Avatar, personByIdStore } from '@hcengineering/contact-resources'
import { getCurrentAccount } from '@hcengineering/core'
import { getClient, playSound, stopSound } from '@hcengineering/presentation'
import { getClient, playSound } from '@hcengineering/presentation'
import { Button, Label } from '@hcengineering/ui'
import { JoinRequest, RequestStatus } from '@hcengineering/love'
import love from '../plugin'
@ -29,6 +29,7 @@
$: person = $personByIdStore.get(request.person)
const client = getClient()
let stopSound: (() => void) | null = null
async function accept (): Promise<void> {
await client.update(request, { status: RequestStatus.Approved })
@ -43,11 +44,13 @@
async function decline (): Promise<void> {
await client.update(request, { status: RequestStatus.Rejected })
}
onMount(() => {
playSound(love.sound.Knock, love.class.JoinRequest, true)
onMount(async () => {
stopSound = await playSound(love.sound.Knock, love.class.JoinRequest, true)
})
onDestroy(() => {
stopSound(love.sound.Knock)
stopSound?.()
})
</script>