From 42a1136e2ebaf41651034a73050a773e6ea1f4db Mon Sep 17 00:00:00 2001 From: rays Date: Fri, 18 Sep 2026 15:01:03 +0000 Subject: [PATCH] Every play button for what is playing shows pause, and pauses it Only the player bar's button changed; the files pane's, the row's and the toolbar's kept showing play while it played. play() now pauses when asked to play what is already playing, which makes each of them a toggle, and syncPlayButtons() repaints them on play, pause and ended and whenever the list or reader is drawn. Closes #34. Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 2 ++ tests/ui/app.spec.js | 21 +++++++++++++++++++++ web/src/items.ts | 4 +++- web/src/player.ts | 18 ++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0aece7..bd6d0d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,8 @@ The long form, with what was wrong before and how it was found, is in higher than a downloaded one's. - Images in posts from sites that refuse images to other sites' pages, such as Jeff Geerling's, now show: ipx asks for them without saying it is the page showing them. +- While an episode plays, its play buttons in the files pane, its row and the toolbar show + pause, as the player bar's does, and pause it when pressed. - An item you open stays read. A list refresh that crossed with marking it read could put its unread dot back until the next refresh. - On the Unread tab, the item you were reading leaves the list as soon as you move to the next diff --git a/tests/ui/app.spec.js b/tests/ui/app.spec.js index f6469ba..1cc624d 100644 --- a/tests/ui/app.spec.js +++ b/tests/ui/app.spec.js @@ -182,6 +182,27 @@ test('the three panes are there and the item text lands in the bottom one', asyn await expect(page.locator('#files [data-a="play"]')).toHaveCount(0); }); +test('while an episode plays, its play buttons all say pause, and pause it', async ({ page }) => { + await page.locator('.feed', { hasText: 'Test Show' }).click(); + await page.locator('.tabs button', { hasText: 'All' }).first().click(); + const downloaded = page.locator('.ep', { has: page.locator('.kind.here') }).first(); + await expect(downloaded).toBeVisible({ timeout: 20_000 }); + await downloaded.click(); + await page.evaluate(() => { audio.muted = true; }); + const pane = page.locator('#files [data-a="play"]'); + await pane.click(); + await expect.poll(() => page.evaluate(() => !audio.paused)).toBe(true); + // The files pane, the row and the toolbar all follow the player bar, not only the bar. + await expect(pane).toHaveAttribute('title', 'Pause'); + await expect(downloaded.locator('[data-a="play"]')).toHaveAttribute('title', 'Pause'); + await expect(page.locator('#tbPlay')).toHaveAttribute('title', 'Pause'); + await pane.click(); // and pressing it pauses + await expect.poll(() => page.evaluate(() => audio.paused)).toBe(true); + await expect(pane).toHaveAttribute('title', 'Play'); + await expect(page.locator('#tbPlay')).toHaveAttribute('title', 'Play the selected item'); + await page.locator('#pclose').click(); +}); + test('a downloaded file that is not audio gets no player', async ({ page }) => { // Regression: anything with a file got an