feat: add chat folders with drag-and-drop organization#27
feat: add chat folders with drag-and-drop organization#27
Conversation
Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
Co-authored-by: OpenSource03 <29690431+OpenSource03@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1d31466f15
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const updatedFolders = (p.folders ?? []).filter((f) => f.id !== folderId); | ||
| return { ...p, folders: updatedFolders }; |
There was a problem hiding this comment.
Clear session folder assignments when deleting a folder
This handler only removes the folder entry from the project and never updates sessions that still reference that folderId. Those sessions are then excluded from the non-foldered list (src/components/sidebar/ProjectSection.tsx groups by session.folderId) and have no folder section to render under, so chats inside a deleted folder disappear from the sidebar and become effectively inaccessible. Deleting a folder should also unset/migrate folderId for affected sessions (including metadata sidecars).
Useful? React with 👍 / 👎.
| if (session.folderId) { | ||
| const existing = foldered.get(session.folderId) || []; | ||
| existing.push(session); | ||
| foldered.set(session.folderId, existing); | ||
| } else { |
There was a problem hiding this comment.
Preserve folder IDs when hydrating sessions for sidebar groups
This grouping path depends on session.folderId, but the session hydration flow still constructs sidebar session objects without folderId (src/hooks/session/useSessionLifecycle.ts maps only id/project/title/timestamps/model/etc.). After restart, moved chats are treated as non-foldered and folder organization appears lost even though folder assignments were saved. The list IPC/type/hydration path needs to carry folderId through.
Useful? React with 👍 / 👎.
| if (sessionId) { | ||
| // Session dropped on folder | ||
| onMoveSessionToFolder(sessionId, targetFolderId); | ||
| } else if (folderId && folderId !== targetFolderId) { |
There was a problem hiding this comment.
Reject cross-project drops when moving sessions to folders
Any dropped session is moved into targetFolderId without verifying project ownership. If a user drags a chat from project A into a folder shown under project B, the session is persisted with a foreign folder id; project A has no matching folder, so that chat no longer renders in the sidebar. Include the source project in drag payload (or validate target folder belongs to the same project) before calling the move handler.
Useful? React with 👍 / 👎.
Summary
Type of Change
Related Issues
Addresses organization features from issue feedback.
How to Test
Screenshots / Screen Recording
Checklist
pnpm build)anytypes introducedms-*/me-*instead ofml-*/mr-*)wrap-break-wordshared/types/, notsrc/types/Implementation Details
Data Model:
ChatFolderinterface withid,name,projectId,createdAt,orderSessionBasewith optionalfolderIdfieldProject.folders[]array in projects.jsonIPC Layer:
UI Components:
FolderSection: Renders collapsible folders with session counts, rename/delete actionsProjectSection: Refactored to separate foldered vs non-foldered sessions, handle drag targetsSessionItem: Made draggable withapplication/x-session-iddata transferDrag-and-Drop:
folderId: null)orderfieldState Management:
useProjectManagerwithcreateFolder,renameFolder,deleteFolder,reorderFolderhandleMoveSessionToFolderin AppLayout for session updatessetProjectsandsetSessionsSessions not in folders render below folders using existing date-based grouping (Today/Yesterday/Last 7 Days/Older). Folder creation uses inline text input with Enter to confirm, Escape to cancel.
Original prompt