Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/components/LoginScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,24 @@ export const LoginScreen: React.FC = () => {
}
};

const handleKeyPress = (e: React.KeyboardEvent) => {
const handleKeyPress = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter' && !isLoading) {
handleConnect();
return;
}

// 兼容桌面端首次登录场景下 Ctrl/Cmd + V 无法触发默认粘贴的问题
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'v' && !isLoading) {
try {
const text = await navigator.clipboard.readText();
if (text) {
setToken(text.trim());
setError('');
}
Comment on lines +50 to +56

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.

⚠️ Potential issue | 🟠 Major

Missing e.preventDefault() may cause double paste behavior.

When the manual clipboard read succeeds, the browser's default paste also fires (via onChange), potentially causing a race condition between the async setToken(text.trim()) and the synchronous setToken(e.target.value) from onChange. This can lead to inconsistent state or the untrimmed value winning.

Call e.preventDefault() before the async clipboard read to suppress the default paste when handling it manually.

🐛 Proposed fix
     // 兼容桌面端首次登录场景下 Ctrl/Cmd + V 无法触发默认粘贴的问题
     if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'v' && !isLoading) {
+      e.preventDefault();
       try {
         const text = await navigator.clipboard.readText();
         if (text) {
           setToken(text.trim());
           setError('');
         }
       } catch (error) {
         // 忽略读取剪贴板失败,让浏览器/系统默认行为继续兜底
         console.warn('Clipboard read failed:', error);
       }
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/LoginScreen.tsx` around lines 50 - 56, In the LoginScreen key
handler where you detect Ctrl/Cmd+V and call navigator.clipboard.readText(), add
e.preventDefault() immediately when the paste hotkey is detected (before the
await) to stop the browser's default paste from also firing; keep the existing
logic that awaits navigator.clipboard.readText(), trims and calls setToken(...)
and clears setError(...), but ensure e.preventDefault() is invoked first to
avoid the race with the onChange handler.

} catch (error) {
// 忽略读取剪贴板失败,让浏览器/系统默认行为继续兜底
console.warn('Clipboard read failed:', error);
}
}
};

Expand Down
18 changes: 18 additions & 0 deletions src/components/SearchBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect, useRef } from 'react';
import { Search, Filter, X, SlidersHorizontal, Monitor, Smartphone, Globe, Terminal, Package, CheckCircle, Bell, BellOff, Apple, Bot } from 'lucide-react';
import { useAppStore } from '../store/useAppStore';
import { AIService } from '../services/aiService';
import { useSearchShortcuts } from '../hooks/useSearchShortcuts';


export const SearchBar: React.FC = () => {
Expand Down Expand Up @@ -509,6 +510,23 @@ export const SearchBar: React.FC = () => {

const t = (zh: string, en: string) => language === 'zh' ? zh : en;

// 全局快捷键支持(Ctrl/Cmd+K、Ctrl/Cmd+Shift+F、/、Escape)
useSearchShortcuts({
onFocusSearch: () => {
searchInputRef.current?.focus();
if (!searchQuery && searchHistory.length > 0) {
setShowSearchHistory(true);
}
},
onClearSearch: () => {
handleClearSearch();
searchInputRef.current?.focus();
},
onToggleFilters: () => {
setShowFilters(prev => !prev);
},
});

return (
<div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-6 mb-6">
{/* Search Input */}
Expand Down