Skip to content

feat: 隐藏wegent button;文件无法上传问题修复;支持文件拖拽 - #1458

Merged
qdaxb merged 6 commits into
wecode-ai:mainfrom
Micro66:human/toucan-20260617-052434
Jun 18, 2026
Merged

qdaxb merged 6 commits into
wecode-ai:mainfrom
Micro66:human/toucan-20260617-052434

Conversation

@Micro66

@Micro66 Micro66 commented Jun 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Desktop chat composer now supports both browser drag-and-drop and native file drops (where available).
    • Branch selector and related floating menus now dynamically choose above/below placement and adjust max height to stay within the viewport.
  • Improvements

    • Attachment upload/deletion is more consistent across runtimes, with centralized response mapping and reliable progress updates.
    • Apps page layout and quick-entry recommendations have been updated (including refreshed icons and counts).
  • Tests

    • Added coverage for responsive /apps layout, attachment API behavior, chat input dropped files, and branch menu sizing/behavior.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 785fcf5f-daf8-41c4-bf16-0d46c382909b

📥 Commits

Reviewing files that changed from the base of the PR and between 5dea63d and 5c745ac.

📒 Files selected for processing (1)
  • wework/src-tauri/tauri.conf.json
✅ Files skipped from review due to trivial changes (1)
  • wework/src-tauri/tauri.conf.json

📝 Walkthrough

Walkthrough

Adds native and browser file drag-and-drop to the Tauri desktop chat composer via a new Rust read_dropped_files command and frontend handlers. Introduces a floating-menu positioning utility used by BranchSelector and WorktreeBranchSelector for dynamic menu placement. Refactors the attachments API to route through the shared HTTP client with conditional Tauri paths. Updates AppsPage breakpoints, CTA navigation, recommended apps list, and summary card values.

Changes

Desktop file drop, dynamic floating menus, and attachment API

Layer / File(s) Summary
Floating menu positioning library
wework/src/lib/floating-menu.ts
New module exports FloatingMenuPlacement type ('above' | 'below'), FloatingMenuBoundsinterface,getFloatingMenuVisibleBounds(DOM-walk function that inspects parent overflow styles and computes constrained bounds), andcalculateFloatingMenuLayout` (chooses placement and clamps maxHeight based on available space).
Dynamic positioning in BranchSelector and WorktreeBranchSelector
wework/src/components/common/BranchSelector.tsx, wework/src/components/chat/composer/WorktreeBranchSelector.tsx
Both selectors add desktopMenuLayout state (placement + maxHeight), updateDesktopMenuLayout callbacks measuring trigger and visible bounds, and dual effects (useLayoutEffect on open + resize/scroll listeners) to keep floating menu position and height current. Popover containers use placement-dependent positioning and inline maxHeight from state. Menu markup refactored for mobile vs desktop layout consistency.
Tauri backend: read_dropped_files command and window config
wework/src-tauri/src/lib.rs, wework/src-tauri/tauri.conf.json, wework/scripts/dev-mac-app.sh
Adds DroppedFilePayload struct and read_dropped_files Tauri command (validates paths, derives UTF-8 filenames, reads file bytes, returns per-file errors). Sets dragDropEnabled: true in window config. Appends --strictPort to Vite dev command.
HTTP client export and attachments API refactor
wework/src/api/http.ts, wework/src/api/attachments.ts
Exports shouldUseTauriFetch for external use. Adds UploadAttachmentResponse type and toAttachmentResponse helper (defaults subtask_id, file_extension, created_at). Refactors uploadAttachment to conditionally use createHttpClient for Tauri with FormData and 0%/100% progress. Migrates deleteAttachment from manual fetch to createHttpClient.delete.
ProjectChatComposer browser and native drag-and-drop
wework/src/components/chat/composer/ProjectChatComposer.tsx
Adds hasDraggedFiles predicate, NativeDroppedFile shape, readNativeDroppedFiles helper (invokes read_dropped_files, converts bytes to File). Implements handleDragOver/handleDrop browser DnD handlers and Tauri-gated useEffect listening for onDragDropEvent, reading files via invoke, forwarding to onFileSelect, with proper cleanup. Form element gains ref, onDragOver, onDrop props.
Tests
wework/src/components/chat/ChatInput.test.tsx, wework/src/api/attachments.test.ts, wework/src/test/macos-window-chrome.test.ts, wework/src/App.apps.test.tsx
Tests for browser file drop on composer, branch menu constrained maxHeight, attachment upload/delete API paths, macOS dragDropEnabled config assertion, and /apps responsive layout. Cleanup added for window.__TAURI_INTERNALS__ between tests.

AppsPage UI updates

Layer / File(s) Summary
AppsPage breakpoints, CTA, and app list
wework/src/pages/AppsPage.tsx
Responsive breakpoints changed from xl to md for sidebar, tabs, and grid. Hero CTA navigates to model proxy settings instead of Wegent. "Wegent Web" removed from recommended apps. "内置应用" count derived from recommendedApps.length. "快速入口" entry uses Cpu icon and Codex-style description.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Form
  participant ProjectChatComposer
  participant TauriRuntime
  participant readDroppedFiles as read_dropped_files<br/>(Rust)

  rect rgba(100, 149, 237, 0.5)
    Note over User, Form: Browser drag-and-drop path
    User->>Form: dragover event
    Form->>ProjectChatComposer: handleDragOver → set dropEffect='copy'
    User->>Form: drop event
    Form->>ProjectChatComposer: handleDrop → extract DataTransfer files
    ProjectChatComposer->>ProjectChatComposer: onFileSelect(files)
  end

  rect rgba(144, 238, 144, 0.5)
    Note over User, readDroppedFiles: Tauri native drop path
    User->>TauriRuntime: native file drop onto window
    TauriRuntime->>ProjectChatComposer: onDragDropEvent(payload.paths)
    ProjectChatComposer->>readDroppedFiles: invoke('read_dropped_files', {paths})
    readDroppedFiles-->>ProjectChatComposer: DroppedFilePayload[] {name, bytes}
    ProjectChatComposer->>ProjectChatComposer: convert bytes → File[]
    ProjectChatComposer->>ProjectChatComposer: onFileSelect(files)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • wecode-ai/Wegent#1177: Introduced ProjectChatComposer, which this PR extends with browser and native Tauri drag-and-drop file handling.
  • wecode-ai/Wegent#1301: Modifies wework/src/components/chat/composer/ProjectChatComposer.tsx for project mode integration, overlapping with the drag-and-drop changes in the same component.
  • wecode-ai/Wegent#1388: Added the initial AppsPage implementation and /apps routing that this PR modifies for breakpoints, CTA, and recommended apps list.

Suggested reviewers

  • qdaxb

🐇 A rabbit hops and drops a file,
Into the chat — now that's in style!
The menu floats above or below,
With breakpoints moved to md we go.
--strictPort keeps the Vite port right,
And bytes become Files overnight! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately covers the three main changes: hiding Wegent button, fixing file upload issue, and adding file drag-and-drop support.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
wework/src-tauri/src/lib.rs (1)

172-202: ⚡ Quick win

Consider adding a file size limit to prevent memory exhaustion.

The command reads entire files into memory without checking their size. The frontend defines MAX_FILE_SIZE = 100 * 1024 * 1024 (100 MB) in attachments.ts, but this backend command will happily load arbitrarily large files. A malicious or accidental drop of a very large file could exhaust memory.

🛡️ Suggested size check before reading
         let name = path
             .file_name()
             .and_then(|value| value.to_str())
             .map(String::from)
             .ok_or_else(|| "Dropped file name is invalid".to_string())?;
+        
+        const MAX_FILE_SIZE: u64 = 100 * 1024 * 1024; // 100 MB
+        let metadata = std::fs::metadata(&path)
+            .map_err(|error| format!("Failed to read file metadata for {name}: {error}"))?;
+        if metadata.len() > MAX_FILE_SIZE {
+            return Err(format!("File {name} exceeds maximum size of 100 MB"));
+        }
+        
         let bytes = std::fs::read(&path)
             .map_err(|error| format!("Failed to read dropped file {name}: {error}"))?;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src-tauri/src/lib.rs` around lines 172 - 202, The read_dropped_files
function reads entire files into memory without validating their size, which
could cause memory exhaustion with large files. Before calling
std::fs::read(&path), add a file size check by using std::fs::metadata to get
the file's size and compare it against a maximum file size limit (matching the
frontend's 100 MB limit defined in attachments.ts). If the file exceeds the
limit, return an appropriate error message instead of proceeding with the read
operation.
wework/src/components/chat/composer/ProjectChatComposer.tsx (1)

104-137: 💤 Low value

Stale disabled or onFileSelect may be captured in the event handler.

The onDragDropEvent callback captures disabled and onFileSelect from the closure, but these values are read inside an async event handler that persists across renders. If disabled or onFileSelect changes, the listener isn't re-registered until the effect re-runs (and the old listener is cleaned up).

This is mostly fine since the effect deps include both values, but there's a brief window where the old callback could fire with stale values before cleanup completes. Consider using refs for these values if this causes issues.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/components/chat/composer/ProjectChatComposer.tsx` around lines 104
- 137, The onDragDropEvent callback captures disabled and onFileSelect from the
closure, which can be stale if these props change. Create refs using useRef for
both disabled and onFileSelect values, then update these refs in a separate
useEffect that depends on these values. Inside the listenForNativeFileDrops
function within the onDragDropEvent callback, access disabled and onFileSelect
through their refs (using ref.current) instead of capturing them from the
closure. This ensures the event handler always uses the current values rather
than stale ones.
wework/src/api/attachments.ts (1)

48-55: 💤 Low value

Tauri upload path only reports 0% and 100% progress.

The Tauri fetch path doesn't support granular upload progress tracking, unlike the XHR path which reports actual progress. This is a known limitation of @tauri-apps/plugin-http. Users may experience a jump from 0% to 100% with no intermediate feedback for large files.

Consider documenting this limitation or showing an indeterminate progress indicator in the UI when running under Tauri.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@wework/src/api/attachments.ts` around lines 48 - 55, The Tauri fetch path in
the shouldUseTauriFetch() block currently only reports progress at 0% and 100%,
which is a limitation of the `@tauri-apps/plugin-http` library that doesn't
support granular upload progress tracking. Add a code comment above the
shouldUseTauriFetch() conditional block to document this limitation and explain
that the onProgress callback will only receive two events (0% and 100%) for
Tauri-based uploads. Optionally, consider using a special progress value or flag
to signal to the caller that the progress tracking is indeterminate when using
Tauri, so the UI can adapt accordingly (such as showing a loading spinner
instead of a progress bar).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@wework/src-tauri/tauri.conf.json`:
- Line 21: The configuration value for dragDropEnabled in tauri.conf.json is set
to false, but the test in macos-window-chrome.test.ts expects it to be true.
Given the test name 'enables native file drop events in the desktop webview'
indicates drag-drop should be enabled, update the dragDropEnabled configuration
from false to true to align with the test expectations and the intended
behavior.

In `@wework/src/components/common/BranchSelector.tsx`:
- Around line 165-169: The t() function calls in the BranchSelector component
(appearing at three locations with setError calls and other message assignments)
include inline fallback literals as the second parameter, which hides missing
translations from being detected. Remove the second string parameter (the
Chinese fallback text like '分支加载失败') from each t() call so they only pass the
translation key, and ensure those translation keys are properly added to the
locale files for all supported languages to provide the translations instead of
relying on inline fallbacks.

In `@wework/src/test/macos-window-chrome.test.ts`:
- Around line 34-40: The test assertion in the 'enables native file drop events
in the desktop webview' test is checking that mainWindow.dragDropEnabled is
true, but according to the drag-and-drop design, the webview drag-drop must be
disabled to allow Tauri native drop events to be handled consistently. Change
the expect statement for mainWindow.dragDropEnabled from toBe(true) to
toBe(false) to match the intended behavior where native file drop events are
enabled by disabling the webview's built-in drag-drop functionality.

---

Nitpick comments:
In `@wework/src-tauri/src/lib.rs`:
- Around line 172-202: The read_dropped_files function reads entire files into
memory without validating their size, which could cause memory exhaustion with
large files. Before calling std::fs::read(&path), add a file size check by using
std::fs::metadata to get the file's size and compare it against a maximum file
size limit (matching the frontend's 100 MB limit defined in attachments.ts). If
the file exceeds the limit, return an appropriate error message instead of
proceeding with the read operation.

In `@wework/src/api/attachments.ts`:
- Around line 48-55: The Tauri fetch path in the shouldUseTauriFetch() block
currently only reports progress at 0% and 100%, which is a limitation of the
`@tauri-apps/plugin-http` library that doesn't support granular upload progress
tracking. Add a code comment above the shouldUseTauriFetch() conditional block
to document this limitation and explain that the onProgress callback will only
receive two events (0% and 100%) for Tauri-based uploads. Optionally, consider
using a special progress value or flag to signal to the caller that the progress
tracking is indeterminate when using Tauri, so the UI can adapt accordingly
(such as showing a loading spinner instead of a progress bar).

In `@wework/src/components/chat/composer/ProjectChatComposer.tsx`:
- Around line 104-137: The onDragDropEvent callback captures disabled and
onFileSelect from the closure, which can be stale if these props change. Create
refs using useRef for both disabled and onFileSelect values, then update these
refs in a separate useEffect that depends on these values. Inside the
listenForNativeFileDrops function within the onDragDropEvent callback, access
disabled and onFileSelect through their refs (using ref.current) instead of
capturing them from the closure. This ensures the event handler always uses the
current values rather than stale ones.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7750c951-b141-46f2-a992-659733c8adad

📥 Commits

Reviewing files that changed from the base of the PR and between ae29121 and 5dea63d.

📒 Files selected for processing (14)
  • wework/scripts/dev-mac-app.sh
  • wework/src-tauri/src/lib.rs
  • wework/src-tauri/tauri.conf.json
  • wework/src/App.apps.test.tsx
  • wework/src/api/attachments.test.ts
  • wework/src/api/attachments.ts
  • wework/src/api/http.ts
  • wework/src/components/chat/ChatInput.test.tsx
  • wework/src/components/chat/composer/ProjectChatComposer.tsx
  • wework/src/components/chat/composer/WorktreeBranchSelector.tsx
  • wework/src/components/common/BranchSelector.tsx
  • wework/src/lib/floating-menu.ts
  • wework/src/pages/AppsPage.tsx
  • wework/src/test/macos-window-chrome.test.ts

Comment thread wework/src-tauri/tauri.conf.json Outdated
Comment thread wework/src/components/common/BranchSelector.tsx
Comment thread wework/src/test/macos-window-chrome.test.ts
@qdaxb
qdaxb merged commit 4591bf8 into wecode-ai:main Jun 18, 2026
24 checks passed
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