Skip to content

Fix new-stack avatar draft leaking after logout#2

Open
Abhash-Chakraborty wants to merge 3 commits into
alp82:mainfrom
Abhash-Chakraborty:Abhash-changes
Open

Fix new-stack avatar draft leaking after logout#2
Abhash-Chakraborty wants to merge 3 commits into
alp82:mainfrom
Abhash-Chakraborty:Abhash-changes

Conversation

@Abhash-Chakraborty

@Abhash-Chakraborty Abhash-Chakraborty commented May 26, 2026

Copy link
Copy Markdown

Summary

  • isolates /stacks/new create drafts by auth state/user so uploaded avatar drafts do not leak after logout
  • remounts the create editor when guest/user identity changes
  • blocks guest avatar file uploads before Convex upload URL generation and shows Sign 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 check
  • pnpm test -- src/features/stack-editor/state/__tests__/editor-reducer.test.ts
  • pnpm build

Screenshots to add

Logged-in avatar upload

Screenshot 2026-05-27 010938

Logged-out guest no longer sees user avatar

Screenshot 2026-05-27 012659

Guest upload prompt

Screenshot 2026-05-27 010331

@Abhash-Chakraborty Abhash-Chakraborty marked this pull request as ready for review May 26, 2026 19:58
Copilot AI review requested due to automatic review settings May 26, 2026 19:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 IntersectionObserver mock and update various UI/tests to be more deterministic.
  • Scope stack editor “create” drafts by owner (guest vs user:<id>) and thread the computed draftKey through 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

  • MockIntersectionObserver declares implements IntersectionObserver, but observe/unobserve method signatures don’t match the DOM interface (they should accept at least an Element argument). This can fail TypeScript compilation in strict projects. Update method signatures to match IntersectionObserver (and if needed, type the global assignment as typeof IntersectionObserver or cast appropriately) so the mock is structurally compatible.
    src/features/stack-editor/state/editorReducer.ts:1
  • getDraftKey is now imported in editor-reducer.test.ts, but in this diff it is not exported from editorReducer.ts. This will cause a module import error in tests/build. Export getDraftKey (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 selectedIndex pointing at an invalid item when flatItems/query changes. Restore dependencies (e.g. flatItems.length and query, or the actual items collection) so selection resets as intended.
    src/components/editor/BaseCard.tsx:1
  • autoResize is now only invoked once on mount, but previously re-ran when draftDescription changed. 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 trigger autoResize on relevant updates.
    src/components/ui/slider.tsx:1
  • Using thumbValue as 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 thread src/components/Header.tsx
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 thread biome.json
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"
}
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.

Fix new-stack avatar draft leaking after logout

2 participants