Преглед изворни кода

Switch to new welcome view (#9741)

Matt Rubens пре 1 месец
родитељ
комит
152af1474e

+ 2 - 23
webview-ui/src/App.tsx

@@ -1,7 +1,6 @@
 import React, { useCallback, useEffect, useRef, useState, useMemo } from "react"
 import { useEvent } from "react-use"
 import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
-import posthog from "posthog-js"
 
 import { ExtensionMessage } from "@roo/ExtensionMessage"
 import TranslationProvider from "./i18n/TranslationContext"
@@ -15,8 +14,7 @@ import { ExtensionStateContextProvider, useExtensionState } from "./context/Exte
 import ChatView, { ChatViewRef } from "./components/chat/ChatView"
 import HistoryView from "./components/history/HistoryView"
 import SettingsView, { SettingsViewRef } from "./components/settings/SettingsView"
-import WelcomeView from "./components/welcome/WelcomeView"
-import WelcomeViewProvider from "./components/welcome/WelcomeViewProvider"
+import WelcomeView from "./components/welcome/WelcomeViewProvider"
 import { MarketplaceView } from "./components/marketplace/MarketplaceView"
 import { HumanRelayDialog } from "./components/human-relay/HumanRelayDialog"
 import { CheckpointRestoreDialog } from "./components/chat/CheckpointRestoreDialog"
@@ -79,21 +77,6 @@ const App = () => {
 		mdmCompliant,
 	} = useExtensionState()
 
-	const [useProviderSignupView, setUseProviderSignupView] = useState(false)
-
-	// Check PostHog feature flag for provider signup view
-	// Wait for telemetry to be initialized before checking feature flags
-	useEffect(() => {
-		if (!didHydrateState || telemetrySetting === "disabled") {
-			return
-		}
-
-		posthog.onFeatureFlags(function () {
-			// Feature flag for new provider-focused welcome view
-			setUseProviderSignupView(posthog?.getFeatureFlag("welcome-provider-signup") === "test")
-		})
-	}, [didHydrateState, telemetrySetting])
-
 	// Create a persistent state manager
 	const marketplaceStateManager = useMemo(() => new MarketplaceViewStateManager(), [])
 
@@ -260,11 +243,7 @@ const App = () => {
 	// Do not conditionally load ChatView, it's expensive and there's state we
 	// don't want to lose (user input, disableInput, askResponse promise, etc.)
 	return showWelcome ? (
-		useProviderSignupView ? (
-			<WelcomeViewProvider />
-		) : (
-			<WelcomeView />
-		)
+		<WelcomeView />
 	) : (
 		<>
 			{tab === "history" && <HistoryView onDone={() => switchTab("chat")} />}

+ 0 - 59
webview-ui/src/__tests__/App.spec.tsx

@@ -2,18 +2,9 @@
 
 import React from "react"
 import { render, screen, act, cleanup } from "@/utils/test-utils"
-import posthog from "posthog-js"
 
 import AppWithProviders from "../App"
 
-// Mock posthog
-vi.mock("posthog-js", () => ({
-	default: {
-		onFeatureFlags: vi.fn(),
-		getFeatureFlag: vi.fn(),
-	},
-}))
-
 vi.mock("@src/utils/vscode", () => ({
 	vscode: {
 		postMessage: vi.fn(),
@@ -312,54 +303,4 @@ describe("App", () => {
 		expect(chatView.getAttribute("data-hidden")).toBe("false")
 		expect(screen.queryByTestId("marketplace-view")).not.toBeInTheDocument()
 	})
-
-	describe("PostHog feature flag initialization", () => {
-		it("waits for state hydration before checking feature flags", () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: false,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: {},
-				language: "en",
-				telemetrySetting: "enabled",
-			})
-
-			render(<AppWithProviders />)
-
-			// PostHog feature flag check should not be called before hydration
-			expect(posthog.onFeatureFlags).not.toHaveBeenCalled()
-		})
-
-		it("checks feature flags after state hydration when telemetry is enabled", () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: true,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: {},
-				language: "en",
-				telemetrySetting: "enabled",
-			})
-
-			render(<AppWithProviders />)
-
-			// PostHog feature flag check should be called after hydration
-			expect(posthog.onFeatureFlags).toHaveBeenCalled()
-		})
-
-		it("does not check feature flags when telemetry is disabled", () => {
-			mockUseExtensionState.mockReturnValue({
-				didHydrateState: true,
-				showWelcome: false,
-				shouldShowAnnouncement: false,
-				experiments: {},
-				language: "en",
-				telemetrySetting: "disabled",
-			})
-
-			render(<AppWithProviders />)
-
-			// PostHog feature flag check should not be called when telemetry is disabled
-			expect(posthog.onFeatureFlags).not.toHaveBeenCalled()
-		})
-	})
 })

+ 0 - 212
webview-ui/src/components/welcome/WelcomeView.tsx

@@ -1,212 +0,0 @@
-import { useCallback, useState, useEffect } from "react"
-import knuthShuffle from "knuth-shuffle-seeded"
-import { Trans } from "react-i18next"
-import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
-import posthog from "posthog-js"
-
-import type { ProviderSettings } from "@roo-code/types"
-import { TelemetryEventName } from "@roo-code/types"
-
-import { useExtensionState } from "@src/context/ExtensionStateContext"
-import { validateApiConfiguration } from "@src/utils/validate"
-import { vscode } from "@src/utils/vscode"
-import { useAppTranslation } from "@src/i18n/TranslationContext"
-import { getRequestyAuthUrl, getOpenRouterAuthUrl } from "@src/oauth/urls"
-import { telemetryClient } from "@src/utils/TelemetryClient"
-import { Button } from "@src/components/ui"
-
-import ApiOptions from "../settings/ApiOptions"
-import { Tab, TabContent } from "../common/Tab"
-
-import RooHero from "./RooHero"
-
-const WelcomeView = () => {
-	const { apiConfiguration, currentApiConfigName, setApiConfiguration, uriScheme, machineId } = useExtensionState()
-	const { t } = useAppTranslation()
-	const [errorMessage, setErrorMessage] = useState<string | undefined>(undefined)
-	const [showRooProvider, setShowRooProvider] = useState(false)
-
-	// Check PostHog feature flag for Roo provider
-	useEffect(() => {
-		posthog.onFeatureFlags(function () {
-			setShowRooProvider(posthog?.getFeatureFlag("roo-provider-featured") === "test")
-		})
-	}, [])
-
-	// Memoize the setApiConfigurationField function to pass to ApiOptions
-	const setApiConfigurationFieldForApiOptions = useCallback(
-		<K extends keyof ProviderSettings>(field: K, value: ProviderSettings[K]) => {
-			setApiConfiguration({ [field]: value })
-		},
-		[setApiConfiguration], // setApiConfiguration from context is stable
-	)
-
-	const handleSubmit = useCallback(() => {
-		const error = apiConfiguration ? validateApiConfiguration(apiConfiguration) : undefined
-
-		if (error) {
-			setErrorMessage(error)
-			return
-		}
-
-		setErrorMessage(undefined)
-		vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration })
-	}, [apiConfiguration, currentApiConfigName])
-
-	// Using a lazy initializer so it reads once at mount
-	const [imagesBaseUri] = useState(() => {
-		const w = window as any
-		return w.IMAGES_BASE_URI || ""
-	})
-
-	return (
-		<Tab>
-			<TabContent className="flex flex-col gap-4 p-6">
-				<RooHero />
-				<h2 className="mt-0 mb-4 text-xl">{t("welcome:greeting")}</h2>
-
-				<div className="text-base text-vscode-foreground py-2 mb-4">
-					<p className="mb-3 leading-relaxed">
-						<Trans i18nKey="welcome:introduction" />
-					</p>
-					<p className="mb-0 leading-relaxed">
-						<Trans i18nKey="welcome:chooseProvider" />
-					</p>
-				</div>
-
-				<div className="mb-4">
-					<p className="text-sm font-medium mt-4 mb-3">{t("welcome:startRouter")}</p>
-
-					<div>
-						{/* Define the providers */}
-						{(() => {
-							// Provider card configuration
-							const baseProviders = [
-								{
-									slug: "requesty",
-									name: "Requesty",
-									description: t("welcome:routers.requesty.description"),
-									incentive: t("welcome:routers.requesty.incentive"),
-									authUrl: getRequestyAuthUrl(uriScheme),
-								},
-								{
-									slug: "openrouter",
-									name: "OpenRouter",
-									description: t("welcome:routers.openrouter.description"),
-									authUrl: getOpenRouterAuthUrl(uriScheme),
-								},
-							]
-
-							// Conditionally add Roo provider based on feature flag
-							const providers = showRooProvider
-								? [
-										...baseProviders,
-										{
-											slug: "roo",
-											name: "Roo Code Cloud",
-											description: t("welcome:routers.roo.description"),
-											incentive: t("welcome:routers.roo.incentive"),
-											authUrl: "#", // Placeholder since onClick handler will prevent default
-										},
-									]
-								: baseProviders
-
-							// Shuffle providers based on machine ID (will be consistent for the same machine)
-							const orderedProviders = [...providers]
-							knuthShuffle(orderedProviders, (machineId as any) || Date.now())
-
-							// Render the provider cards
-							return orderedProviders.map((provider, index) => (
-								<a
-									key={index}
-									href={provider.authUrl}
-									className="relative flex-1 border border-vscode-panel-border hover:bg-secondary rounded-md py-3 px-4 mb-2 flex flex-row gap-3 cursor-pointer transition-all no-underline text-inherit"
-									target="_blank"
-									rel="noopener noreferrer"
-									onClick={(e) => {
-										// Track telemetry for featured provider click
-										telemetryClient.capture(TelemetryEventName.FEATURED_PROVIDER_CLICKED, {
-											provider: provider.slug,
-										})
-
-										// Special handling for Roo provider
-										if (provider.slug === "roo") {
-											e.preventDefault()
-
-											// Set the Roo provider configuration
-											const rooConfig: ProviderSettings = {
-												apiProvider: "roo",
-											}
-
-											// Save the Roo provider configuration
-											vscode.postMessage({
-												type: "upsertApiConfiguration",
-												text: currentApiConfigName,
-												apiConfiguration: rooConfig,
-											})
-
-											// Then trigger cloud sign-in
-											vscode.postMessage({ type: "rooCloudSignIn" })
-										}
-										// For other providers, let the default link behavior work
-									}}>
-									{provider.incentive && (
-										<div className="absolute top-0 right-0 text-[10px] text-vscode-badge-foreground bg-vscode-badge-background px-2 py-0.5 rounded-bl rounded-tr-md">
-											{provider.incentive}
-										</div>
-									)}
-									<div className="w-8 h-8 flex-shrink-0">
-										<img
-											src={`${imagesBaseUri}/${provider.slug}.png`}
-											alt={provider.name}
-											className="w-full h-full object-contain"
-										/>
-									</div>
-									<div>
-										<div className="text-sm font-medium text-vscode-foreground">
-											{provider.name}
-										</div>
-										<div className="text-xs text-vscode-descriptionForeground">
-											{provider.description}
-										</div>
-									</div>
-								</a>
-							))
-						})()}
-					</div>
-
-					<p className="text-sm font-medium mt-6 mb-3">{t("welcome:startCustom")}</p>
-					<ApiOptions
-						fromWelcomeView
-						apiConfiguration={apiConfiguration || {}}
-						uriScheme={uriScheme}
-						setApiConfigurationField={setApiConfigurationFieldForApiOptions}
-						errorMessage={errorMessage}
-						setErrorMessage={setErrorMessage}
-					/>
-				</div>
-			</TabContent>
-			<div className="sticky bottom-0 bg-vscode-sideBar-background p-4 border-t border-vscode-panel-border">
-				<div className="flex flex-col gap-2">
-					<div className="flex justify-end">
-						<VSCodeLink
-							href="#"
-							onClick={(e) => {
-								e.preventDefault()
-								vscode.postMessage({ type: "importSettings" })
-							}}
-							className="text-sm">
-							{t("welcome:importSettings")}
-						</VSCodeLink>
-					</div>
-					<Button onClick={handleSubmit} variant="primary">
-						{t("welcome:start")}
-					</Button>
-					{errorMessage && <div className="text-vscode-errorForeground">{errorMessage}</div>}
-				</div>
-			</div>
-		</Tab>
-	)
-}
-
-export default WelcomeView