diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index a54dc97986..4021d6bccf 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -630,6 +630,9 @@ export class ClineProvider implements vscode.WebviewViewProvider { case "getLatestState": await this.postStateToWebview() break + case "subscribeEmail": + this.subscribeEmail(message.text) + break case "accountLoginClicked": { // Generate nonce for state validation const nonce = crypto.randomBytes(32).toString("hex") @@ -699,6 +702,36 @@ export class ClineProvider implements vscode.WebviewViewProvider { ) } + async subscribeEmail(email?: string) { + if (!email) { + return + } + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/ + if (!emailRegex.test(email)) { + vscode.window.showErrorMessage("Please enter a valid email address") + return + } + console.log("Subscribing email:", email) + this.postMessageToWebview({ type: "emailSubscribed" }) + // Currently ignoring errors to this endpoint, but after accounts we'll remove this anyways + try { + const response = await axios.post( + "https://app.cline.bot/api/mailing-list", + { + email: email, + }, + { + headers: { + "Content-Type": "application/json", + }, + }, + ) + console.log("Email subscribed successfully. Response:", response.data) + } catch (error) { + console.error("Failed to subscribe email:", error) + } + } + async cancelTask() { if (this.cline) { const { historyItem } = await this.getTaskWithId(this.cline.taskId) diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index 164b7c101b..306fbd00c0 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -25,6 +25,7 @@ export interface ExtensionMessage { | "relinquishControl" | "vsCodeLmModels" | "requestVsCodeLmModels" + | "emailSubscribed" text?: string action?: | "chatButtonClicked" diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index f5fb6eb9be..a18a3c405a 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -41,6 +41,7 @@ export interface WebviewMessage { | "getLatestState" | "accountLoginClicked" | "accountLogoutClicked" + | "subscribeEmail" // | "relaunchChromeDebugMode" text?: string disabled?: boolean diff --git a/webview-ui/src/components/welcome/WelcomeView.tsx b/webview-ui/src/components/welcome/WelcomeView.tsx index d3bbfbb9dc..a610f827f3 100644 --- a/webview-ui/src/components/welcome/WelcomeView.tsx +++ b/webview-ui/src/components/welcome/WelcomeView.tsx @@ -1,12 +1,14 @@ -import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react" -import { useEffect, useState } from "react" +import { VSCodeButton, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react" +import { useEffect, useState, useCallback } from "react" import { useExtensionState } from "../../context/ExtensionStateContext" import { validateApiConfiguration } from "../../utils/validate" import { vscode } from "../../utils/vscode" import ApiOptions from "../settings/ApiOptions" import { useTranslation } from "react-i18next" -import LanguageOptions from "../settings/LanguageOptions" import { Trans } from "react-i18next" +import { useEvent } from "react-use" +import { ExtensionMessage } from "../../../../src/shared/ExtensionMessage" +import LanguageOptions from "../settings/LanguageOptions" const WelcomeView = () => { const { t } = useTranslation("translation", { keyPrefix: "welcomeView" }) @@ -14,6 +16,8 @@ const WelcomeView = () => { const { apiConfiguration } = useExtensionState() const [apiErrorMessage, setApiErrorMessage] = useState(undefined) + const [email, setEmail] = useState("") + const [isSubscribed, setIsSubscribed] = useState(false) const disableLetsGoButton = apiErrorMessage != null @@ -21,10 +25,27 @@ const WelcomeView = () => { vscode.postMessage({ type: "apiConfiguration", apiConfiguration }) } + const handleSubscribe = () => { + if (email) { + vscode.postMessage({ type: "subscribeEmail", text: email }) + } + } + useEffect(() => { setApiErrorMessage(validateApiConfiguration(apiConfiguration)) }, [apiConfiguration]) + // Add message handler for subscription confirmation + const handleMessage = useCallback((e: MessageEvent) => { + const message: ExtensionMessage = e.data + if (message.type === "emailSubscribed") { + setIsSubscribed(true) + setEmail("") + } + }, []) + + useEvent("message", handleMessage) + return (
{ left: 0, right: 0, bottom: 0, - padding: "0 20px", }}> -

{t("greeting")}

-

- - ), - }} - /> -

+
+

{t("greeting")}

- {t("getStarted")} +
+ +
-
- - - - {t("letsGo")} - +

+ + ), + }} + /> +

+ + {t("getStarted")} + +
+ {isSubscribed ? ( +

+ + Thanks for subscribing! We'll keep you updated on new features. +

+ ) : ( + <> +

+ While Cline currently requires you bring your own API key, we are working on an official accounts + system with additional capabilities. Subscribe to our mailing list to get updates! +

+
+ setEmail(e.target.value)} + placeholder="Enter your email" + style={{ flex: 1 }} + /> + + Subscribe + +
+ + )} +
+ +
+ + + {t("letsGo")} + +
)