fix(canvas): make the channel sidebar feel instant#2681
Merged
Conversation
Creating a channel only invalidated the ["canvas-channels"] query, which forced a full paginated re-fetch of the desktop file system before the new channel appeared in the left sidebar — making the app feel unresponsive. The create API already returns the fully-formed channel, so insert it into the query cache on success and let the invalidation reconcile in the background. The sidebar selector already sorts folders alphabetically, so the new channel lands in the right position instantly. Adds a test asserting the channel appears from the optimistic cache write without waiting on the refetch. Generated-By: PostHog Code Task-Id: fcd3b6b6-ee4f-4861-9bba-c0ea91b13262
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/ui/src/features/canvas/hooks/useChannels.test.tsx:17-20
**Mock object cast avoids required interface fields**
`{ id, path, type: "folder" } as unknown as Schemas.FileSystem` sidesteps any additional required fields in the `FileSystem` interface. If the interface gains a required field that the production code relies on, these tests will silently pass with incomplete mocks. Prefer populating all required fields so TypeScript catches drift (or use a typed factory that provides safe defaults).
### Issue 2 of 2
packages/ui/src/features/canvas/hooks/useChannels.test.tsx:37-63
**Duplicate-ID guard has no test**
The PR description explicitly calls out "a duplicate-id guard avoids a double insert if the 30s poll landed it first," but only the happy-path insertion is exercised here. A second test case — seed the list with the created channel already present, call `createChannel`, and assert the list length hasn't grown — would give that guard the same coverage as the optimistic-insert path.
Reviews (1): Last reviewed commit: "fix(canvas): show newly created channel ..." | Re-trigger Greptile |
Listing channels fetched the entire desktop file system — every dashboard and filed task included — page by page (up to 50 sequential round-trips), then filtered to type === "folder" on the client. On startup this delayed the sidebar until the whole tree had been walked. Filter to type=folder server-side and request a larger page (limit=200), so the common case is a single round-trip returning only channels. The endpoint already accepts type filtering (channel tasks use type=task). The result set is identical to the prior client-side filter, so the sidebar's defensive folder filter is retained but now a no-op. Renames getDesktopFileSystem -> getDesktopFileSystemChannels to reflect the narrowed contract; its only caller is the channel sidebar. Generated-By: PostHog Code Task-Id: fcd3b6b6-ee4f-4861-9bba-c0ea91b13262
Address review feedback on useChannels.test.tsx: - Replace the `as unknown as Schemas.FileSystem` cast with a factory that populates all required fields, so TypeScript catches interface drift. - Add a test for the duplicate-id guard: when the poll has already landed the channel, creating it again keeps the list at one entry. Generated-By: PostHog Code Task-Id: fcd3b6b6-ee4f-4861-9bba-c0ea91b13262
Contributor
|
Reviews (2): Last reviewed commit: "test(canvas): type the channel fixture a..." | Re-trigger Greptile |
adamleithp
approved these changes
Jun 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The channel sidebar felt slow in two ways. Both come down to the same backing query —
["canvas-channels"], populated by a paginated GET over the desktop file system — and this PR fixes each.1. A newly-created channel was slow to appear
On create, the code only called
invalidateQueries, forcing a full re-fetch to complete before the new channel showed up — even though the create API already returns the fully-formed channel.Fix:
createMutation.onSuccessnow writes the returned channel straight into the cache, then invalidates to reconcile in the background. The sidebar selector already sorts folders alphabetically, so it lands in the right spot the instant the POST resolves — before navigation completes. A duplicate-id guard avoids a double insert if the 30s poll landed it first.2. The channel list was slow to load on app start
getDesktopFileSystem()fetched every entry in the desktop file system — all dashboards and filed tasks too — page by page, up to 50 sequential round-trips, then filtered totype === "folder"on the client. On startup the sidebar waited for that whole tree walk.Fix: filter to
type=folderserver-side and request a larger page (limit=200), so the common case is a single round-trip returning only channels. The endpoint already acceptstypefiltering (channel tasks usetype=task). The returned set is identical to the prior client-side filter, so behavior is unchanged. RenamedgetDesktopFileSystem→getDesktopFileSystemChannelsto reflect the narrowed contract (its only caller is this sidebar).Verification
useChannels.test.tsxproves the created channel appears from the optimistic write while the refetch is hung.pnpm --filter @posthog/api-client typecheck,pnpm --filter @posthog/ui typecheck, the UI test, and Biome all clean.🤖 Generated with Claude Code