Fix new-stack avatar draft leaking after logout#2
Open
Abhash-Chakraborty wants to merge 3 commits into
Open
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR primarily refactors/standardizes imports and hook dependencies across the app, introduces user-scoped draft keys for the stack editor (to avoid draft collisions), and adds guest-mode restrictions + testing utilities to stabilize UI behavior in tests.
Changes:
- Add a test
IntersectionObservermock and update various UI/tests to be more deterministic. - Scope stack editor “create” drafts by owner (
guestvsuser:<id>) and thread the computeddraftKeythrough editor code. - Broad import/order cleanups plus accessibility state attributes in the stack editor sidebar.
Reviewed changes
Copilot reviewed 80 out of 80 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/test/setup.ts | Adds IntersectionObserver mock for jsdom-based tests. |
| src/routes/tools.tsx | Import re-order/type import cleanup. |
| src/routes/stacks.new.tsx | Uses shared CreatorProfile, scopes guest creator id, and forces StackEditor remount via key. |
| src/routes/stacks.index.tsx | Memoizes search filter via useCallback and adjusts deps. |
| src/routes/stacks.$slug_.edit.tsx | Switches creator state to CreatorProfile and expands effect deps. |
| src/routes/stacks.$slug.tsx | Import ordering/type import cleanup. |
| src/routes/signin.tsx | Import reorder. |
| src/routes/signin-publish.tsx | Import reorder. |
| src/routes/reset-password.tsx | Import reorder. |
| src/routes/index.tsx | Import reorder. |
| src/routes/forgot-password.tsx | Import reorder. |
| src/routes/cli.auth.tsx | Import reorder. |
| src/routes/admin.tsx | Import reorder. |
| src/routes/about.tsx | Import reorder. |
| src/router.tsx | Uses typed import.meta.env access and runtime check. |
| src/lib/theme.tsx | Import ordering. |
| src/lib/auth-server.ts | Adds requiredEnv helper to validate env vars. |
| src/integrations/convex/provider.tsx | Uses typed import.meta.env access. |
| src/features/stack-editor/state/useEditorState.ts | Adds draftOwner and threads draftKey into reducer + return value. |
| src/features/stack-editor/state/editorSelectors.ts | Import ordering. |
| src/features/stack-editor/state/editorReducer.ts | Changes getDraftKey format and draft loading behavior. |
| src/features/stack-editor/state/tests/editor-reducer.test.ts | Adds test coverage for draft key scoping. |
| src/features/stack-editor/sections/ToolsSection.tsx | Import reorder. |
| src/features/stack-editor/sections/ProfileSection.tsx | Import reorder. |
| src/features/stack-editor/sections/DescriptionSection.tsx | Import reorder. |
| src/features/stack-editor/context/EditorContext.tsx | Minor null-safe check simplification. |
| src/features/stack-editor/components/ToolsStep.tsx | Import reorder. |
| src/features/stack-editor/components/ToolsSidebar.tsx | Import reorder + sticky layout constants. |
| src/features/stack-editor/components/DetailsStep.tsx | Plumbs guest/session props into avatar editor and adjusts effect deps. |
| src/features/stack-editor/tests/editor-status-ui.test.tsx | Updates expected UI labels/status text. |
| src/features/stack-editor/tests/editor-sections.test.tsx | Updates save/publish guard expectations. |
| src/features/landing/tests/landing-sections.test.tsx | Updates router/convex mocks and heading/card expectations. |
| src/emails/WaitlistLaunchEmail.tsx | Import ordering. |
| src/emails/VerifyEmail.tsx | Import ordering. |
| src/emails/ResetPasswordEmail.tsx | Import ordering. |
| src/emails/MagicLinkEmail.tsx | Import ordering. |
| src/components/ui/slider.tsx | Changes thumb rendering loop and thumb key strategy. |
| src/components/ui/hover-card.tsx | Refactors placeholder parsing loop typing. |
| src/components/ui/form-select.tsx | Import reorder. |
| src/components/ui/Dialog.tsx | Import reorder. |
| src/components/ui/ConfirmDialog.tsx | Import reorder. |
| src/components/picker/index.ts | Reorders exports. |
| src/components/picker/TierSelector.tsx | Import reorder. |
| src/components/picker/PickerEntryCard.tsx | Import reorder. |
| src/components/picker/PickerBrowser.tsx | Import style adjustment. |
| src/components/editor/ToolSuggestionPlugin.tsx | Import reorder/type import. |
| src/components/editor/SlashCommandPlugin.tsx | Adds PM node typing, optional chains, and modifies selection reset effect deps. |
| src/components/editor/ModelSuggestionPlugin.tsx | Import reorder/type import. |
| src/components/editor/BaseCard.tsx | Changes layout effect dependencies. |
| src/components/editor/AIResourceGroup.tsx | Import reorder. |
| src/components/editor/AIResourceCard.tsx | Import reorder. |
| src/components/admin/EmailTemplatesSection.tsx | Import reorder. |
| src/components/admin/EmailBroadcastsSection.tsx | Import reorder. |
| src/components/admin/AdminReviewTab.tsx | Makes original tool fields optional and adjusts list keys. |
| src/components/admin/AdminQualityTab.tsx | Import reorder + minor formatting. |
| src/components/admin/AdminEmailTab.tsx | Import reorder. |
| src/components/ToolPicker.tsx | Import reorder, optional chaining, and effect deps adjustments. |
| src/components/TiptapEditor.tsx | Hook dependency tweaks and z-index/layout adjustments. |
| src/components/TableOfContents.tsx | Adds radix to parseInt. |
| src/components/StackEditorSidebar.tsx | Adds aria-current and aria-invalid for section buttons. |
| src/components/StackEditor.tsx | Uses returned draftKey when clearing localStorage; passes guest props through. |
| src/components/Stack.tsx | Memoizes callback and adjusts effect deps. |
| src/components/SimpleSimulator.tsx | Import reorder and changes list key. |
| src/components/ResourceListItem.tsx | Import reorder. |
| src/components/ProjectsSection.tsx | Simplifies boolean expression. |
| src/components/ModelPicker.tsx | Import reorder and optional chaining. |
| src/components/JsonLd.tsx | Import reorder. |
| src/components/ItemIcon.tsx | Import reorder. |
| src/components/Header.tsx | Import reorder and changes avatar error reset effect deps. |
| src/components/EmailPreviewCenter.tsx | Import reorder. |
| src/components/BundlePicker.tsx | Import reorder and optional chaining. |
| src/components/AvatarEditor.tsx | Adds guest-mode upload restrictions and plumbs sign-in callback. |
| src/components/AddItemModal.tsx | Import reorder. |
| packages/cli/src/scanner.ts | Minor string template cleanup and import reorder. |
| packages/cli/src/index.ts | Import reorder. |
| packages/cli/src/commands/login.ts | Import reorder. |
| packages/cli/src/commands/create.ts | Import reorder + string template cleanup. |
| packages/cli/src/commands/collect.ts | Import reorder + string template cleanup. |
| packages/cli/src/classifier.ts | Import reorder. |
| biome.json | Disables multiple Biome lint rules globally. |
Comments suppressed due to low confidence (5)
src/test/setup.ts:1
MockIntersectionObserverdeclaresimplements IntersectionObserver, butobserve/unobservemethod signatures don’t match the DOM interface (they should accept at least anElementargument). This can fail TypeScript compilation in strict projects. Update method signatures to matchIntersectionObserver(and if needed, type the global assignment astypeof IntersectionObserveror cast appropriately) so the mock is structurally compatible.
src/features/stack-editor/state/editorReducer.ts:1getDraftKeyis now imported ineditor-reducer.test.ts, but in this diff it is not exported fromeditorReducer.ts. This will cause a module import error in tests/build. ExportgetDraftKey(or stop importing it directly and test via a public API).
src/components/editor/SlashCommandPlugin.tsx:1- This effect comment says it should reset selection when items change, but the dependency array is now empty, so it only runs once on mount. That can leave
selectedIndexpointing at an invalid item whenflatItems/querychanges. Restore dependencies (e.g.flatItems.lengthandquery, or the actual items collection) so selection resets as intended.
src/components/editor/BaseCard.tsx:1 autoResizeis now only invoked once on mount, but previously re-ran whendraftDescriptionchanged. If the textarea content changes after mount, the height may not update correctly. Reintroduce a dependency that changes with the textarea content (e.g.draftDescription) or otherwise triggerautoResizeon relevant updates.
src/components/ui/slider.tsx:1- Using
thumbValueas the React key can create duplicate keys when thumbs share the same value (e.g., range slider where both thumbs overlap, or repeated values). Include the index (or another stable unique identifier) in the key to avoid reconciliation bugs.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
95
to
+98
| // Reset error state when avatar URL changes | ||
| useEffect(() => { | ||
| setAvatarError(false); | ||
| }, [avatarUrl]); | ||
| }, []); |
| setEditingSuggestionId(suggestion._id); | ||
| setEditingTool({ | ||
| _id: suggestion.originalTool!._id, | ||
| _id: suggestion.originalTool?._id, |
Comment on lines
356
to
+360
| suggestion.suggestedIconStorageId ?? | ||
| suggestion.originalTool!.iconStorageId, | ||
| suggestion.originalTool?.iconStorageId, | ||
| iconUrl: | ||
| suggestion.suggestedIconUrl ?? | ||
| suggestion.originalTool!.iconUrl, | ||
| suggestion.originalTool?.iconUrl, |
Comment on lines
+27
to
+44
| "recommended": true, | ||
| "a11y": { | ||
| "noLabelWithoutControl": "off", | ||
| "noStaticElementInteractions": "off", | ||
| "noSvgWithoutTitle": "off", | ||
| "useFocusableInteractive": "off", | ||
| "useKeyWithClickEvents": "off", | ||
| "useSemanticElements": "off" | ||
| }, | ||
| "correctness": { | ||
| "useUniqueElementIds": "off" | ||
| }, | ||
| "security": { | ||
| "noDangerouslySetInnerHtml": "off" | ||
| }, | ||
| "suspicious": { | ||
| "noCommentText": "off" | ||
| } |
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.
Summary
/stacks/newcreate drafts by auth state/user so uploaded avatar drafts do not leak after logoutSign in to upload an image.Fixes #1
Root cause
The create-stack draft used one shared localStorage key,
stackDraft-new, for both authenticated users and guests. A logged-in user's uploaded avatar URL could be saved into that shared draft and then read by the guest editor after logout.Testing
pnpm checkpnpm test -- src/features/stack-editor/state/__tests__/editor-reducer.test.tspnpm buildScreenshots to add
Logged-in avatar upload
Logged-out guest no longer sees user avatar
Guest upload prompt