mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
onboarding screen iteration
This commit is contained in:
Vendored
+11
-15
@@ -21,26 +21,22 @@
|
||||
"name": "Run Extension (Fresh Install Mode)",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceFolder} --profile-temp"],
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--profile-temp",
|
||||
"--sync", "off",
|
||||
"--disable-extensions",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"preLaunchTask": "${defaultBuildTask}",
|
||||
"preLaunchTask": "clean-sandbox",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"postDebugTask": "stop",
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Run Extension (Test Mode)",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"preLaunchTask": "${defaultBuildTask}",
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"IS_TEST": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+6
@@ -185,6 +185,12 @@
|
||||
"label": "stop",
|
||||
"command": "echo ${input:terminate}",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"label": "clean-sandbox",
|
||||
"type": "shell",
|
||||
"dependsOn": ["watch"],
|
||||
"command": "rm -rf .vscode-dev"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
+1
-6
@@ -285,11 +285,6 @@
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Controls whether the MCP Marketplace is enabled."
|
||||
},
|
||||
"cline.showWelcomeTabOnInstall": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Controls whether the welcome tab is shown when the extension is installed."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -419,4 +414,4 @@
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"zod": "^3.24.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1704,6 +1704,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
||||
mcpMarketplaceEnabled,
|
||||
telemetrySetting,
|
||||
planActSeparateModelsSetting,
|
||||
showWelcome: false,
|
||||
vscMachineId: vscode.env.machineId,
|
||||
globalClineRulesToggles: globalClineRulesToggles || {},
|
||||
localClineRulesToggles: localClineRulesToggles || {},
|
||||
|
||||
@@ -5,9 +5,13 @@ import { getUri } from "./getUri"
|
||||
import { getTheme } from "@integrations/theme/getTheme"
|
||||
import { Controller } from "@core/controller/index"
|
||||
import { findLast } from "@shared/array"
|
||||
<<<<<<< HEAD
|
||||
import { readFile } from "fs/promises"
|
||||
import path from "node:path"
|
||||
|
||||
=======
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
>>>>>>> 7d06d3ab (onboarding screen iteration)
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/customSidebarViewProvider.ts
|
||||
@@ -24,6 +28,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
constructor(
|
||||
readonly context: vscode.ExtensionContext,
|
||||
private readonly outputChannel: vscode.OutputChannel,
|
||||
private readonly webviewType: WebviewType = "sidebar",
|
||||
) {
|
||||
WebviewProvider.activeInstances.add(this)
|
||||
this.controller = new Controller(context, outputChannel, (message) => this.view?.webview.postMessage(message))
|
||||
@@ -65,6 +70,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
webviewView.webview.options = {
|
||||
// Allow scripts in the webview
|
||||
enableScripts: true,
|
||||
|
||||
localResourceRoots: [this.context.extensionUri],
|
||||
}
|
||||
|
||||
@@ -331,6 +337,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta http-equiv="Content-Security-Policy" content="${csp.join("; ")}">
|
||||
<meta name="webview-type" content="${this.webviewType}">
|
||||
<link rel="stylesheet" type="text/css" href="${stylesUri}">
|
||||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<link href="${katexCssUri}" rel="stylesheet" />
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
import * as vscode from "vscode"
|
||||
import * as path from "path"
|
||||
import { Logger } from "../../services/logging/Logger"
|
||||
import { getUri } from "../webview/getUri"
|
||||
|
||||
export class WelcomeTabProvider {
|
||||
private static readonly WELCOME_TAB_SHOWN_KEY = "cline.welcomeTabShown"
|
||||
|
||||
constructor(private readonly context: vscode.ExtensionContext) {}
|
||||
|
||||
/**
|
||||
* Shows the welcome tab if it hasn't been shown before and is enabled in settings
|
||||
*/
|
||||
public async showWelcomeTabIfNeeded(): Promise<void> {
|
||||
// Check if we've already shown the welcome tab
|
||||
const hasShownWelcomeTab = this.context.globalState.get<boolean>(WelcomeTabProvider.WELCOME_TAB_SHOWN_KEY, false)
|
||||
|
||||
// Check if showing the welcome tab on install is enabled in settings
|
||||
const showWelcomeTabOnInstall = vscode.workspace.getConfiguration("cline").get<boolean>("showWelcomeTabOnInstall", true)
|
||||
|
||||
if (!hasShownWelcomeTab && showWelcomeTabOnInstall) {
|
||||
await this.showWelcomeTab()
|
||||
// Mark that we've shown the welcome tab
|
||||
await this.context.globalState.update(WelcomeTabProvider.WELCOME_TAB_SHOWN_KEY, true)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the welcome tab
|
||||
*/
|
||||
public async showWelcomeTab(): Promise<vscode.WebviewPanel> {
|
||||
Logger.log("Showing welcome tab")
|
||||
|
||||
// Create and show the webview panel
|
||||
const panel = vscode.window.createWebviewPanel(
|
||||
"clineWelcomeTab", // Unique ID
|
||||
"Welcome to Cline", // Title displayed in the tab
|
||||
vscode.ViewColumn.One, // Show in the first column
|
||||
{
|
||||
enableScripts: true,
|
||||
localResourceRoots: [this.context.extensionUri],
|
||||
},
|
||||
)
|
||||
|
||||
// Set the icon for the tab
|
||||
panel.iconPath = {
|
||||
light: vscode.Uri.joinPath(this.context.extensionUri, "assets", "icons", "robot_panel_light.png"),
|
||||
dark: vscode.Uri.joinPath(this.context.extensionUri, "assets", "icons", "robot_panel_dark.png"),
|
||||
}
|
||||
|
||||
// Get the content of the welcome tab
|
||||
panel.webview.html = await this.getWelcomeTabContent(panel.webview)
|
||||
|
||||
// Handle messages from the webview
|
||||
panel.webview.onDidReceiveMessage(
|
||||
(message) => {
|
||||
switch (message.command) {
|
||||
case "openCline":
|
||||
// Open Cline when the button is clicked
|
||||
vscode.commands.executeCommand("cline.openInNewTab")
|
||||
return
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
this.context.subscriptions,
|
||||
)
|
||||
|
||||
return panel
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTML content for the welcome tab
|
||||
*/
|
||||
private async getWelcomeTabContent(webview: vscode.Webview): Promise<string> {
|
||||
// Get the path to the welcome tab HTML file
|
||||
const htmlPath = vscode.Uri.joinPath(this.context.extensionUri, "webview-ui", "src", "assets", "welcome-tab.html")
|
||||
|
||||
// Read the HTML file
|
||||
const htmlContent = await vscode.workspace.fs.readFile(htmlPath)
|
||||
let htmlString = Buffer.from(htmlContent).toString("utf-8")
|
||||
|
||||
// Get the base path for assets
|
||||
const assetsPath = vscode.Uri.joinPath(this.context.extensionUri, "webview-ui", "src", "assets")
|
||||
|
||||
// Convert resource paths to webview URIs
|
||||
const cssUri = webview.asWebviewUri(vscode.Uri.joinPath(assetsPath, "css", "styles.css"))
|
||||
const jsUri = webview.asWebviewUri(vscode.Uri.joinPath(assetsPath, "js", "script.js"))
|
||||
|
||||
// Replace CSS and JS paths
|
||||
htmlString = htmlString.replace("css/styles.css", cssUri.toString())
|
||||
htmlString = htmlString.replace("js/script.js", jsUri.toString())
|
||||
|
||||
// Replace image paths
|
||||
const imageFiles = [
|
||||
"back-icon.svg",
|
||||
"vector.svg",
|
||||
"vector-1.svg",
|
||||
"feature-icon-1.svg",
|
||||
"feature-icon-2.svg",
|
||||
"feature-icon-3.svg",
|
||||
"feature-icon-4.svg",
|
||||
"action-icon-1.svg",
|
||||
"action-icon-2.svg",
|
||||
"button-icon-1.svg",
|
||||
"anthropic-model.jpg",
|
||||
"google-model.jpg",
|
||||
"meta-model.jpg",
|
||||
"feature-bg.png",
|
||||
"50.svg",
|
||||
]
|
||||
|
||||
for (const imageFile of imageFiles) {
|
||||
const imageUri = webview.asWebviewUri(vscode.Uri.joinPath(assetsPath, "images", imageFile))
|
||||
htmlString = htmlString.replace(`images/${imageFile}`, imageUri.toString())
|
||||
}
|
||||
|
||||
// Add Content Security Policy
|
||||
const csp = `
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none';
|
||||
style-src ${webview.cspSource} https://fonts.googleapis.com;
|
||||
font-src ${webview.cspSource} https://fonts.googleapis.com https://fonts.gstatic.com;
|
||||
img-src ${webview.cspSource} https: data:;
|
||||
script-src ${webview.cspSource};">
|
||||
`
|
||||
|
||||
// Insert CSP meta tag into the head section
|
||||
htmlString = htmlString.replace("</head>", `${csp}</head>`)
|
||||
|
||||
// Get the logo path (if needed)
|
||||
const logoUri = webview.asWebviewUri(vscode.Uri.joinPath(this.context.extensionUri, "assets", "icons", "icon.png"))
|
||||
|
||||
// Replace the placeholder with the actual logo path (if needed)
|
||||
htmlString = htmlString.replace("{{logoPath}}", logoUri.toString())
|
||||
|
||||
return htmlString
|
||||
}
|
||||
}
|
||||
+22
-20
@@ -12,7 +12,6 @@ import { telemetryService } from "./services/telemetry/TelemetryService"
|
||||
import { WebviewProvider } from "./core/webview"
|
||||
import { ErrorService } from "./services/error/ErrorService"
|
||||
import { initializeTestMode, cleanupTestMode } from "./services/test/TestMode"
|
||||
import { WelcomeTabProvider } from "./core/welcome/WelcomeTabProvider"
|
||||
|
||||
/*
|
||||
Built using https://github.com/microsoft/vscode-webview-ui-toolkit
|
||||
@@ -35,24 +34,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
Logger.initialize(outputChannel)
|
||||
Logger.log("Cline extension activated")
|
||||
|
||||
// Create the welcome tab provider
|
||||
const welcomeTabProvider = new WelcomeTabProvider(context)
|
||||
|
||||
// Show the welcome tab if it hasn't been shown before
|
||||
welcomeTabProvider.showWelcomeTabIfNeeded().catch((err) => {
|
||||
Logger.error("Failed to show welcome tab", err)
|
||||
})
|
||||
|
||||
// Register command to manually show the welcome tab
|
||||
context.subscriptions.push(
|
||||
vscode.commands.registerCommand("cline.showWelcomeTab", () => {
|
||||
welcomeTabProvider.showWelcomeTab().catch((err) => {
|
||||
Logger.error("Failed to show welcome tab", err)
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
const sidebarWebview = new WebviewProvider(context, outputChannel)
|
||||
const sidebarWebview = new WebviewProvider(context, outputChannel, "sidebar")
|
||||
|
||||
// Initialize test mode and add disposables to context
|
||||
context.subscriptions.push(...initializeTestMode(context, sidebarWebview))
|
||||
@@ -104,7 +86,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
Logger.log("Opening Cline in new tab")
|
||||
// (this example uses webviewProvider activation event which is necessary to deserialize cached webview, but since we use retainContextWhenHidden, we don't need to use that event)
|
||||
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
|
||||
const tabWebview = new WebviewProvider(context, outputChannel)
|
||||
const tabWebview = new WebviewProvider(context, outputChannel, "tab")
|
||||
//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
|
||||
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
|
||||
|
||||
@@ -133,6 +115,8 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
await vscode.commands.executeCommand("workbench.action.lockEditorGroup")
|
||||
}
|
||||
|
||||
checkInstallationStatus(context)
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand("cline.popoutButtonClicked", openClineInNewTab))
|
||||
context.subscriptions.push(vscode.commands.registerCommand("cline.openInNewTab", openClineInNewTab))
|
||||
|
||||
@@ -441,6 +425,24 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
)
|
||||
|
||||
return createClineAPI(outputChannel, sidebarWebview.controller)
|
||||
|
||||
async function checkInstallationStatus(context: vscode.ExtensionContext) {
|
||||
const VERSION_KEY = "cline.version"
|
||||
const current = context.extension.packageJSON.version as string
|
||||
const previous = context.globalState.get<string>(VERSION_KEY)
|
||||
|
||||
if (!previous) {
|
||||
// ── first-ever install ──
|
||||
WebviewProvider.getTabInstances().forEach(async (tab) => {
|
||||
const state = await tab.controller.getStateToPostToWebview()
|
||||
state.showWelcome = true
|
||||
await tab.controller.postMessageToWebview({ type: "state", state })
|
||||
})
|
||||
openClineInNewTab()
|
||||
}
|
||||
// persist for the next activation
|
||||
await context.globalState.update(VERSION_KEY, current)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find a solution for automatically removing DEV related content from production builds.
|
||||
|
||||
@@ -143,6 +143,7 @@ export interface ExtensionState {
|
||||
localClineRulesToggles: ClineRulesToggles
|
||||
localCursorRulesToggles: ClineRulesToggles
|
||||
localWindsurfRulesToggles: ClineRulesToggles
|
||||
showWelcome: boolean
|
||||
}
|
||||
|
||||
export interface ClineMessage {
|
||||
|
||||
@@ -125,3 +125,5 @@ export type ClineAskResponse = "yesButtonClicked" | "noButtonClicked" | "message
|
||||
export type ClineCheckpointRestore = "task" | "workspace" | "taskAndWorkspace"
|
||||
|
||||
export type TaskFeedbackType = "thumbs_up" | "thumbs_down"
|
||||
|
||||
export type WebviewType = "sidebar" | "tab"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { useEvent } from "react-use"
|
||||
import { ExtensionMessage } from "@shared/ExtensionMessage"
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
import ChatView from "./components/chat/ChatView"
|
||||
import HistoryView from "./components/history/HistoryView"
|
||||
import SettingsView from "./components/settings/SettingsView"
|
||||
import WelcomeView from "./components/welcome/WelcomeView"
|
||||
import AccountView from "./components/account/AccountView"
|
||||
import { useExtensionState } from "./context/ExtensionStateContext"
|
||||
import { vscode } from "./utils/vscode"
|
||||
@@ -97,7 +97,7 @@ const AppContent = () => {
|
||||
return (
|
||||
<>
|
||||
{showWelcome ? (
|
||||
<WelcomeView />
|
||||
<WelcomeWrapper />
|
||||
) : (
|
||||
<>
|
||||
{showSettings && <SettingsView onDone={hideSettings} />}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#006FEE" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 214 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#F31260" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 214 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#F5A524" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 214 B |
@@ -1,126 +0,0 @@
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Tab switching functionality
|
||||
const tabButtons = document.querySelectorAll(".tab-button")
|
||||
|
||||
tabButtons.forEach((button) => {
|
||||
button.addEventListener("click", function () {
|
||||
// Remove active class from all tabs
|
||||
tabButtons.forEach((btn) => {
|
||||
btn.classList.remove("active")
|
||||
})
|
||||
|
||||
// Add active class to clicked tab
|
||||
this.classList.add("active")
|
||||
|
||||
// Here you would typically show/hide content based on the selected tab
|
||||
// For this demo, we're just changing the active state of the tab
|
||||
})
|
||||
})
|
||||
|
||||
// Button hover effects
|
||||
const allButtons = document.querySelectorAll("button")
|
||||
|
||||
allButtons.forEach((button) => {
|
||||
button.addEventListener("mouseenter", function () {
|
||||
this.style.opacity = "1"
|
||||
this.style.transform = "scale(1.02)"
|
||||
this.style.transition = "all 0.2s ease"
|
||||
})
|
||||
|
||||
button.addEventListener("mouseleave", function () {
|
||||
this.style.transform = "scale(1)"
|
||||
|
||||
// Only reset opacity for action buttons that have default opacity of 0.5
|
||||
if (this.classList.contains("action-button")) {
|
||||
this.style.opacity = "0.5"
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
// Feature card hover effects
|
||||
const featureCards = document.querySelectorAll(".feature-card")
|
||||
|
||||
featureCards.forEach((card) => {
|
||||
card.addEventListener("mouseenter", function () {
|
||||
this.style.transform = "translateY(-5px)"
|
||||
this.style.boxShadow = "0 10px 20px rgba(0, 0, 0, 0.2)"
|
||||
this.style.transition = "all 0.3s ease"
|
||||
})
|
||||
|
||||
card.addEventListener("mouseleave", function () {
|
||||
this.style.transform = "translateY(0)"
|
||||
this.style.boxShadow = "none"
|
||||
})
|
||||
})
|
||||
|
||||
// Feature option hover effects
|
||||
const featureOptions = document.querySelectorAll(".feature-option")
|
||||
|
||||
featureOptions.forEach((option) => {
|
||||
option.addEventListener("mouseenter", function () {
|
||||
this.style.backgroundColor = "rgba(43, 43, 43, 0.5)"
|
||||
this.style.transition = "all 0.2s ease"
|
||||
})
|
||||
|
||||
option.addEventListener("mouseleave", function () {
|
||||
this.style.backgroundColor = "transparent"
|
||||
})
|
||||
})
|
||||
|
||||
// Input field focus effect
|
||||
const inputField = document.querySelector(".input-field")
|
||||
const inputPlaceholder = document.querySelector(".input-placeholder")
|
||||
|
||||
if (inputField && inputPlaceholder) {
|
||||
inputField.addEventListener("click", function () {
|
||||
inputPlaceholder.style.opacity = "0.7"
|
||||
inputField.style.borderColor = "#4DAAFC"
|
||||
|
||||
// Create a temporary input element for demonstration
|
||||
if (!document.querySelector(".temp-input")) {
|
||||
const tempInput = document.createElement("input")
|
||||
tempInput.type = "text"
|
||||
tempInput.className = "temp-input"
|
||||
tempInput.style.width = "100%"
|
||||
tempInput.style.background = "transparent"
|
||||
tempInput.style.border = "none"
|
||||
tempInput.style.outline = "none"
|
||||
tempInput.style.color = "#FFFFFF"
|
||||
tempInput.style.fontSize = "14px"
|
||||
tempInput.style.fontFamily = "SF Pro, Inter, sans-serif"
|
||||
|
||||
inputPlaceholder.style.display = "none"
|
||||
inputField.insertBefore(tempInput, inputField.firstChild)
|
||||
tempInput.focus()
|
||||
|
||||
tempInput.addEventListener("blur", function () {
|
||||
if (!this.value) {
|
||||
inputPlaceholder.style.display = "block"
|
||||
inputPlaceholder.style.opacity = "1"
|
||||
this.remove()
|
||||
}
|
||||
inputField.style.borderColor = "#3C3C3C"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Back button hover effect
|
||||
const backButton = document.querySelector(".back-button-container")
|
||||
|
||||
if (backButton) {
|
||||
backButton.addEventListener("mouseenter", function () {
|
||||
this.style.opacity = "0.8"
|
||||
this.style.cursor = "pointer"
|
||||
})
|
||||
|
||||
backButton.addEventListener("mouseleave", function () {
|
||||
this.style.opacity = "1"
|
||||
})
|
||||
|
||||
backButton.addEventListener("click", function () {
|
||||
// This would typically navigate back to the main Cline page
|
||||
alert("Navigating back to Cline...")
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -1,406 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Cline - Extension v1.0</title>
|
||||
<link rel="stylesheet" href="css/styles.css" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Azeret+Mono:wght@400;500&family=Inter:wght@400;500;600&family=SF+Pro:wght@400;500&display=swap"
|
||||
rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="home">
|
||||
<div class="main-container">
|
||||
<!-- Back Button Container -->
|
||||
<div class="back-button-container">
|
||||
<div class="back-icon">
|
||||
<img src="images/back-icon.svg" alt="Back Icon" />
|
||||
</div>
|
||||
<div class="back-text">Back to Cline</div>
|
||||
</div>
|
||||
|
||||
<!-- Account Info -->
|
||||
<div class="account-info">
|
||||
<img src="images/vector.svg" alt="Vector" class="vector-icon" />
|
||||
|
||||
<div class="welcome-message-container">
|
||||
<h1 class="welcome-message">Get Started on Cline</h1>
|
||||
<p class="description">Let's start and learn the basics of Cline</p>
|
||||
</div>
|
||||
|
||||
<div class="buttons-container">
|
||||
<button class="primary-button">Let's Create your Account!</button>
|
||||
<button class="secondary-button">Start Coding!</button>
|
||||
</div>
|
||||
|
||||
<div class="features-container">
|
||||
<div class="feature-row">
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon-container">
|
||||
<img src="images/feature-icon-1.svg" alt="Feature Icon" class="feature-icon" />
|
||||
<div class="feature-title">Snake game</div>
|
||||
</div>
|
||||
<div class="feature-description">> Build a Snake game...</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon-container">
|
||||
<img src="images/feature-icon-2.svg" alt="Feature Icon" class="feature-icon" />
|
||||
<div class="feature-title">To-do App</div>
|
||||
</div>
|
||||
<div class="feature-description">> Generate a to-do App...</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon-container">
|
||||
<img src="images/feature-icon-3.svg" alt="Feature Icon" class="feature-icon" />
|
||||
<div class="feature-title">Script</div>
|
||||
</div>
|
||||
<div class="feature-description">> Write a script and then...</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-card">
|
||||
<div class="feature-icon-container">
|
||||
<img src="images/feature-icon-4.svg" alt="Feature Icon" class="feature-icon" />
|
||||
<div class="feature-title">New Feature</div>
|
||||
</div>
|
||||
<div class="feature-description">> Read my code & suggest...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div class="input-field">
|
||||
<div class="input-placeholder">Type your prompt here...</div>
|
||||
|
||||
<div class="input-actions-container">
|
||||
<div class="input-actions">
|
||||
<button class="action-button action-button-secondary">
|
||||
<img src="images/action-icon-1.svg" alt="Action Icon" class="action-icon" />
|
||||
<span class="action-text">Improve prompt</span>
|
||||
</button>
|
||||
|
||||
<button class="action-button action-button-primary">
|
||||
<img src="images/action-icon-2.svg" alt="Action Icon" class="action-icon" />
|
||||
<span class="action-text">Start construction</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- Features Section -->
|
||||
<div class="features-section-container">
|
||||
<div class="features-text-container">
|
||||
<h2 class="features-heading">Work better with the best features of Cline</h2>
|
||||
<p class="features-description">
|
||||
It's easy to lose control as they make rapid changes to your codebase. That's why we built safe
|
||||
features to make the control on your code.
|
||||
</p>
|
||||
|
||||
<div class="divider-dashed"></div>
|
||||
|
||||
<div class="features-tabs-container">
|
||||
<button class="tab-button active">Key Features</button>
|
||||
<button class="tab-button">Tools</button>
|
||||
<button class="tab-button">Checkpoints</button>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="additional-feedback-container feature-highlight">
|
||||
<div class="icon-container">
|
||||
<img src="images/vector-1.svg" alt="Vector 1" class="vector-1-icon" />
|
||||
</div>
|
||||
|
||||
<div class="prompt-container">
|
||||
<div class="prompt-text-container">
|
||||
<h3 class="feature-title">File Editing</h3>
|
||||
<p class="feature-description">More context of this key feature</p>
|
||||
</div>
|
||||
|
||||
<div class="divider-dashed"></div>
|
||||
|
||||
<div class="prompt-buttons-container">
|
||||
<button class="feature-button">
|
||||
<img src="images/button-icon-1.svg" alt="Button Icon" class="button-icon" />
|
||||
<span class="button-text">Create new files</span>
|
||||
</button>
|
||||
|
||||
<button class="feature-button">
|
||||
<img src="images/button-icon-1.svg" alt="Button Icon" class="button-icon" />
|
||||
<span class="button-text">Modify existing code</span>
|
||||
</button>
|
||||
|
||||
<button class="feature-button">
|
||||
<img src="images/button-icon-1.svg" alt="Button Icon" class="button-icon" />
|
||||
<span class="button-text">Search and replace across files</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="additional-feedback-container feature-option">
|
||||
<div class="feature-circle"></div>
|
||||
<h3 class="feature-title">Terminal Commands</h3>
|
||||
</div>
|
||||
|
||||
<div class="additional-feedback-container feature-option">
|
||||
<div class="feature-circle"></div>
|
||||
<h3 class="feature-title">Code Analysis</h3>
|
||||
</div>
|
||||
|
||||
<div class="additional-feedback-container feature-option">
|
||||
<div class="feature-circle"></div>
|
||||
<h3 class="feature-title">Browser Integration</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="feature-image-container">
|
||||
<div class="feature-bg"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- Models Section -->
|
||||
<div class="models-container">
|
||||
<h2 class="models-heading">Top 3 models for coding</h2>
|
||||
|
||||
<div class="models-section-container">
|
||||
<!-- Anthropic Model Card -->
|
||||
<div class="model-card">
|
||||
<div class="model-header">
|
||||
<div class="model-name">anthropic</div>
|
||||
<div class="model-badge best">Best</div>
|
||||
</div>
|
||||
|
||||
<div class="model-description">Leading model for agentic coding</div>
|
||||
|
||||
<div class="model-divider"></div>
|
||||
|
||||
<img src="images/anthropic-model.jpg" alt="Anthropic Model" class="model-image" />
|
||||
|
||||
<button class="model-button">Create a new project</button>
|
||||
</div>
|
||||
|
||||
<!-- Google Model Card -->
|
||||
<div class="model-card">
|
||||
<div class="model-header">
|
||||
<div class="model-name">google</div>
|
||||
<div class="model-badge trending">Trending</div>
|
||||
</div>
|
||||
|
||||
<div class="model-description">Large 1M context window, great value</div>
|
||||
|
||||
<div class="model-divider"></div>
|
||||
|
||||
<img src="images/google-model.jpg" alt="Google Model" class="model-image" />
|
||||
|
||||
<button class="model-button">Create a new project</button>
|
||||
</div>
|
||||
|
||||
<!-- Meta-Llama Model Card -->
|
||||
<div class="model-card">
|
||||
<div class="model-header">
|
||||
<div class="model-name">meta-llama</div>
|
||||
<div class="model-badge new">New</div>
|
||||
</div>
|
||||
|
||||
<div class="model-description">Efficient performance at lower cost</div>
|
||||
|
||||
<div class="model-divider"></div>
|
||||
|
||||
<img src="images/meta-model.jpg" alt="Meta-Llama Model" class="model-image" />
|
||||
|
||||
<button class="model-button">Create a new project</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- Plan/Act Mode Section -->
|
||||
<div class="plan-act-container">
|
||||
<h2 class="plan-act-heading">Plan/Act Mode</h2>
|
||||
<p class="plan-act-description">Lorem Ipsum about this topic</p>
|
||||
|
||||
<div class="divider-dashed"></div>
|
||||
|
||||
<div class="plan-act-content">
|
||||
<!-- Plan Mode Column -->
|
||||
<div class="plan-mode-container">
|
||||
<div class="mode-header">
|
||||
<h3 class="mode-title">Plan Mode</h3>
|
||||
</div>
|
||||
<div class="mode-content">
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon plan-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0Y1QTUyNCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Plan Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon plan-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0Y1QTUyNCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Plan Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Strategy Development</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon plan-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0Y1QTUyNCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Plan Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Context Gathering</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon plan-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0Y1QTUyNCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Plan Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Requirements Analysis</div>
|
||||
</div>
|
||||
<div class="mode-item disabled">
|
||||
<div class="mode-icon plan-icon-disabled">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0YzMTI2MCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Disabled Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div class="mode-item disabled">
|
||||
<div class="mode-icon plan-icon-disabled">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iI0YzMTI2MCIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Disabled Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Act Mode Column -->
|
||||
<div class="act-mode-container">
|
||||
<div class="mode-header">
|
||||
<h3 class="mode-title">Act Mode</h3>
|
||||
</div>
|
||||
<div class="mode-content">
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Execute Commands</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Run Tests</div>
|
||||
</div>
|
||||
<div class="mode-item">
|
||||
<div class="mode-icon act-icon">
|
||||
<img
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxwYXRoIGQ9Ik0xIDdIMTMiIHN0cm9rZT0iIzAwNkZFRSIgc3Ryb2tlLXdpZHRoPSIyLjMzMzMzIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+"
|
||||
alt="Act Icon"
|
||||
class="line-icon" />
|
||||
</div>
|
||||
<div class="mode-text">Deploy Changes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- MCP Servers Section -->
|
||||
<div class="mcp-servers-container">
|
||||
<div class="mcp-content-container">
|
||||
<div class="mcp-text-container">
|
||||
<h2 class="mcp-heading">The largest ecosystem of MCP Servers for VS Code</h2>
|
||||
<p class="mcp-description">
|
||||
The Model Context Protocol (MCP) allows seamless communication with locally running servers that
|
||||
extend Cline's functionality with additional tools and context-aware resources.
|
||||
</p>
|
||||
<button class="mcp-button">Add an MCP Server</button>
|
||||
</div>
|
||||
<div class="mcp-count">
|
||||
<svg width="1048" height="187" viewBox="0 0 1048 187" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M64.0535 186.531C51.9601 186.531 41.2428 184.279 31.9016 179.775C22.6439 175.271 15.221 169.141 9.63304 161.385C4.12845 153.545 0.959134 144.704 0.125104 134.863L0 133.361H26.7724L26.8975 134.237C27.7315 139.658 29.8166 144.579 33.1527 148.999C36.5722 153.336 40.9509 156.798 46.2886 159.383C51.6264 161.885 57.5898 163.136 64.1786 163.136C71.7683 163.136 78.4822 161.51 84.3204 158.257C90.1586 155.004 94.7041 150.501 97.9568 144.746C101.21 138.991 102.836 132.402 102.836 124.979V124.729C102.836 117.39 101.168 110.884 97.8317 105.213C94.579 99.5414 90.0752 95.0794 84.3204 91.8267C78.5656 88.574 71.9768 86.9476 64.5539 86.9476C58.9659 86.9476 53.7949 87.7816 49.0409 89.4497C44.287 91.0343 40.0751 93.453 36.4054 96.7057C34.8207 98.1236 33.2778 99.7082 31.7765 101.46C30.3587 103.211 29.0659 105.088 27.8983 107.089H3.25272L12.1351 3.00251H119.85V26.6472H34.9041L29.3995 83.82H30.0251C32.694 79.7332 36.0718 76.272 40.1585 73.4363C44.3287 70.6006 48.9992 68.4738 54.1702 67.056C59.4246 65.5547 65.0126 64.8041 70.9342 64.8041C82.4438 64.8041 92.6607 67.3896 101.585 72.5606C110.509 77.6482 117.515 84.654 122.602 93.5781C127.773 102.502 130.359 112.719 130.359 124.229V124.479C130.359 136.656 127.523 147.415 121.852 156.756C116.18 166.097 108.34 173.395 98.3321 178.649C88.4071 183.904 76.9809 186.531 64.0535 186.531Z"
|
||||
fill="white" />
|
||||
<path
|
||||
d="M218.933 186.531C204.587 186.531 192.244 182.736 181.902 175.146C171.643 167.557 163.762 156.798 158.257 142.869C152.753 128.941 150 112.427 150 93.3279V93.0777C150 73.9784 152.753 57.4646 158.257 43.5363C163.762 29.6081 171.643 18.8908 181.902 11.3845C192.244 3.79483 204.587 0 218.933 0C233.278 0 245.58 3.79483 255.839 11.3845C266.181 18.8908 274.104 29.6081 279.608 43.5363C285.196 57.4646 287.99 73.9784 287.99 93.0777V93.3279C287.99 112.427 285.196 128.941 279.608 142.869C274.104 156.798 266.181 167.557 255.839 175.146C245.58 182.736 233.278 186.531 218.933 186.531ZM218.933 163.011C227.523 163.011 234.821 160.217 240.826 154.629C246.914 149.041 251.543 141.034 254.713 130.609C257.965 120.184 259.592 107.757 259.592 93.3279V93.0777C259.592 78.649 257.965 66.2637 254.713 55.9217C251.543 45.4963 246.914 37.4896 240.826 31.9016C234.821 26.3136 227.523 23.5196 218.933 23.5196C210.342 23.5196 203.003 26.3136 196.914 31.9016C190.909 37.4896 186.322 45.4963 183.153 55.9217C179.984 66.2637 178.399 78.649 178.399 93.0777V93.3279C178.399 107.757 179.984 120.184 183.153 130.609C186.322 141.034 190.909 149.041 196.914 154.629C203.003 160.217 210.342 163.011 218.933 163.011Z"
|
||||
fill="white" />
|
||||
<path
|
||||
d="M313.512 122.602V97.9568H443.745V122.602H313.512ZM366.306 173.019V47.5397H390.826V173.019H366.306Z"
|
||||
fill="white" />
|
||||
<path
|
||||
d="M526.44 183.528V3.00251H558.842L617.265 146.998H618.016L676.44 3.00251H708.967V183.528H683.321V50.4171H670.435L699.709 8.00668L628.024 183.528H607.257L535.697 8.00668L564.972 50.4171H552.086V183.528H526.44Z"
|
||||
fill="white" />
|
||||
<path
|
||||
d="M819.559 186.531C802.545 186.531 787.741 182.736 775.147 175.146C762.637 167.557 752.962 156.798 746.123 142.869C739.284 128.858 735.864 112.302 735.864 93.2028V93.0777C735.864 73.9784 739.284 57.4646 746.123 43.5363C752.962 29.6081 762.637 18.8908 775.147 11.3845C787.658 3.79483 802.462 0 819.559 0C832.82 0 844.789 2.54379 855.464 7.63137C866.14 12.719 874.939 19.7665 881.861 28.774C888.784 37.7815 893.162 48.2486 894.997 60.1752L895.122 61.4263H867.224L866.473 58.9242C864.555 51.8349 861.428 45.7465 857.091 40.6589C852.837 35.5714 847.541 31.6931 841.202 29.0242C834.947 26.2719 827.733 24.8958 819.559 24.8958C808.383 24.8958 798.667 27.6898 790.41 33.2778C782.236 38.8658 775.898 46.7474 771.394 56.9225C766.89 67.0977 764.638 79.1494 764.638 93.0777V93.2028C764.638 107.048 766.89 119.141 771.394 129.483C775.898 139.742 782.278 147.665 790.535 153.253C798.792 158.841 808.467 161.635 819.559 161.635C827.566 161.635 834.697 160.301 840.952 157.632C847.291 154.879 852.67 150.876 857.091 145.622C861.511 140.367 864.805 133.945 866.974 126.355L867.349 125.104H895.247L894.997 126.355C893.162 138.366 888.784 148.916 881.861 158.007C875.022 167.014 866.265 174.02 855.589 179.024C844.914 184.029 832.904 186.531 819.559 186.531Z"
|
||||
fill="white" />
|
||||
<path
|
||||
d="M934.78 121.852V98.3321H981.069C993.163 98.3321 1002.55 95.2045 1009.22 88.9493C1015.97 82.6106 1019.35 73.8533 1019.35 62.6773V62.4271C1019.35 51.0843 1015.97 42.2853 1009.22 36.0301C1002.55 29.7749 993.163 26.6472 981.069 26.6472H934.78V3.00251H988.075C999.918 3.00251 1010.3 5.5046 1019.23 10.5088C1028.23 15.4295 1035.28 22.352 1040.37 31.2761C1045.46 40.1168 1048 50.4171 1048 62.1769V62.4271C1048 74.1869 1045.46 84.5706 1040.37 93.5781C1035.28 102.502 1028.23 109.466 1019.23 114.471C1010.3 119.391 999.918 121.852 988.075 121.852H934.78ZM920.769 183.528V3.00251H948.792V183.528H920.769Z"
|
||||
fill="white" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,42 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { validateApiConfiguration } from "@/utils/validate"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import ApiOptions from "@/components/settings/ApiOptions"
|
||||
|
||||
interface ApiOptionsSectionProps {
|
||||
showApiOptions: boolean
|
||||
}
|
||||
|
||||
const ApiOptionsSection = ({ showApiOptions }: ApiOptionsSectionProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
|
||||
const disableLetsGoButton = apiErrorMessage != null
|
||||
|
||||
const handleSubmit = () => {
|
||||
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setApiErrorMessage(validateApiConfiguration(apiConfiguration))
|
||||
}, [apiConfiguration])
|
||||
|
||||
if (!showApiOptions) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-4.5 mb-8">
|
||||
<div>
|
||||
<ApiOptions showModelOptions={false} />
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} className="mt-0.75">
|
||||
Let's go!
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ApiOptionsSection
|
||||
@@ -0,0 +1,550 @@
|
||||
import { useState, useRef, useEffect, memo, Dispatch, SetStateAction } from "react"
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { EmptyRequest } from "@shared/proto/common"
|
||||
import ClineLogoWhite from "@/assets/ClineLogoWhite"
|
||||
import ApiOptionsSection from "./ApiOptionsSection"
|
||||
|
||||
// Import images
|
||||
import featureIcon1 from "@/assets/images/feature-icon-1.svg"
|
||||
import featureIcon2 from "@/assets/images/feature-icon-2.svg"
|
||||
import featureIcon3 from "@/assets/images/feature-icon-3.svg"
|
||||
import featureIcon4 from "@/assets/images/feature-icon-4.svg"
|
||||
import actionIcon1 from "@/assets/images/action-icon-1.svg"
|
||||
import actionIcon2 from "@/assets/images/action-icon-2.svg"
|
||||
import vector1 from "@/assets/images/vector-1.svg"
|
||||
import buttonIcon1 from "@/assets/images/button-icon-1.svg"
|
||||
import anthropicModel from "@/assets/images/anthropic-model.jpg"
|
||||
import googleModel from "@/assets/images/google-model.jpg"
|
||||
import metaModel from "@/assets/images/meta-model.jpg"
|
||||
import planLine from "@/assets/images/plan-line.svg"
|
||||
import actLine from "@/assets/images/act-line.svg"
|
||||
import disabledLine from "@/assets/images/disabled-line.svg"
|
||||
import featureImage from "@/assets/images/feature-image.jpg"
|
||||
import featureBg from "@/assets/images/feature-bg.png"
|
||||
|
||||
// Import CSS styles
|
||||
import "@/assets/css/styles.css"
|
||||
|
||||
interface WelcomeTabViewProps {
|
||||
onToggleView?: () => void
|
||||
showApiOptions?: boolean
|
||||
setShowApiOptions?: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const WelcomeTabView = memo(({ onToggleView, showApiOptions, setShowApiOptions }: WelcomeTabViewProps = {}) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const [activeTab, setActiveTab] = useState("Key Features")
|
||||
const inputFieldRef = useRef<HTMLDivElement>(null)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
const [inputValue, setInputValue] = useState("")
|
||||
const [showPlaceholder, setShowPlaceholder] = useState(true)
|
||||
|
||||
const handleLogin = () => {
|
||||
AccountServiceClient.accountLoginClicked(EmptyRequest.create()).catch((err) =>
|
||||
console.error("Failed to get login URL:", err),
|
||||
)
|
||||
}
|
||||
|
||||
const handleTabClick = (tabName: string) => {
|
||||
setActiveTab(tabName)
|
||||
}
|
||||
|
||||
const handleInputFieldClick = () => {
|
||||
setShowPlaceholder(false)
|
||||
inputRef.current?.focus()
|
||||
}
|
||||
|
||||
const handleInputBlur = () => {
|
||||
if (!inputValue) {
|
||||
setShowPlaceholder(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value)
|
||||
}
|
||||
|
||||
const handleCreateProject = (model: string) => {
|
||||
console.log(`Creating project with ${model} model`)
|
||||
// Implement project creation logic
|
||||
}
|
||||
|
||||
// Equivalent to document.addEventListener("DOMContentLoaded", ...)
|
||||
useEffect(() => {
|
||||
// No need to implement DOM manipulation here as we're using React state
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="home">
|
||||
{/* Toggle button to switch between old and new welcome views */}
|
||||
{onToggleView && (
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "10px",
|
||||
right: "10px",
|
||||
zIndex: 100,
|
||||
}}>
|
||||
<button
|
||||
onClick={onToggleView}
|
||||
style={{
|
||||
padding: "8px 12px",
|
||||
backgroundColor: "#0078d4",
|
||||
color: "#ffffff",
|
||||
border: "none",
|
||||
borderRadius: "4px",
|
||||
cursor: "pointer",
|
||||
fontSize: "12px",
|
||||
fontWeight: "bold",
|
||||
}}>
|
||||
Switch to Classic View
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="main-container">
|
||||
{/* Account Info */}
|
||||
<div className="account-info">
|
||||
<ClineLogoWhite className="vector-icon" />
|
||||
|
||||
<div className="welcome-message-container">
|
||||
<h1 className="welcome-message">Get Started on Cline</h1>
|
||||
<p className="description">Let's start and learn the basics of Cline</p>
|
||||
</div>
|
||||
|
||||
<div className="buttons-container">
|
||||
<button className="primary-button" onClick={handleLogin}>
|
||||
Let's Create your Account!
|
||||
</button>
|
||||
{showApiOptions !== undefined && setShowApiOptions !== undefined && !showApiOptions && (
|
||||
<button className="secondary-button" onClick={() => setShowApiOptions(true)}>
|
||||
Use your own API key
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{showApiOptions !== undefined && <ApiOptionsSection showApiOptions={showApiOptions} />}
|
||||
|
||||
<div className="features-container">
|
||||
<div className="feature-row">
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-1"></div>
|
||||
<div className="feature-title">Snake game</div>
|
||||
</div>
|
||||
<div className="feature-description">> Build a Snake game...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-2"></div>
|
||||
<div className="feature-title">To-do App</div>
|
||||
</div>
|
||||
<div className="feature-description">> Generate a to-do App...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-3"></div>
|
||||
<div className="feature-title">Script</div>
|
||||
</div>
|
||||
<div className="feature-description">> Write a script and then...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-4"></div>
|
||||
<div className="feature-title">New Feature</div>
|
||||
</div>
|
||||
<div className="feature-description">> Read my code & suggest...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="footer">
|
||||
<div
|
||||
className="input-field"
|
||||
ref={inputFieldRef}
|
||||
onClick={handleInputFieldClick}
|
||||
style={{
|
||||
position: "relative",
|
||||
cursor: "text",
|
||||
}}>
|
||||
{showPlaceholder && <div className="input-placeholder">Type your prompt here...</div>}
|
||||
{!showPlaceholder && (
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={handleInputChange}
|
||||
onBlur={handleInputBlur}
|
||||
style={{
|
||||
width: "100%",
|
||||
background: "transparent",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
color: "#FFFFFF",
|
||||
fontSize: "14px",
|
||||
fontFamily: "SF Pro, Inter, sans-serif",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="input-actions-container">
|
||||
<div className="input-actions">
|
||||
<button
|
||||
className="action-button action-button-secondary"
|
||||
style={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: 0.5,
|
||||
}}>
|
||||
<div className="action-icon action-icon-1"></div>
|
||||
<span className="action-text">Improve prompt</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="action-button action-button-primary"
|
||||
style={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: 0.5,
|
||||
}}>
|
||||
<div className="action-icon action-icon-2"></div>
|
||||
<span className="action-text">Start construction</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Features Section */}
|
||||
<div className="features-section-container">
|
||||
<div className="features-text-container">
|
||||
<h2 className="features-heading">Work better with the best features of Cline</h2>
|
||||
<p className="features-description">
|
||||
It's easy to lose control as they make rapid changes to your codebase. That's why we built safe
|
||||
features to make the control on your code.
|
||||
</p>
|
||||
|
||||
<div className="divider-dashed"></div>
|
||||
|
||||
<div className="features-tabs-container">
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Key Features" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Key Features")}>
|
||||
Key Features
|
||||
</button>
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Tools" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Tools")}>
|
||||
Tools
|
||||
</button>
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Checkpoints" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Checkpoints")}>
|
||||
Checkpoints
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{activeTab === "Key Features" && (
|
||||
<div className="feature-content">
|
||||
<div className="feature-selected">
|
||||
<div className="feature-check-icon">✓</div>
|
||||
<div className="feature-info">
|
||||
<h3 className="feature-title">File Editing</h3>
|
||||
<p className="feature-subtitle">Cline can write your code for you</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="feature-buttons-container">
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Create new files
|
||||
</button>
|
||||
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Modify existing code
|
||||
</button>
|
||||
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Search and replace across files
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="feature-options">
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Terminal Commands</span>
|
||||
</div>
|
||||
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Code Analysis</span>
|
||||
</div>
|
||||
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Browser Integration</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "Tools" && (
|
||||
<div className="feature-content">
|
||||
<p className="feature-description">Cline provides powerful tools to help you code faster</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "Checkpoints" && (
|
||||
<div className="feature-content">
|
||||
<p className="feature-description">Cline creates checkpoints to help you track changes</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img src={featureBg} alt="Feature Background" className="feature-bg" />
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Models Section */}
|
||||
<div className="models-container">
|
||||
<h2 className="models-heading">Top 3 models for coding</h2>
|
||||
|
||||
<div className="models-section-container">
|
||||
{/* Anthropic Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">anthropic</div>
|
||||
<div className="model-badge best">Best</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Leading model for agentic coding</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image anthropic-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("anthropic")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Google Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">google</div>
|
||||
<div className="model-badge trending">Trending</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Large 1M context window, great value</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image google-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("google")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Meta-Llama Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">meta-llama</div>
|
||||
<div className="model-badge new">New</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Efficient performance at lower cost</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image meta-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("meta-llama")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Plan/Act Mode Section */}
|
||||
<div className="plan-act-container">
|
||||
<h2 className="plan-act-heading">Plan/Act Mode</h2>
|
||||
<p className="plan-act-description">
|
||||
Switch between planning and execution modes to better control how Cline assists you. Plan mode helps you
|
||||
strategize while Act mode implements your solutions.
|
||||
</p>
|
||||
|
||||
<div className="divider-dashed"></div>
|
||||
|
||||
<div className="plan-act-content">
|
||||
{/* Plan Mode Column */}
|
||||
<div className="plan-mode-container">
|
||||
<div className="mode-header">
|
||||
<h3 className="mode-title">Plan Mode</h3>
|
||||
</div>
|
||||
<div className="mode-content">
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Strategy Development</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Context Gathering</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Requirements Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item disabled">
|
||||
<div className="mode-icon plan-icon-disabled">
|
||||
<div className="line-icon disabled-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div className="mode-item disabled">
|
||||
<div className="mode-icon plan-icon-disabled">
|
||||
<div className="line-icon disabled-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Act Mode Column */}
|
||||
<div className="act-mode-container">
|
||||
<div className="mode-header">
|
||||
<h3 className="mode-title">Act Mode</h3>
|
||||
</div>
|
||||
<div className="mode-content">
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Execute Commands</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Run Tests</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Deploy Changes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* MCP Servers Section */}
|
||||
<div className="mcp-servers-container">
|
||||
<div className="mcp-content-container">
|
||||
<div className="mcp-text-container">
|
||||
<h2 className="mcp-heading">The largest ecosystem of MCP Servers for VS Code</h2>
|
||||
<p className="mcp-description">
|
||||
The Model Context Protocol (MCP) allows seamless communication with locally running servers that
|
||||
extend Cline's functionality with additional tools and context-aware resources.
|
||||
</p>
|
||||
<button className="mcp-button">Add an MCP Server</button>
|
||||
</div>
|
||||
<div className="mcp-count">
|
||||
<svg width="1048" height="187" viewBox="0 0 1048 187" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M64.0535 186.531C51.9601 186.531 41.2428 184.279 31.9016 179.775C22.6439 175.271 15.221 169.141 9.63304 161.385C4.12845 153.545 0.959134 144.704 0.125104 134.863L0 133.361H26.7724L26.8975 134.237C27.7315 139.658 29.8166 144.579 33.1527 148.999C36.5722 153.336 40.9509 156.798 46.2886 159.383C51.6264 161.885 57.5898 163.136 64.1786 163.136C71.7683 163.136 78.4822 161.51 84.3204 158.257C90.1586 155.004 94.7041 150.501 97.9568 144.746C101.21 138.991 102.836 132.402 102.836 124.979V124.729C102.836 117.39 101.168 110.884 97.8317 105.213C94.579 99.5414 90.0752 95.0794 84.3204 91.8267C78.5656 88.574 71.9768 86.9476 64.5539 86.9476C58.9659 86.9476 53.7949 87.7816 49.0409 89.4497C44.287 91.0343 40.0751 93.453 36.4054 96.7057C34.8207 98.1236 33.2778 99.7082 31.7765 101.46C30.3587 103.211 29.0659 105.088 27.8983 107.089H3.25272L12.1351 3.00251H119.85V26.6472H34.9041L29.3995 83.82H30.0251C32.694 79.7332 36.0718 76.272 40.1585 73.4363C44.3287 70.6006 48.9992 68.4738 54.1702 67.056C59.4246 65.5547 65.0126 64.8041 70.9342 64.8041C82.4438 64.8041 92.6607 67.3896 101.585 72.5606C110.509 77.6482 117.515 84.654 122.602 93.5781C127.773 102.502 130.359 112.719 130.359 124.229V124.479C130.359 136.656 127.523 147.415 121.852 156.756C116.18 166.097 108.34 173.395 98.3321 178.649C88.4071 183.904 76.9809 186.531 64.0535 186.531Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M218.933 186.531C204.587 186.531 192.244 182.736 181.902 175.146C171.643 167.557 163.762 156.798 158.257 142.869C152.753 128.941 150 112.427 150 93.3279V93.0777C150 73.9784 152.753 57.4646 158.257 43.5363C163.762 29.6081 171.643 18.8908 181.902 11.3845C192.244 3.79483 204.587 0 218.933 0C233.278 0 245.58 3.79483 255.839 11.3845C266.181 18.8908 274.104 29.6081 279.608 43.5363C285.196 57.4646 287.99 73.9784 287.99 93.0777V93.3279C287.99 112.427 285.196 128.941 279.608 142.869C274.104 156.798 266.181 167.557 255.839 175.146C245.58 182.736 233.278 186.531 218.933 186.531ZM218.933 163.011C227.523 163.011 234.821 160.217 240.826 154.629C246.914 149.041 251.543 141.034 254.713 130.609C257.965 120.184 259.592 107.757 259.592 93.3279V93.0777C259.592 78.649 257.965 66.2637 254.713 55.9217C251.543 45.4963 246.914 37.4896 240.826 31.9016C234.821 26.3136 227.523 23.5196 218.933 23.5196C210.342 23.5196 203.003 26.3136 196.914 31.9016C190.909 37.4896 186.322 45.4963 183.153 55.9217C179.984 66.2637 178.399 78.649 178.399 93.0777V93.3279C178.399 107.757 179.984 120.184 183.153 130.609C186.322 141.034 190.909 149.041 196.914 154.629C203.003 160.217 210.342 163.011 218.933 163.011Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M313.512 122.602V97.9568H443.745V122.602H313.512ZM366.306 173.019V47.5397H390.826V173.019H366.306Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M526.44 183.528V3.00251H558.842L617.265 146.998H618.016L676.44 3.00251H708.967V183.528H683.321V50.4171H670.435L699.709 8.00668L628.024 183.528H607.257L535.697 8.00668L564.972 50.4171H552.086V183.528H526.44Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M819.559 186.531C802.545 186.531 787.741 182.736 775.147 175.146C762.637 167.557 752.962 156.798 746.123 142.869C739.284 128.858 735.864 112.302 735.864 93.2028V93.0777C735.864 73.9784 739.284 57.4646 746.123 43.5363C752.962 29.6081 762.637 18.8908 775.147 11.3845C787.658 3.79483 802.462 0 819.559 0C832.82 0 844.789 2.54379 855.464 7.63137C866.14 12.719 874.939 19.7665 881.861 28.774C888.784 37.7815 893.162 48.2486 894.997 60.1752L895.122 61.4263H867.224L866.473 58.9242C864.555 51.8349 861.428 45.7465 857.091 40.6589C852.837 35.5714 847.541 31.6931 841.202 29.0242C834.947 26.2719 827.733 24.8958 819.559 24.8958C808.383 24.8958 798.667 27.6898 790.41 33.2778C782.236 38.8658 775.898 46.7474 771.394 56.9225C766.89 67.0977 764.638 79.1494 764.638 93.0777V93.2028C764.638 107.048 766.89 119.141 771.394 129.483C775.898 139.742 782.278 147.665 790.535 153.253C798.792 158.841 808.467 161.635 819.559 161.635C827.566 161.635 834.697 160.301 840.952 157.632C847.291 154.879 852.67 150.876 857.091 145.622C861.511 140.367 864.805 133.945 866.974 126.355L867.349 125.104H895.247L894.997 126.355C893.162 138.366 888.784 148.916 881.861 158.007C875.022 167.014 866.265 174.02 855.589 179.024C844.914 184.029 832.904 186.531 819.559 186.531Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M934.78 121.852V98.3321H981.069C993.163 98.3321 1002.55 95.2045 1009.22 88.9493C1015.97 82.6106 1019.35 73.8533 1019.35 62.6773V62.4271C1019.35 51.0843 1015.97 42.2853 1009.22 36.0301C1002.55 29.7749 993.163 26.6472 981.069 26.6472H934.78V3.00251H988.075C999.918 3.00251 1010.3 5.5046 1019.23 10.5088C1028.23 15.4295 1035.28 22.352 1040.37 31.2761C1045.46 40.1168 1048 50.4171 1048 62.1769V62.4271C1048 74.1869 1045.46 84.5706 1040.37 93.5781C1035.28 102.502 1028.23 109.466 1019.23 114.471C1010.3 119.391 999.918 121.852 988.075 121.852H934.78ZM920.769 183.528V3.00251H948.792V183.528H920.769Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
export default WelcomeTabView
|
||||
@@ -1,34 +1,22 @@
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useEffect, useState, memo } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { validateApiConfiguration } from "@/utils/validate"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import ApiOptions from "@/components/settings/ApiOptions"
|
||||
import { memo, Dispatch, SetStateAction } from "react"
|
||||
import ClineLogoWhite from "@/assets/ClineLogoWhite"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { EmptyRequest } from "@shared/proto/common"
|
||||
import ApiOptionsSection from "./ApiOptionsSection"
|
||||
|
||||
const WelcomeView = memo(() => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
const [showApiOptions, setShowApiOptions] = useState(false)
|
||||
|
||||
const disableLetsGoButton = apiErrorMessage != null
|
||||
interface WelcomeViewProps {
|
||||
showApiOptions: boolean
|
||||
setShowApiOptions: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
const WelcomeView = memo(({ showApiOptions, setShowApiOptions }: WelcomeViewProps) => {
|
||||
const handleLogin = () => {
|
||||
AccountServiceClient.accountLoginClicked(EmptyRequest.create()).catch((err) =>
|
||||
console.error("Failed to get login URL:", err),
|
||||
)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setApiErrorMessage(validateApiConfiguration(apiConfiguration))
|
||||
}, [apiConfiguration])
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 p-0 flex flex-col">
|
||||
<div className="h-full px-5 overflow-auto">
|
||||
@@ -64,16 +52,7 @@ const WelcomeView = memo(() => {
|
||||
</VSCodeButton>
|
||||
)}
|
||||
|
||||
<div className="mt-4.5">
|
||||
{showApiOptions && (
|
||||
<div>
|
||||
<ApiOptions showModelOptions={false} />
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} className="mt-0.75">
|
||||
Let's go!
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ApiOptionsSection showApiOptions={showApiOptions} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useState, memo } from "react"
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
import WelcomeView from "./WelcomeView"
|
||||
import WelcomeTabView from "./WelcomeTabView"
|
||||
|
||||
const WelcomeWrapper = memo(() => {
|
||||
const [showApiOptions, setShowApiOptions] = useState(false)
|
||||
|
||||
// Determine which welcome view to show based on webview type
|
||||
const webviewType = (document.querySelector('meta[name="webview-type"]')?.getAttribute("content") || "sidebar") as WebviewType
|
||||
|
||||
return (
|
||||
<>
|
||||
{webviewType === "sidebar" ? (
|
||||
<WelcomeView showApiOptions={showApiOptions} setShowApiOptions={setShowApiOptions} />
|
||||
) : (
|
||||
<WelcomeTabView showApiOptions={showApiOptions} setShowApiOptions={setShowApiOptions} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default WelcomeWrapper
|
||||
@@ -61,6 +61,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
clineMessages: [],
|
||||
taskHistory: [],
|
||||
shouldShowAnnouncement: false,
|
||||
showWelcome: false,
|
||||
autoApprovalSettings: DEFAULT_AUTO_APPROVAL_SETTINGS,
|
||||
browserSettings: DEFAULT_BROWSER_SETTINGS,
|
||||
chatSettings: DEFAULT_CHAT_SETTINGS,
|
||||
@@ -106,33 +107,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
: prevState.autoApprovalSettings,
|
||||
}
|
||||
})
|
||||
const config = message.state?.apiConfiguration
|
||||
const hasKey = config
|
||||
? [
|
||||
config.apiKey,
|
||||
config.openRouterApiKey,
|
||||
config.awsRegion,
|
||||
config.vertexProjectId,
|
||||
config.openAiApiKey,
|
||||
config.ollamaModelId,
|
||||
config.lmStudioModelId,
|
||||
config.liteLlmApiKey,
|
||||
config.geminiApiKey,
|
||||
config.openAiNativeApiKey,
|
||||
config.deepSeekApiKey,
|
||||
config.requestyApiKey,
|
||||
config.togetherApiKey,
|
||||
config.qwenApiKey,
|
||||
config.doubaoApiKey,
|
||||
config.mistralApiKey,
|
||||
config.vsCodeLmModelSelector,
|
||||
config.clineApiKey,
|
||||
config.asksageApiKey,
|
||||
config.xaiApiKey,
|
||||
config.sambanovaApiKey,
|
||||
].some((key) => key !== undefined)
|
||||
: false
|
||||
setShowWelcome(!hasKey)
|
||||
setShowWelcome(true)
|
||||
setDidHydrateState(true)
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user