Skip to content

feat: allow chip click to open doc or history tab#1475

Merged
zhouyu123666 merged 2 commits intochaterm:mainfrom
dsd2077:main
Jan 23, 2026
Merged

feat: allow chip click to open doc or history tab#1475
zhouyu123666 merged 2 commits intochaterm:mainfrom
dsd2077:main

Conversation

@dsd2077
Copy link
Contributor

@dsd2077 dsd2077 commented Jan 22, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Added drag-and-drop support for documents, chats, and hosts directly into the message input area.
    • Enabled interactive chips—clicking document or chat references now navigates to the relevant context or history.
    • Made chat tabs draggable to easily reference conversation context.
  • Tests

    • Added comprehensive test coverage for drag-and-drop payload parsing and chip interaction workflows.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 22, 2026

📝 Walkthrough

Walkthrough

This PR implements drag-and-drop functionality for document and chat chips within the AI Tab editor. Users can drag docs, chats, and hosts into the input area, with payloads parsed and converted to chips. Chip clicks trigger navigation via handlers that manage document opening and history tab restoration. Path normalization and event-based signaling coordinate interactions between composables and components.

Changes

Cohort / File(s) Summary
Core InputSendContainer Component
src/renderer/src/views/components/AiTab/components/InputSendContainer.vue
Added drag-and-drop handling via handleEditableDrop function; processes doc, chat, and host payloads. Introduced openHistoryTab prop to enable history tab restoration. Added resolveKbAbsPath helper for path normalization. Extended context usage to expose onHostClick and integrated handleChipClick callback into useEditableContent. Minor UI: cursor pointer on mention chips.
Context Composable
src/renderer/src/views/components/AiTab/composables/useContext.ts
Introduced openDocFromChip function to handle doc chip interactions by resolving relative paths and emitting openUserTab events. Added ContextDocRef type import and path normalization helpers. Exposed handler in public API for chip-click scenarios.
Editable Content Composable
src/renderer/src/views/components/AiTab/composables/useEditableContent.ts
Added drag-payload parsing via parseContextDragPayload function supporting custom MIME and text fallback formats. Introduced ContextDragPayload discriminated type for doc, chat, and host contexts. Extended UseEditableContentOptions with handleChipClick callback. Wired chip click handling to invoke callback for doc and chat chip interactions. Added title attributes to chips for accessibility.
Tab Management Composable
src/renderer/src/views/components/AiTab/composables/useTabManagement.ts
Extended restoreHistoryTab signature to accept optional forceNewTab flag, conditionally creating a new tab instead of replacing the current one when flag is set.
Test Coverage
src/renderer/src/views/components/AiTab/composables/__tests__/useContext.test.ts, useEditableContent.test.ts, useTabManagement.test.ts
Added comprehensive test suites covering doc chip opening, chip click interactions, drag payload parsing for doc/chat/host contexts, and force-new-tab behavior in tab restoration.
Parent Component Wiring
src/renderer/src/views/components/AiTab/index.vue
Wired tab drag-start handler to emit chat context payloads from tab titles. Imported context drag constants. Bound open-history-tab prop to InputSendContainer.
Terminal Layout Integration
src/renderer/src/views/layouts/TerminalLayout.vue
Added setupTabDragToAi to configure drag payloads for tabs: KnowledgeCenterEditor tabs emit doc payloads with relative paths; host/terminal tabs emit host payloads with connection metadata. Invoked during dock ready lifecycle.

Sequence Diagram

sequenceDiagram
    actor User
    participant TerminalTab as Terminal/KB Tab
    participant EditableArea as InputSendContainer<br/>(Editable Area)
    participant EditableComposable as useEditableContent
    participant ContextComposable as useContext
    participant TabMgmt as useTabManagement
    participant EventBus as EventBus

    User->>TerminalTab: Drag tab (doc or host)
    TerminalTab->>EditableArea: dataTransfer with<br/>context payload
    User->>EditableArea: Drop on input area
    EditableArea->>EditableArea: handleEditableDrop()
    EditableArea->>EditableComposable: parseContextDragPayload()
    EditableComposable-->>EditableArea: ContextDragPayload<br/>(doc/chat/host)
    EditableArea->>EditableArea: Insert chip element
    
    User->>EditableArea: Click on doc/chat chip
    EditableArea->>EditableComposable: handleChipClick()
    EditableComposable-->>EditableArea: callback invoked
    alt Doc Chip
        EditableArea->>ContextComposable: openDocFromChip(docRef)
        ContextComposable->>ContextComposable: Resolve KB root & relPath
        ContextComposable->>EventBus: emit openUserTab
        EventBus->>TerminalTab: Navigate to KB Editor
    else Chat Chip
        EditableArea->>TabMgmt: openHistoryTab(history)
        TabMgmt->>TabMgmt: Check forceNewTab flag
        TabMgmt-->>EditableArea: New tab created/restored
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 Hoppity drops and chips do click,
Drag from tabs—the code's so slick!
Paths resolve from root to deep,
Chats and docs in storage keep. 🎯📄

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: enabling chip click interactions to open documentation or history tabs, which aligns with the main functionality added across multiple components.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@codecov
Copy link

codecov bot commented Jan 22, 2026

Copy link
Contributor

@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.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/renderer/src/views/components/AiTab/composables/useContext.ts`:
- Around line 866-880: The openDocFromChip function emits the event
'openUserTab' but the app listens for 'open-user-tab', causing clicks to no-op;
update openDocFromChip to emit 'open-user-tab' (preserving payload shape) so it
matches the listener (or alternatively change the listener to 'openUserTab') and
also update the test expectation in useContext.test.ts to the chosen event name;
ensure references to the event key in eventBus.emit inside openDocFromChip and
any related tests are consistent.

In `@src/renderer/src/views/components/AiTab/index.vue`:
- Around line 12-18: handleTabDragStart is serializing a drag payload using
tab.title which can be undefined and later fails parseContextDragPayload
expecting a string title; update handleTabDragStart (and any other drag-start
handlers for tabs) to ensure the payload always includes a string title by
providing a fallback (e.g., tab.title || '' or tab.title || 'Untitled') before
serializing so parseContextDragPayload will accept it on drop.

In `@src/renderer/src/views/layouts/TerminalLayout.vue`:
- Around line 2230-2238: In TerminalLayout.vue update the dragPayload
construction so the connect property uses an explicit connection type instead of
falling back to params.ip: use data.connect or data.connectionType (or a safe
default like 'ssh' or null) and remove the params.ip fallback; modify the
dragPayload creation near the host context block (the object with keys
contextType, uuid, label, connect, assetType, isLocalHost) to read connect:
data.connect || data.connectionType || 'ssh' (or null) so chips always receive a
connection-type string rather than an IP.
- Around line 2215-2217: The code uses a loose Record<string, any> for panel
params which defeats TS safety; define a DockviewPanelParams interface (or type)
listing the expected fields: content, title, ip, organizationId, id, props, and
data, then replace the cast in TerminalLayout.vue so const params = panel.params
as DockviewPanelParams | undefined; update any usages in this file to rely on
those typed fields (e.g., content, title, ip, organizationId, id, props, data)
to restore type checking and avoid any implicit any.
♻️ Duplicate comments (1)
src/renderer/src/views/components/AiTab/composables/__tests__/useContext.test.ts (1)

268-287: Expectation should track the final event name.
Keep this assertion aligned with the emitter name finalized in useContext.ts.

🧹 Nitpick comments (1)
src/renderer/src/views/components/AiTab/components/InputSendContainer.vue (1)

343-347: Remove the commented-out dragover handler or wire it up

Commented blocks tend to rot; either connect it via @dragover or delete it.

Proposed cleanup
-// const handleEditableDragOver = (e: DragEvent) => {
-//   const dragPayload = parseContextDragPayload(e.dataTransfer)
-//   if (!dragPayload) return
-//   e.preventDefault()
-// }

@zhouyu123666 zhouyu123666 merged commit f59fc06 into chaterm:main Jan 23, 2026
7 checks passed
@github-actions
Copy link

❤️ Great PR @dsd2077 ❤️

Thank you for your contribution to Chaterm! The growth of this project is inseparable from community feedback and contributions like yours.

We appreciate your time and effort in making Chaterm better! 🎉

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.

2 participants