Unverified 提交 d1a607f8 authored 作者: wwwillchen-bot's avatar wwwillchen-bot 提交者: GitHub

Remove ChatActivity component and associated references (#2648)

## Summary - Remove the unused `ChatActivity.tsx` component - Clean up all references including i18n translations (en, pt-BR, zh-CN) - Update e2e test helpers and concurrent chat spec to remove ChatActivity-related code ## Test plan - [x] Lint checks pass - [x] TypeScript compilation succeeds - [x] All 33 test files pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/dyad-sh/dyad/pull/2648" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Removed the unused ChatActivity component and the bell entry point. Updated tests and i18n; e2e now targets the chat tabs “in progress” indicator instead of the activity list. - **Refactors** - Deleted ChatActivity.tsx and removed ChatActivityButton from TitleBar and ActionHeader. - Removed related i18n keys in en, pt-BR, and zh-CN. - Dropped e2e helpers for the activity list and updated concurrent_chat.spec to select the “Chat in progress” tab. <sup>Written for commit b005943bc7b87c8dfe6375504fbbbca088b7aabb. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. --> --------- Co-authored-by: 's avatarWill Chen <willchen90@gmail.com> Co-authored-by: 's avatarClaude Opus 4.5 <noreply@anthropic.com>
上级 fb73c208
......@@ -12,14 +12,17 @@ test("concurrent chat", async ({ po }) => {
await po.navigation.goToAppsTab();
await po.sendPrompt("tc=chat2");
await po.snapshotMessages();
await po.chatActions.clickChatActivityButton();
// Chat #1 will be the last in the list
expect(
await po.page.getByTestId(`chat-activity-list-item-1`).textContent(),
).toContain("Chat #1");
await po.page.getByTestId(`chat-activity-list-item-1`).click();
await po.snapshotMessages({ timeout: 12_000 });
// Chat #1 tab should be visible in the chat tabs with an "in progress" indicator
// Find the tab that contains the "Chat in progress" indicator and click it
const chat1TabContainer = po.page
.locator('[aria-label="Chat in progress"]')
.locator(
"xpath=ancestor::div[contains(@class, 'flex') and contains(@class, 'h-10')]",
);
await expect(chat1TabContainer).toBeVisible();
//
// Click the button inside the tab to select it
await chat1TabContainer.locator("button").first().click();
await po.snapshotMessages({ timeout: 12_000 });
});
......@@ -115,16 +115,6 @@ export class ChatActions {
await this.selectChatMode("local-agent");
}
async clickChatActivityButton() {
await this.page.getByTestId("chat-activity-button").click();
}
async snapshotChatActivityList() {
await expect(
this.page.getByTestId("chat-activity-list"),
).toMatchAriaSnapshot();
}
async snapshotChatInputContainer() {
await expect(this.getChatInputContainer()).toMatchAriaSnapshot();
}
......
差异被折叠。
......@@ -21,10 +21,9 @@ import {
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { ChatActivityButton } from "@/components/chat/ChatActivity";
import { ChatTabs } from "@/components/chat/ChatTabs";
import { selectedChatIdAtom } from "@/atoms/chatAtoms";
import { MoreVertical, Cog, Trash2 } from "lucide-react";
import { Wrench, Cog, Trash2 } from "lucide-react";
import {
DropdownMenu,
DropdownMenuContent,
......@@ -195,6 +194,7 @@ function WindowsControls() {
function TitleBarActions() {
const { t } = useTranslation("home");
const selectedAppId = useAtomValue(selectedAppIdAtom);
const { restartApp, refreshAppIframe } = useRunApp();
const onCleanRestart = useCallback(() => {
......@@ -223,14 +223,16 @@ function TitleBarActions() {
}, [clearSessionData]);
return (
<div className="flex items-center gap-0.5 no-app-region-drag mr-2">
<ChatActivityButton />
<div
className="flex items-center gap-0.5 no-app-region-drag mr-2"
style={{ visibility: selectedAppId ? "visible" : "hidden" }}
>
<DropdownMenu>
<DropdownMenuTrigger
data-testid="preview-more-options-button"
className="flex items-center justify-center w-8 h-8 rounded-md text-sm hover:bg-sidebar-accent transition-colors"
>
<MoreVertical size={16} />
<Wrench size={16} />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-60">
<DropdownMenuItem onClick={onCleanRestart}>
......
import { useMemo, useState } from "react";
import { Bell, Loader2, CheckCircle2 } from "lucide-react";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import type { ChatSummary } from "@/lib/schemas";
import { useAtomValue } from "jotai";
import {
isStreamingByIdAtom,
recentStreamChatIdsAtom,
} from "@/atoms/chatAtoms";
import { useLoadApps } from "@/hooks/useLoadApps";
import { useSelectChat } from "@/hooks/useSelectChat";
import { useChats } from "@/hooks/useChats";
export function ChatActivityButton() {
const [open, setOpen] = useState(false);
const isStreamingById = useAtomValue(isStreamingByIdAtom);
const isAnyStreaming = useMemo(() => {
for (const v of isStreamingById.values()) {
if (v) return true;
}
return false;
}, [isStreamingById]);
return (
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger
className="no-app-region-drag relative flex items-center justify-center p-1.5 rounded-md text-sm hover:bg-[var(--background-darkest)] transition-colors"
data-testid="chat-activity-button"
title="Recent chat activity"
>
{isAnyStreaming && (
<span className="pointer-events-none absolute inset-0 flex items-center justify-center">
<span className="block size-7 rounded-full border-3 border-blue-500/60 border-t-transparent animate-spin" />
</span>
)}
<Bell size={16} />
</PopoverTrigger>
<PopoverContent
align="end"
className="w-80 p-0 max-h-[50vh] overflow-y-auto"
>
<ChatActivityList onSelect={() => setOpen(false)} />
</PopoverContent>
</Popover>
);
}
function ChatActivityList({ onSelect }: { onSelect?: () => void }) {
const isStreamingById = useAtomValue(isStreamingByIdAtom);
const recentStreamChatIds = useAtomValue(recentStreamChatIdsAtom);
const apps = useLoadApps();
const { selectChat } = useSelectChat();
const { chats: allChats, loading } = useChats(null);
const rows = useMemo(() => {
const recent = Array.from(recentStreamChatIds)
.map((id) => allChats.find((c: ChatSummary) => c.id === id))
.filter((c): c is ChatSummary => c !== undefined);
return [...recent].reverse().slice(0, 30);
}, [recentStreamChatIds, allChats]);
if (loading) {
return (
<div className="p-4 text-sm text-muted-foreground flex items-center gap-2">
<Loader2 size={16} className="animate-spin" />
Loading activity…
</div>
);
}
if (rows.length === 0) {
return (
<div className="p-4 text-sm text-muted-foreground">No recent chats</div>
);
}
return (
<div className="py-1" data-testid="chat-activity-list">
{rows.map((c) => {
const inProgress = isStreamingById.get(c.id) === true;
return (
<button
key={c.id}
className="w-full text-left px-3 py-2 flex items-center justify-between gap-2 rounded-md hover:bg-[var(--background-darker)] dark:hover:bg-[var(--background-lighter)] transition-colors"
onClick={() => {
onSelect?.();
selectChat({ chatId: c.id, appId: c.appId });
}}
data-testid={`chat-activity-list-item-${c.id}`}
>
<div className="min-w-0">
<div className="truncate text-sm font-medium">
{c.title ?? `Chat #${c.id}`}
</div>
<div className="text-xs text-muted-foreground">
{apps.apps.find((a) => a.id === c.appId)?.name}
</div>
</div>
<div className="flex items-center gap-2">
{inProgress ? (
<div className="flex items-center text-purple-600">
<Loader2 size={16} className="animate-spin" />
</div>
) : (
<div className="flex items-center text-emerald-600">
<CheckCircle2 size={16} />
</div>
)}
</div>
</button>
);
})}
</div>
);
}
......@@ -13,7 +13,6 @@ import {
Globe,
Shield,
} from "lucide-react";
import { ChatActivityButton } from "@/components/chat/ChatActivity";
import { motion } from "framer-motion";
import { useEffect, useRef, useState, useCallback } from "react";
......@@ -264,9 +263,7 @@ export const ActionHeader = () => {
"publish-mode-button",
)}
</div>
{/* Chat activity bell */}
<div className="flex items-center gap-1">
<ChatActivityButton />
<DropdownMenu>
<Tooltip>
<TooltipTrigger
......
......@@ -64,9 +64,6 @@
"allowOnce": "Allow once",
"alwaysAllow": "Always allow",
"removeAttachment": "Remove attachment",
"recentChatActivity": "Recent chat activity",
"loadingActivity": "Loading activity...",
"noRecentChats": "No recent chats",
"uncommittedChanges": "You have {{count}} uncommitted change(s).",
"reviewAndCommit": "Review & commit",
"reviewCommitChanges": "Review & Commit Changes",
......
......@@ -64,9 +64,6 @@
"allowOnce": "Permitir uma vez",
"alwaysAllow": "Sempre permitir",
"removeAttachment": "Remover anexo",
"recentChatActivity": "Atividade recente de chat",
"loadingActivity": "Carregando atividade...",
"noRecentChats": "Nenhum chat recente",
"uncommittedChanges": "Você tem {{count}} alteração(ões) não comitada(s).",
"reviewAndCommit": "Revisar e comitar",
"reviewCommitChanges": "Revisar e Comitar Alterações",
......
......@@ -64,9 +64,6 @@
"allowOnce": "允许一次",
"alwaysAllow": "始终允许",
"removeAttachment": "移除附件",
"recentChatActivity": "最近的聊天活动",
"loadingActivity": "正在加载活动...",
"noRecentChats": "没有最近的聊天",
"uncommittedChanges": "您有 {{count}} 个未提交的更改。",
"reviewAndCommit": "审查并提交",
"reviewCommitChanges": "审查并提交更改",
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论