Skip to content

Shell DnD extensions: Messages source, Library source, TextEditor target#242

Merged
jaylfc merged 1 commit into
masterfrom
feat/shell-dnd-extensions
Apr 20, 2026
Merged

Shell DnD extensions: Messages source, Library source, TextEditor target#242
jaylfc merged 1 commit into
masterfrom
feat/shell-dnd-extensions

Conversation

@jaylfc
Copy link
Copy Markdown
Owner

@jaylfc jaylfc commented Apr 20, 2026

Summary

Extends the shell cross-app drag-drop primitive (#239) to cover three more wirings, closing the second half of the DnD rollout.

New drag sources

  • Messages — each message row gets a ⋮⋮ drag handle in the hover toolbar. Dragging publishes `{kind:"message", channel_id, message_id, author_id, excerpt}` + HTML5 `text/plain` ("@agent: excerpt") + `text/uri-list` (deep-link to the message).
  • Library — knowledge item rows become drag sources with `{kind:"knowledge", id, title, url}` + `text/plain` (title) + `text/uri-list` (if url present).

New drop target

  • TextEditorApp — accepts `message` + `knowledge` payloads. Inserts markdown at the cursor:
    • Message: quoted block + deep link (`> @author: excerpt\n>\n> Open in chat`)
    • Knowledge: `title` (or plain title if no url)

Implementation notes

  • `MessageHoverActions` gained an optional `dragHandle` render slot. No breaking change.
  • `LibraryApp` uses a `KnowledgeItemDragWrapper` subcomponent to satisfy hooks-in-loops. Mobile + desktop lists both wired.
  • `TextEditorApp`'s `MarkdownEditor` is now `React.forwardRef` exposing `insertAtCursor(text)` so the parent drop target can write into the CodeMirror view at cursor.

Test plan

  • Frontend: 297/300 (3 pre-existing snap-zones unrelated).
  • Backend: 786/787 (1 pre-existing Mac-arm hardware test unrelated).
  • Bundle rebuilt.
  • Manual: drag a message onto the text editor and see markdown quote inserted; drag a library item into chat composer; drag a message into another chat channel (cross-channel forward — still routes via existing file drop path, message drop in chat target would need separate wiring).

Follow-ups (not in this PR)

  • No CanvasApp exists in the codebase yet — skipped.
  • Message-source → chat-target (forward to another channel) — not wired; today you'd need a cross-channel drop target on MessagesApp. Add with the other channel composer work.
  • Touch long-press drag on mobile.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added drag-and-drop support for knowledge items and messages directly into the text editor
    • Knowledge items and messages now display draggable handles for seamless integration
  • Improvements

    • Simplified chat interface by removing in-app Help Panel and "All threads" panel
    • Chat guide now accessible as an external link

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b89bebf0-5e5e-4eed-8ac8-d1dafe839788

📥 Commits

Reviewing files that changed from the base of the PR and between bf27dbe and 3b1bb71.

📒 Files selected for processing (47)
  • desktop/src/apps/LibraryApp.tsx
  • desktop/src/apps/MessagesApp.tsx
  • desktop/src/apps/TextEditorApp.tsx
  • desktop/src/apps/chat/MessageHoverActions.tsx
  • static/desktop/assets/FilesApp-DpnvIlme.js
  • static/desktop/assets/FilesApp-hHoWf0qk.js
  • static/desktop/assets/LibraryApp-B3Qs_vI3.js
  • static/desktop/assets/LibraryApp-BD1Wtjm7.js
  • static/desktop/assets/MCPApp-H2J5boA9.js
  • static/desktop/assets/MessagesApp-DUf1SE96.js
  • static/desktop/assets/ProvidersApp-CZ2Evm5X.js
  • static/desktop/assets/SettingsApp-BFimPgYE.js
  • static/desktop/assets/TextEditorApp-B1gGb1kQ.js
  • static/desktop/assets/chat-R1TWzDnn.js
  • static/desktop/assets/dnd-bus-CVZcw0P6.js
  • static/desktop/assets/index-B-i367VX.js
  • static/desktop/assets/index-B9J0eMlg.js
  • static/desktop/assets/index-BCptoF-3.js
  • static/desktop/assets/index-BEv-dcGk.js
  • static/desktop/assets/index-BMX3OI1B.js
  • static/desktop/assets/index-BNNBySNU.js
  • static/desktop/assets/index-BbkpXBNy.js
  • static/desktop/assets/index-BjF_tFpD.js
  • static/desktop/assets/index-Bm3UY28S.js
  • static/desktop/assets/index-Bs5JT6mG.js
  • static/desktop/assets/index-By3Mzjc4.js
  • static/desktop/assets/index-CRWv8a-3.js
  • static/desktop/assets/index-Crp4FTaY.js
  • static/desktop/assets/index-DMFyin8A.js
  • static/desktop/assets/index-DTZBLne8.js
  • static/desktop/assets/index-DUWvMC11.js
  • static/desktop/assets/index-DYziI-B-.js
  • static/desktop/assets/index-DuDKTnwy.js
  • static/desktop/assets/index-Dw_yo5I1.js
  • static/desktop/assets/index-EGXegujk.js
  • static/desktop/assets/index-HCqzTdtf.js
  • static/desktop/assets/index-OlIDYpbO.js
  • static/desktop/assets/index-TacK6wxg.js
  • static/desktop/assets/index-o7Ll8rKG.js
  • static/desktop/assets/main-BpjQDe-1.js
  • static/desktop/assets/tokens-5I7LQC7l.js
  • static/desktop/assets/tokens-BCNCV_Mq.css
  • static/desktop/assets/use-drag-source-t6Ma6rgI.js
  • static/desktop/assets/use-drop-target-DMliBCfi.js
  • static/desktop/assets/vendor-codemirror-DhKtWjws.js
  • static/desktop/chat.html
  • static/desktop/index.html

📝 Walkthrough

Walkthrough

This PR implements drag-and-drop functionality across the application. It adds drag sources to library knowledge items and chat messages, enables a drop target in the text editor that accepts both payload types, and converts dropped content into appropriately formatted Markdown. The editor now exposes an imperative insertAtCursor method via React.forwardRef.

Changes

Cohort / File(s) Summary
DnD Source Components
desktop/src/apps/LibraryApp.tsx, desktop/src/apps/MessagesApp.tsx, desktop/src/apps/chat/MessageHoverActions.tsx
Added drag-source wiring: KnowledgeItemDragWrapper calls useDragSource with { kind: "knowledge", id, title, url } payload and htmlMirror mapping; MessageHoverActions accepts optional dragHandle prop; message hover actions compute excerpts and call startDrag/endDrag with message metadata and deep-link URL.
DnD Drop Target & Editor Refactor
desktop/src/apps/TextEditorApp.tsx
Converted MarkdownEditor to React.forwardRef<MarkdownEditorHandle> exposing imperative insertAtCursor(text) method; wired useDropTarget handler accepting "message" and "knowledge" payloads, converts them to Markdown (blockquote with link for messages, link or title for knowledge), and inserts via ref; added drop-state styling (dropHandlers, accent ring).
Removed UI Features
desktop/src/apps/MessagesApp.tsx
Removed ephemeral TTL display, in-app Help Panel and "All threads" panels; converted "chat guide" to external link.
Build Artifacts - Rebuilt App Bundles
static/desktop/assets/LibraryApp-B3Qs_vI3.js, static/desktop/assets/MessagesApp-DUf1SE96.js
New compiled bundles exporting LibraryApp and MessagesApp components with integrated DnD logic and UI changes.
Build Artifacts - Deleted Bundles
static/desktop/assets/FilesApp-DpnvIlme.js, static/desktop/assets/LibraryApp-BD1Wtjm7.js, static/desktop/assets/index-BEv-dcGk.js (Vue), static/desktop/assets/index-DTZBLne8.js (PHP), static/desktop/assets/index-DUWvMC11.js (Liquid), static/desktop/assets/index-Crp4FTaY.js (Angular)
Removed outdated asset bundles (replaced/consolidated with newer versions).
Build Artifacts - CodeMirror Language Modules
static/desktop/assets/index-B-i367VX.js (Angular), static/desktop/assets/index-BMX3OI1B.js (Jinja), static/desktop/assets/index-BNNBySNU.js (Sass), static/desktop/assets/index-Bm3UY28S.js (PHP), static/desktop/assets/index-CRWv8a-3.js (Vue)
New CodeMirror language support bundles for Angular, Jinja, Sass, PHP, and Vue templating with tokenization and completion logic.
Build Artifacts - Vendor Updates
static/desktop/assets/index-BCptoF-3.js, static/desktop/assets/index-BbkpXBNy.js, static/desktop/assets/index-BjF_tFpD.js, static/desktop/assets/index-Bs5JT6mG.js, static/desktop/assets/index-By3Mzjc4.js, static/desktop/assets/index-DMFyin8A.js, static/desktop/assets/index-DYziI-B-.js
Updated CodeMirror vendor dependency imports from vendor-codemirror-aNcHammg.js to vendor-codemirror-DhKtWjws.js across Python, YAML, Java, Wast, Kotlin, XML, and Markdown language bundles.
Build Artifacts - Module Registration & Entry Points
static/desktop/assets/dnd-bus-CVZcw0P6.js, static/desktop/assets/chat-R1TWzDnn.js, static/desktop/assets/MCPApp-H2J5boA9.js, static/desktop/assets/ProvidersApp-CZ2Evm5X.js, static/desktop/assets/SettingsApp-BFimPgYE.js
Updated module import paths, dependency hashes, and __vite__mapDeps mappings to reflect new asset filenames and added use-drop-target-DMliBCfi.js chunk; remapped dnd-bus exports (swapped setter and listener function export names).

Sequence Diagram

sequenceDiagram
    actor User
    participant LibraryApp
    participant MessageHoverActions
    participant DnDBus as DnD Bus
    participant TextEditorApp
    participant CodeMirror

    User->>LibraryApp: Drag knowledge item
    LibraryApp->>DnDBus: useDragSource({ kind: "knowledge", id, title, url })
    DnDBus->>DnDBus: Set htmlMirror (text/plain, text/uri-list)
    DnDBus->>DnDBus: startDrag() event

    User->>MessageHoverActions: Drag message via handle
    MessageHoverActions->>DnDBus: useDragSource({ kind: "message", channel_id, excerpt, url })
    DnDBus->>DnDBus: Set htmlMirror (blockquote + link)
    DnDBus->>DnDBus: startDrag() event

    User->>TextEditorApp: Drop over editor
    TextEditorApp->>DnDBus: useDropTarget listener
    DnDBus->>TextEditorApp: Emit payload (kind, data)
    TextEditorApp->>TextEditorApp: Convert to Markdown
    TextEditorApp->>CodeMirror: editorRef.insertAtCursor(markdown)
    CodeMirror->>User: Text inserted at cursor
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #239: Introduces the core DnD primitives (useDragSource, useDropTarget, startDrag, endDrag, and DragPayload types) that this PR applies across multiple components.
  • PR #242: Implements the identical DnD integrations across LibraryApp, MessagesApp, TextEditorApp, and related components with matching drag/drop payload handling.
  • PR #241: Adds UI features to the Messages app (Help Panel, All Threads panels) that are removed in this PR, representing a conflicting scope change.

Poem

🐰 A rabbit drags knowledge through the air,
Messages dance from chat to editor's care,
Drop them in, they transform to prose,
Text flows freely where it goes!
Hop, drag, drop—the DnD flow,
Building links wherever you go! 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.10% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Shell DnD extensions: Messages source, Library source, TextEditor target' clearly and specifically summarizes the main change—adding drag-and-drop extensions to three app components. It is concise, directly related to the changeset, and provides meaningful information about the primary additions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/shell-dnd-extensions

Comment @coderabbitai help to get the list of available commands and usage tips.

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot Bot commented Apr 20, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 2
SUGGESTION 0
Issue Details (click to expand)

CRITICAL

File Line Issue Status
desktop/src/apps/TextEditorApp.tsx 339 Same editorRef is used for both sidebar and main MarkdownEditor instances. Only the last rendered editor will work with insertAtCursor when both are mounted (non-mobile view). This will break drag & drop functionality on desktop devices. Unresolved

WARNING

File Line Issue Status
desktop/src/apps/TextEditorApp.tsx 387 Duplicate ref usage for MarkdownEditor. Both sidebar and main editor instances point to the same ref. When both render simultaneously (desktop view), only the last one will have the ref properly set, causing drag & drop operations to fail on the first instance. Unresolved
desktop/src/apps/MessagesApp.tsx 1529 e.stopPropagation() on dragStart prevents parent drop targets from receiving this event. This may prevent global drop handlers from working correctly. Unresolved
Files Reviewed (5 files)
  • desktop/src/apps/LibraryApp.tsx - No issues
  • desktop/src/apps/MessagesApp.tsx - 1 issue
  • desktop/src/apps/TextEditorApp.tsx - 2 issues
  • desktop/src/apps/chat/MessageHoverActions.tsx - No issues
  • static/desktop/assets/* - Generated files skipped

Fix these issues in Kilo Cloud


Reviewed by seed-2-0-pro-260328 · 235,685 tokens

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
desktop/src/apps/TextEditorApp.tsx (1)

232-245: Consider adding type guards for payload properties.

The onDrop handler accesses payload properties (channel_id, message_id, author_id, excerpt, title, url) without type narrowing beyond payload.kind. While the accept array filters valid payloads, adding explicit type definitions would improve maintainability and catch integration issues early.

💡 Optional: Define payload types
interface MessagePayload {
  kind: "message";
  channel_id: string;
  message_id: string;
  author_id: string;
  excerpt: string;
}

interface KnowledgePayload {
  kind: "knowledge";
  id: string;
  title: string;
  url?: string;
}

type DropPayload = MessagePayload | KnowledgePayload;

// Then in onDrop:
onDrop(payload: DropPayload) {
  // TypeScript will now narrow based on kind check
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@desktop/src/apps/TextEditorApp.tsx` around lines 232 - 245, Declare explicit
discriminated union types for the drop payload (e.g., MessagePayload with kind:
"message" and fields channel_id, message_id, author_id, excerpt;
KnowledgePayload with kind: "knowledge" and fields id, title, url?) and a
DropPayload = MessagePayload | KnowledgePayload, then annotate the onDrop
parameter in the useDropTarget call as (payload: DropPayload) so TypeScript
narrows by payload.kind inside the onDrop handler; update references in onDrop
(the branch for "message" should use MessagePayload properties and the
"knowledge" branch should use KnowledgePayload properties) and keep the final
editorRef.current?.insertAtCursor(text) call unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@desktop/src/apps/TextEditorApp.tsx`:
- Around line 232-245: Declare explicit discriminated union types for the drop
payload (e.g., MessagePayload with kind: "message" and fields channel_id,
message_id, author_id, excerpt; KnowledgePayload with kind: "knowledge" and
fields id, title, url?) and a DropPayload = MessagePayload | KnowledgePayload,
then annotate the onDrop parameter in the useDropTarget call as (payload:
DropPayload) so TypeScript narrows by payload.kind inside the onDrop handler;
update references in onDrop (the branch for "message" should use MessagePayload
properties and the "knowledge" branch should use KnowledgePayload properties)
and keep the final editorRef.current?.insertAtCursor(text) call unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d03cc5e8-1b62-4e10-af3e-3f4a11a95625

📥 Commits

Reviewing files that changed from the base of the PR and between 3ba7668 and bf27dbe.

📒 Files selected for processing (49)
  • desktop/src/apps/LibraryApp.tsx
  • desktop/src/apps/MessagesApp.tsx
  • desktop/src/apps/TextEditorApp.tsx
  • desktop/src/apps/chat/MessageHoverActions.tsx
  • static/desktop/assets/FilesApp-DpnvIlme.js
  • static/desktop/assets/FilesApp-hHoWf0qk.js
  • static/desktop/assets/LibraryApp-B3Qs_vI3.js
  • static/desktop/assets/LibraryApp-BD1Wtjm7.js
  • static/desktop/assets/MCPApp-X5Od8JcZ.js
  • static/desktop/assets/MessagesApp-CkhTvSE9.js
  • static/desktop/assets/MessagesApp-DQEnD9za.js
  • static/desktop/assets/ProvidersApp-DXGqum2f.js
  • static/desktop/assets/SettingsApp-gwQ4lLOZ.js
  • static/desktop/assets/TextEditorApp-B1gGb1kQ.js
  • static/desktop/assets/chat-CwQLh7dR.js
  • static/desktop/assets/dnd-bus-CVZcw0P6.js
  • static/desktop/assets/index-B-i367VX.js
  • static/desktop/assets/index-B9J0eMlg.js
  • static/desktop/assets/index-BCptoF-3.js
  • static/desktop/assets/index-BEv-dcGk.js
  • static/desktop/assets/index-BMX3OI1B.js
  • static/desktop/assets/index-BNNBySNU.js
  • static/desktop/assets/index-BbkpXBNy.js
  • static/desktop/assets/index-BjF_tFpD.js
  • static/desktop/assets/index-Bm3UY28S.js
  • static/desktop/assets/index-Bs5JT6mG.js
  • static/desktop/assets/index-By3Mzjc4.js
  • static/desktop/assets/index-CRWv8a-3.js
  • static/desktop/assets/index-Crp4FTaY.js
  • static/desktop/assets/index-DMFyin8A.js
  • static/desktop/assets/index-DTZBLne8.js
  • static/desktop/assets/index-DUWvMC11.js
  • static/desktop/assets/index-DYziI-B-.js
  • static/desktop/assets/index-DuDKTnwy.js
  • static/desktop/assets/index-Dw_yo5I1.js
  • static/desktop/assets/index-EGXegujk.js
  • static/desktop/assets/index-HCqzTdtf.js
  • static/desktop/assets/index-OlIDYpbO.js
  • static/desktop/assets/index-TacK6wxg.js
  • static/desktop/assets/index-o7Ll8rKG.js
  • static/desktop/assets/main-DL8nigqD.js
  • static/desktop/assets/main-FOmUFQfu.js
  • static/desktop/assets/tokens-D7VjNhnz.js
  • static/desktop/assets/tokens-DzPH3AJU.css
  • static/desktop/assets/use-drag-source-t6Ma6rgI.js
  • static/desktop/assets/use-drop-target-DMliBCfi.js
  • static/desktop/assets/vendor-codemirror-DhKtWjws.js
  • static/desktop/chat.html
  • static/desktop/index.html
💤 Files with no reviewable changes (7)
  • static/desktop/assets/index-Crp4FTaY.js
  • static/desktop/assets/index-BEv-dcGk.js
  • static/desktop/assets/LibraryApp-BD1Wtjm7.js
  • static/desktop/assets/FilesApp-DpnvIlme.js
  • static/desktop/assets/index-DUWvMC11.js
  • static/desktop/assets/index-DTZBLne8.js
  • static/desktop/assets/MessagesApp-CkhTvSE9.js

…arget

- MessageHoverActions gains optional dragHandle slot
- MessagesApp adds a ⋮⋮ drag handle in the hover toolbar per message;
  publishes {kind:"message", channel_id, message_id, author_id, excerpt}
  + text/plain + text/uri-list mirrors
- LibraryApp knowledge items become drag sources via KnowledgeItemDragWrapper
  ({kind:"knowledge", id, title, url} + text/plain/uri-list)
- TextEditorApp (CodeMirror) accepts message + knowledge drops;
  MarkdownEditor exposes insertAtCursor via forwardRef so the parent drop
  target can write markdown at the caret
@jaylfc jaylfc force-pushed the feat/shell-dnd-extensions branch from bf27dbe to 3b1bb71 Compare April 20, 2026 14:13
@jaylfc jaylfc merged commit f735537 into master Apr 20, 2026
7 of 8 checks passed
@jaylfc jaylfc deleted the feat/shell-dnd-extensions branch April 25, 2026 17:58
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.

1 participant