Skip to content

Commit 277f484

Browse files
authored
fix: add state to pause existing audio for demo menus, add support fo… (anomalyco#10428)
1 parent a2fe37e commit 277f484

3 files changed

Lines changed: 35 additions & 7 deletions

File tree

packages/app/src/components/settings-general.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ import { useSettings, monoFontFamily } from "@/context/settings"
77
import { playSound, SOUND_OPTIONS } from "@/utils/sound"
88
import { Link } from "./link"
99

10+
11+
let demoSoundState = {
12+
cleanup: undefined as (() => void) | undefined,
13+
timeout: undefined as NodeJS.Timeout | undefined,
14+
}
15+
16+
// To prevent audio from overlapping/playing very quickly when navigating the settings menus,
17+
// delay the playback by 100ms during quick selection changes and pause existing sounds.
18+
const playDemoSound = (src: string) => {
19+
if (demoSoundState.cleanup) {
20+
demoSoundState.cleanup();
21+
}
22+
23+
clearTimeout(demoSoundState.timeout)
24+
25+
demoSoundState.timeout = setTimeout(() => {
26+
demoSoundState.cleanup = playSound(src)
27+
}, 100)
28+
}
29+
1030
export const SettingsGeneral: Component = () => {
1131
const theme = useTheme()
1232
const language = useLanguage()
@@ -211,12 +231,12 @@ export const SettingsGeneral: Component = () => {
211231
label={(o) => language.t(o.label)}
212232
onHighlight={(option) => {
213233
if (!option) return
214-
playSound(option.src)
234+
playDemoSound(option.src)
215235
}}
216236
onSelect={(option) => {
217237
if (!option) return
218238
settings.sounds.setAgent(option.id)
219-
playSound(option.src)
239+
playDemoSound(option.src)
220240
}}
221241
variant="secondary"
222242
size="small"
@@ -235,12 +255,12 @@ export const SettingsGeneral: Component = () => {
235255
label={(o) => language.t(o.label)}
236256
onHighlight={(option) => {
237257
if (!option) return
238-
playSound(option.src)
258+
playDemoSound(option.src)
239259
}}
240260
onSelect={(option) => {
241261
if (!option) return
242262
settings.sounds.setPermissions(option.id)
243-
playSound(option.src)
263+
playDemoSound(option.src)
244264
}}
245265
variant="secondary"
246266
size="small"
@@ -259,12 +279,12 @@ export const SettingsGeneral: Component = () => {
259279
label={(o) => language.t(o.label)}
260280
onHighlight={(option) => {
261281
if (!option) return
262-
playSound(option.src)
282+
playDemoSound(option.src)
263283
}}
264284
onSelect={(option) => {
265285
if (!option) return
266286
settings.sounds.setErrors(option.id)
267-
playSound(option.src)
287+
playDemoSound(option.src)
268288
}}
269289
variant="secondary"
270290
size="small"

packages/app/src/utils/sound.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,12 @@ export function soundSrc(id: string | undefined) {
106106
export function playSound(src: string | undefined) {
107107
if (typeof Audio === "undefined") return
108108
if (!src) return
109-
void new Audio(src).play().catch(() => undefined)
109+
const audio = new Audio(src)
110+
audio.play().catch(() => undefined)
111+
112+
// Return a cleanup function to pause the sound.
113+
return () => {
114+
audio.pause()
115+
audio.currentTime = 0
116+
}
110117
}

packages/ui/src/components/select.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export function Select<T>(props: SelectProps<T> & Omit<ButtonProps, "children">)
105105
}}
106106
onPointerEnter={() => move(itemProps.item.rawValue)}
107107
onPointerMove={() => move(itemProps.item.rawValue)}
108+
onFocus={() => move(itemProps.item.rawValue)}
108109
>
109110
<Kobalte.ItemLabel data-slot="select-select-item-label">
110111
{local.children

0 commit comments

Comments
 (0)