From f8c64decf18f3df5a4c38f90cb136c918effc3f2 Mon Sep 17 00:00:00 2001 From: zhoujun0601 Date: Thu, 13 Aug 2026 12:47:10 -0400 Subject: [PATCH] fix: enlarge authenticated brand icon --- docs/frontend/application.md | 2 +- frontend/src/styles.css | 5 ++++ frontend/tests/settings-layout.spec.ts | 32 +++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/frontend/application.md b/docs/frontend/application.md index e10fccd..8790920 100644 --- a/docs/frontend/application.md +++ b/docs/frontend/application.md @@ -4,7 +4,7 @@ ## 状态与路由 -应用启动先请求 `system/status`,已初始化时再请求 `auth/me`。未初始化渲染安装页;未登录渲染登录页;登录后由 `BrowserRouter` 提供 `/` 总览和 `/settings` 设置,未知路径回到 `/`。状态响应中的构建版本以 `v` 徽标显示在安装页、登录页和登录后侧栏的品牌区域;品牌图标、名称和版本徽标保持单行排列。这些分支只负责交互,服务端 session 才是安全边界。 +应用启动先请求 `system/status`,已初始化时再请求 `auth/me`。未初始化渲染安装页;未登录渲染登录页;登录后由 `BrowserRouter` 提供 `/` 总览和 `/settings` 设置,未知路径回到 `/`。状态响应中的构建版本以 `v` 徽标显示在安装页、登录页和登录后侧栏的品牌区域;登录后侧栏使用放大的品牌图标,图标、名称和版本徽标保持单行排列。这些分支只负责交互,服务端 session 才是安全边界。 主题以服务端通用设置为持久来源,`localStorage` 仅用于首屏缓存;system 模式会跟随系统主题变化。当前账号 ID 保存到 `localStorage`。总览先加载账号列表,为当前账号加载 Dashboard,并在每轮请求完成 30 秒后刷新;切换账号会取消旧请求并校验响应账号,避免迟到响应覆盖当前账号。手动刷新调用账号级 sync 后重新读取 Dashboard。 diff --git a/frontend/src/styles.css b/frontend/src/styles.css index a6945c7..5afcc3e 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -230,6 +230,11 @@ aside { aside .logo { padding: 0 10px 28px; } +aside .logo svg { + width: 30px; + height: 30px; + flex-shrink: 0; +} nav { display: flex; flex-direction: column; diff --git a/frontend/tests/settings-layout.spec.ts b/frontend/tests/settings-layout.spec.ts index 7e06875..b97318d 100644 --- a/frontend/tests/settings-layout.spec.ts +++ b/frontend/tests/settings-layout.spec.ts @@ -49,10 +49,16 @@ const responses: Record = { }, }; -async function openSettings(page: Page) { +async function openSettings(page: Page, version = "0.3.0-beta.1") { await page.route("**/api/v1/**", async (route) => { const key = new URL(route.request().url()).pathname.replace("/api/v1/", ""); await new Promise((resolve) => setTimeout(resolve, 40)); + if (key === "system/status") { + await route.fulfill({ + json: { initialized: true, appServer: true, version }, + }); + return; + } await route.fulfill({ json: responses[key] ?? {} }); }); await page.goto("/settings"); @@ -82,10 +88,34 @@ test("shows the build version in the authenticated brand", async ({ page }) => { badgeCenter: badgeRect.top + badgeRect.height / 2, nameCenter: nameRect.top + nameRect.height / 2, iconCenter: iconRect.top + iconRect.height / 2, + iconWidth: iconRect.width, + iconHeight: iconRect.height, + iconFlexShrink: getComputedStyle(iconElement).flexShrink, }; }); expect(Math.abs(layout.badgeCenter - layout.nameCenter)).toBeLessThan(1); expect(Math.abs(layout.iconCenter - layout.nameCenter)).toBeLessThan(1); + expect(layout.iconWidth).toBe(30); + expect(layout.iconHeight).toBe(30); + expect(layout.iconFlexShrink).toBe("0"); +}); + +test("keeps the authenticated brand on one line with a release version", async ({ + page, +}) => { + await openSettings(page, "0.2.0"); + const brand = page.locator("aside .logo"); + await expect(brand).toContainText("Codex Helper"); + await expect(brand.locator(".version-badge")).toHaveText("v0.2.0"); + const centers = await brand + .locator("svg, .brand-name, .version-badge") + .evaluateAll((elements) => + elements.map((element) => { + const rect = element.getBoundingClientRect(); + return rect.top + rect.height / 2; + }), + ); + expect(Math.max(...centers) - Math.min(...centers)).toBeLessThan(1); }); test("shows the build version before setup", async ({ page }) => {