diff --git a/packages/app/e2e/helpers/terminal-perf.ts b/packages/app/e2e/helpers/terminal-perf.ts index 2902ce3d7..8b11d55e6 100644 --- a/packages/app/e2e/helpers/terminal-perf.ts +++ b/packages/app/e2e/helpers/terminal-perf.ts @@ -100,7 +100,19 @@ function buildWorkspaceUrl(workspaceId: string): string { export async function getTerminalBufferText(page: Page): Promise { return page.evaluate(() => { - const term = (window as any).__paseoTerminal; + const term = ( + window as Window & { + __paseoTerminal?: { + buffer: { + active: { + length: number; + getLine: (i: number) => { translateToString: (trim: boolean) => string } | null; + }; + }; + onWriteParsed: (cb: () => void) => { dispose: () => void }; + }; + } + ).__paseoTerminal; if (!term) { return ""; } @@ -205,12 +217,16 @@ export interface LatencySample { */ export async function measureKeystrokeLatency(page: Page, char: string): Promise { await page.evaluate(() => { - const term = (window as any).__paseoTerminal; - if (!term) { + const win = window as Window & { + __paseoTerminal?: { onWriteParsed: (cb: () => void) => { dispose: () => void } }; + __perfKeystroke?: { promise: Promise | null }; + }; + if (!win.__paseoTerminal) { throw new Error("__paseoTerminal not available"); } + const term = win.__paseoTerminal; - const state = ((window as any).__perfKeystroke = { + const state = (win.__perfKeystroke = { promise: null as Promise | null, }); @@ -236,7 +252,11 @@ export async function measureKeystrokeLatency(page: Page, char: string): Promise await page.keyboard.press(char); - return page.evaluate(() => (window as any).__perfKeystroke.promise); + return page.evaluate( + () => + (window as unknown as { __perfKeystroke: { promise: Promise } }).__perfKeystroke + .promise, + ); } export function computePercentile(samples: number[], p: number): number { diff --git a/packages/app/src/components/stream-strategy.ts b/packages/app/src/components/stream-strategy.ts index 4c5289a9b..6d7cd681b 100644 --- a/packages/app/src/components/stream-strategy.ts +++ b/packages/app/src/components/stream-strategy.ts @@ -32,9 +32,9 @@ export type StreamNearBottomInput = StreamViewportMetrics & { }; export interface StreamEdgeSlotProps { - ListHeaderComponent?: ReactElement | ComponentType | null; + ListHeaderComponent?: ReactElement | ComponentType | null; ListHeaderComponentStyle?: StyleProp; - ListFooterComponent?: ReactElement | ComponentType | null; + ListFooterComponent?: ReactElement | ComponentType | null; ListFooterComponentStyle?: StyleProp; } @@ -85,7 +85,7 @@ export interface StreamStrategy { isNearBottom: (input: StreamNearBottomInput) => boolean; getBottomOffset: (metrics: StreamViewportMetrics) => number; getEdgeSlotProps: ( - component: ReactElement | ComponentType | null, + component: ReactElement | ComponentType | null, gapSize: number, ) => StreamEdgeSlotProps; getMaintainVisibleContentPosition: () => MaintainVisibleContentPositionConfig | undefined; @@ -262,7 +262,7 @@ export function getBottomOffsetForStreamRenderStrategy( export function getStreamEdgeSlotProps(params: { strategy: StreamStrategy; - component: ReactElement | ComponentType | null; + component: ReactElement | ComponentType | null; gapSize: number; }): StreamEdgeSlotProps { return params.strategy.getEdgeSlotProps(params.component, params.gapSize); diff --git a/packages/app/src/components/use-web-scrollbar.tsx b/packages/app/src/components/use-web-scrollbar.tsx index 469627700..5156fe66f 100644 --- a/packages/app/src/components/use-web-scrollbar.tsx +++ b/packages/app/src/components/use-web-scrollbar.tsx @@ -60,8 +60,12 @@ export function useWebElementScrollbar( if (!element) return; element.setAttribute("data-hide-scrollbar", ""); - (element.style as any).scrollbarWidth = "none"; - (element.style as any).msOverflowStyle = "none"; + ( + element.style as CSSStyleDeclaration & { scrollbarWidth: string; msOverflowStyle: string } + ).scrollbarWidth = "none"; + ( + element.style as CSSStyleDeclaration & { scrollbarWidth: string; msOverflowStyle: string } + ).msOverflowStyle = "none"; ensureHideScrollbarStyle(); function update() { @@ -90,8 +94,12 @@ export function useWebElementScrollbar( element.removeEventListener("scroll", update); resizeObserver.disconnect(); element.removeAttribute("data-hide-scrollbar"); - (element.style as any).scrollbarWidth = ""; - (element.style as any).msOverflowStyle = ""; + ( + element.style as CSSStyleDeclaration & { scrollbarWidth: string; msOverflowStyle: string } + ).scrollbarWidth = ""; + ( + element.style as CSSStyleDeclaration & { scrollbarWidth: string; msOverflowStyle: string } + ).msOverflowStyle = ""; }; }, [contentRef, elementRef, enabled]); diff --git a/packages/app/src/components/web-desktop-scrollbar.tsx b/packages/app/src/components/web-desktop-scrollbar.tsx index 4bd1dafe9..6792dffbb 100644 --- a/packages/app/src/components/web-desktop-scrollbar.tsx +++ b/packages/app/src/components/web-desktop-scrollbar.tsx @@ -27,7 +27,15 @@ const HANDLE_WIDTH_TRANSITION_DURATION_MS = 240; const HANDLE_SCROLL_VISIBILITY_MS = 1200; const HANDLE_SCROLL_ACTIVE_MS = 110; -function readClientY(event: any): number | null { +interface PointerLikeEvent { + clientY?: number; + pageY?: number; + nativeEvent?: { clientY?: number; pageY?: number; preventDefault?: () => void }; + preventDefault?: () => void; + stopPropagation?: () => void; +} + +function readClientY(event: PointerLikeEvent): number | null { const value = event?.nativeEvent?.clientY ?? event?.clientY ?? event?.nativeEvent?.pageY ?? event?.pageY; return typeof value === "number" ? value : null; @@ -281,7 +289,7 @@ export function WebDesktopScrollbarOverlay({ }); }, [applyDragDelta]); - const startWebDrag = useCallback((event: any) => { + const startWebDrag = useCallback((event: PointerLikeEvent) => { if (!platformIsWeb) { return; } @@ -371,7 +379,7 @@ export function WebDesktopScrollbarOverlay({ transitionProperty: "transform", transitionDuration: `${handleTravelDurationMs}ms`, transitionTimingFunction: "linear", - } as any), + } as object), ], [thumbRegionHeight, thumbRegionOffset, handleCursor, handleTravelDurationMs], ); @@ -391,7 +399,7 @@ export function WebDesktopScrollbarOverlay({ transitionProperty: "opacity, width, background-color", transitionDuration: `${HANDLE_FADE_DURATION_MS}ms, ${HANDLE_WIDTH_TRANSITION_DURATION_MS}ms, ${HANDLE_FADE_DURATION_MS}ms`, transitionTimingFunction: "ease-out, cubic-bezier(0.22, 0.75, 0.2, 1), ease-out", - } as any), + } as object), ], [handleInsetTop, geometry.handleSize, handleWidth, handleColor, handleOpacity], ); @@ -409,7 +417,7 @@ export function WebDesktopScrollbarOverlay({ onPointerLeave: handleGrabHoverOut, onMouseEnter: handleGrabHoverIn, onMouseLeave: handleGrabHoverOut, - } as any) + } as object) : null)} > diff --git a/packages/app/src/dictation/dictation-stream-sender.test.ts b/packages/app/src/dictation/dictation-stream-sender.test.ts index 9fa75315d..ee5707a8d 100644 --- a/packages/app/src/dictation/dictation-stream-sender.test.ts +++ b/packages/app/src/dictation/dictation-stream-sender.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it } from "vitest"; +import type { DaemonClient } from "@server/client/daemon-client"; import { DictationStreamSender } from "@/dictation/dictation-stream-sender"; @@ -55,7 +56,7 @@ describe("DictationStreamSender", () => { const client = new FakeDaemonClient(); const ids = ["d1"]; const sender = new DictationStreamSender({ - client: client as any, + client: client as unknown as DaemonClient, format: "audio/pcm;rate=16000;bits=16", createDictationId: () => ids.shift() ?? "dX", }); @@ -76,7 +77,7 @@ describe("DictationStreamSender", () => { const client = new FakeDaemonClient(); const ids = ["d1", "d2"]; const sender = new DictationStreamSender({ - client: client as any, + client: client as unknown as DaemonClient, format: "audio/pcm;rate=16000;bits=16", createDictationId: () => ids.shift() ?? "dX", }); @@ -99,7 +100,7 @@ describe("DictationStreamSender", () => { const client = new FakeDaemonClient(); const ids = ["d1"]; const sender = new DictationStreamSender({ - client: client as any, + client: client as unknown as DaemonClient, format: "audio/pcm;rate=16000;bits=16", createDictationId: () => ids.shift() ?? "dX", }); @@ -120,7 +121,7 @@ describe("DictationStreamSender", () => { client.isConnected = false; const ids = ["d1"]; const sender = new DictationStreamSender({ - client: client as any, + client: client as unknown as DaemonClient, format: "audio/pcm;rate=16000;bits=16", createDictationId: () => ids.shift() ?? "dX", }); diff --git a/packages/app/src/stores/checkout-git-actions-store.test.ts b/packages/app/src/stores/checkout-git-actions-store.test.ts index 22794270e..2c85aa30b 100644 --- a/packages/app/src/stores/checkout-git-actions-store.test.ts +++ b/packages/app/src/stores/checkout-git-actions-store.test.ts @@ -52,18 +52,18 @@ describe("checkout-git-actions-store", () => { vi.useFakeTimers(); __resetCheckoutGitActionsStoreForTests(); appQueryClient.clear(); - useSessionStore.setState((state) => ({ ...state, sessions: {} as any })); + useSessionStore.setState((state) => ({ ...state, sessions: {} })); }); afterEach(() => { vi.useRealTimers(); __resetCheckoutGitActionsStoreForTests(); appQueryClient.clear(); - useSessionStore.setState((state) => ({ ...state, sessions: {} as any })); + useSessionStore.setState((state) => ({ ...state, sessions: {} })); }); it("shares pending state per checkout and de-dupes in-flight calls", async () => { - const deferred = createDeferred(); + const deferred = createDeferred(); const client = { checkoutCommit: vi.fn(() => deferred.promise), }; @@ -71,8 +71,8 @@ describe("checkout-git-actions-store", () => { useSessionStore.setState((state) => ({ ...state, sessions: { - ...(state.sessions as any), - [serverId]: { client } as any, + ...state.sessions, + [serverId]: { client } as unknown as (typeof state.sessions)[string], }, }));