Skip to content

Commit 1c17fd5

Browse files
authored
feat(ui): add mobile cron session filter
Add the existing desktop cron-session visibility toggle to the mobile chat settings dropdown, reusing the shared session filtering state and cron filter icon path. Also add focused browser render coverage for the mobile dropdown so the cron filter button, hidden-count title, active/pressed state, and click behavior are covered. Validated: - pnpm exec oxfmt --check --threads=1 ui/src/ui/app-render.helpers.browser.test.ts - pnpm test ui/src/ui/app-render.helpers.browser.test.ts ui/src/ui/app-render.helpers.node.test.ts - pnpm lint --threads=8 Thanks @luzhidong.
1 parent 3c19588 commit 1c17fd5

2 files changed

Lines changed: 59 additions & 1 deletion

File tree

ui/src/ui/app-render.helpers.browser.test.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import { render } from "lit";
22
import { describe, expect, it } from "vitest";
33
import { t } from "../i18n/index.ts";
4-
import { renderChatControls } from "./app-render.helpers.ts";
4+
import { renderChatControls, renderChatMobileToggle } from "./app-render.helpers.ts";
55
import type { AppViewState } from "./app-view-state.ts";
6+
import type { SessionsListResult } from "./types.ts";
7+
8+
type SessionRow = SessionsListResult["sessions"][number];
9+
10+
function row(overrides: Partial<SessionRow> & { key: string }): SessionRow {
11+
return { kind: "direct", updatedAt: 0, ...overrides };
12+
}
613

714
function createState(overrides: Partial<AppViewState> = {}) {
815
return {
@@ -66,4 +73,35 @@ describe("chat header controls (browser)", () => {
6673
expect(button.getAttribute("aria-label")).toBe(button.getAttribute("data-tooltip"));
6774
}
6875
});
76+
77+
it("renders the cron session filter in the mobile dropdown controls", async () => {
78+
const state = createState({
79+
sessionsResult: {
80+
ts: 0,
81+
path: "",
82+
count: 2,
83+
defaults: { modelProvider: "openai", model: "gpt-5", contextTokens: null },
84+
sessions: [row({ key: "main" }), row({ key: "agent:main:cron:daily-briefing" })],
85+
},
86+
});
87+
const container = document.createElement("div");
88+
render(renderChatMobileToggle(state), container);
89+
await Promise.resolve();
90+
91+
const buttons = Array.from(
92+
container.querySelectorAll<HTMLButtonElement>(".chat-controls__thinking .btn--icon"),
93+
);
94+
95+
expect(buttons).toHaveLength(4);
96+
const cronButton = buttons.at(-1);
97+
expect(cronButton?.classList.contains("active")).toBe(true);
98+
expect(cronButton?.getAttribute("aria-pressed")).toBe("true");
99+
expect(cronButton?.getAttribute("title")).toBe(
100+
t("chat.showCronSessionsHidden", { count: "1" }),
101+
);
102+
103+
cronButton?.click();
104+
105+
expect(state.sessionsHideCron).toBe(false);
106+
});
69107
});

ui/src/ui/app-render.helpers.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ export function renderChatMobileToggle(state: AppViewState) {
386386
const showThinking = state.onboarding ? false : state.settings.chatShowThinking;
387387
const showToolCalls = state.onboarding ? true : state.settings.chatShowToolCalls;
388388
const focusActive = state.onboarding ? true : state.settings.chatFocusMode;
389+
const hideCron = state.sessionsHideCron ?? true;
390+
const hiddenCronCount = hideCron
391+
? countHiddenCronSessions(state.sessionKey, state.sessionsResult)
392+
: 0;
389393
const toolCallsIcon = html`
390394
<svg
391395
width="18"
@@ -543,6 +547,22 @@ export function renderChatMobileToggle(state: AppViewState) {
543547
>
544548
${focusIcon}
545549
</button>
550+
<button
551+
class="btn btn--sm btn--icon ${hideCron ? "active" : ""}"
552+
@click=${() => {
553+
state.sessionsHideCron = !hideCron;
554+
}}
555+
aria-pressed=${hideCron}
556+
title=${
557+
hideCron
558+
? hiddenCronCount > 0
559+
? t("chat.showCronSessionsHidden", { count: String(hiddenCronCount) })
560+
: t("chat.showCronSessions")
561+
: t("chat.hideCronSessions")
562+
}
563+
>
564+
${renderCronFilterIcon(hiddenCronCount)}
565+
</button>
546566
</div>
547567
</div>
548568
</div>

0 commit comments

Comments
 (0)