diff --git a/ui/src/ui/app-render.ts b/ui/src/ui/app-render.ts index d13f593b04a3..7f7aa7bf7e75 100644 --- a/ui/src/ui/app-render.ts +++ b/ui/src/ui/app-render.ts @@ -3082,23 +3082,30 @@ export function renderApp(state: AppViewState) { : nothing} ${state.tab === "skillWorkshop" ? renderLazyView(lazySkillWorkshop, (m) => { - const proposals = state.skillWorkshopProposals; + const visibleProposals = m.filterSkillWorkshopProposals( + state.skillWorkshopProposals, + state.skillWorkshopStatusFilter, + state.skillWorkshopQuery, + ); const selectedIndex = Math.max( 0, - proposals.findIndex((proposal) => proposal.key === state.skillWorkshopSelectedKey), + visibleProposals.findIndex( + (proposal) => proposal.key === state.skillWorkshopSelectedKey, + ), ); const selectRelativeProposal = (delta: -1 | 1) => { - if (proposals.length === 0) { + if (visibleProposals.length === 0) { return; } - const nextIndex = (selectedIndex + delta + proposals.length) % proposals.length; - selectSkillWorkshopProposal(state, proposals[nextIndex].key); + const nextIndex = + (selectedIndex + delta + visibleProposals.length) % visibleProposals.length; + selectSkillWorkshopProposal(state, visibleProposals[nextIndex].key); }; return m.renderSkillWorkshop({ loading: state.skillWorkshopLoading, error: state.skillWorkshopError, inspectingKey: state.skillWorkshopInspectingKey, - proposals, + proposals: state.skillWorkshopProposals, selectedKey: state.skillWorkshopSelectedKey, statusFilter: state.skillWorkshopStatusFilter, query: state.skillWorkshopQuery, @@ -3111,7 +3118,7 @@ export function renderApp(state: AppViewState) { revisionKey: state.skillWorkshopRevisionKey, revisionDraft: state.skillWorkshopRevisionDraft, assistantName: state.assistantName, - counts: countSkillWorkshopProposals(proposals), + counts: countSkillWorkshopProposals(state.skillWorkshopProposals), onStatusFilterChange: (status) => (state.skillWorkshopStatusFilter = status), onQueryChange: (query) => (state.skillWorkshopQuery = query), onFilePreviewQueryChange: (query) => (state.skillWorkshopFilePreviewQuery = query), diff --git a/ui/src/ui/app-view-state.ts b/ui/src/ui/app-view-state.ts index 341cbbb54fdd..a00b1fcfe271 100644 --- a/ui/src/ui/app-view-state.ts +++ b/ui/src/ui/app-view-state.ts @@ -11,6 +11,7 @@ import type { CronModelSuggestionsState, CronState } from "./controllers/cron.ts import type { DevicePairingList } from "./controllers/devices.ts"; import type { ExecApprovalRequest } from "./controllers/exec-approval.ts"; import type { ExecApprovalsFile, ExecApprovalsSnapshot } from "./controllers/exec-approvals.ts"; +import type { SkillWorkshopState } from "./controllers/skill-workshop.ts"; import type { ClawHubSearchResult, ClawHubSkillSecurityVerdict, @@ -51,13 +52,6 @@ import type { } from "./types.ts"; import type { ChatAttachment, ChatQueueItem } from "./ui-types.ts"; import type { NostrProfileFormState } from "./views/channels.nostr-profile-form.ts"; -import type { - SkillWorkshopActionBusy, - SkillWorkshopActionNotice, - SkillWorkshopMode, - SkillWorkshopProposal, - SkillWorkshopStatusFilter, -} from "./views/skill-workshop.ts"; import type { SessionLogEntry } from "./views/usage.ts"; export type AppViewState = { @@ -432,23 +426,6 @@ export type AppViewState = { skillCardContentKeys: Record; skillCardLoadingKey: string | null; skillCardErrors: Record; - skillWorkshopLoading: boolean; - skillWorkshopLoaded: boolean; - skillWorkshopError: string | null; - skillWorkshopInspectingKey: string | null; - skillWorkshopProposals: SkillWorkshopProposal[]; - skillWorkshopSelectedKey: string | null; - skillWorkshopActionBusy: SkillWorkshopActionBusy | null; - skillWorkshopActionNotice: SkillWorkshopActionNotice | null; - skillWorkshopActionNoticeTimer?: ReturnType | number | null; - skillWorkshopRevisionKey: string | null; - skillWorkshopRevisionDraft: string; - skillWorkshopStatusFilter: SkillWorkshopStatusFilter; - skillWorkshopQuery: string; - skillWorkshopFilePreviewKey: string | null; - skillWorkshopFilePreviewQuery: string; - skillWorkshopQueueWidth: number; - skillWorkshopMode: SkillWorkshopMode; healthLoading: boolean; healthResult: HealthSummary | null; healthError: string | null; @@ -576,4 +553,4 @@ export type AppViewState = { handleWebPushSubscribe: () => Promise; handleWebPushUnsubscribe: () => Promise; handleWebPushTest: () => Promise; - }; + } & SkillWorkshopState; diff --git a/ui/src/ui/app.ts b/ui/src/ui/app.ts index de19aa9c0dc0..a5dd25eeaca8 100644 --- a/ui/src/ui/app.ts +++ b/ui/src/ui/app.ts @@ -103,6 +103,7 @@ import { type ExecApprovalRequest, } from "./controllers/exec-approval.ts"; import type { ExecApprovalsFile, ExecApprovalsSnapshot } from "./controllers/exec-approvals.ts"; +import type { SkillWorkshopState } from "./controllers/skill-workshop.ts"; import type { ClawHubSearchResult, ClawHubSkillSecurityVerdict, @@ -144,13 +145,6 @@ import type { import type { ChatAttachment, ChatQueueItem, CronFormState } from "./ui-types.ts"; import { generateUUID } from "./uuid.ts"; import type { NostrProfileFormState } from "./views/channels.nostr-profile-form.ts"; -import type { - SkillWorkshopActionBusy, - SkillWorkshopActionNotice, - SkillWorkshopMode, - SkillWorkshopProposal, - SkillWorkshopStatusFilter, -} from "./views/skill-workshop.ts"; declare global { interface Window { @@ -637,19 +631,19 @@ export class OpenClawApp extends LitElement { @state() skillWorkshopLoaded = false; @state() skillWorkshopError: string | null = null; @state() skillWorkshopInspectingKey: string | null = null; - @state() skillWorkshopProposals: SkillWorkshopProposal[] = []; + @state() skillWorkshopProposals: SkillWorkshopState["skillWorkshopProposals"] = []; @state() skillWorkshopSelectedKey: string | null = null; - @state() skillWorkshopActionBusy: SkillWorkshopActionBusy | null = null; - @state() skillWorkshopActionNotice: SkillWorkshopActionNotice | null = null; + @state() skillWorkshopActionBusy: SkillWorkshopState["skillWorkshopActionBusy"] = null; + @state() skillWorkshopActionNotice: SkillWorkshopState["skillWorkshopActionNotice"] = null; skillWorkshopActionNoticeTimer: ReturnType | number | null = null; @state() skillWorkshopRevisionKey: string | null = null; @state() skillWorkshopRevisionDraft = ""; - @state() skillWorkshopStatusFilter: SkillWorkshopStatusFilter = "pending"; + @state() skillWorkshopStatusFilter: SkillWorkshopState["skillWorkshopStatusFilter"] = "pending"; @state() skillWorkshopQuery = ""; @state() skillWorkshopFilePreviewKey: string | null = null; @state() skillWorkshopFilePreviewQuery = ""; @state() skillWorkshopQueueWidth = 360; - @state() skillWorkshopMode: SkillWorkshopMode = "today"; + @state() skillWorkshopMode: SkillWorkshopState["skillWorkshopMode"] = "today"; @state() healthLoading = false; @state() healthResult: HealthSummary | null = null; diff --git a/ui/src/ui/controllers/skill-workshop.ts b/ui/src/ui/controllers/skill-workshop.ts index 7a8c085ef91a..54049ae0ca01 100644 --- a/ui/src/ui/controllers/skill-workshop.ts +++ b/ui/src/ui/controllers/skill-workshop.ts @@ -2,7 +2,9 @@ import type { GatewayBrowserClient } from "../gateway.ts"; import type { SkillWorkshopAction, SkillWorkshopActionNotice, + SkillWorkshopMode, SkillWorkshopProposal, + SkillWorkshopStatusFilter, } from "../views/skill-workshop.ts"; const SKILL_WORKSHOP_NOTICE_MS = 2800; @@ -84,6 +86,12 @@ export type SkillWorkshopState = { skillWorkshopActionNoticeTimer?: ReturnType | number | null; skillWorkshopRevisionKey: string | null; skillWorkshopRevisionDraft: string; + skillWorkshopStatusFilter: SkillWorkshopStatusFilter; + skillWorkshopQuery: string; + skillWorkshopFilePreviewKey: string | null; + skillWorkshopFilePreviewQuery: string; + skillWorkshopQueueWidth: number; + skillWorkshopMode: SkillWorkshopMode; }; function getErrorMessage(err: unknown): string {