Skip to content

feat(macOS): 统一文件与终端标签拖拽及双向停靠 - #228

Merged
1lck merged 7 commits into
preview/0.3.0from
fix/issue-226
Aug 22, 2026
Merged

feat(macOS): 统一文件与终端标签拖拽及双向停靠#228
1lck merged 7 commits into
preview/0.3.0from
fix/issue-226

Conversation

@xiaoyumuxi

Copy link
Copy Markdown
Collaborator

变更说明

统一编辑器中的文件标签和终端标签模型,使两类标签能够共享顺序并进行混合重排。

Closes #226

主要改动

  • 新增统一的 EditorTabItem 和标签顺序模型
  • 支持文件标签与终端标签混合排列
  • 支持终端标签向左、向右拖动重排
  • 标签栏内使用横向吸附效果和插入位置指示线
  • 终端从工具窗口拖入编辑器时,只有进入标签栏才会触发停靠
  • 支持将编辑器终端拖回终端工具窗口
  • 编辑器正文区域明确拒绝终端标签拖放
  • 移除编辑器终端“移回工具窗口”的右键菜单入口,统一使用拖拽操作
  • 修复终端停靠过程中原生 NSView 被旧容器移除,导致终端标签打开后内容空白的问题
  • 终端迁移和重排不会重建或停止已有终端会话

交互行为

工具窗口 → 编辑器

必须将终端拖入编辑器标签栏才会完成停靠,拖入编辑器正文区域不会触发。

编辑器标签栏内部

终端标签只能沿标签栏横向重排,并显示目标位置的吸附和插入线。

编辑器 → 工具窗口

将终端标签拖入终端工具窗口即可恢复为工具窗口终端。

验证

已手动验证:

  • 文件标签可以正常重排
  • 终端标签可以向左、向右重排
  • 文件标签和终端标签可以混合排列
  • 工具窗口终端可以拖入编辑器标签栏
  • 拖入编辑器正文不会触发停靠
  • 编辑器终端可以拖回终端工具窗口
  • 终端双向迁移后仍可正常显示和输入
  • 多终端切换时不会出现原生终端视图空白

自动化测试未运行。

提交拆分

  1. feat(editor): 统一文件与终端标签顺序
  2. fix(editor): 限制终端仅拖入编辑器标签栏
  3. feat(editor): 支持文件与终端标签横向吸附重排
  4. fix(terminal): 恢复拖回终端工具窗口
  5. fix(terminal): 停靠时保留终端原生视图

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.

🟡 Changes recommended

TerminalTabDragPayload.loadSessionID currently uses MainActor.assumeIsolated, which can trap if invoked off the MainActor (drop callbacks aren’t guaranteed to be MainActor-isolated).

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR introduces a unified “mixed” editor tab ordering model on macOS so document tabs and editor-terminal tabs can share a single sequence, enabling cross-type reordering and bidirectional docking between the editor tab strip and the Terminal tool window.

Changes:

  • Added EditorTabItem + EditorTabOrderFeatureModel to own a mixed [document|terminal] tab order, and wired it into AppModel for reconciliation/reordering.
  • Reworked editor tab interactions to support horizontal snap reordering and insertion indicators, plus refined drop acceptance (tab bar accepts terminal drops; editor text area rejects terminal drops).
  • Hardened terminal view hosting during moves to prevent the native terminal NSView from being detached by stale container updates, and expanded test coverage for the new ordering behavior.
File summaries
File Description
Tests/LitheTests/TerminalPlacementFeatureModelTests.swift Adds coverage for reconciling editor-terminal order against mixed tab projection.
Tests/LitheTests/LitheCoreLogicTests.swift Updates CodeTextView drag/drop expectations to ensure terminal-tab drops are rejected.
Tests/LitheTests/EditorTabOrderFeatureModelTests.swift New suite validating mixed document/terminal ordering semantics.
Tests/LitheTests/EditorTabLayoutTests.swift Expands drag payload + drop-geometry coverage for the new tab behaviors.
Sources/Lithe/Views/Terminal/TerminalView.swift Enables dropping editor-terminal tabs back into the Terminal tool window.
Sources/Lithe/Views/Terminal/TerminalTabDragPayload.swift Adjusts provider + load semantics for terminal-tab drags (process-local resolution).
Sources/Lithe/Views/Terminal/TerminalSurfaceView.swift Keeps the native terminal view attached correctly across container moves.
Sources/Lithe/Views/Editor/EditorTabFlowLayout.swift Extends tab drag state to support non-document items + shared drop geometry rules.
Sources/Lithe/Views/Editor/EditorAreaView.swift Implements mixed tab rendering, horizontal snap reordering, and refined drop targeting.
Sources/Lithe/Views/Editor/CodeEditorView.swift Removes terminal-tab drop handling from the code editor text view.
Sources/Lithe/Models/Editor/EditorTabItem.swift New shared identifier for mixed editor tab items.
Sources/Lithe/Models/AppModel/AppModel+Terminal.swift Integrates terminal moves with the mixed tab order model.
Sources/Lithe/Models/AppModel/AppModel+FeatureState.swift Introduces moveEditorTab and routes document moves through mixed ordering.
Sources/Lithe/Models/AppModel/AppModel.swift Adds EditorTabOrderFeatureModel and reconciles it with the document collection.
Sources/Lithe/Application/Features/TerminalPlacementFeatureModel.swift Adds editor-session reordering reconciliation.
Sources/Lithe/Application/Features/EditorTabOrderFeatureModel.swift New feature model owning the mixed tab presentation order.
Sources/Lithe/Application/Features/DocumentFeatureModel.swift Adds reorderDocuments(orderedIDs:) to apply mixed-order document sequences.
Review details
  • Files reviewed: 17/17 changed files
  • Comments generated: 2
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +48 to +57
guard !providers.isEmpty else { return false }
// Terminal tab drags are process-local and only one native drag can be
// active at a time. Resolve that identity immediately so a promised
// representation cannot turn a valid drop into a silent no-op.
if let sessionID = activeDrag.sessionID {
MainActor.assumeIsolated {
completion(sessionID)
}
return true
}
Comment on lines +14 to +16
// AppKit needs a concrete standard representation to establish the
// native drag session. CodeTextView explicitly rejects providers that
// also advertise the private terminal-tab type.
@xiaoyumuxi

Copy link
Copy Markdown
Collaborator Author
image 支持文件还有终端的乱序重排操作 image 将识别的区域从原来的全部页面变成仅仅 Tab 标签栏

@1lck
1lck merged commit 9129aee into preview/0.3.0 Aug 22, 2026
15 checks passed
@xiaoyumuxi xiaoyumuxi linked an issue Aug 22, 2026 that may be closed by this pull request
15 tasks
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.

[Feature] 支持编辑器文件与终端标签统一混排和任意拖拽排序

3 participants