fix(uploads): load audio previews only on play
This commit is contained in:
1 parent
af06cf1e75
commit
ca2a50b515
3 files changed
+24
-6
No files matched your search
@@ -180,16 +180,31 @@ test('queue shows the current full destination after saving a changed source tem
|
||||
await expect(page.getByText('Artist/Album/Song.flac', { exact: true })).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('queue preview loads duration before play and plays signed audio', async ({ page }) => {
|
||||
test('queue preview only requests audio after play', async ({ page }) => {
|
||||
const wav = previewWav();
|
||||
await page.route('**/api/v1/admin/uploads/files/*/stream?*', (route) => route.fulfill({ contentType: 'audio/wav', body: wav }));
|
||||
let requested = 0;
|
||||
let otherRequested = 0;
|
||||
await page.route('**/api/v1/admin/uploads/files/*/stream?*', (route) => {
|
||||
requested++;
|
||||
return route.fulfill({ contentType: 'audio/wav', body: wav });
|
||||
});
|
||||
await page.route('**/api/v1/stream/mobile-preview', (route) => {
|
||||
otherRequested++;
|
||||
return route.fulfill({ contentType: 'audio/wav', body: wav });
|
||||
});
|
||||
await setup(page, 'queue');
|
||||
await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click();
|
||||
const audio = page.locator('audio').first();
|
||||
await expect(audio).toHaveAttribute('preload', 'metadata');
|
||||
await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.duration)).toBe(2);
|
||||
await expect(audio).toHaveAttribute('preload', 'none');
|
||||
await page.getByRole('button', { name: 'Свернуть пачку', exact: true }).click();
|
||||
await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click();
|
||||
expect(requested).toBe(0);
|
||||
expect(otherRequested).toBe(0);
|
||||
await audio.evaluate((el: HTMLAudioElement) => el.play());
|
||||
await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.duration)).toBe(2);
|
||||
await expect.poll(() => audio.evaluate((el: HTMLAudioElement) => el.currentTime)).toBeGreaterThan(0);
|
||||
expect(requested).toBeGreaterThan(0);
|
||||
expect(otherRequested).toBe(0);
|
||||
expect(await audio.evaluate((el: HTMLAudioElement) => el.error)).toBeNull();
|
||||
});
|
||||
|
||||
@@ -210,6 +225,7 @@ test('queue preview explains HTTP failures and recovers on retry', async ({ page
|
||||
});
|
||||
await page.getByRole('button', { name: 'Развернуть пачку', exact: true }).click();
|
||||
const preview = page.locator('audio').first().locator('..');
|
||||
await preview.locator('audio').evaluate((el: HTMLAudioElement) => el.play().catch(() => undefined));
|
||||
await expect(preview.getByRole('alert')).toHaveText('Не удалось загрузить аудио: HTTP 403.');
|
||||
available = true;
|
||||
await preview.getByRole('button', { name: 'Повторить', exact: true }).click();
|
||||
|
||||
@@ -45,10 +45,11 @@ export function AudioPreview({ url, name, active }: { url: string; name: string;
|
||||
setHttpStatus(null);
|
||||
void queryClient.invalidateQueries({ queryKey: ['admin-uploads'] });
|
||||
audio.current?.load();
|
||||
void audio.current?.play().catch(() => { /* Native media errors are shown below. */ });
|
||||
};
|
||||
|
||||
return <div className={u.preview}>
|
||||
<audio ref={audio} controls preload={active ? 'metadata' : 'none'} src={url}
|
||||
<audio ref={audio} controls preload="none" src={url}
|
||||
aria-label={t('uploads.listen', { name })}
|
||||
onPlay={(event) => {
|
||||
if (event.currentTarget.paused) return;
|
||||
|
||||
+2
-1
@@ -165,7 +165,8 @@
|
||||
Если рассчитать путь нельзя, показаны причина и действие для исправления вместо старого пути.
|
||||
- Прослушивание staging выдаёт сам API с поддержкой Range: приватные файлы tus (`0640`, каталоги `0750`)
|
||||
недоступны пользователю nginx. Выдача не зависит от `X_ACCEL`; права существующих файлов менять не нужно.
|
||||
Метаданные аудио загружаются после раскрытия пачки; при сбое показана ошибка (включая HTTP-статус, если доступен)
|
||||
Аудио и его метаданные загружаются только после Play (`preload="none"`); раскрытие пачки не запускает запросы к файлам.
|
||||
При сбое показана ошибка (включая HTTP-статус, если доступен)
|
||||
и кнопка повторной попытки с обновлением подписанных ссылок.
|
||||
Одновременно играет только один предпросмотр: запуск другого ставит предыдущий на паузу с сохранением позиции.
|
||||
Сворачивание пачки или уход со страницы также останавливает её прослушивание.
|
||||
|
||||
Reference in new issue
Block a user