DeadAir in the page: a switch per show, one beside the speed, and the time saved (#172)
A DeadAir switch in each show's settings, and the same switch beside
the speed for the show that is playing, drawn as a waveform with its gap
closed up, outlined when off and solid when on, with aria-pressed. A
file the server gives a copy for plays from /media/{id}/deadair. An
episode's line says how much shorter it is, and Settings says how much
DeadAir has saved you.
Turning it on or off mid-episode saves the place with a request it waits
for, not a beacon, then asks for the entry again from the new
GET /api/entries/{feed}/{guid}, whose position is in the clock of the
version it now plays, and carries on there. A copy not made yet plays
from the next time. Turning a show on wakes the copy maker, so the copy
is there in seconds rather than at its next pass.
The browser test plays a real MP3 with long silences, quiet.mp3, from a
show it adds and removes itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1750,3 +1750,45 @@ test('a feed\'s settings say what downloads, take words as chips, and keep what
|
||||
await expect(page.locator('#skw .chip, #sblock .chip')).toHaveCount(0);
|
||||
await page.keyboard.press('Escape');
|
||||
});
|
||||
|
||||
test('DeadAir is off until turned on for a show, then plays its shortened copy and switches back', async ({ page }) => {
|
||||
// #171/#172. A show of its own, with real audio, added here and left at the end.
|
||||
const { id } = await (await page.request.post('/api/feeds', { data: { url: 'http://127.0.0.1:8792/quiet.xml' } })).json();
|
||||
const entry = async () => {
|
||||
const r = await page.request.get(`/api/feeds/${encodeURIComponent(id)}/entries`);
|
||||
return (await r.json()).entries?.[0];
|
||||
};
|
||||
await expect.poll(async () => (await entry())?.guid, { timeout: 15_000 }).toBe('quiet-1');
|
||||
await page.request.post(`/api/feeds/${encodeURIComponent(id)}/download-latest`, { data: { count: 1 } });
|
||||
await expect.poll(async () => !!(await entry())?.enclosures[0]?.path, { timeout: 15_000 }).toBe(true);
|
||||
// Off for a show until someone turns it on: no copy is made.
|
||||
expect((await entry()).enclosures[0].deadair).toBeUndefined();
|
||||
await page.reload();
|
||||
|
||||
// On, in the show's settings.
|
||||
await page.locator('#feedlist .feed', { hasText: 'Quiet Show' }).first().click();
|
||||
await page.locator('#content .acts [data-a="settings"]').click();
|
||||
const sw = page.locator('#sdead');
|
||||
await expect(sw).not.toBeChecked();
|
||||
await sw.locator('xpath=..').click();
|
||||
await page.locator('#ssave').click();
|
||||
// Made at once, not at the next pass: about 1.8 s off each of four 2 s silences.
|
||||
await expect.poll(async () => (await entry()).enclosures[0].deadair ?? 0, { timeout: 20_000 }).toBeGreaterThan(5);
|
||||
await page.reload();
|
||||
await page.locator('#feedlist .feed', { hasText: 'Quiet Show' }).first().click();
|
||||
const row = page.locator('.ep', { hasText: 'Pauses Between' });
|
||||
await expect(row).toContainText('s shorter');
|
||||
|
||||
// Played from the copy, with the switch beside the speed pressed.
|
||||
await row.locator('[data-a=play]').click();
|
||||
await expect.poll(() => page.evaluate(() => document.querySelector('#audio').getAttribute('src'))).toMatch(/\/deadair$/);
|
||||
await expect(page.locator('#pdead')).toHaveAttribute('aria-pressed', 'true');
|
||||
// Off from the player: the original, from the same place.
|
||||
await page.locator('#pdead').click();
|
||||
await expect(page.locator('#pdead')).toHaveAttribute('aria-pressed', 'false');
|
||||
await expect.poll(() => page.evaluate(() => document.querySelector('#audio').getAttribute('src'))).toMatch(/\/media\/\d+$/);
|
||||
expect((await entry()).enclosures[0].deadair).toBeUndefined();
|
||||
|
||||
await page.locator('#pclose').click();
|
||||
await page.request.delete(`/api/feeds/${encodeURIComponent(id)}`);
|
||||
});
|
||||
|
||||
BIN
tests/ui/fixtures/quiet.mp3
Normal file
BIN
tests/ui/fixtures/quiet.mp3
Normal file
Binary file not shown.
8
tests/ui/fixtures/quiet.xml
Normal file
8
tests/ui/fixtures/quiet.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0"?>
|
||||
<rss version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd">
|
||||
<channel><title>Quiet Show</title><link>http://127.0.0.1:8792/</link><description>Real audio with long silences, for DeadAir.</description>
|
||||
<item><title>Pauses Between</title><guid>quiet-1</guid>
|
||||
<pubDate>Mon, 15 Sep 2026 10:00:00 +0000</pubDate>
|
||||
<description>A second of tone, then two of silence, five times.</description>
|
||||
<enclosure url="http://127.0.0.1:8792/quiet.mp3" length="60518" type="audio/mpeg"/></item>
|
||||
</channel></rss>
|
||||
Reference in New Issue
Block a user