From 0ff2a2057716612fe8ef192c6224001c00824877 Mon Sep 17 00:00:00 2001 From: Sean McNamara Date: Fri, 15 May 2026 15:03:49 -0400 Subject: [PATCH] chore(ui): remove nag surfaces --- packages/types/src/global-settings.ts | 4 - packages/types/src/vscode-extension-host.ts | 10 - src/core/webview/ClineProvider.ts | 10 +- .../webview/__tests__/ClineProvider.spec.ts | 1 - src/core/webview/webviewMessageHandler.ts | 39 -- webview-ui/src/App.tsx | 16 +- webview-ui/src/__tests__/App.spec.tsx | 5 - .../src/components/chat/Announcement.tsx | 128 ---- webview-ui/src/components/chat/ChatView.tsx | 26 +- .../chat/__tests__/Announcement.spec.tsx | 94 --- .../__tests__/ChatView.keyboard-fix.spec.tsx | 11 - .../ChatView.notification-sound.spec.tsx | 17 - .../ChatView.preserve-images.spec.tsx | 17 - .../ChatView.scroll-debug-repro.spec.tsx | 6 - .../chat/__tests__/ChatView.spec.tsx | 37 +- .../__tests__/IndexingStatusBadge.spec.tsx | 1 - .../components/common/DismissibleUpsell.tsx | 177 ----- .../components/common/VersionIndicator.tsx | 10 +- .../__tests__/DismissibleUpsell.spec.tsx | 625 ------------------ .../settings/__tests__/SettingsView.spec.tsx | 1 - .../src/context/ExtensionStateContext.tsx | 3 - .../__tests__/ExtensionStateContext.spec.tsx | 2 - webview-ui/src/i18n/locales/ca/chat.json | 28 +- webview-ui/src/i18n/locales/de/chat.json | 28 +- webview-ui/src/i18n/locales/en/chat.json | 23 +- webview-ui/src/i18n/locales/es/chat.json | 28 +- webview-ui/src/i18n/locales/fr/chat.json | 28 +- webview-ui/src/i18n/locales/hi/chat.json | 28 +- webview-ui/src/i18n/locales/id/chat.json | 28 +- webview-ui/src/i18n/locales/it/chat.json | 28 +- webview-ui/src/i18n/locales/ja/chat.json | 28 +- webview-ui/src/i18n/locales/ko/chat.json | 28 +- webview-ui/src/i18n/locales/nl/chat.json | 28 +- webview-ui/src/i18n/locales/pl/chat.json | 28 +- webview-ui/src/i18n/locales/pt-BR/chat.json | 28 +- webview-ui/src/i18n/locales/ru/chat.json | 28 +- webview-ui/src/i18n/locales/tr/chat.json | 28 +- webview-ui/src/i18n/locales/vi/chat.json | 28 +- webview-ui/src/i18n/locales/zh-CN/chat.json | 28 +- webview-ui/src/i18n/locales/zh-TW/chat.json | 23 +- 40 files changed, 33 insertions(+), 1701 deletions(-) delete mode 100644 webview-ui/src/components/chat/Announcement.tsx delete mode 100644 webview-ui/src/components/chat/__tests__/Announcement.spec.tsx delete mode 100644 webview-ui/src/components/common/DismissibleUpsell.tsx delete mode 100644 webview-ui/src/components/common/__tests__/DismissibleUpsell.spec.tsx diff --git a/packages/types/src/global-settings.ts b/packages/types/src/global-settings.ts index 288f6c2118..f3efb5a740 100644 --- a/packages/types/src/global-settings.ts +++ b/packages/types/src/global-settings.ts @@ -83,10 +83,8 @@ export const globalSettingsSchema = z.object({ listApiConfigMeta: z.array(providerSettingsEntrySchema).optional(), pinnedApiConfigs: z.record(z.string(), z.boolean()).optional(), - lastShownAnnouncementId: z.string().optional(), customInstructions: z.string().optional(), taskHistory: z.array(historyItemSchema).optional(), - dismissedUpsells: z.array(z.string()).optional(), // Image generation settings (experimental) - flattened for simplicity imageGenerationProvider: z.enum(["openrouter", "roo"]).optional(), @@ -320,8 +318,6 @@ export const isGlobalStateKey = (key: string): key is Keys => export const EVALS_SETTINGS: RooCodeSettings = { apiProvider: "openrouter", - lastShownAnnouncementId: "jul-09-2025-3-23-0", - pinnedApiConfigs: {}, autoApprovalEnabled: true, diff --git a/packages/types/src/vscode-extension-host.ts b/packages/types/src/vscode-extension-host.ts index 202326eb01..958f401afe 100644 --- a/packages/types/src/vscode-extension-host.ts +++ b/packages/types/src/vscode-extension-host.ts @@ -86,7 +86,6 @@ export interface ExtensionMessage { | "showEditMessageDialog" | "commands" | "insertTextIntoTextarea" - | "dismissedUpsells" | "organizationSwitchResult" | "interactionRequired" | "customToolsResult" @@ -175,7 +174,6 @@ export interface ExtensionMessage { context?: string commands?: Command[] queuedMessages?: QueuedMessage[] - list?: string[] // For dismissedUpsells organizationId?: string | null // For organizationSwitchResult tools?: SerializedCustomToolDefinition[] // For customToolsResult skills?: SkillMetadata[] // For skills response @@ -251,7 +249,6 @@ export type ExtensionState = Pick< | "listApiConfigMeta" | "pinnedApiConfigs" | "customInstructions" - | "dismissedUpsells" | "autoApprovalEnabled" | "alwaysAllowReadOnly" | "alwaysAllowReadOnlyOutsideWorkspace" @@ -314,7 +311,6 @@ export type ExtensionState = Pick< currentTaskTodos?: TodoItem[] // Initial todos for the current task apiConfiguration: ProviderSettings uriScheme?: string - shouldShowAnnouncement: boolean taskHistory: HistoryItem[] @@ -366,7 +362,6 @@ export type ExtensionState = Pick< hasOpenedModeSelector: boolean openRouterImageApiKey?: string messageQueue?: QueuedMessage[] - lastShownAnnouncementId?: string apiModelId?: string mcpServers?: McpServer[] mdmCompliant?: boolean @@ -431,7 +426,6 @@ export interface WebviewMessage { | "askResponse" | "terminalOperation" | "clearTask" - | "didShowAnnouncement" | "selectImages" | "exportCurrentTask" | "shareCurrentTask" @@ -552,8 +546,6 @@ export interface WebviewMessage { | "queueMessage" | "removeQueuedMessage" | "editQueuedMessage" - | "dismissUpsell" - | "getDismissedUpsells" | "openMarkdownPreview" | "updateSettings" | "allowedCommands" @@ -648,8 +640,6 @@ export interface WebviewMessage { visibility?: ShareVisibility // For share visibility hasContent?: boolean // For checkRulesDirectoryResult checkOnly?: boolean // For deleteCustomMode check - upsellId?: string // For dismissUpsell - list?: string[] // For dismissedUpsells response organizationId?: string | null // For organization switching useProviderSignup?: boolean // For rooCloudSignIn to use provider signup flow codeIndexSettings?: { diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index ad339f52a4..cd15ccb6ab 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -169,7 +169,6 @@ export class ClineProvider public isViewLaunched = false public settingsImportedAt?: number - public readonly latestAnnouncementId = "apr-2026-v3.53.0-community-handoff-gpt55-opus47" // v3.53.0 Community handoff, GPT-5.5, Claude Opus 4.7, checkpoint navigation public readonly providerSettingsManager: ProviderSettingsManager public readonly customModesManager: CustomModesManager @@ -2057,7 +2056,6 @@ export class ClineProvider const { apiConfiguration, - lastShownAnnouncementId, customInstructions, alwaysAllowReadOnly, alwaysAllowReadOnlyOutsideWorkspace, @@ -2228,8 +2226,6 @@ export class ClineProvider ttsSpeed: ttsSpeed ?? 1.0, enableCheckpoints: enableCheckpoints ?? true, checkpointTimeout: checkpointTimeout ?? DEFAULT_CHECKPOINT_TIMEOUT_SECONDS, - shouldShowAnnouncement: - telemetrySetting !== "unset" && lastShownAnnouncementId !== this.latestAnnouncementId, allowedCommands: mergedAllowedCommands, deniedCommands: mergedDeniedCommands, soundVolume: soundVolume ?? 0.5, @@ -2333,10 +2329,7 @@ export class ClineProvider */ async getState(): Promise< - Omit< - ExtensionState, - "clineMessages" | "renderContext" | "hasOpenedModeSelector" | "version" | "shouldShowAnnouncement" - > + Omit > { const stateValues = this.contextProxy.getValues() const customModes = await this.customModesManager.getCustomModes() @@ -2407,7 +2400,6 @@ export class ClineProvider // Return the same structure as before. return { apiConfiguration: providerSettings, - lastShownAnnouncementId: stateValues.lastShownAnnouncementId, customInstructions: stateValues.customInstructions, apiModelId: stateValues.apiModelId, alwaysAllowReadOnly: stateValues.alwaysAllowReadOnly ?? false, diff --git a/src/core/webview/__tests__/ClineProvider.spec.ts b/src/core/webview/__tests__/ClineProvider.spec.ts index d25c6971d2..67d1d65988 100644 --- a/src/core/webview/__tests__/ClineProvider.spec.ts +++ b/src/core/webview/__tests__/ClineProvider.spec.ts @@ -521,7 +521,6 @@ describe("ClineProvider", () => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, apiConfiguration: { apiProvider: "openrouter", }, diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index dc029cb7dd..7e3abd3ee6 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -770,10 +770,6 @@ export const webviewMessageHandler = async ( await provider.clearTask() await provider.postStateToWebview() break - case "didShowAnnouncement": - await updateGlobalState("lastShownAnnouncementId", provider.latestAnnouncementId) - await provider.postStateToWebview() - break case "selectImages": const images = await selectImages() await provider.postMessageToWebview({ @@ -3225,41 +3221,6 @@ export const webviewMessageHandler = async ( break } - case "dismissUpsell": { - if (message.upsellId) { - try { - // Get current list of dismissed upsells - const dismissedUpsells = getGlobalState("dismissedUpsells") || [] - - // Add the new upsell ID if not already present - let updatedList = dismissedUpsells - if (!dismissedUpsells.includes(message.upsellId)) { - updatedList = [...dismissedUpsells, message.upsellId] - await updateGlobalState("dismissedUpsells", updatedList) - } - - // Send updated list back to webview (use the already computed updatedList) - await provider.postMessageToWebview({ - type: "dismissedUpsells", - list: updatedList, - }) - } catch (error) { - // Fail silently as per Bruno's comment - it's OK to fail silently in this case - provider.log(`Failed to dismiss upsell: ${error instanceof Error ? error.message : String(error)}`) - } - } - break - } - case "getDismissedUpsells": { - // Send the current list of dismissed upsells to the webview - const dismissedUpsells = getGlobalState("dismissedUpsells") || [] - await provider.postMessageToWebview({ - type: "dismissedUpsells", - list: dismissedUpsells, - }) - break - } - case "openMarkdownPreview": { if (message.text) { try { diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 6f39e806d0..6fdc5a6f01 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -55,7 +55,6 @@ const App = () => { didHydrateState, showWelcome, settingsImportedAt, - shouldShowAnnouncement, telemetrySetting, telemetryKey, machineId, @@ -66,7 +65,6 @@ const App = () => { // Create a persistent state manager const marketplaceStateManager = useMemo(() => new MarketplaceViewStateManager(), []) - const [showAnnouncement, setShowAnnouncement] = useState(false) const [tab, setTab] = useState("chat") const handledImportRef = useRef(undefined) @@ -164,13 +162,6 @@ const App = () => { useEvent("message", onMessage) - useEffect(() => { - if (shouldShowAnnouncement && tab === "chat") { - setShowAnnouncement(true) - vscode.postMessage({ type: "didShowAnnouncement" }) - } - }, [shouldShowAnnouncement, tab]) - useEffect(() => { const isRecoverableTab = tab === "settings" || tab === "marketplace" @@ -246,12 +237,7 @@ const App = () => { targetTab={currentMarketplaceTab as "mcp" | "mode" | undefined} /> )} - setShowAnnouncement(false)} - /> + {deleteMessageDialogState.hasCheckpoint ? ( { mockUseExtensionState.mockReturnValue({ didHydrateState: true, showWelcome: false, - shouldShowAnnouncement: false, experiments: {}, language: "en", telemetrySetting: "enabled", @@ -191,7 +190,6 @@ describe("App", () => { const createSetupIncompleteState = () => ({ didHydrateState: true, showWelcome: true, - shouldShowAnnouncement: false, experiments: {}, language: "en", telemetrySetting: "enabled", @@ -209,7 +207,6 @@ describe("App", () => { mockUseExtensionState.mockReturnValue({ didHydrateState: true, showWelcome: true, - shouldShowAnnouncement: false, experiments: {}, language: "en", telemetrySetting: "enabled", @@ -242,7 +239,6 @@ describe("App", () => { mockUseExtensionState.mockReturnValue({ didHydrateState: true, showWelcome: true, - shouldShowAnnouncement: false, experiments: {}, language: "en", telemetrySetting: "enabled", @@ -262,7 +258,6 @@ describe("App", () => { mockUseExtensionState.mockReturnValue({ didHydrateState: true, showWelcome: true, - shouldShowAnnouncement: false, experiments: {}, language: "en", telemetrySetting: "enabled", diff --git a/webview-ui/src/components/chat/Announcement.tsx b/webview-ui/src/components/chat/Announcement.tsx deleted file mode 100644 index 557c15388b..0000000000 --- a/webview-ui/src/components/chat/Announcement.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { memo, type ReactNode, useState } from "react" -import { Trans } from "react-i18next" -import { SiDiscord, SiReddit, SiX } from "react-icons/si" -import { VSCodeLink } from "@vscode/webview-ui-toolkit/react" - -import { Package } from "@roo/package" -import { useAppTranslation } from "@src/i18n/TranslationContext" -import { vscode } from "@src/utils/vscode" -import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@src/components/ui" -import { EXTERNAL_LINKS } from "@src/constants/externalLinks" - -interface AnnouncementProps { - hideAnnouncement: () => void -} - -/** - * You must update the `latestAnnouncementId` in ClineProvider for new - * announcements to show to users. This new id will be compared with what's in - * state for the 'last announcement shown', and if it's different then the - * announcement will render. As soon as an announcement is shown, the id will be - * updated in state. This ensures that announcements are not shown more than - * once, even if the user doesn't close it themselves. - */ - -const Announcement = ({ hideAnnouncement }: AnnouncementProps) => { - const { t } = useAppTranslation() - const [open, setOpen] = useState(true) - - return ( - { - setOpen(open) - - if (!open) { - hideAnnouncement() - } - }}> - - - {t("chat:announcement.title", { version: Package.version })} - -
- {/* Community Handoff Notice */} -
-

- {t("chat:announcement.handoff.heading")} -

-

- }} /> -

- { - e.preventDefault() - vscode.postMessage({ - type: "openExternal", - url: "https://www.zoocode.dev?utm_source=zoocode&utm_medium=announcement&utm_campaign=community_handoff", - }) - }}> - {t("chat:announcement.handoff.readMore")} - -
- - {/* Regular Release Highlights */} -
-

{t("chat:announcement.release.heading")}

-
    -
  • {t("chat:announcement.release.gpt55")}
  • -
  • {t("chat:announcement.release.claudeOpus47")}
  • -
  • {t("chat:announcement.release.checkpointNav")}
  • -
-
- -
-
- } - label="X" - href="https://x.com/ZooCodeDev" - /> - } - label="Discord" - href="https://discord.gg/VxfP4Vx3gX" - /> - } - label="Reddit" - href="https://www.reddit.com/r/ZooCode/" - /> -
-
- -
- }} /> -
-
-
-
- ) -} - -const SocialLink = ({ icon, label, href }: { icon: ReactNode; label: string; href: string }) => ( - { - e.preventDefault() - vscode.postMessage({ type: "openExternal", url: href }) - }}> - {icon} - {label} - -) - -const GitHubLink = ({ children }: { children?: ReactNode }) => ( - { - e.preventDefault() - vscode.postMessage({ type: "openExternal", url: EXTERNAL_LINKS.GITHUB_REPO }) - }}> - {children} - -) - -export default memo(Announcement) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 7026d093f5..bb2c7c7a6a 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -33,7 +33,6 @@ import { StandardTooltip, Button } from "@src/components/ui" import TelemetryBanner from "../common/TelemetryBanner" import VersionIndicator from "../common/VersionIndicator" import HistoryPreview from "../history/HistoryPreview" -import Announcement from "./Announcement" import ChatRow from "./ChatRow" import WarningRow from "./WarningRow" import { ChatTextArea } from "./ChatTextArea" @@ -47,8 +46,6 @@ import { useScrollLifecycle } from "@src/hooks/useScrollLifecycle" export interface ChatViewProps { isHidden: boolean - showAnnouncement: boolean - hideAnnouncement: () => void } export interface ChatViewRef { @@ -59,10 +56,7 @@ export const MAX_IMAGES_PER_MESSAGE = 20 // This is the Anthropic limit. const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0 -const ChatViewComponent: React.ForwardRefRenderFunction = ( - { isHidden, showAnnouncement, hideAnnouncement }, - ref, -) => { +const ChatViewComponent: React.ForwardRefRenderFunction = ({ isHidden }, ref) => { const [audioBaseUri] = useState(() => { return (window as unknown as { AUDIO_BASE_URI?: string }).AUDIO_BASE_URI || "" }) @@ -154,7 +148,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction(undefined) const [isCondensing, setIsCondensing] = useState(false) - const [showAnnouncementModal, setShowAnnouncementModal] = useState(false) const everVisibleMessagesTsRef = useRef>( new LRUCache({ max: 100, @@ -1555,18 +1548,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction {telemetrySetting === "unset" && } - {(showAnnouncement || showAnnouncementModal) && ( - { - if (showAnnouncementModal) { - setShowAnnouncementModal(false) - } - if (showAnnouncement) { - hideAnnouncement() - } - }} - /> - )} {task ? ( <>
- setShowAnnouncementModal(true)} - className="absolute top-2 right-3 z-10" - /> +
diff --git a/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx b/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx deleted file mode 100644 index 5757b996df..0000000000 --- a/webview-ui/src/components/chat/__tests__/Announcement.spec.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import React from "react" - -import { render, screen } from "@/utils/test-utils" -import { EXTERNAL_LINKS } from "@/constants/externalLinks" - -import Announcement from "../Announcement" - -vi.mock("@src/utils/vscode", () => ({ - vscode: { - postMessage: vi.fn(), - }, -})) - -vi.mock("@roo/package", () => ({ - Package: { - version: "3.53.0", - }, -})) - -vi.mock("@vscode/webview-ui-toolkit/react", () => ({ - VSCodeLink: ({ children, href, onClick, ...props }: React.AnchorHTMLAttributes) => ( - - {children} - - ), -})) - -vi.mock("react-i18next", () => ({ - Trans: ({ i18nKey, components }: { i18nKey: string; components?: Record }) => { - if (i18nKey === "chat:announcement.support" && components?.githubLink) { - return React.cloneElement(components.githubLink, undefined, "GitHub") - } - - return {i18nKey} - }, -})) - -vi.mock("@src/i18n/TranslationContext", () => ({ - useAppTranslation: () => ({ - t: (key: string, options?: { version?: string }) => { - const translations: Record = { - "chat:announcement.release.heading": "What's New:", - "chat:announcement.release.gpt55": - "GPT-5.5 via OpenAI Codex: Added GPT-5.5 support in the OpenAI Codex provider so you can use the latest model straight from Roo Code.", - "chat:announcement.release.claudeOpus47": - "Claude Opus 4.7 on Vertex AI: Added Claude Opus 4.7 to the Vertex AI provider for Anthropic's newest flagship reasoning model.", - "chat:announcement.release.checkpointNav": - "Previous Checkpoint Navigation: Added controls in chat to jump back through prior checkpoints, with full i18n support.", - "chat:announcement.handoff.heading": "The Roo Code plugin is not going away.", - } - - if (key === "chat:announcement.title") { - return `Roo Code ${options?.version ?? ""} Released` - } - - return translations[key] ?? key - }, - }), -})) - -describe("Announcement", () => { - it("renders the v3.53.0 announcement title and highlights", () => { - render() - - expect(screen.getByText("Roo Code 3.53.0 Released")).toBeInTheDocument() - expect( - screen.getByText( - "GPT-5.5 via OpenAI Codex: Added GPT-5.5 support in the OpenAI Codex provider so you can use the latest model straight from Roo Code.", - ), - ).toBeInTheDocument() - expect( - screen.getByText( - "Claude Opus 4.7 on Vertex AI: Added Claude Opus 4.7 to the Vertex AI provider for Anthropic's newest flagship reasoning model.", - ), - ).toBeInTheDocument() - expect( - screen.getByText( - "Previous Checkpoint Navigation: Added controls in chat to jump back through prior checkpoints, with full i18n support.", - ), - ).toBeInTheDocument() - }) - - it("renders exactly three release highlight bullets", () => { - render() - - expect(screen.getAllByRole("listitem")).toHaveLength(3) - }) - - it("links support users to the Zoo Code GitHub repository", () => { - render() - - expect(screen.getByRole("link", { name: "GitHub" })).toHaveAttribute("href", EXTERNAL_LINKS.GITHUB_REPO) - }) -}) diff --git a/webview-ui/src/components/chat/__tests__/ChatView.keyboard-fix.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.keyboard-fix.spec.tsx index 78dcce08ae..38bba41c53 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.keyboard-fix.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.keyboard-fix.spec.tsx @@ -36,14 +36,6 @@ vi.mock("../../common/VersionIndicator", () => ({ default: () => null, })) -vi.mock("@src/components/modals/Announcement", () => ({ - default: () => null, -})) - -vi.mock("@src/components/welcome/RooCloudCTA", () => ({ - default: () => null, -})) - vi.mock("@src/components/welcome/RooTips", () => ({ default: () => null, })) @@ -100,7 +92,6 @@ const mockPostMessage = (state: any) => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], alwaysAllowExecute: false, cloudIsAuthenticated: false, @@ -116,8 +107,6 @@ const mockPostMessage = (state: any) => { const defaultProps: ChatViewProps = { isHidden: false, - showAnnouncement: false, - hideAnnouncement: () => {}, } const queryClient = new QueryClient() diff --git a/webview-ui/src/components/chat/__tests__/ChatView.notification-sound.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.notification-sound.spec.tsx index 581fb95041..5a6fc6f2f8 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.notification-sound.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.notification-sound.spec.tsx @@ -28,7 +28,6 @@ interface ExtensionState { version: string clineMessages: ClineMessage[] taskHistory: any[] - shouldShowAnnouncement: boolean messageQueue?: QueuedMessage[] [key: string]: any } @@ -64,19 +63,6 @@ vi.mock("../../common/VersionIndicator", () => ({ default: vi.fn(() => null), })) -vi.mock("../Announcement", () => ({ - default: function MockAnnouncement({ hideAnnouncement }: { hideAnnouncement: () => void }) { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const React = require("react") - return React.createElement( - "div", - { "data-testid": "announcement-modal" }, - React.createElement("div", null, "What's New"), - React.createElement("button", { onClick: hideAnnouncement }, "Close"), - ) - }, -})) - // Mock QueuedMessages component vi.mock("../QueuedMessages", () => ({ QueuedMessages: function MockQueuedMessages({ @@ -240,7 +226,6 @@ const mockPostMessage = (state: Partial) => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, cloudIsAuthenticated: false, telemetrySetting: "enabled", messageQueue: [], @@ -253,8 +238,6 @@ const mockPostMessage = (state: Partial) => { const defaultProps: ChatViewProps = { isHidden: false, - showAnnouncement: false, - hideAnnouncement: () => {}, } const queryClient = new QueryClient() diff --git a/webview-ui/src/components/chat/__tests__/ChatView.preserve-images.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.preserve-images.spec.tsx index 23ed8dd35a..d49afd7205 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.preserve-images.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.preserve-images.spec.tsx @@ -22,7 +22,6 @@ interface ExtensionState { version: string clineMessages: ClineMessage[] taskHistory: any[] - shouldShowAnnouncement: boolean allowedCommands: string[] alwaysAllowExecute: boolean [key: string]: any @@ -59,19 +58,6 @@ vi.mock("../../common/VersionIndicator", () => ({ default: vi.fn(() => null), })) -vi.mock("../Announcement", () => ({ - default: function MockAnnouncement({ hideAnnouncement }: { hideAnnouncement: () => void }) { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const React = require("react") - return React.createElement( - "div", - { "data-testid": "announcement-modal" }, - React.createElement("div", null, "What's New"), - React.createElement("button", { onClick: hideAnnouncement }, "Close"), - ) - }, -})) - // Mock QueuedMessages component vi.mock("../QueuedMessages", () => ({ QueuedMessages: function MockQueuedMessages({ @@ -226,7 +212,6 @@ const mockPostMessage = (state: Partial) => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], alwaysAllowExecute: false, cloudIsAuthenticated: false, @@ -240,8 +225,6 @@ const mockPostMessage = (state: Partial) => { const defaultProps: ChatViewProps = { isHidden: false, - showAnnouncement: false, - hideAnnouncement: () => {}, } const queryClient = new QueryClient() diff --git a/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx index 12f98898f4..de57cd120d 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.scroll-debug-repro.spec.tsx @@ -16,7 +16,6 @@ interface ExtensionStateMessage { version: string clineMessages: ClineMessage[] taskHistory: unknown[] - shouldShowAnnouncement: boolean allowedCommands: string[] alwaysAllowExecute: boolean cloudIsAuthenticated: boolean @@ -81,10 +80,8 @@ vi.mock("../common/VersionIndicator", nullDefaultModule) vi.mock("../history/HistoryPreview", nullDefaultModule) vi.mock("@src/components/welcome/RooHero", nullDefaultModule) vi.mock("@src/components/welcome/RooTips", nullDefaultModule) -vi.mock("../Announcement", nullDefaultModule) vi.mock("./TaskHeader", () => ({ default: () =>
})) vi.mock("./ProfileViolationWarning", nullDefaultModule) -vi.mock("../common/DismissibleUpsell", nullDefaultModule) vi.mock("./CheckpointWarning", () => ({ CheckpointWarning: () => null })) vi.mock("./QueuedMessages", () => ({ QueuedMessages: () => null })) @@ -201,8 +198,6 @@ vi.mock("react-virtuoso", () => { const props: ChatViewProps = { isHidden: false, - showAnnouncement: false, - hideAnnouncement: () => {}, } const buildMessages = (baseTs: number): ClineMessage[] => [ @@ -243,7 +238,6 @@ const postState = (clineMessages: ClineMessage[]) => { version: "1.0.0", clineMessages, taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], alwaysAllowExecute: false, cloudIsAuthenticated: false, diff --git a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx index 3fba140222..b3704d556a 100644 --- a/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/ChatView.spec.tsx @@ -23,7 +23,6 @@ interface ExtensionState { version: string clineMessages: ClineMessage[] taskHistory: any[] - shouldShowAnnouncement: boolean allowedCommands: string[] alwaysAllowExecute: boolean [key: string]: any @@ -85,19 +84,6 @@ vi.mock("../../common/VersionIndicator", () => ({ // Get the mock function after the module is mocked const mockVersionIndicator = vi.mocked((await import("../../common/VersionIndicator")).default) -vi.mock("../Announcement", () => ({ - default: function MockAnnouncement({ hideAnnouncement }: { hideAnnouncement: () => void }) { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const React = require("react") - return React.createElement( - "div", - { "data-testid": "announcement-modal" }, - React.createElement("div", null, "What's New"), - React.createElement("button", { onClick: hideAnnouncement }, "Close"), - ) - }, -})) - // Mock QueuedMessages component vi.mock("../QueuedMessages", () => ({ QueuedMessages: function MockQueuedMessages({ @@ -272,7 +258,6 @@ const mockPostMessage = (state: Partial) => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], alwaysAllowExecute: false, cloudIsAuthenticated: false, @@ -286,8 +271,6 @@ const mockPostMessage = (state: Partial) => { const defaultProps: ChatViewProps = { isHidden: false, - showAnnouncement: false, - hideAnnouncement: () => {}, } const queryClient = new QueryClient() @@ -542,16 +525,14 @@ describe("ChatView - Version Indicator Tests", () => { expect(getByTestId("version-indicator")).toBeInTheDocument() }) - it("opens announcement modal when version indicator is clicked", async () => { - // Mock VersionIndicator to return a button with onClick - mockVersionIndicator.mockImplementation(({ onClick }: { onClick?: () => void }) => + it("does not open release notes when version indicator is clicked", async () => { + mockVersionIndicator.mockReturnValue( React.createElement("button", { "data-testid": "version-indicator", - onClick, }), ) - const { getByTestId, queryByTestId } = renderChatView({ showAnnouncement: false }) + const { getByTestId, queryByTestId } = renderChatView() // Hydrate state mockPostMessage({ @@ -570,10 +551,7 @@ describe("ChatView - Version Indicator Tests", () => { versionIndicator.click() }) - // Wait for announcement modal to appear - await waitFor(() => { - expect(queryByTestId("announcement-modal")).toBeInTheDocument() - }) + expect(queryByTestId("announcement-modal")).not.toBeInTheDocument() }) it("version indicator has correct styling classes", () => { @@ -601,12 +579,10 @@ describe("ChatView - Version Indicator Tests", () => { }) it("version indicator has proper accessibility attributes", () => { - // Mock VersionIndicator to return a button with aria-label mockVersionIndicator.mockReturnValue( - React.createElement("button", { + React.createElement("span", { "data-testid": "version-indicator", "aria-label": "Version 1.0.0", - role: "button", }), ) @@ -620,7 +596,7 @@ describe("ChatView - Version Indicator Tests", () => { const versionIndicator = getByTestId("version-indicator") expect(versionIndicator.getAttribute("aria-label")).toBe("Version 1.0.0") - expect(versionIndicator.getAttribute("role")).toBe("button") + expect(versionIndicator.getAttribute("role")).toBeNull() }) it("does not display version indicator when there is an active task", () => { @@ -829,6 +805,7 @@ describe("ChatView - Message Queueing Tests", () => { // Simulate user typing and sending a message during the spinner const chatTextArea = getByTestId("chat-textarea") const input = chatTextArea.querySelector("input")! as HTMLInputElement + await waitFor(() => expect(input).toHaveAttribute("data-sending-disabled", "true")) // Trigger message send by simulating typing and Enter key press await act(async () => { diff --git a/webview-ui/src/components/chat/__tests__/IndexingStatusBadge.spec.tsx b/webview-ui/src/components/chat/__tests__/IndexingStatusBadge.spec.tsx index 25f92757f8..e9326a8d15 100644 --- a/webview-ui/src/components/chat/__tests__/IndexingStatusBadge.spec.tsx +++ b/webview-ui/src/components/chat/__tests__/IndexingStatusBadge.spec.tsx @@ -61,7 +61,6 @@ vi.mock("@/context/ExtensionStateContext", () => ({ version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, language: "en", }), ExtensionStateContextProvider: ({ children }: { children: React.ReactNode }) => <>{children}, diff --git a/webview-ui/src/components/common/DismissibleUpsell.tsx b/webview-ui/src/components/common/DismissibleUpsell.tsx deleted file mode 100644 index 6f0e1ad2dc..0000000000 --- a/webview-ui/src/components/common/DismissibleUpsell.tsx +++ /dev/null @@ -1,177 +0,0 @@ -import { memo, ReactNode, useEffect, useState, useRef } from "react" -import { vscode } from "@src/utils/vscode" -import { useAppTranslation } from "@src/i18n/TranslationContext" -import { telemetryClient } from "@src/utils/TelemetryClient" -import { TelemetryEventName } from "@roo-code/types" - -interface DismissibleUpsellProps { - /** Required unique identifier for this upsell */ - upsellId: string - /** Optional CSS class name for styling */ - className?: string - /** Optional Icon component */ - icon?: ReactNode - /** Content to display inside the upsell */ - children: ReactNode - /** Visual variant of the upsell */ - variant?: "default" | "banner" - /** Optional callback when upsell is dismissed */ - onDismiss?: () => void - /** Optional callback when upsell is clicked */ - onClick?: () => void - /** Whether clicking the upsell should also dismiss it (default: false) */ - dismissOnClick?: boolean -} - -const DismissIcon = () => ( - -) - -const DismissibleUpsell = memo( - ({ - upsellId, - className, - icon, - children, - variant = "default", - onDismiss, - onClick, - dismissOnClick = false, - }: DismissibleUpsellProps) => { - const { t } = useAppTranslation() - const [isVisible, setIsVisible] = useState(false) - const isMountedRef = useRef(true) - - useEffect(() => { - // Track mounted state - isMountedRef.current = true - - // Request the current list of dismissed upsells from the extension - vscode.postMessage({ type: "getDismissedUpsells" }) - - // Listen for the response - const handleMessage = (event: MessageEvent) => { - // Only update state if component is still mounted - if (!isMountedRef.current) return - - const message = event.data - // Add null/undefined check for message - if (message && message.type === "dismissedUpsells" && Array.isArray(message.list)) { - // Check if this upsell has been dismissed - if (!message.list.includes(upsellId)) { - setIsVisible(true) - } - } - } - - window.addEventListener("message", handleMessage) - return () => { - isMountedRef.current = false - window.removeEventListener("message", handleMessage) - } - }, [upsellId]) - - const handleDismiss = () => { - // Track telemetry for dismissal - telemetryClient.capture(TelemetryEventName.UPSELL_DISMISSED, { - upsellId: upsellId, - }) - - // First notify the extension to persist the dismissal - // This ensures the message is sent even if the component unmounts quickly - vscode.postMessage({ - type: "dismissUpsell", - upsellId: upsellId, - }) - - // Then hide the upsell - setIsVisible(false) - - // Call the optional callback - onDismiss?.() - } - - // Don't render if not visible - if (!isVisible) { - return null - } - - const variants = { - banner: { - container: - "p-2 bg-vscode-badge-background/80 text-vscode-badge-foreground border-vscode-dropdown-border border", - button: "text-vscode-badge-foreground", - }, - default: { - container: "bg-vscode-notifications-background text-vscode-notifications-foreground", - button: "text-vscode-notifications-foreground", - }, - } - // Build container classes based on variant and presence of click handler - const containerClasses = [ - "relative flex items-start justify-between gap-2", - "text-sm", - variants[variant].container, - onClick && "cursor-pointer hover:opacity-90 transition-opacity duration-200", - className, - ] - .filter(Boolean) - .join(" ") - - // Build button classes based on variant - const buttonClasses = [ - "flex items-center justify-center", - "rounded", - "bg-transparent", - "border-none", - "cursor-pointer", - "hover:opacity-50 transition-opacity duration-200", - variants[variant].button, - "focus:outline focus:outline-1 focus:outline-vscode-focusBorder focus:outline-offset-1", - ].join(" ") - - return ( -
{ - // Track telemetry for click - if (onClick) { - telemetryClient.capture(TelemetryEventName.UPSELL_CLICKED, { - upsellId: upsellId, - }) - } - - // Call the onClick handler if provided - onClick?.() - // Also dismiss if dismissOnClick is true - if (dismissOnClick) { - handleDismiss() - } - }}> - {icon && icon} -
{children}
- -
- ) - }, -) - -DismissibleUpsell.displayName = "DismissibleUpsell" - -export default DismissibleUpsell diff --git a/webview-ui/src/components/common/VersionIndicator.tsx b/webview-ui/src/components/common/VersionIndicator.tsx index ac4a1c5146..b66e295afa 100644 --- a/webview-ui/src/components/common/VersionIndicator.tsx +++ b/webview-ui/src/components/common/VersionIndicator.tsx @@ -3,20 +3,18 @@ import { useTranslation } from "react-i18next" import { Package } from "@roo/package" interface VersionIndicatorProps { - onClick: () => void className?: string } -const VersionIndicator: React.FC = ({ onClick, className = "" }) => { +const VersionIndicator: React.FC = ({ className = "" }) => { const { t } = useTranslation() return ( - + ) } diff --git a/webview-ui/src/components/common/__tests__/DismissibleUpsell.spec.tsx b/webview-ui/src/components/common/__tests__/DismissibleUpsell.spec.tsx deleted file mode 100644 index 69e4e94a4f..0000000000 --- a/webview-ui/src/components/common/__tests__/DismissibleUpsell.spec.tsx +++ /dev/null @@ -1,625 +0,0 @@ -import { render, screen, fireEvent, waitFor, act } from "@testing-library/react" -import { describe, it, expect, vi, beforeEach, afterEach } from "vitest" -import DismissibleUpsell from "../DismissibleUpsell" -import { TelemetryEventName } from "@roo-code/types" - -// Mock the vscode API -const mockPostMessage = vi.fn() -vi.mock("@src/utils/vscode", () => ({ - vscode: { - postMessage: (message: any) => mockPostMessage(message), - }, -})) - -// Mock telemetryClient -const mockCapture = vi.fn() -vi.mock("@src/utils/TelemetryClient", () => ({ - telemetryClient: { - capture: (eventName: string, properties?: Record) => mockCapture(eventName, properties), - }, -})) - -// Mock the translation hook -vi.mock("@src/i18n/TranslationContext", () => ({ - useAppTranslation: () => ({ - t: (key: string) => { - const translations: Record = { - "common:dismiss": "Dismiss", - "common:dismissAndDontShowAgain": "Dismiss and don't show again", - } - return translations[key] || key - }, - }), -})) - -describe("DismissibleUpsell", () => { - beforeEach(() => { - mockPostMessage.mockClear() - mockCapture.mockClear() - vi.clearAllTimers() - }) - - afterEach(() => { - vi.clearAllTimers() - }) - - // Helper function to make the component visible - const makeUpsellVisible = () => { - const messageEvent = new MessageEvent("message", { - data: { - type: "dismissedUpsells", - list: [], // Empty list means no upsells are dismissed - }, - }) - window.dispatchEvent(messageEvent) - } - - it("renders children content", async () => { - render( - -
Test content
-
, - ) - - // Component starts hidden, make it visible - makeUpsellVisible() - - // Wait for component to become visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - }) - - it("requests dismissed upsells list on mount", () => { - render( - -
Test content
-
, - ) - - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "getDismissedUpsells", - }) - }) - - it("hides the upsell when dismiss button is clicked and tracks telemetry", async () => { - const onDismiss = vi.fn() - const { container } = render( - -
Test content
-
, - ) - - // Make component visible first - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Find and click the dismiss button - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - fireEvent.click(dismissButton) - - // Check that telemetry was tracked - expect(mockCapture).toHaveBeenCalledWith(TelemetryEventName.UPSELL_DISMISSED, { - upsellId: "test-upsell", - }) - - // Check that the dismiss message was sent BEFORE hiding - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - - // Check that the component is no longer visible - await waitFor(() => { - expect(container.firstChild).toBeNull() - }) - - // Check that the callback was called - expect(onDismiss).toHaveBeenCalled() - }) - - it("hides the upsell if it's in the dismissed list", async () => { - const { container } = render( - -
Test content
-
, - ) - - // Component starts hidden by default - expect(container.firstChild).toBeNull() - - // Simulate receiving a message that this upsell is dismissed - const messageEvent = new MessageEvent("message", { - data: { - type: "dismissedUpsells", - list: ["test-upsell", "other-upsell"], - }, - }) - window.dispatchEvent(messageEvent) - - // Check that the component remains hidden - await waitFor(() => { - expect(container.firstChild).toBeNull() - }) - }) - - it("remains visible if not in the dismissed list", async () => { - render( - -
Test content
-
, - ) - - // Simulate receiving a message that doesn't include this upsell - const messageEvent = new MessageEvent("message", { - data: { - type: "dismissedUpsells", - list: ["other-upsell"], - }, - }) - window.dispatchEvent(messageEvent) - - // Check that the component is still visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - }) - - it("applies the className prop to the container", async () => { - const { container } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(container.firstChild).not.toBeNull() - }) - - expect(container.firstChild).toHaveClass("custom-class") - }) - - it("dismiss button has proper accessibility attributes", async () => { - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - expect(dismissButton).toHaveAttribute("aria-label", "Dismiss") - expect(dismissButton).toHaveAttribute("title", "Dismiss and don't show again") - }) - - // New edge case tests - it("handles multiple rapid dismissals of the same component", async () => { - const onDismiss = vi.fn() - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - - // Click multiple times rapidly - fireEvent.click(dismissButton) - fireEvent.click(dismissButton) - fireEvent.click(dismissButton) - - // Should only send one message - expect(mockPostMessage).toHaveBeenCalledTimes(2) // 1 for getDismissedUpsells, 1 for dismissUpsell - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - - // Callback should only be called once - expect(onDismiss).toHaveBeenCalledTimes(1) - }) - - it("does not update state after component unmounts", async () => { - const { unmount } = render( - -
Test content
-
, - ) - - // Unmount the component - unmount() - - // Simulate receiving a message after unmount - const messageEvent = new MessageEvent("message", { - data: { - type: "dismissedUpsells", - list: ["test-upsell"], - }, - }) - - // This should not cause any errors - act(() => { - window.dispatchEvent(messageEvent) - }) - - // No errors should be thrown - expect(true).toBe(true) - }) - - it("handles invalid/malformed messages gracefully", async () => { - render( - -
Test content
-
, - ) - - // First make it visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Send various malformed messages - const malformedMessages = [ - { type: "dismissedUpsells", list: null }, - { type: "dismissedUpsells", list: "not-an-array" }, - { type: "dismissedUpsells" }, // missing list - { type: "wrongType", list: ["test-upsell"] }, - null, - undefined, - "string-message", - ] - - malformedMessages.forEach((data) => { - const messageEvent = new MessageEvent("message", { data }) - window.dispatchEvent(messageEvent) - }) - - // Component should still be visible - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - it("ensures message is sent before component unmounts on dismiss", async () => { - const { unmount } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - fireEvent.click(dismissButton) - - // Message should be sent immediately - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - - // Unmount immediately after clicking - unmount() - - // Message was already sent before unmount - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - }) - - it("uses separate id and className props correctly", async () => { - const { container } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(container.firstChild).not.toBeNull() - }) - - // className should be applied to the container - expect(container.firstChild).toHaveClass("styling-class") - - // When dismissed, should use the id, not className - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - fireEvent.click(dismissButton) - - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "unique-id", - }) - }) - - it("calls onClick when the container is clicked and tracks telemetry", async () => { - const onClick = vi.fn() - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Click on the container (not the dismiss button) - const container = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(container) - - expect(onClick).toHaveBeenCalledTimes(1) - - // Check that telemetry was tracked - expect(mockCapture).toHaveBeenCalledWith(TelemetryEventName.UPSELL_CLICKED, { - upsellId: "test-upsell", - }) - }) - - it("does not call onClick when dismiss button is clicked", async () => { - const onClick = vi.fn() - const onDismiss = vi.fn() - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Click the dismiss button - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - fireEvent.click(dismissButton) - - // onClick should not be called, but onDismiss should - expect(onClick).not.toHaveBeenCalled() - expect(onDismiss).toHaveBeenCalledTimes(1) - }) - - it("adds cursor-pointer class when onClick is provided", async () => { - const { container, rerender } = render( - {}}> -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(container.firstChild).not.toBeNull() - }) - - // Should have cursor-pointer when onClick is provided - expect(container.firstChild).toHaveClass("cursor-pointer") - - // Re-render without onClick - rerender( - -
Test content
-
, - ) - - // Should not have cursor-pointer when onClick is not provided - expect(container.firstChild).not.toHaveClass("cursor-pointer") - }) - - it("handles both onClick and onDismiss independently", async () => { - const onClick = vi.fn() - const onDismiss = vi.fn() - const { container } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Click on the container - const containerDiv = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(containerDiv) - expect(onClick).toHaveBeenCalledTimes(1) - expect(onDismiss).not.toHaveBeenCalled() - - // Reset mocks - onClick.mockClear() - onDismiss.mockClear() - - // Click the dismiss button - const dismissButton = screen.getByRole("button", { name: /dismiss/i }) - fireEvent.click(dismissButton) - - // Only onDismiss should be called - expect(onClick).not.toHaveBeenCalled() - expect(onDismiss).toHaveBeenCalledTimes(1) - - // Component should be hidden after dismiss - await waitFor(() => { - expect(container.firstChild).toBeNull() - }) - }) - - it("dismisses when clicked if dismissOnClick is true and tracks both telemetry events", async () => { - const onClick = vi.fn() - const onDismiss = vi.fn() - const { container } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const containerDiv = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(containerDiv) - - expect(onClick).toHaveBeenCalledTimes(1) - expect(onDismiss).toHaveBeenCalledTimes(1) - - // Check that both telemetry events were tracked - expect(mockCapture).toHaveBeenCalledWith(TelemetryEventName.UPSELL_CLICKED, { - upsellId: "test-upsell", - }) - expect(mockCapture).toHaveBeenCalledWith(TelemetryEventName.UPSELL_DISMISSED, { - upsellId: "test-upsell", - }) - - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - - await waitFor(() => { - expect(container.firstChild).toBeNull() - }) - }) - - it("dismisses on container click when dismissOnClick is true and no onClick is provided; tracks only dismissal", async () => { - const onDismiss = vi.fn() - const { container } = render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - // Click on the container (not the dismiss button) - const containerDiv = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(containerDiv) - - // onDismiss should be called - expect(onDismiss).toHaveBeenCalledTimes(1) - - // Telemetry: only dismissal should be tracked - expect(mockCapture).toHaveBeenCalledWith(TelemetryEventName.UPSELL_DISMISSED, { - upsellId: "test-upsell", - }) - expect(mockCapture).not.toHaveBeenCalledWith(TelemetryEventName.UPSELL_CLICKED, expect.anything()) - - // Dismiss message should be sent - expect(mockPostMessage).toHaveBeenCalledWith({ - type: "dismissUpsell", - upsellId: "test-upsell", - }) - - // Component should be hidden - await waitFor(() => { - expect(container.firstChild).toBeNull() - }) - }) - it("does not dismiss when clicked if dismissOnClick is false", async () => { - const onClick = vi.fn() - const onDismiss = vi.fn() - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const containerDiv = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(containerDiv) - - expect(onClick).toHaveBeenCalledTimes(1) - expect(onDismiss).not.toHaveBeenCalled() - - expect(mockPostMessage).not.toHaveBeenCalledWith(expect.objectContaining({ type: "dismissUpsell" })) - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - it("does not dismiss when clicked if dismissOnClick is not provided (defaults to false)", async () => { - const onClick = vi.fn() - const onDismiss = vi.fn() - render( - -
Test content
-
, - ) - - // Make component visible - makeUpsellVisible() - - // Wait for component to be visible - await waitFor(() => { - expect(screen.getByText("Test content")).toBeInTheDocument() - }) - - const containerDiv = screen.getByText("Test content").parentElement as HTMLElement - fireEvent.click(containerDiv) - - expect(onClick).toHaveBeenCalledTimes(1) - expect(onDismiss).not.toHaveBeenCalled() - expect(screen.getByText("Test content")).toBeInTheDocument() - }) -}) diff --git a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx index 6fa34ebe81..e8b02f3266 100644 --- a/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx +++ b/webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx @@ -273,7 +273,6 @@ const mockPostMessage = (state: any) => { version: "1.0.0", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], alwaysAllowExecute: false, ttsEnabled: false, diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index 10b49e3de0..49f9604615 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -71,7 +71,6 @@ export interface ExtensionStateContextType extends ExtensionState { setAlwaysAllowSubtasks: (value: boolean) => void setShowRooIgnoredFiles: (value: boolean) => void setEnableSubfolderRules: (value: boolean) => void - setShowAnnouncement: (value: boolean) => void setAllowedCommands: (value: string[]) => void setDeniedCommands: (value: string[]) => void setAllowedMaxRequests: (value: number | undefined) => void @@ -195,7 +194,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode version: "", clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, allowedCommands: [], deniedCommands: [], soundEnabled: false, @@ -514,7 +512,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode setAlwaysAllowFollowupQuestions, setFollowupAutoApproveTimeoutMs: (value) => setState((prevState) => ({ ...prevState, followupAutoApproveTimeoutMs: value })), - setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })), setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })), setDeniedCommands: (value) => setState((prevState) => ({ ...prevState, deniedCommands: value })), setAllowedMaxRequests: (value) => setState((prevState) => ({ ...prevState, allowedMaxRequests: value })), diff --git a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx index 2a5e74c40d..93639f906b 100644 --- a/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx +++ b/webview-ui/src/context/__tests__/ExtensionStateContext.spec.tsx @@ -190,7 +190,6 @@ describe("mergeExtensionState", () => { mcpEnabled: false, clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, enableCheckpoints: true, writeDelayMs: 1000, mode: "default", @@ -259,7 +258,6 @@ describe("mergeExtensionState", () => { mcpEnabled: false, clineMessages: [], taskHistory: [], - shouldShowAnnouncement: false, enableCheckpoints: true, writeDelayMs: 1000, mode: "default", diff --git a/webview-ui/src/i18n/locales/ca/chat.json b/webview-ui/src/i18n/locales/ca/chat.json index dc3b1b6be8..f9f1d177d4 100644 --- a/webview-ui/src/i18n/locales/ca/chat.json +++ b/webview-ui/src/i18n/locales/ca/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Copiar a l'entrada (o Shift + clic)", "timerPrefix": "Aprovació automàtica habilitada. Seleccionant en {{seconds}}s…" }, - "announcement": { - "title": "S'ha publicat Zoo Code {{version}}", - "support": "Dona suport a Zoo Code fent-nos una estrella a GitHub.", - "handoff": { - "heading": "Roo Code ha tornat! Ara com a connector mantingut per la comunitat anomenat Zoo Code!!", - "description": "Per si no ho havies seguit, l'equip de Roo Code ha anunciat fa poc que deixa de desenvolupar Roo Code i n'arxiva la feina feta. Però no pateixis: la comunitat ha fet un pas endavant per continuar el llegat de Roo Code amb un nom nou i una llar nova! Ja no som només un sol \"Roo\", som una comunitat, un \"Zoo\" si vols. Zoo Code és un connector mantingut per la comunitat que reprèn el camí on Roo Code ho va deixar, i ens comprometem a mantenir viu l'esperit de Roo mentre també hi incorporem funcions i millores noves. Volem donar un enorme agraïment a tot l'equip de Roo Code per la feina increïble que han fet i per haver creat una eina tan extraordinària per als desenvolupadors. Ens fa molta il·lusió continuar construint sobre la seva base i veure fins on porta la comunitat Zoo Code en el futur!", - "readMore": "Mira la nova pàgina principal de Zoo Code i llegeix l'anunci complet" - }, - "release": { - "heading": "Què hi ha de nou:", - "gpt55": "GPT-5.5 via OpenAI Codex: S'ha afegit suport per a GPT-5.5 al proveïdor OpenAI Codex perquè puguis fer servir el model més recent directament des de Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 a Vertex AI: S'ha afegit Claude Opus 4.7 al proveïdor Vertex AI, el nou model de raonament emblemàtic d'Anthropic.", - "checkpointNav": "Navegació per Checkpoints Anteriors: S'han afegit controls al xat per tornar enrere pels checkpoints previs, amb suport complet d'i18n." - }, - "cloudAgents": { - "heading": "Novetats al núvol:", - "specialized": "Presentem Explainer, Planner i Coder - tres agents al núvol especialitzats per millorar els teus fluxos de treball.", - "description": "Els agents treballen junts al núvol i es poden activar des del web o mitjançant Slack.", - "tryButton": "Prova els Agents al Núvol" - } - }, "costs": { "totalWithSubtasks": "Cost total (subtasques incloses): ${{cost}}", "total": "Cost total: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Aturant la indexació..." }, "versionIndicator": { - "ariaLabel": "Versió {{version}} - Feu clic per veure les notes de llançament" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud està evolucionant!", - "description": "Executa agents remots al núvol, accedeix a les teves tasques des de qualsevol lloc, col·labora amb altres i molt més.", - "joinWaitlist": "Registra't per rebre les últimes actualitzacions." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Edita el teu missatge..." diff --git a/webview-ui/src/i18n/locales/de/chat.json b/webview-ui/src/i18n/locales/de/chat.json index 46f5d9b2fd..959e4ecf0c 100644 --- a/webview-ui/src/i18n/locales/de/chat.json +++ b/webview-ui/src/i18n/locales/de/chat.json @@ -327,27 +327,6 @@ "copyToInput": "In Eingabefeld kopieren (oder Shift + Klick)", "timerPrefix": "Automatische Genehmigung aktiviert. Wähle in {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} veröffentlicht", - "support": "Bitte unterstütze Zoo Code, indem du uns auf GitHub einen Stern gibst.", - "handoff": { - "heading": "Roo Code ist zurück! Jetzt als Community-gepflegtes Plugin namens Zoo Code!!", - "description": "Falls du es nicht mitbekommen hast: Das Roo Code Team hat vor Kurzem angekündigt, die Entwicklung von Roo Code einzustellen und die bisherige Arbeit zu archivieren. Aber keine Sorge: Die Community ist eingesprungen, um das Vermächtnis von Roo Code unter neuem Namen und in einem neuen Zuhause weiterzuführen! Wir sind nicht mehr nur ein einzelnes \"Roo\", sondern eine Community – ein \"Zoo\", wenn du so willst. Zoo Code ist ein Community-gepflegtes Plugin, das dort weitermacht, wo Roo Code aufgehört hat. Wir wollen den Geist von Roo bewahren und gleichzeitig neue Funktionen und Verbesserungen einführen. Dem gesamten Roo Code Team gilt ein riesiges Dankeschön für die unglaubliche Arbeit und dafür, dass es so ein großartiges Tool für Entwickler geschaffen hat. Wir freuen uns darauf, auf diesem Fundament weiterzubauen und zu sehen, wohin die Community Zoo Code in Zukunft führt!", - "readMore": "Sieh dir die neue Zoo Code Startseite an und lies die vollständige Ankündigung" - }, - "release": { - "heading": "Was ist neu:", - "gpt55": "GPT-5.5 via OpenAI Codex: GPT-5.5-Unterstützung im OpenAI Codex-Provider hinzugefügt, damit du das neueste Modell direkt in Zoo Code nutzen kannst.", - "claudeOpus47": "Claude Opus 4.7 auf Vertex AI: Claude Opus 4.7 zum Vertex AI-Provider hinzugefügt – Anthropics neuestes Flaggschiff-Reasoning-Modell.", - "checkpointNav": "Navigation zu vorherigen Checkpoints: Neue Steuerelemente im Chat, um durch frühere Checkpoints zurückzuspringen, mit vollständiger i18n-Unterstützung." - }, - "cloudAgents": { - "heading": "Neu in der Cloud:", - "specialized": "Wir stellen Explainer, Planner und Coder vor - drei spezialisierte Cloud-Agenten zur Verbesserung deiner Workflows.", - "description": "Die Agenten arbeiten zusammen in der Cloud und können vom Web oder über Slack ausgelöst werden.", - "tryButton": "Probiere Cloud-Agenten aus" - } - }, "costs": { "totalWithSubtasks": "Gesamtkosten (inkl. Unteraufgaben): ${{cost}}", "total": "Gesamtkosten: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Indexierung wird gestoppt..." }, "versionIndicator": { - "ariaLabel": "Version {{version}} - Klicken Sie, um die Versionshinweise anzuzeigen" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud entwickelt sich weiter!", - "description": "Führe Remote-Agenten in der Cloud aus, greife von überall auf deine Aufgaben zu, arbeite mit anderen zusammen und vieles mehr.", - "joinWaitlist": "Melde dich an, um die neuesten Updates zu erhalten." + "ariaLabel": "Version {{version}}" }, "command": { "triggerDescription": "Starte den {{name}} Befehl" diff --git a/webview-ui/src/i18n/locales/en/chat.json b/webview-ui/src/i18n/locales/en/chat.json index b682954f2b..509066dba9 100644 --- a/webview-ui/src/i18n/locales/en/chat.json +++ b/webview-ui/src/i18n/locales/en/chat.json @@ -346,27 +346,6 @@ "triggerLabel_other": "{{count}} auto-approved", "triggerLabelAll": "BRRR" }, - "announcement": { - "title": "Zoo Code {{version}} Released", - "support": "Please support Zoo Code by starring us on GitHub.", - "handoff": { - "heading": "Roo Code is back! Now as a community-maintained plugin called Zoo Code!!", - "description": "If you haven't been following, the Roo Code team recently announced they are sun setting the development of Roo Code and are archiving the work they have done. But fear not, the community has stepped up to continue the legacy of Roo Code with a new name and a new home! We are not just a single \"Roo\" anymore, we are a community, a \"Zoo\" if you will, Zoo Code is a community-maintained plugin that picks up where Roo Code left off, and we're committed to keeping the spirit of Roo alive while also introducing new features and improvements. We want to give a huge shoutout to the entire Roo Code team for their incredible work and for creating such an amazing tool for developers. We're excited to continue building on their foundation and to see where the community takes Zoo Code in the future!", - "readMore": "See the new home page of Zoo Code and read the full announcement" - }, - "release": { - "heading": "What's New:", - "gpt55": "GPT-5.5 via OpenAI Codex: Added GPT-5.5 support in the OpenAI Codex provider so you can use the latest model straight from Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 on Vertex AI: Added Claude Opus 4.7 to the Vertex AI provider for Anthropic's newest flagship reasoning model.", - "checkpointNav": "Previous Checkpoint Navigation: Added controls in chat to jump back through prior checkpoints, with full i18n support." - }, - "cloudAgents": { - "heading": "New in the Cloud:", - "specialized": "Introducing Explainer, Planner, and Coder - three specialized cloud agents to enhance your workflows.", - "description": "The agents work together in the cloud and can be triggered from the web or through Slack.", - "tryButton": "Try Cloud Agents" - } - }, "reasoning": { "thinking": "Thinking", "seconds": "{{count}}s" @@ -414,7 +393,7 @@ "stopping": "Stopping indexing..." }, "versionIndicator": { - "ariaLabel": "Version {{version}} - Click to view release notes" + "ariaLabel": "Version {{version}}" }, "command": { "triggerDescription": "Trigger the {{name}} command" diff --git a/webview-ui/src/i18n/locales/es/chat.json b/webview-ui/src/i18n/locales/es/chat.json index 81493d20c8..21de3f02fc 100644 --- a/webview-ui/src/i18n/locales/es/chat.json +++ b/webview-ui/src/i18n/locales/es/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Copiar a la entrada (o Shift + clic)", "timerPrefix": "Aprobación automática habilitada. Seleccionando en {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} publicado", - "support": "Apoya a Zoo Code dándonos una estrella en GitHub.", - "handoff": { - "heading": "¡Roo Code ha vuelto! Ahora como un plugin mantenido por la comunidad llamado Zoo Code!!", - "description": "Si no has estado al tanto, el equipo de Roo Code anunció recientemente que va a dejar de desarrollar Roo Code y archivará el trabajo realizado. Pero no te preocupes: la comunidad ha dado un paso al frente para continuar el legado de Roo Code con un nuevo nombre y un nuevo hogar. Ya no somos solo un \"Roo\", somos una comunidad, un \"Zoo\", si quieres verlo así. Zoo Code es un plugin mantenido por la comunidad que continúa donde Roo Code lo dejó, y estamos comprometidos a mantener vivo el espíritu de Roo mientras introducimos nuevas funciones y mejoras. Queremos dar un enorme agradecimiento a todo el equipo de Roo Code por su increíble trabajo y por crear una herramienta tan increíble para desarrolladores. Nos entusiasma seguir construyendo sobre sus cimientos y ver hasta dónde lleva la comunidad a Zoo Code en el futuro.", - "readMore": "Visita la nueva página principal de Zoo Code y lee el anuncio completo" - }, - "release": { - "heading": "Qué hay de nuevo:", - "gpt55": "GPT-5.5 vía OpenAI Codex: Se añadió soporte para GPT-5.5 en el proveedor OpenAI Codex para que puedas usar el modelo más reciente directamente desde Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 en Vertex AI: Se añadió Claude Opus 4.7 al proveedor Vertex AI, el modelo de razonamiento insignia más reciente de Anthropic.", - "checkpointNav": "Navegación por Checkpoints Anteriores: Se añadieron controles en el chat para retroceder por los checkpoints previos, con soporte completo de i18n." - }, - "cloudAgents": { - "heading": "Novedades en la Nube:", - "specialized": "Presentamos Explainer, Planner y Coder - tres agentes en la nube especializados para mejorar tus flujos de trabajo.", - "description": "Los agentes trabajan juntos en la nube y se pueden activar desde la web o mediante Slack.", - "tryButton": "Prueba los Agentes en la Nube" - } - }, "costs": { "totalWithSubtasks": "Costo total (incluyendo subtareas): ${{cost}}", "total": "Costo total: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Deteniendo la indexación..." }, "versionIndicator": { - "ariaLabel": "Versión {{version}} - Haz clic para ver las notas de la versión" - }, - "rooCloudCTA": { - "title": "¡Zoo Code Cloud está evolucionando!", - "description": "Ejecuta agentes remotos en la nube, accede a tus tareas desde cualquier lugar, colabora con otros y mucho más.", - "joinWaitlist": "Regístrate para recibir las últimas actualizaciones." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Edita tu mensaje..." diff --git a/webview-ui/src/i18n/locales/fr/chat.json b/webview-ui/src/i18n/locales/fr/chat.json index 0a66b8eb61..5b9049ef79 100644 --- a/webview-ui/src/i18n/locales/fr/chat.json +++ b/webview-ui/src/i18n/locales/fr/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Copier vers l'entrée (ou Shift + clic)", "timerPrefix": "Approbation automatique activée. Sélection dans {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} est disponible", - "support": "Soutiens Zoo Code en nous donnant une étoile sur GitHub.", - "handoff": { - "heading": "Roo Code est de retour ! Désormais comme plugin maintenu par la communauté sous le nom Zoo Code !!", - "description": "Si tu n'as pas suivi, l'équipe Roo Code a récemment annoncé qu'elle arrêtait le développement de Roo Code et archivait le travail accompli. Mais pas de panique : la communauté a pris le relais pour faire vivre l'héritage de Roo Code avec un nouveau nom et un nouveau foyer ! Nous ne sommes plus juste un seul « Roo », nous sommes une communauté, un « Zoo » si tu veux. Zoo Code est un plugin maintenu par la communauté qui reprend là où Roo Code s'est arrêté, et nous nous engageons à préserver l'esprit de Roo tout en ajoutant de nouvelles fonctionnalités et améliorations. Nous voulons adresser un immense merci à toute l'équipe Roo Code pour son travail incroyable et pour avoir créé un outil aussi formidable pour les développeurs. Nous sommes ravis de poursuivre sur leurs bases et de voir jusqu'où la communauté mènera Zoo Code.", - "readMore": "Voir la nouvelle page d'accueil de Zoo Code et lire l'annonce complète" - }, - "release": { - "heading": "Quoi de neuf :", - "gpt55": "GPT-5.5 via OpenAI Codex : Le support de GPT-5.5 a été ajouté au fournisseur OpenAI Codex pour que tu puisses utiliser le tout dernier modèle directement depuis Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 sur Vertex AI : Claude Opus 4.7 a été ajouté au fournisseur Vertex AI, le tout nouveau modèle de raisonnement phare d'Anthropic.", - "checkpointNav": "Navigation vers les checkpoints précédents : Des contrôles ont été ajoutés dans le chat pour revenir en arrière à travers les checkpoints précédents, avec un support i18n complet." - }, - "cloudAgents": { - "heading": "Nouveautés dans le Cloud :", - "specialized": "Présentation d'Explainer, Planner et Coder - trois agents cloud spécialisés pour améliorer tes workflows.", - "description": "Les agents travaillent ensemble dans le cloud et peuvent être déclenchés depuis le web ou via Slack.", - "tryButton": "Essayer les Agents Cloud" - } - }, "costs": { "totalWithSubtasks": "Coût total (sous-tâches comprises) : ${{cost}}", "total": "Coût total : ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Arrêt de l'indexation..." }, "versionIndicator": { - "ariaLabel": "Version {{version}} - Cliquez pour voir les notes de version" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud évolue !", - "description": "Exécutez des agents distants dans le cloud, accédez à vos tâches de n'importe où, collaborez avec d'autres et bien plus encore.", - "joinWaitlist": "Inscrivez-vous pour recevoir les dernières mises à jour." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Modifiez votre message..." diff --git a/webview-ui/src/i18n/locales/hi/chat.json b/webview-ui/src/i18n/locales/hi/chat.json index a1f5181ff3..be0fd052e0 100644 --- a/webview-ui/src/i18n/locales/hi/chat.json +++ b/webview-ui/src/i18n/locales/hi/chat.json @@ -327,27 +327,6 @@ "copyToInput": "इनपुट में कॉपी करें (या Shift + क्लिक)", "timerPrefix": "ऑटो-अनुमोदन सक्षम है। {{seconds}}s में चयन किया जा रहा है…" }, - "announcement": { - "title": "Zoo Code {{version}} रिलीज़ हो गया", - "support": "कृपया GitHub पर हमें स्टार देकर Zoo Code का समर्थन करें।", - "handoff": { - "heading": "Roo Code वापस आ गया है! अब Zoo Code नाम के community-maintained plugin के रूप में!!", - "description": "अगर आपने हाल की खबर नहीं देखी, तो Roo Code टीम ने हाल ही में घोषणा की कि वे Roo Code का विकास बंद कर रहे हैं और अब तक किए गए काम को archive कर रहे हैं। लेकिन चिंता मत करें, community नए नाम और नए घर के साथ Roo Code की विरासत को आगे बढ़ाने के लिए आगे आई है! अब हम सिर्फ एक \"Roo\" नहीं हैं, हम एक community हैं — अगर चाहो तो एक \"Zoo\"। Zoo Code एक community-maintained plugin है जो वहीं से आगे बढ़ता है जहाँ Roo Code रुका था, और हम Roo की भावना को ज़िंदा रखते हुए नई सुविधाएँ और सुधार लाने के लिए प्रतिबद्ध हैं। हम पूरी Roo Code टीम को उनके शानदार काम और डेवलपर्स के लिए इतना बेहतरीन tool बनाने के लिए दिल से धन्यवाद देना चाहते हैं। हम उनकी बनाई नींव पर आगे निर्माण करने और यह देखने के लिए उत्साहित हैं कि community Zoo Code को आगे कहाँ ले जाती है!", - "readMore": "Zoo Code का नया होम पेज देखें और पूरी घोषणा पढ़ें" - }, - "release": { - "heading": "नया क्या है:", - "gpt55": "OpenAI Codex के माध्यम से GPT-5.5: OpenAI Codex provider में GPT-5.5 सपोर्ट जोड़ा गया, ताकि आप नवीनतम मॉडल का उपयोग सीधे Zoo Code से कर सकें।", - "claudeOpus47": "Vertex AI पर Claude Opus 4.7: Anthropic के नवीनतम flagship reasoning मॉडल के लिए Vertex AI provider में Claude Opus 4.7 जोड़ा गया।", - "checkpointNav": "पिछले Checkpoint की Navigation: चैट में controls जोड़े गए ताकि आप पिछले checkpoints पर वापस जा सकें, पूर्ण i18n सपोर्ट के साथ।" - }, - "cloudAgents": { - "heading": "क्लाउड में नया:", - "specialized": "Explainer, Planner, और Coder की शुरुआत - तीन विशेष क्लाउड एजेंट आपके वर्कफ़्लो को बेहतर बनाने के लिए।", - "description": "एजेंट क्लाउड में एक साथ काम करते हैं और web या Slack के माध्यम से ट्रिगर किए जा सकते हैं।", - "tryButton": "क्लाउड एजेंट आज़माएं" - } - }, "costs": { "totalWithSubtasks": "कुल लागत (उप-कार्यों सहित): ${{cost}}", "total": "कुल लागत: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "इंडेक्सिंग रोक रहा है..." }, "versionIndicator": { - "ariaLabel": "संस्करण {{version}} - रिलीज़ नोट्स देखने के लिए क्लिक करें" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud विकसित हो रहा है!", - "description": "क्लाउड में रिमोट एजेंट चलाएं, कहीं से भी अपने कार्यों तक पहुंचें, दूसरों के साथ सहयोग करें, और बहुत कुछ।", - "joinWaitlist": "नवीनतम अपडेट प्राप्त करने के लिए साइन अप करें।" + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "अपना संदेश संपादित करें..." diff --git a/webview-ui/src/i18n/locales/id/chat.json b/webview-ui/src/i18n/locales/id/chat.json index bb7aa8c7bf..fbc1087f3d 100644 --- a/webview-ui/src/i18n/locales/id/chat.json +++ b/webview-ui/src/i18n/locales/id/chat.json @@ -356,27 +356,6 @@ "triggerLabel_other": "{{count}} disetujui otomatis", "triggerLabelAll": "BRRR" }, - "announcement": { - "title": "Zoo Code {{version}} Dirilis", - "support": "Dukung Zoo Code dengan memberi kami bintang di GitHub.", - "handoff": { - "heading": "Roo Code kembali! Sekarang sebagai plugin yang dikelola komunitas bernama Zoo Code!!", - "description": "Kalau kamu belum mengikuti kabarnya, tim Roo Code baru-baru ini mengumumkan bahwa mereka menghentikan pengembangan Roo Code dan mengarsipkan pekerjaan yang telah mereka lakukan. Tapi jangan khawatir, komunitas telah melangkah maju untuk melanjutkan warisan Roo Code dengan nama baru dan rumah baru! Kita bukan lagi satu \"Roo\" saja, kita adalah sebuah komunitas, sebuah \"Zoo\" kalau boleh dibilang. Zoo Code adalah plugin yang dikelola komunitas dan melanjutkan dari titik terakhir Roo Code, dan kami berkomitmen menjaga semangat Roo tetap hidup sambil menghadirkan fitur dan peningkatan baru. Kami juga ingin memberi apresiasi besar kepada seluruh tim Roo Code atas kerja luar biasa mereka dan karena telah menciptakan alat yang luar biasa untuk para developer. Kami antusias melanjutkan fondasi mereka dan melihat ke mana komunitas akan membawa Zoo Code ke depannya!", - "readMore": "Lihat halaman beranda baru Zoo Code dan baca pengumuman lengkapnya" - }, - "release": { - "heading": "Yang Baru:", - "gpt55": "GPT-5.5 via OpenAI Codex: Dukungan GPT-5.5 ditambahkan di provider OpenAI Codex agar kamu bisa menggunakan model terbaru langsung dari Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 di Vertex AI: Claude Opus 4.7 ditambahkan ke provider Vertex AI untuk model reasoning andalan terbaru dari Anthropic.", - "checkpointNav": "Navigasi Checkpoint Sebelumnya: Menambahkan kontrol di chat untuk melompat kembali ke checkpoint sebelumnya, dengan dukungan i18n penuh." - }, - "cloudAgents": { - "heading": "Baru di Cloud:", - "specialized": "Memperkenalkan Explainer, Planner, dan Coder - tiga agen cloud khusus untuk meningkatkan alur kerja Anda.", - "description": "Agen bekerja bersama di cloud dan dapat dipicu dari web atau melalui Slack.", - "tryButton": "Coba Agen Cloud" - } - }, "reasoning": { "thinking": "Berpikir", "seconds": "{{count}}d" @@ -424,12 +403,7 @@ "stopping": "Menghentikan pengindeksan..." }, "versionIndicator": { - "ariaLabel": "Versi {{version}} - Klik untuk melihat catatan rilis" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud sedang berkembang!", - "description": "Jalankan agen jarak jauh di cloud, akses tugas Anda dari mana saja, berkolaborasi dengan orang lain, dan banyak lagi.", - "joinWaitlist": "Daftar untuk mendapatkan pembaruan terbaru." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Edit pesan Anda..." diff --git a/webview-ui/src/i18n/locales/it/chat.json b/webview-ui/src/i18n/locales/it/chat.json index fb1ab9cd76..53ac3c3e74 100644 --- a/webview-ui/src/i18n/locales/it/chat.json +++ b/webview-ui/src/i18n/locales/it/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Copia nell'input (o Shift + clic)", "timerPrefix": "Approvazione automatica abilitata. Selezione tra {{seconds}}s…" }, - "announcement": { - "title": "Rilasciato Zoo Code {{version}}", - "support": "Sostieni Zoo Code lasciandoci una stella su GitHub.", - "handoff": { - "heading": "Roo Code è tornato! Ora come plugin mantenuto dalla community chiamato Zoo Code!!", - "description": "Se non l'hai seguito, il team di Roo Code ha annunciato di recente che interromperà lo sviluppo di Roo Code e archivierà il lavoro svolto. Ma niente paura: la community si è fatta avanti per continuare l'eredità di Roo Code con un nuovo nome e una nuova casa! Non siamo più solo un singolo \"Roo\", ma una community, uno \"Zoo\" se vuoi. Zoo Code è un plugin mantenuto dalla community che riprende da dove Roo Code si era fermato, e ci impegniamo a mantenere vivo lo spirito di Roo introducendo anche nuove funzionalità e miglioramenti. Vogliamo ringraziare di cuore tutto il team di Roo Code per il lavoro incredibile e per aver creato uno strumento così straordinario per gli sviluppatori. Siamo entusiasti di continuare a costruire sulla loro base e di vedere dove la community porterà Zoo Code in futuro!", - "readMore": "Vai alla nuova home page di Zoo Code e leggi l'annuncio completo" - }, - "release": { - "heading": "Novità:", - "gpt55": "GPT-5.5 via OpenAI Codex: Aggiunto il supporto a GPT-5.5 nel provider OpenAI Codex così puoi usare il modello più recente direttamente da Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 su Vertex AI: Aggiunto Claude Opus 4.7 al provider Vertex AI, il nuovo modello di ragionamento di punta di Anthropic.", - "checkpointNav": "Navigazione Checkpoint Precedenti: Aggiunti controlli nella chat per tornare indietro ai checkpoint precedenti, con pieno supporto i18n." - }, - "cloudAgents": { - "heading": "Novità nel Cloud:", - "specialized": "Presentazione di Explainer, Planner e Coder - tre agenti cloud specializzati per migliorare i tuoi flussi di lavoro.", - "description": "Gli agenti lavorano insieme nel cloud e possono essere attivati dal web o tramite Slack.", - "tryButton": "Prova gli Agenti Cloud" - } - }, "costs": { "totalWithSubtasks": "Costo totale (sottoattività incluse): ${{cost}}", "total": "Costo totale: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Interruzione dell'indicizzazione..." }, "versionIndicator": { - "ariaLabel": "Versione {{version}} - Clicca per visualizzare le note di rilascio" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud si sta evolvendo!", - "description": "Esegui agenti remoti nel cloud, accedi alle tue attività da qualsiasi luogo, collabora con altri e molto altro.", - "joinWaitlist": "Registrati per ricevere gli ultimi aggiornamenti." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Modifica il tuo messaggio..." diff --git a/webview-ui/src/i18n/locales/ja/chat.json b/webview-ui/src/i18n/locales/ja/chat.json index 92a031383a..5a03b82775 100644 --- a/webview-ui/src/i18n/locales/ja/chat.json +++ b/webview-ui/src/i18n/locales/ja/chat.json @@ -327,27 +327,6 @@ "copyToInput": "入力欄にコピー(またはShift + クリック)", "timerPrefix": "自動承認が有効です。{{seconds}}秒後に選択中…" }, - "announcement": { - "title": "Zoo Code {{version}} リリース", - "support": "GitHubでスターを付けて Zoo Code を応援してください。", - "handoff": { - "heading": "Roo Code が帰ってきた!今度はコミュニティメンテナンスのプラグイン、Zoo Code です!!", - "description": "まだ追えていない方のために言うと、Roo Code チームは最近、Roo Code の開発を終了し、これまでの成果をアーカイブすると発表しました。でも心配はいりません。コミュニティが新しい名前と新しい拠点のもとで、Roo Code のレガシーを引き継ぐために立ち上がりました! もう私たちは 1 匹の「Roo」ではなく、いわば「Zoo」というコミュニティです。Zoo Code は Roo Code が残したところを引き継ぐコミュニティメンテナンスのプラグインで、Roo の精神を大切にしながら、新機能や改善も加えていくことを約束します。開発者のための素晴らしいツールを生み出してくれた Roo Code チーム全員に、心から大きな感謝を伝えたいです。彼らの土台の上にさらに築いていき、これからコミュニティが Zoo Code をどこまで育てていくのかを見るのが楽しみです!", - "readMore": "Zoo Code の新しいホームページを見て、完全なお知らせを読む" - }, - "release": { - "heading": "新機能:", - "gpt55": "OpenAI Codex 経由の GPT-5.5: OpenAI Codex プロバイダーで GPT-5.5 のサポートを追加しました。Zoo Code から最新モデルを直接利用できます。", - "claudeOpus47": "Vertex AI 上の Claude Opus 4.7: Anthropic の最新フラッグシップ推論モデルとして、Vertex AI プロバイダーに Claude Opus 4.7 を追加しました。", - "checkpointNav": "以前のチェックポイントへのナビゲーション: チャットから以前のチェックポイントへ戻るためのコントロールを追加しました。i18n にも完全対応しています。" - }, - "cloudAgents": { - "heading": "クラウドの新機能:", - "specialized": "ExplainerPlannerCoder の 3 つの専門クラウドエージェントを紹介します。ワークフローを強化します。", - "description": "エージェントはクラウドで連携して動作し、Web または Slack からトリガーできます。", - "tryButton": "クラウドエージェントを試す" - } - }, "costs": { "totalWithSubtasks": "合計コスト(サブタスク含む): ${{cost}}", "total": "合計コスト: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "インデックス作成を停止中..." }, "versionIndicator": { - "ariaLabel": "バージョン {{version}} - クリックしてリリースノートを表示" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud が進化中!", - "description": "クラウドでリモートエージェントを実行し、どこからでもタスクにアクセスし、他の人と協力し、その他多くの機能を利用できます。", - "joinWaitlist": "最新のアップデートを受け取るためにサインアップしてください。" + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "メッセージを編集..." diff --git a/webview-ui/src/i18n/locales/ko/chat.json b/webview-ui/src/i18n/locales/ko/chat.json index 6a69ebb2af..339752dd07 100644 --- a/webview-ui/src/i18n/locales/ko/chat.json +++ b/webview-ui/src/i18n/locales/ko/chat.json @@ -327,27 +327,6 @@ "copyToInput": "입력창에 복사 (또는 Shift + 클릭)", "timerPrefix": "자동 승인 활성화됨. {{seconds}}초 후 선택 중…" }, - "announcement": { - "title": "Zoo Code {{version}} 출시", - "support": "GitHub에서 별표를 눌러 Zoo Code를 응원해 주세요.", - "handoff": { - "heading": "Roo Code가 돌아왔습니다! 이제 커뮤니티가 유지 관리하는 플러그인 Zoo Code입니다!!", - "description": "최근 소식을 못 보셨다면, Roo Code 팀이 Roo Code 개발을 종료하고 지금까지의 작업을 아카이브하겠다고 발표했어요. 하지만 걱정하지 마세요. 커뮤니티가 나서서 Roo Code의 유산을 새로운 이름과 새로운 터전에서 이어가고 있어요! 이제 우리는 더 이상 하나의 \"Roo\"가 아니라, 말 그대로 하나의 커뮤니티, 즉 \"Zoo\"입니다. Zoo Code는 Roo Code가 멈춘 지점에서 이어받는 커뮤니티 유지 관리 플러그인이며, Roo의 정신을 지키면서도 새로운 기능과 개선 사항을 계속 추가해 나가겠습니다. 개발자들에게 이렇게 훌륭한 도구를 만들어 준 Roo Code 팀 전체에 진심으로 큰 감사를 전합니다. 그들이 만든 기반 위에 계속해서 쌓아 올리고, 앞으로 커뮤니티가 Zoo Code를 어디까지 발전시킬지 정말 기대하고 있습니다!", - "readMore": "Zoo Code의 새 홈페이지에서 전체 공지를 읽어보세요" - }, - "release": { - "heading": "새로운 기능:", - "gpt55": "OpenAI Codex를 통한 GPT-5.5: OpenAI Codex 제공업체에 GPT-5.5 지원을 추가해, Zoo Code에서 바로 최신 모델을 사용할 수 있어요.", - "claudeOpus47": "Vertex AI에서 Claude Opus 4.7: Anthropic의 최신 플래그십 추론 모델인 Claude Opus 4.7을 Vertex AI 제공업체에 추가했어요.", - "checkpointNav": "이전 체크포인트 탐색: 이전 체크포인트로 돌아갈 수 있는 컨트롤을 채팅에 추가했고, i18n을 완벽하게 지원해요." - }, - "cloudAgents": { - "heading": "클라우드의 새로운 기능:", - "specialized": "Explainer, Planner, Coder 세 가지 전문 클라우드 에이전트를 소개합니다. 워크플로우를 향상시킵니다.", - "description": "에이전트는 클라우드에서 함께 작동하며 웹 또는 Slack을 통해 트리거할 수 있습니다.", - "tryButton": "클라우드 에이전트 사용해보기" - } - }, "costs": { "totalWithSubtasks": "총 비용 (하위 작업 포함): ${{cost}}", "total": "총 비용: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "인덱싱 중지 중..." }, "versionIndicator": { - "ariaLabel": "버전 {{version}} - 릴리스 노트를 보려면 클릭하세요" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud가 진화하고 있습니다!", - "description": "클라우드에서 원격 에이전트를 실행하고, 어디서나 작업에 액세스하고, 다른 사람들과 협업하는 등 다양한 기능을 이용하세요.", - "joinWaitlist": "최신 업데이트를 받으려면 가입하세요." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "메시지 편집..." diff --git a/webview-ui/src/i18n/locales/nl/chat.json b/webview-ui/src/i18n/locales/nl/chat.json index 928bde4e0c..3528c14ec3 100644 --- a/webview-ui/src/i18n/locales/nl/chat.json +++ b/webview-ui/src/i18n/locales/nl/chat.json @@ -300,27 +300,6 @@ "triggerLabel_other": "{{count}} automatisch goedgekeurd", "triggerLabelAll": "BRRR" }, - "announcement": { - "title": "Zoo Code {{version}} uitgebracht", - "support": "Steun Zoo Code door ons een ster te geven op GitHub.", - "handoff": { - "heading": "Roo Code is terug! Nu als een door de community onderhouden plugin genaamd Zoo Code!!", - "description": "Als je het gemist hebt: het Roo Code-team heeft onlangs aangekondigd dat het de ontwikkeling van Roo Code afbouwt en het bestaande werk archiveert. Maar geen zorgen: de community is opgestaan om de erfenis van Roo Code voort te zetten met een nieuwe naam en een nieuw thuis. We zijn niet langer slechts één \"Roo\", maar een community — een \"Zoo\", zogezegd. Zoo Code is een door de community onderhouden plugin die verdergaat waar Roo Code ophield, en we zetten ons ervoor in om de geest van Roo levend te houden terwijl we ook nieuwe functies en verbeteringen introduceren. We willen het hele Roo Code-team enorm bedanken voor hun geweldige werk en voor het maken van zo'n fantastisch hulpmiddel voor ontwikkelaars. We kijken ernaar uit om verder te bouwen op hun fundament en te zien waar de community Zoo Code in de toekomst naartoe brengt!", - "readMore": "Bekijk de nieuwe homepage van Zoo Code en lees de volledige aankondiging" - }, - "release": { - "heading": "Wat is er nieuw:", - "gpt55": "GPT-5.5 via OpenAI Codex: GPT-5.5-ondersteuning toegevoegd in de OpenAI Codex-provider, zodat je het nieuwste model direct vanuit Zoo Code kunt gebruiken.", - "claudeOpus47": "Claude Opus 4.7 op Vertex AI: Claude Opus 4.7 toegevoegd aan de Vertex AI-provider voor Anthropic's nieuwste vlaggenschip-reasoningmodel.", - "checkpointNav": "Navigatie naar vorige checkpoints: Bediening toegevoegd in de chat om terug te springen door eerdere checkpoints, met volledige i18n-ondersteuning." - }, - "cloudAgents": { - "heading": "Nieuw in de Cloud:", - "specialized": "Introductie van Explainer, Planner en Coder - drie gespecialiseerde cloud-agents om je workflows te verbeteren.", - "description": "De agents werken samen in de cloud en kunnen worden geactiveerd vanaf het web of via Slack.", - "tryButton": "Probeer Cloud-agents" - } - }, "reasoning": { "thinking": "Denkt na", "seconds": "{{count}}s" @@ -418,12 +397,7 @@ "stopping": "Indexering wordt gestopt..." }, "versionIndicator": { - "ariaLabel": "Versie {{version}} - Klik om release notes te bekijken" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud evolueert!", - "description": "Voer externe agenten uit in de cloud, krijg overal toegang tot je taken, werk samen met anderen en nog veel meer.", - "joinWaitlist": "Meld je aan om de laatste updates te ontvangen." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Bewerk je bericht..." diff --git a/webview-ui/src/i18n/locales/pl/chat.json b/webview-ui/src/i18n/locales/pl/chat.json index 41763d1ca6..69e4a5d18f 100644 --- a/webview-ui/src/i18n/locales/pl/chat.json +++ b/webview-ui/src/i18n/locales/pl/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Kopiuj do pola wprowadzania (lub Shift + kliknięcie)", "timerPrefix": "Automatyczne zatwierdzanie włączone. Zaznaczanie za {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} wydany", - "support": "Wesprzyj Zoo Code, dając nam gwiazdkę na GitHub.", - "handoff": { - "heading": "Roo Code wraca! Teraz jako wtyczka utrzymywana przez społeczność pod nazwą Zoo Code!!", - "description": "Jeśli nie jesteś na bieżąco, zespół Roo Code niedawno ogłosił, że wygasza rozwój Roo Code i archiwizuje dotychczasową pracę. Ale bez obaw — społeczność ruszyła do działania, aby kontynuować dziedzictwo Roo Code pod nową nazwą i w nowym domu! Nie jesteśmy już tylko jednym „Roo” — jesteśmy społecznością, czyli „Zoo”, jeśli wolisz. Zoo Code to wtyczka utrzymywana przez społeczność, która przejmuje pałeczkę tam, gdzie Roo Code skończył, i zobowiązujemy się zachować ducha Roo, jednocześnie wprowadzając nowe funkcje i ulepszenia. Chcemy też ogromnie podziękować całemu zespołowi Roo Code za ich niesamowitą pracę i stworzenie tak świetnego narzędzia dla deweloperów. Cieszymy się, że możemy rozwijać ich dorobek i zobaczyć, dokąd społeczność zaprowadzi Zoo Code w przyszłości!", - "readMore": "Zobacz nową stronę główną Zoo Code i przeczytaj pełne ogłoszenie" - }, - "release": { - "heading": "Co nowego:", - "gpt55": "GPT-5.5 przez OpenAI Codex: Dodano obsługę GPT-5.5 w dostawcy OpenAI Codex, żebyś mógł korzystać z najnowszego modelu bezpośrednio z Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 w Vertex AI: Dodano Claude Opus 4.7 do dostawcy Vertex AI - najnowszy flagowy model rozumowania od Anthropic.", - "checkpointNav": "Nawigacja po poprzednich checkpointach: Dodano kontrolki w czacie, żebyś mógł cofać się do wcześniejszych checkpointów, z pełną obsługą i18n." - }, - "cloudAgents": { - "heading": "Nowości w chmurze:", - "specialized": "Przedstawiamy Explainer, Planner i Coder - trzech wyspecjalizowanych agentów chmurowych, aby ulepszyć Twoje przepływy pracy.", - "description": "Agenci pracują razem w chmurze i mogą być uruchamiani z sieci lub przez Slack.", - "tryButton": "Wypróbuj agentów chmurowych" - } - }, "costs": { "totalWithSubtasks": "Całkowity koszt (w tym podzadania): ${{cost}}", "total": "Całkowity koszt: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Zatrzymywanie indeksowania..." }, "versionIndicator": { - "ariaLabel": "Wersja {{version}} - Kliknij, aby wyświetlić informacje o wydaniu" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud się rozwija!", - "description": "Uruchamiaj zdalne agenty w chmurze, uzyskuj dostęp do swoich zadań z dowolnego miejsca, współpracuj z innymi i wiele więcej.", - "joinWaitlist": "Zarejestruj się, aby otrzymywać najnowsze aktualizacje." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Edytuj swoją wiadomość..." diff --git a/webview-ui/src/i18n/locales/pt-BR/chat.json b/webview-ui/src/i18n/locales/pt-BR/chat.json index 3d2e7f8df7..9aa8a4f49b 100644 --- a/webview-ui/src/i18n/locales/pt-BR/chat.json +++ b/webview-ui/src/i18n/locales/pt-BR/chat.json @@ -327,27 +327,6 @@ "copyToInput": "Copiar para entrada (ou Shift + clique)", "timerPrefix": "Aprovação automática ativada. Selecionando em {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} lançado", - "support": "Apoie o Zoo Code nos dando uma estrela no GitHub.", - "handoff": { - "heading": "O Roo Code está de volta, agora como um plugin mantido pela comunidade chamado Zoo Code!!", - "description": "Se você não acompanhou, a equipe do Roo Code anunciou recentemente que vai encerrar o desenvolvimento do Roo Code e arquivar o trabalho que fez. Mas não se preocupe: a comunidade assumiu para continuar o legado do Roo Code com um novo nome e um novo lar! Não somos mais apenas um único \"Roo\" — somos uma comunidade, um \"Zoo\", por assim dizer. O Zoo Code é um plugin mantido pela comunidade que continua de onde o Roo Code parou, e estamos comprometidos em manter vivo o espírito do Roo enquanto também trazemos novos recursos e melhorias. Queremos deixar um enorme agradecimento a toda a equipe do Roo Code pelo trabalho incrível e por criar uma ferramenta tão fantástica para desenvolvedores. Estamos animados para continuar construindo sobre essa base e ver até onde a comunidade levará o Zoo Code no futuro!", - "readMore": "Veja a nova página inicial do Zoo Code e leia o anúncio completo" - }, - "release": { - "heading": "Novidades:", - "gpt55": "GPT-5.5 via OpenAI Codex: Adicionado suporte ao GPT-5.5 no provedor OpenAI Codex para você usar o modelo mais recente diretamente do Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 no Vertex AI: Adicionado o Claude Opus 4.7 ao provedor Vertex AI, o mais novo modelo de raciocínio flagship da Anthropic.", - "checkpointNav": "Navegação por checkpoints anteriores: Adicionados controles no chat para voltar por checkpoints anteriores, com suporte completo a i18n." - }, - "cloudAgents": { - "heading": "Novidades na Nuvem:", - "specialized": "Apresentando Explainer, Planner e Coder - três agentes em nuvem especializados para aprimorar seus fluxos de trabalho.", - "description": "Os agentes trabalham juntos na nuvem e podem ser acionados a partir da web ou por meio do Slack.", - "tryButton": "Experimentar Agentes em Nuvem" - } - }, "costs": { "totalWithSubtasks": "Custo Total (incluindo subtarefas): ${{cost}}", "total": "Custo Total: ${{cost}}", @@ -418,12 +397,7 @@ "stopping": "Parando a indexação..." }, "versionIndicator": { - "ariaLabel": "Versão {{version}} - Clique para ver as notas de lançamento" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud está evoluindo!", - "description": "Execute agentes remotos na nuvem, acesse suas tarefas de qualquer lugar, colabore com outros e muito mais.", - "joinWaitlist": "Cadastre-se para receber as últimas atualizações." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Edite sua mensagem..." diff --git a/webview-ui/src/i18n/locales/ru/chat.json b/webview-ui/src/i18n/locales/ru/chat.json index f144d796a2..e497abb487 100644 --- a/webview-ui/src/i18n/locales/ru/chat.json +++ b/webview-ui/src/i18n/locales/ru/chat.json @@ -301,27 +301,6 @@ "triggerLabel_other": "{{count}} авто-утвержденных", "triggerLabelAll": "BRRR" }, - "announcement": { - "title": "Выпущен Zoo Code {{version}}", - "support": "Поддержите Zoo Code, поставив нам звезду на GitHub.", - "handoff": { - "heading": "Roo Code вернулся — теперь это плагин сообщества под названием Zoo Code!!", - "description": "Если ты не следил за новостями, команда Roo Code недавно объявила, что сворачивает разработку Roo Code и архивирует всю проделанную работу. Но не переживай: сообщество взяло эстафету, чтобы продолжить наследие Roo Code под новым именем и в новом доме! Теперь это уже не просто один «Roo», а целое сообщество — «Zoo», если хочешь. Zoo Code — это плагин, который поддерживает сообщество и продолжает путь с того места, где остановился Roo Code. Мы намерены сохранить дух Roo и при этом привносить новые функции и улучшения. Огромное спасибо всей команде Roo Code за их невероятную работу и за создание такого замечательного инструмента для разработчиков. Нам не терпится развивать их основу дальше и увидеть, куда сообщество приведёт Zoo Code в будущем!", - "readMore": "Открыть новую домашнюю страницу Zoo Code и прочитать полное объявление" - }, - "release": { - "heading": "Что нового:", - "gpt55": "GPT-5.5 через OpenAI Codex: Добавлена поддержка GPT-5.5 в провайдере OpenAI Codex, чтобы ты мог использовать новейшую модель прямо из Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 в Vertex AI: Добавлен Claude Opus 4.7 в провайдер Vertex AI — новейшую флагманскую модель рассуждений от Anthropic.", - "checkpointNav": "Навигация по предыдущим контрольным точкам: Добавлены элементы управления в чат, чтобы переходить назад по предыдущим контрольным точкам, с полной поддержкой i18n." - }, - "cloudAgents": { - "heading": "Новое в облаке:", - "specialized": "Представляем Explainer, Planner и Coder - трёх специализированных облачных агентов для улучшения ваших рабочих процессов.", - "description": "Агенты работают вместе в облаке и могут быть запущены из веб-интерфейса или через Slack.", - "tryButton": "Попробовать облачных агентов" - } - }, "reasoning": { "thinking": "Обдумывание", "seconds": "{{count}}с" @@ -419,12 +398,7 @@ "stopping": "Остановка индексации..." }, "versionIndicator": { - "ariaLabel": "Версия {{version}} - Нажмите, чтобы просмотреть примечания к выпуску" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud развивается!", - "description": "Запускайте удаленные агенты в облаке, получайте доступ к своим задачам из любого места, сотрудничайте с другими и многое другое.", - "joinWaitlist": "Зарегистрируйтесь, чтобы получать последние обновления." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Редактировать сообщение..." diff --git a/webview-ui/src/i18n/locales/tr/chat.json b/webview-ui/src/i18n/locales/tr/chat.json index 90a6273c8f..6c0cff5fe0 100644 --- a/webview-ui/src/i18n/locales/tr/chat.json +++ b/webview-ui/src/i18n/locales/tr/chat.json @@ -328,27 +328,6 @@ "copyToInput": "Giriş alanına kopyala (veya Shift + tıklama)", "timerPrefix": "Otomatik onay etkinleştirildi. {{seconds}}s içinde seçim yapılıyor…" }, - "announcement": { - "title": "Zoo Code {{version}} yayınlandı", - "support": "Lütfen GitHub'da bize yıldız vererek Zoo Code'u destekle.", - "handoff": { - "heading": "Roo Code geri döndü! Artık Zoo Code adlı, topluluk tarafından sürdürülen bir eklenti!!", - "description": "Takip etmiyorsan kaçırmış olabilirsin: Roo Code ekibi kısa süre önce Roo Code geliştirmesini aşamalı olarak sonlandırdığını ve yaptıkları çalışmaları arşivlediğini duyurdu. Ama endişelenme; topluluk, Roo Code mirasını yeni bir ad ve yeni bir yuva ile sürdürmek için öne çıktı! Artık sadece tek bir \"Roo\" değiliz; bir topluluğuz, istersen bir \"Zoo\" diyebilirsin. Zoo Code, Roo Code'un bıraktığı yerden devam eden, topluluk tarafından sürdürülen bir eklenti ve Roo'nun ruhunu korurken yeni özellikler ve iyileştirmeler sunmaya kararlıyız. Geliştiriciler için böylesine harika bir araç yarattıkları ve yaptıkları inanılmaz iş için tüm Roo Code ekibine kocaman bir teşekkür göndermek istiyoruz. Onların temeli üzerine inşa etmeyi sürdürmekten ve topluluğun gelecekte Zoo Code'u nereye taşıyacağını görmekten heyecan duyuyoruz!", - "readMore": "Zoo Code'un yeni ana sayfasına göz at ve tam duyuruyu oku" - }, - "release": { - "heading": "Yenilikler:", - "gpt55": "OpenAI Codex üzerinden GPT-5.5: En son modeli doğrudan Zoo Code'dan kullanabilmen için OpenAI Codex sağlayıcısına GPT-5.5 desteği eklendi.", - "claudeOpus47": "Vertex AI'da Claude Opus 4.7: Anthropic'in en yeni amiral gemisi akıl yürütme modeli olan Claude Opus 4.7 Vertex AI sağlayıcısına eklendi.", - "checkpointNav": "Önceki Checkpoint Navigasyonu: Sohbetten önceki checkpoint'lere geri atlayabilmen için kontroller eklendi ve tam i18n desteği sunuluyor." - }, - "cloudAgents": { - "heading": "Cloud'daki yenilikler:", - "specialized": "Explainer, Planner ve Coder tanıtımı - iş akışlarını geliştirmek için üç özel bulut ajanı.", - "description": "Ajanlar bulutta birlikte çalışır ve web'den veya Slack üzerinden tetiklenebilir.", - "tryButton": "Bulut Ajanlarını Dene" - } - }, "costs": { "totalWithSubtasks": "Toplam Maliyet (alt görevler dahil): ${{cost}}", "total": "Toplam Maliyet: ${{cost}}", @@ -419,12 +398,7 @@ "stopping": "İndeksleme durduruluyor..." }, "versionIndicator": { - "ariaLabel": "Sürüm {{version}} - Sürüm notlarını görüntülemek için tıklayın" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud gelişiyor!", - "description": "Bulutta uzak ajanlar çalıştırın, görevlerinize her yerden erişin, başkalarıyla işbirliği yapın ve daha fazlası.", - "joinWaitlist": "En son güncellemeleri almak için kaydolun." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Mesajını düzenle..." diff --git a/webview-ui/src/i18n/locales/vi/chat.json b/webview-ui/src/i18n/locales/vi/chat.json index fdc104f64f..52bf48c4c8 100644 --- a/webview-ui/src/i18n/locales/vi/chat.json +++ b/webview-ui/src/i18n/locales/vi/chat.json @@ -328,27 +328,6 @@ "copyToInput": "Sao chép vào ô nhập liệu (hoặc Shift + nhấp chuột)", "timerPrefix": "Phê duyệt tự động được bật. Chọn trong {{seconds}}s…" }, - "announcement": { - "title": "Zoo Code {{version}} đã phát hành", - "support": "Hãy ủng hộ Zoo Code bằng cách tặng sao cho chúng tôi trên GitHub.", - "handoff": { - "heading": "Roo Code đã trở lại, giờ là plugin do cộng đồng duy trì với tên gọi Zoo Code!!", - "description": "Nếu bạn chưa theo dõi, đội ngũ Roo Code gần đây đã thông báo họ sẽ dừng phát triển Roo Code và lưu trữ lại những gì họ đã xây dựng. Nhưng đừng lo, cộng đồng đã đứng ra tiếp nối di sản của Roo Code với một cái tên mới và một mái nhà mới! Chúng ta không còn chỉ là một \"Roo\" nữa, mà là cả một cộng đồng, một \"Zoo\" đúng nghĩa. Zoo Code là plugin do cộng đồng duy trì, tiếp nối từ nơi Roo Code dừng lại, và chúng tôi cam kết giữ vững tinh thần của Roo đồng thời mang đến các tính năng và cải tiến mới. Chúng tôi cũng muốn gửi lời cảm ơn sâu sắc đến toàn bộ đội ngũ Roo Code vì công sức tuyệt vời của họ và vì đã tạo ra một công cụ tuyệt vời cho các nhà phát triển. Chúng tôi rất háo hức được tiếp tục phát triển trên nền tảng đó và chờ xem cộng đồng sẽ đưa Zoo Code tiến xa đến đâu trong tương lai!", - "readMore": "Xem trang chủ mới của Zoo Code và đọc toàn bộ thông báo" - }, - "release": { - "heading": "Tính năng mới:", - "gpt55": "GPT-5.5 qua OpenAI Codex: Đã thêm hỗ trợ GPT-5.5 trong nhà cung cấp OpenAI Codex để bạn có thể dùng model mới nhất trực tiếp từ Zoo Code.", - "claudeOpus47": "Claude Opus 4.7 trên Vertex AI: Đã thêm Claude Opus 4.7 vào nhà cung cấp Vertex AI - model reasoning flagship mới nhất của Anthropic.", - "checkpointNav": "Điều hướng Checkpoint trước đó: Đã thêm các điều khiển trong chat để quay lại các checkpoint trước, với hỗ trợ i18n đầy đủ." - }, - "cloudAgents": { - "heading": "Mới trên Cloud:", - "specialized": "Giới thiệu Explainer, PlannerCoder - ba agent đám mây chuyên biệt để nâng cao quy trình làm việc của bạn.", - "description": "Các agent làm việc cùng nhau trên đám mây và có thể được kích hoạt từ web hoặc qua Slack.", - "tryButton": "Dùng thử Agents trên Cloud" - } - }, "costs": { "totalWithSubtasks": "Tổng chi phí (bao gồm các tác vụ phụ): ${{cost}}", "total": "Tổng chi phí: ${{cost}}", @@ -419,12 +398,7 @@ "stopping": "Đang dừng lập chỉ mục..." }, "versionIndicator": { - "ariaLabel": "Phiên bản {{version}} - Nhấp để xem ghi chú phát hành" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud đang phát triển!", - "description": "Chạy các agent từ xa trên cloud, truy cập các tác vụ của bạn từ mọi nơi, cộng tác với người khác và nhiều hơn nữa.", - "joinWaitlist": "Đăng ký để nhận các cập nhật mới nhất." + "ariaLabel": "Version {{version}}" }, "editMessage": { "placeholder": "Chỉnh sửa tin nhắn của bạn..." diff --git a/webview-ui/src/i18n/locales/zh-CN/chat.json b/webview-ui/src/i18n/locales/zh-CN/chat.json index ee61bdcad6..37c0e23566 100644 --- a/webview-ui/src/i18n/locales/zh-CN/chat.json +++ b/webview-ui/src/i18n/locales/zh-CN/chat.json @@ -328,27 +328,6 @@ "copyToInput": "复制到输入框(或按住Shift点击)", "timerPrefix": "自动批准已启用。{{seconds}}秒后选择中…" }, - "announcement": { - "title": "Zoo Code {{version}} 已发布", - "support": "请在 GitHub 上为 Zoo Code 点星支持我们。", - "handoff": { - "heading": "Roo Code 回来了!现在以社区维护的 Zoo Code 插件之名继续前进!!", - "description": "如果你还没关注到,Roo Code 团队最近宣布将逐步停止 Roo Code 的开发,并归档他们已经完成的工作。但别担心,社区已经站了出来,以全新的名称和新家园延续 Roo Code 的传承!我们不再只是一个单独的“Roo”,而是一个社区,一个“Zoo”。Zoo Code 是一个由社区维护的插件,在 Roo Code 停下的地方继续前进。我们会继续保留 Roo 的精神,同时带来新功能和改进。我们也要向整个 Roo Code 团队致以诚挚感谢,感谢他们的卓越工作,打造出这样一款出色的开发者工具。我们很高兴能在他们打下的基础上继续建设,也期待看到社区未来会把 Zoo Code 带到哪里!", - "readMore": "查看 Zoo Code 的新主页并阅读完整公告" - }, - "release": { - "heading": "新增功能:", - "gpt55": "通过 OpenAI Codex 支持 GPT-5.5:已在 OpenAI Codex 提供商中新增 GPT-5.5 支持,让你可以直接在 Zoo Code 中使用最新模型。", - "claudeOpus47": "Vertex AI 上的 Claude Opus 4.7:已将 Anthropic 最新旗舰推理模型 Claude Opus 4.7 添加到 Vertex AI 提供商。", - "checkpointNav": "上一存档点导航:在聊天中新增控件,可回退到此前的存档点,并提供完整的 i18n 支持。" - }, - "cloudAgents": { - "heading": "云端新功能:", - "specialized": "推出 ExplainerPlannerCoder - 三个专业云代理来增强你的工作流程。", - "description": "代理在云端协同工作,可从网页或通过 Slack 触发。", - "tryButton": "试用云代理" - } - }, "costs": { "totalWithSubtasks": "总成本(包括子任务): ${{cost}}", "total": "总成本: ${{cost}}", @@ -419,12 +398,7 @@ "stopping": "正在停止索引..." }, "versionIndicator": { - "ariaLabel": "版本 {{version}} - 点击查看发布说明" - }, - "rooCloudCTA": { - "title": "Zoo Code Cloud 正在进化!", - "description": "在云端运行远程代理,随时随地访问任务,与他人协作等更多功能。", - "joinWaitlist": "注册获取最新更新。" + "ariaLabel": "Version {{version}}" }, "command": { "triggerDescription": "触发 {{name}} 命令" diff --git a/webview-ui/src/i18n/locales/zh-TW/chat.json b/webview-ui/src/i18n/locales/zh-TW/chat.json index 14ef57c080..d35f3db0b4 100644 --- a/webview-ui/src/i18n/locales/zh-TW/chat.json +++ b/webview-ui/src/i18n/locales/zh-TW/chat.json @@ -349,27 +349,6 @@ "triggerLabel_other": "{{count}} 個自動核准", "triggerLabelAll": "BRRR" }, - "announcement": { - "title": "Zoo Code {{version}} 已發布", - "support": "請在 GitHub 上為 Zoo Code 加星支持我們。", - "handoff": { - "heading": "Roo Code 回來了!現在以社群維護的 Zoo Code 外掛重新登場!!", - "description": "如果你最近沒有追蹤消息,Roo Code 團隊最近宣布將逐步停止 Roo Code 的開發,並封存他們至今完成的工作。不過別擔心,社群已經挺身而出,將以新名稱與新家園延續 Roo Code 的傳承!我們不再只是單一的「Roo」,而是一個社群,也就是你可以稱之為「Zoo」的集合。Zoo Code 是一款由社群維護的外掛,接續 Roo Code 停下的地方繼續前進;我們承諾在保留 Roo 精神的同時,也會帶來新功能與改進。我們也要向整個 Roo Code 團隊致上最深的敬意,感謝他們不可思議的付出,以及為開發者打造出如此出色的工具。我們很期待在他們奠定的基礎上繼續建設,也期待看看社群未來會把 Zoo Code 帶往何方!", - "readMore": "查看 Zoo Code 的新首頁並閱讀完整公告" - }, - "release": { - "heading": "新增功能:", - "gpt55": "透過 OpenAI Codex 支援 GPT-5.5:已在 OpenAI Codex 供應商中新增 GPT-5.5 支援,讓你可以直接在 Zoo Code 中使用最新模型。", - "claudeOpus47": "Vertex AI 上的 Claude Opus 4.7:已將 Anthropic 最新旗艦推理模型 Claude Opus 4.7 新增至 Vertex AI 供應商。", - "checkpointNav": "前一個存檔點導覽:在聊天中新增控制項,可回到此前的存檔點,並提供完整的 i18n 支援。" - }, - "cloudAgents": { - "heading": "雲端的新功能:", - "specialized": "推出 ExplainerPlannerCoder,三個專業雲端代理用來強化工作流程。", - "description": "代理在雲端協同工作,可從網頁或透過 Slack 觸發。", - "tryButton": "試用雲端代理" - } - }, "reasoning": { "thinking": "思考中", "seconds": "{{count}} 秒" @@ -417,7 +396,7 @@ "stopping": "正在停止索引..." }, "versionIndicator": { - "ariaLabel": "版本 {{version}} - 點選查看發布說明" + "ariaLabel": "Version {{version}}" }, "command": { "triggerDescription": "觸發 {{name}} 命令"