Skip to content

feat: speedtest visualization webview#890

Merged
EhabY merged 6 commits intomainfrom
feat/speedtest-visualization-888
Apr 30, 2026
Merged

feat: speedtest visualization webview#890
EhabY merged 6 commits intomainfrom
feat/speedtest-visualization-888

Conversation

@EhabY
Copy link
Copy Markdown
Collaborator

@EhabY EhabY commented Apr 15, 2026

Renders speed test results in a Canvas line chart with throughput over time, a summary header, hover tooltips, and a View JSON action. Duration input drives a real-time progress bar while the CLI runs.

Extension

  • Zod-validated payload handed to the webview as typed data; shared SpeedtestResult / SpeedtestData / SpeedtestInterval in @repo/shared
  • SpeedtestPanelFactory owned by ServiceContainer encapsulates panel creation, message handling, and error surfacing via the logger
  • reportElapsedProgress extracted into progress.ts for reuse by other long-running commands

Webview

  • chart.ts does canvas drawing; pure helpers (niceStep, formatTick, findNearest*, toChartSamples) live in chartUtils.ts for direct unit testing
  • Layout scales with webview font size via em-based padding; empty results short-circuit with a readable message instead of an empty axis
  • New subscribeNotification helper in @repo/webview-shared; useIpc delegates to it

Protocol

  • buildApiHook and useIpc take RequestDef / CommandDef / NotificationDef directly in both overloads, no casts

Shared

  • toError moved into @repo/shared with a serialize hook so the extension keeps util.inspect formatting
  • createBaseWebviewConfig split into createWebviewConfig and createReactWebviewConfig

Closes #888

@EhabY EhabY marked this pull request as draft April 15, 2026 09:08
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch from b4cb6cc to a37b1ac Compare April 16, 2026 15:33
@EhabY EhabY self-assigned this Apr 18, 2026
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch 5 times, most recently from 781bd7a to 8c6204a Compare April 20, 2026 15:20
@EhabY EhabY marked this pull request as ready for review April 20, 2026 16:46
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch 5 times, most recently from 83a1ca1 to 1ce0401 Compare April 21, 2026 14:22
@jakehwll jakehwll self-requested a review April 23, 2026 12:25
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch 5 times, most recently from 04e4c55 to 13ee0b6 Compare April 28, 2026 12:47
@EhabY
Copy link
Copy Markdown
Collaborator Author

EhabY commented Apr 29, 2026

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well-structured PR. The separation into @repo/shared, vanilla-JS speedtest webview, and typed IPC protocol is clean. The canvas chart avoids the React framework overhead, chartUtils.ts is well-extracted for testability, and the disposal/cleanup chains are thorough. Zoro nailed it: "Vanilla JS webview is the correct choice; avoids ~200KB of React/framework deps for a static canvas chart."

3 P2, 9 P3, 4 Nit, 6 Note.

The P2s are: (1) a division-by-zero when all samples have x=0, producing a silently blank chart, (2) Zod validation errors surfaced raw as a JSON array in the user dialog, and (3) canvas draw errors inside requestAnimationFrame escaping the top-level try/catch with no user feedback. The P3s cluster around the gradient hex-color assumption (7 reviewers independently flagged it), stale canvasRect on scroll, and missing error context in the message handler.

Netero found 2 P3 coverage gaps (reportElapsedProgress and parseSpeedtestResult untested) and a spurious blank line. Those travel with the panel findings below.

Process note: the PR description says "createBaseWebviewConfig split into createWebviewConfig and createReactWebviewConfig." The base code had createWebviewConfig (no "Base" prefix). Minor but worth correcting for review accuracy.


src/webviews/util.ts:35

P3 [DEREM-15] <title>${title}</title> interpolates without escaping. The title comes from Speed Test: ${workspaceName} where workspaceName is user-derived. A workspace name containing </title> breaks the HTML structure. CSP prevents script execution, but HTML injection can still cause rendering artifacts. Escape <, >, & in the title.

(Pariston P3, Chopper P4)

🤖

🤖 This review was automatically generated with Coder Agents.

Comment thread packages/speedtest/src/chart.ts Outdated
Comment thread src/commands.ts Outdated
Comment thread packages/speedtest/src/index.ts Outdated
Comment thread packages/speedtest/src/chart.ts Outdated
Comment thread packages/speedtest/src/index.ts Outdated
Comment thread src/commands.ts Outdated
Comment thread packages/speedtest/src/chart.ts Outdated
Comment thread packages/speedtest/src/chart.ts Outdated
Comment thread src/progress.ts
Comment thread src/webviews/speedtest/types.ts
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch from 13ee0b6 to 9fbd977 Compare April 29, 2026 14:11
EhabY added 5 commits April 29, 2026 18:45
After running a speed test, results are now displayed in a lightweight
Canvas-based chart (4.5KB JS) instead of raw JSON. The webview shows
throughput over time with hover tooltips, a summary header, and a
"View JSON" button for the raw data.

- Add `packages/speedtest/` webview (vanilla TS, no framework)
- Extract `createBaseWebviewConfig` from the React-specific variant
  so lightweight webviews can reuse the shared Vite config
- Add typed IPC via `SpeedtestApi` in `@repo/shared`
- Accept duration as seconds, show real-time progress bar
- Expose `extensionUri` through `ServiceContainer`
- Time-proportional x-axis with dashed leader line from t=0
- Uniform tick labels with smart unit selection (s/m/h) that scale
  from seconds to hours
- Dynamic y-axis padding based on measured label width
- Binary search hit-test with crosshair-snap for dense data
- ResizeObserver debounced via requestAnimationFrame
- Tooltip clamped to container bounds
- General cleanup: named constants, single-pass data prep, responsive
  layout, safer error handling, input validation, missing dependency
- Plumb workspaceName from the command through to the panel title and
  the in-chart heading; drop the generic "Speed Test Results" label.
- Read chart accent from the theme's button color so it tracks the
  active theme instead of being stuck on blue.
- Re-send data on active-theme change so canvas pixels repaint against
  the new theme (DOM CSS vars update live, canvas doesn't).
- Restructure chart.ts into readTheme/layoutChart/drawAxes/drawSeries,
  export niceStep/formatTick for testing.
- Rename the panel viewType to coder.speedtestPanel to match the
  tasks/chat conventions.
- Clean up the duration prompt and tests.
Validate CLI output with Zod on the extension side so the webview trusts
typed data and stops hand-parsing JSON. Share SpeedtestResult types via
@repo/shared and flatten the message payload.

Webview cleanup: newspaper-ordered index.ts with a main() entrypoint,
em-scaled chart layout, named constants in place of magic numbers, empty
samples handled with a message, and a subscribeNotification helper that
useIpc now delegates to. Pure helpers (niceStep, formatTick, findNearest*,
toChartSamples) live in chartUtils.ts for easy unit testing.

Panel: extract webview panel logic into SpeedtestPanelFactory, a
ServiceContainer-owned class that takes extensionUri + logger in its
constructor and exposes show(payload). Surfaces webview handler errors
through the logger and tracks every subscription in a disposables array.
Drops the now-unused isGoDuration helper.

Tests: cover SpeedtestPanelFactory end-to-end with a reusable
createMockWebviewPanel harness in testHelpers, plus chartUtils and
renderLineChart unit tests. Canvas 2D is stubbed globally in
test/webview/setup.ts so chart tests don't need per-test plumbing.

Protocol: buildApiHook and useIpc now take RequestDef, CommandDef, and
NotificationDef directly in both overloads, no casts needed.

Platform: move toError into shared with a serialize hook so the extension
keeps util.inspect output, rename createBaseWebviewConfig to
createWebviewConfig, add createReactWebviewConfig, extract
reportElapsedProgress for reuse by other long running commands, and drop
the createWebviewConfig eslint ignore.
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch from 9fbd977 to bfb8ce3 Compare April 29, 2026 15:45
@EhabY EhabY force-pushed the feat/speedtest-visualization-888 branch from 4886505 to 9003aa1 Compare April 30, 2026 11:57
@EhabY EhabY merged commit e4a8fed into main Apr 30, 2026
10 checks passed
@EhabY EhabY deleted the feat/speedtest-visualization-888 branch April 30, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Speedtest visualization in a lightweight webview

2 participants