diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c67b29..015fbe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- The Modern theme takes its colours from the new logo: its navy, the blue of its bars and the + orange of its needle. +- The logo follows the page: the dark version in a dark theme, the light one in a light theme. - Between releases, the version on the logo says so: 0.9.1-dev, not 0.9.0. - The logo's needle is a brighter, redder orange that stands apart from the blue bars. - The logo is in the top bar beside the add-feed button, in place of the name at the top of the diff --git a/src/web.rs b/src/web.rs index d97d735..396edc8 100644 --- a/src/web.rs +++ b/src/web.rs @@ -68,6 +68,7 @@ pub fn router(state: WebState) -> Router { .route("/api/login", post(login)) .route("/icon.png", get(icon)) .route("/logo.svg", get(logo)) + .route("/logo-dark.svg", get(logo_dark)) .route("/favicon.ico", get(favicon)) .route("/favicon.png", get(favicon)) .route("/apple-touch-icon.png", get(touch_icon)) @@ -562,6 +563,15 @@ async fn logo() -> impl IntoResponse { ) } +/// logo.svg recoloured for a dark page. The pages pick one or the other by their light or dark +/// mode. +async fn logo_dark() -> impl IntoResponse { + ( + [(header::CONTENT_TYPE, "image/svg+xml"), (header::CACHE_CONTROL, "max-age=86400")], + include_str!("../web/logo-dark.svg"), + ) +} + /// The 2004 icon. Nothing here shows it any more; it stays for whatever outside ipx links to it. async fn icon() -> impl IntoResponse { ( diff --git a/tests/ui/app.spec.js b/tests/ui/app.spec.js index 3129b22..d875439 100644 --- a/tests/ui/app.spec.js +++ b/tests/ui/app.spec.js @@ -47,10 +47,10 @@ test('Settings picks a theme and, where it has both, light, dark or Auto', async // Auto follows the system, live, with no reload. await page.emulateMedia({ colorScheme: 'light' }); await expect.poll(root).toEqual(['modern', 'light']); - await expect.poll(bg).toBe('rgb(242, 244, 247)'); // Modern's light --bg + await expect.poll(bg).toBe('rgb(238, 245, 251)'); // Modern's light --bg await page.emulateMedia({ colorScheme: 'dark' }); await expect.poll(root).toEqual(['modern', 'dark']); - await expect.poll(bg).toBe('rgb(14, 19, 27)'); // Modern's dark --bg + await expect.poll(bg).toBe('rgb(10, 23, 38)'); // Modern's dark --bg // Dracula, then its light half, Alucard. await page.locator('#stheme').selectOption('dracula'); @@ -559,9 +559,11 @@ test('a second person has their own feeds and their own read state', async ({ br const page = await ctx.newPage(); await page.goto('/login'); // The sign-in page shows the logo, so it has to load before anyone has signed in. - const logo = await page.request.get('/logo.svg'); - expect(logo.status()).toBe(200); - expect(logo.headers()['content-type']).toBe('image/svg+xml'); + for (const path of ['/logo.svg', '/logo-dark.svg']) { + const logo = await page.request.get(path); + expect(logo.status(), path).toBe(200); + expect(logo.headers()['content-type'], path).toBe('image/svg+xml'); + } await page.locator('#name').fill('sam'); await page.locator('#pw').fill('sampassword'); await page.locator('button[type=submit]').click(); @@ -1178,6 +1180,18 @@ test('a file not yet downloaded has its icon in line with the rest of its row', for (const o of offsets) expect(Math.abs(o)).toBeLessThanOrEqual(1); }); +test('the logo is the dark one in dark mode and the light one in light mode', async ({ page }) => { + const shown = () => page.locator('#applogo img:visible').getAttribute('src'); + await page.evaluate(() => setTheme('modern', 'dark')); + expect(await shown()).toMatch(/^\/logo-dark\.svg\?v=/); + await page.evaluate(() => setTheme('modern', 'light')); + expect(await shown()).toMatch(/^\/logo\.svg\?v=/); + // Paper has only a light palette, so the light logo whatever the mode asked. + await page.evaluate(() => setTheme('paper', 'dark')); + expect(await shown()).toMatch(/^\/logo\.svg\?v=/); + await page.evaluate(() => setTheme('modern', 'dark')); +}); + test('the favicon is the logo, square, from both pages', async ({ page }) => { await expect(page.locator('link[rel="icon"]')).toHaveAttribute('href', /^\/favicon\.png\?v=[0-9a-f]{12}$/); // A browser asks for /favicon.ico on its own, signed in or not. diff --git a/web/admin.html b/web/admin.html index 3a6b970..8f04894 100644 --- a/web/admin.html +++ b/web/admin.html @@ -13,7 +13,7 @@
- +

Admin