diff --git a/CHANGELOG.md b/CHANGELOG.md index a4370e4..4b28c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,12 @@ The long form, with what was wrong before and how it was found, is in - Buttons are icons, with the words in their tooltips: the Files pane (save, delete, view, download), an item's own buttons (mark read, keep, open the original), the feed header (scan, download latest, mark all read, settings, unsubscribe), and the Settings, feed settings and - Download latest dialogs (save, download, cancel). + Download latest dialogs (save, download, cancel). The icons are drawn, from one set, rather + than font characters: ⟳ ⤓ ↗ and the like came out thin and tiny and differed from font to + font. Keep is a flag everywhere, as it was in the original. +- A file's state and type are icons: a check when it is downloaded, a warning when it failed + (the error is in the tooltip), and nothing while it waits; audio, video, image, PDF, torrent + and other files each have their own. The DOWNLOADED and PENDING labels are gone. ### Security diff --git a/tests/ui/app.spec.js b/tests/ui/app.spec.js index 19de1a0..03ca1b9 100644 --- a/tests/ui/app.spec.js +++ b/tests/ui/app.spec.js @@ -87,7 +87,7 @@ test('the three panes are there and the item text lands in the bottom one', asyn // Only the downloaded one gets a player, and max_new_per_check is 1, so find it by // its chip rather than assuming which episode the daemon happened to fetch. - const downloaded = page.locator('.ep', { hasText: 'downloaded' }).first(); + const downloaded = page.locator('.ep', { has: page.locator('[title="Downloaded"]') }).first(); await downloaded.click(); await expect(page.locator('#files audio')).toBeVisible(); await expect(page.locator('#files .encbox [title="Save to this computer"]')).toBeVisible(); @@ -110,8 +110,9 @@ test('a downloaded file that is not audio gets no player', async ({ page }) => { await expect(page.locator('#detail .dt')).toHaveText('An Article'); await expect(page.locator('#files audio')).toHaveCount(0); - await expect(page.locator('#files .encbox')).toContainText('image'); - await expect(page.locator('#files .encbox')).toContainText('downloaded'); + // What it is and that it is here, as icons with the words in their tooltips. + await expect(page.locator('#files .encbox [title="image"]')).toBeVisible(); + await expect(page.locator('#files .encbox [title="Downloaded"]')).toBeVisible(); // Still offered as a file, just not as an episode: viewable and keepable. await expect(page.locator('#files [title="Save to this computer"]')).toBeVisible(); const view = page.locator('#files a[title="View in a new tab"]'); @@ -130,7 +131,7 @@ test('an item with several enclosures lists them all', async ({ page }) => { await row.click(); // The Files pane lists every one: the audio and the image. await expect(page.locator('#files .encbox')).toHaveCount(2); - await expect(page.locator('#files .encbox').nth(1)).toContainText('image'); + await expect(page.locator('#files .encbox').nth(1).locator('[title="image"]')).toBeVisible(); }); test('the filter tabs change what is listed', async ({ page }) => { @@ -673,7 +674,7 @@ test('a deleted file looks as if it was never downloaded', async ({ page }) => { await page.locator('#files button[data-a="del"]').click(); // No "reaped", no chip at all: just the way to get it again. - await expect(row).not.toContainText('downloaded'); + await expect(row.locator('[title="Downloaded"]')).toHaveCount(0); await expect(row).not.toContainText(/reaped/i); await row.click(); await expect(page.locator('#files')).not.toContainText(/reaped/i); diff --git a/web/index.html b/web/index.html index a8b1bac..a2f48c6 100644 --- a/web/index.html +++ b/web/index.html @@ -236,6 +236,18 @@ a.btn{text-decoration:none;color:inherit} .btn.danger:hover{border-color:var(--bad);color:var(--bad)} /* An icon in place of a word; the word is in its tooltip. */ .btn.ico{padding:4px 9px;min-width:32px;font-size:14px;line-height:1.25;text-align:center} +/* A drawn icon: bold strokes in the button's own colour. */ +.i{ + display:inline-block;width:16px;height:16px;vertical-align:-3px;flex:none; + fill:none;stroke:currentColor;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round; +} +.i.f{fill:currentColor;stroke:none} +/* A file's state and type, as icons in place of the old DOWNLOADED / PENDING / audio chips. */ +.fst,.kind{display:inline-grid;place-items:center} +.fst{color:var(--good)} +.fst.bad{color:var(--bad)} +.kind{color:var(--dim)} +.fhead .art .i{width:22px;height:22px} .toolbar{ display:flex;gap:10px;align-items:center;margin-bottom:12px;flex-wrap:wrap; position:sticky;top:0;background:var(--bg);padding:6px 0 8px;z-index:3; @@ -494,7 +506,9 @@ input[type=range]::-moz-range-thumb{width:12px;height:12px;border:0;border-radiu :root[data-theme="classic"] .ep.sel .line, :root[data-theme="classic"] .ep.sel .st, :root[data-theme="classic"] .ep.sel .fl, -:root[data-theme="classic"] .ep.sel .file{color:#fff} +:root[data-theme="classic"] .ep.sel .file, +:root[data-theme="classic"] .ep.sel .fst, +:root[data-theme="classic"] .ep.sel .kind{color:#fff} /* Lists were white in the original; the pale blue-grey belongs to the source list alone. */ :root[data-theme="classic"] .childrow{background:#fff} :root[data-theme="classic"] .dt{background:linear-gradient(#80aae6,#3f78cf);color:#fff;padding:6px 12px;border-radius:4px} @@ -502,33 +516,33 @@ input[type=range]::-moz-range-thumb{width:12px;height:12px;border:0;border-radiu