diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 332ac16..77e9e38 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -1517,7 +1517,7 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "mangalord" -version = "0.88.0" +version = "0.89.0" dependencies = [ "anyhow", "argon2", diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 88ade25..765d388 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mangalord" -version = "0.88.0" +version = "0.89.0" edition = "2021" default-run = "mangalord" diff --git a/frontend/e2e/reader-mode.spec.ts b/frontend/e2e/reader-mode.spec.ts index b31cd8b..012bc90 100644 --- a/frontend/e2e/reader-mode.spec.ts +++ b/frontend/e2e/reader-mode.spec.ts @@ -66,6 +66,15 @@ async function mockReaderApis(page: Page) { body: JSON.stringify({ error: { code: 'unauthenticated', message: '' } }) }) ); + // Anonymous reader: read-progress reads/writes are unauthenticated. Without + // this the GET/PUT fall through to the (absent) backend and stall the load. + await page.route('**/api/v1/me/read-progress/**', (route) => + route.fulfill({ + status: 401, + contentType: 'application/json', + body: JSON.stringify({ error: { code: 'unauthenticated', message: '' } }) + }) + ); await page.route(`**/api/v1/mangas/${mangaId}`, (route) => route.fulfill({ status: 200, @@ -126,6 +135,7 @@ test.beforeEach(async ({ context }) => { try { localStorage.removeItem('mangalord-reader-mode'); localStorage.removeItem('mangalord-reader-gap'); + localStorage.removeItem('mangalord-reader-brightness'); } catch { // ignore — about:blank doesn't expose localStorage yet. } @@ -181,6 +191,64 @@ test('gap select updates the inline gap on the continuous container', async ({ p await expect(container).toHaveAttribute('style', /gap:\s*64px/); }); +test('desktop reader nav exposes a brightness control that dims and undims the reader', async ({ + page +}) => { + // The brightness slider used to live only in the mobile settings sheet, + // so desktop users couldn't dim — and could be stuck dimmed by a value a + // phone had persisted. The desktop nav now carries its own slider. + await mockReaderApis(page); + await page.goto(`/manga/${mangaId}/chapter/${chapterId}`); + + const slider = page.getByTestId('reader-brightness-desktop'); + await expect(slider).toBeVisible(); + + const dim = () => + page.evaluate(() => + document.documentElement.style.getPropertyValue('--reader-dim') + ); + + // Default brightness is full → no dim overlay. + await expect.poll(async () => Number(await dim())).toBe(0); + + // Dimming raises the overlay opacity… + await slider.fill('0.3'); + await expect.poll(async () => Number(await dim())).toBeGreaterThan(0); + + // …and restoring it clears the dim, so a desktop user is never stuck. + await slider.fill('1'); + await expect.poll(async () => Number(await dim())).toBe(0); +}); + +test('a brightness value persisted by a phone is recoverable on desktop', async ({ + page, + context +}) => { + // Seed a dimmed value as if set on mobile, then open the reader on a + // desktop viewport: the dim applies and the desktop control reflects it. + await context.addInitScript(() => { + try { + localStorage.setItem('mangalord-reader-brightness', '0.3'); + } catch { + // about:blank — ignore + } + }); + await mockReaderApis(page); + await page.goto(`/manga/${mangaId}/chapter/${chapterId}`); + + const slider = page.getByTestId('reader-brightness-desktop'); + await expect(slider).toHaveValue('0.3'); + await expect + .poll(async () => + Number( + await page.evaluate(() => + document.documentElement.style.getPropertyValue('--reader-dim') + ) + ) + ) + .toBeGreaterThan(0); +}); + test('reader-mode preference set on one page is honored when the reader opens', async ({ page, context diff --git a/frontend/package.json b/frontend/package.json index 18e80b3..50639c3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "mangalord-frontend", - "version": "0.88.0", + "version": "0.89.0", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/routes/manga/[id]/chapter/[chapter_id]/+page.svelte b/frontend/src/routes/manga/[id]/chapter/[chapter_id]/+page.svelte index cd2b865..c59893f 100644 --- a/frontend/src/routes/manga/[id]/chapter/[chapter_id]/+page.svelte +++ b/frontend/src/routes/manga/[id]/chapter/[chapter_id]/+page.svelte @@ -1094,6 +1094,28 @@ {/if} + + +