mirror of
https://github.com/cline/cline.git
synced 2026-09-19 02:05:44 +08:00
Update welcome page and cline account view
This commit is contained in:
+1
-11
@@ -90,11 +90,6 @@
|
||||
"title": "Settings",
|
||||
"icon": "$(settings-gear)"
|
||||
},
|
||||
{
|
||||
"command": "cline.accountLoginClicked",
|
||||
"title": "Account",
|
||||
"icon": "$(account)"
|
||||
},
|
||||
{
|
||||
"command": "cline.openInNewTab",
|
||||
"title": "Open In New Tab",
|
||||
@@ -123,14 +118,9 @@
|
||||
"group": "navigation@4",
|
||||
"when": "view == claude-dev.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "cline.accountLoginClicked",
|
||||
"group": "navigation@5",
|
||||
"when": "view == claude-dev.SidebarProvider"
|
||||
},
|
||||
{
|
||||
"command": "cline.settingsButtonClicked",
|
||||
"group": "navigation@6",
|
||||
"group": "navigation@5",
|
||||
"when": "view == claude-dev.SidebarProvider"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -604,6 +604,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
asksageApiUrl,
|
||||
xaiApiKey,
|
||||
thinkingBudgetTokens,
|
||||
clineApiKey,
|
||||
} = message.apiConfiguration
|
||||
await this.updateGlobalState("apiProvider", apiProvider)
|
||||
await this.updateGlobalState("apiModelId", apiModelId)
|
||||
@@ -650,6 +651,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
|
||||
await this.storeSecret("asksageApiKey", asksageApiKey)
|
||||
await this.updateGlobalState("asksageApiUrl", asksageApiUrl)
|
||||
await this.updateGlobalState("thinkingBudgetTokens", thinkingBudgetTokens)
|
||||
await this.storeSecret("clineApiKey", clineApiKey)
|
||||
if (this.cline) {
|
||||
this.cline.api = buildApiHandler(message.apiConfiguration)
|
||||
}
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeButton, VSCodeDivider } from "@vscode/webview-ui-toolkit/react"
|
||||
import { memo } from "react"
|
||||
import { useFirebaseAuth } from "../../context/FirebaseAuthContext"
|
||||
import { vscode } from "../../utils/vscode"
|
||||
import VSCodeButtonLink from "../common/VSCodeButtonLink"
|
||||
|
||||
type AccountViewProps = {
|
||||
onDone: () => void
|
||||
}
|
||||
|
||||
const AccountView = ({ onDone }: AccountViewProps) => {
|
||||
const { user, handleSignOut } = useFirebaseAuth()
|
||||
|
||||
const handleLogin = () => {
|
||||
vscode.postMessage({ type: "accountLoginClicked" })
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
// First notify extension to clear API keys and state
|
||||
vscode.postMessage({ type: "accountLogoutClicked" })
|
||||
// Then sign out of Firebase
|
||||
handleSignOut()
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -54,33 +42,132 @@ const AccountView = ({ onDone }: AccountViewProps) => {
|
||||
flexDirection: "column",
|
||||
}}>
|
||||
<div style={{ marginBottom: 5 }}>
|
||||
{user ? (
|
||||
<>
|
||||
{user.photoURL && (
|
||||
<img
|
||||
src={user.photoURL}
|
||||
alt="Profile"
|
||||
style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: "50%",
|
||||
marginBottom: 10,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div style={{ fontSize: "14px", marginBottom: 10 }}>
|
||||
{user.displayName && <div>{user.displayName}</div>}
|
||||
{user.email && <div>{user.email}</div>}
|
||||
</div>
|
||||
<VSCodeButton onClick={handleLogout}>Log out</VSCodeButton>
|
||||
</>
|
||||
) : (
|
||||
<VSCodeButton onClick={handleLogin}>Log in to Cline</VSCodeButton>
|
||||
)}
|
||||
<ClineAccountView />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const ClineAccountView = () => {
|
||||
const { user, handleSignOut } = useFirebaseAuth()
|
||||
|
||||
const handleLogin = () => {
|
||||
vscode.postMessage({ type: "accountLoginClicked" })
|
||||
}
|
||||
|
||||
const handleLogout = () => {
|
||||
// First notify extension to clear API keys and state
|
||||
vscode.postMessage({ type: "accountLogoutClicked" })
|
||||
// Then sign out of Firebase
|
||||
handleSignOut()
|
||||
}
|
||||
return (
|
||||
<div style={{ maxWidth: "600px" }}>
|
||||
{user ? (
|
||||
<div
|
||||
style={{
|
||||
padding: "12px 16px",
|
||||
border: "1px solid var(--vscode-widget-border)",
|
||||
borderRadius: "6px",
|
||||
backgroundColor: "var(--vscode-editor-background)",
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "16px",
|
||||
}}>
|
||||
{user.photoURL ? (
|
||||
<img
|
||||
src={user.photoURL}
|
||||
alt="Profile"
|
||||
style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: "50%",
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div
|
||||
style={{
|
||||
width: 48,
|
||||
height: 48,
|
||||
borderRadius: "50%",
|
||||
backgroundColor: "var(--vscode-button-background)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontSize: "20px",
|
||||
color: "var(--vscode-button-foreground)",
|
||||
}}>
|
||||
{user.displayName?.[0] || user.email?.[0] || "?"}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "4px",
|
||||
}}>
|
||||
{user.displayName && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: "13px",
|
||||
fontWeight: "bold",
|
||||
color: "var(--vscode-foreground)",
|
||||
}}>
|
||||
{user.displayName}
|
||||
</div>
|
||||
)}
|
||||
{user.email && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: "13px",
|
||||
color: "var(--vscode-descriptionForeground)",
|
||||
}}>
|
||||
{user.email}
|
||||
</div>
|
||||
)}
|
||||
<div style={{ display: "flex", gap: "8px" }}>
|
||||
<VSCodeButtonLink
|
||||
href="https://app.cline.bot/account"
|
||||
appearance="primary"
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
width: "fit-content",
|
||||
marginTop: 2,
|
||||
marginBottom: -2,
|
||||
marginRight: -8,
|
||||
}}>
|
||||
Account
|
||||
</VSCodeButtonLink>
|
||||
<VSCodeButton
|
||||
appearance="secondary"
|
||||
onClick={handleLogout}
|
||||
style={{
|
||||
transform: "scale(0.85)",
|
||||
transformOrigin: "left center",
|
||||
width: "fit-content",
|
||||
marginTop: 2,
|
||||
marginBottom: -2,
|
||||
}}>
|
||||
Log out
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{}}>
|
||||
<VSCodeButton onClick={handleLogin} style={{ marginTop: 6 }}>
|
||||
Sign Up with Cline
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(AccountView)
|
||||
|
||||
@@ -49,6 +49,7 @@ import { vscode } from "../../utils/vscode"
|
||||
import { getAsVar, VSC_DESCRIPTION_FOREGROUND } from "../../utils/vscStyles"
|
||||
import VSCodeButtonLink from "../common/VSCodeButtonLink"
|
||||
import OpenRouterModelPicker, { ModelDescriptionMarkdown } from "./OpenRouterModelPicker"
|
||||
import AccountView, { ClineAccountView } from "../account/AccountView"
|
||||
|
||||
interface ApiOptionsProps {
|
||||
showModelOptions: boolean
|
||||
@@ -91,10 +92,6 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
|
||||
const [modelConfigurationSelected, setModelConfigurationSelected] = useState(false)
|
||||
const [isDescriptionExpanded, setIsDescriptionExpanded] = useState(false)
|
||||
|
||||
const handleClineLogin = () => {
|
||||
vscode.postMessage({ type: "accountLoginClicked" })
|
||||
}
|
||||
|
||||
const handleInputChange = (field: keyof ApiConfiguration) => (event: any) => {
|
||||
setApiConfiguration({
|
||||
...apiConfiguration,
|
||||
@@ -213,36 +210,8 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
|
||||
</DropdownContainer>
|
||||
|
||||
{selectedProvider === "cline" && (
|
||||
<div>
|
||||
{apiConfiguration?.clineApiKey && (
|
||||
<VSCodeTextField
|
||||
value={apiConfiguration.clineApiKey}
|
||||
style={{ width: "100%" }}
|
||||
type="password"
|
||||
onInput={handleInputChange("clineApiKey")}
|
||||
placeholder={"enterApiKey"}>
|
||||
<span style={{ fontWeight: 500 }}>Cline API Key</span>
|
||||
</VSCodeTextField>
|
||||
)}
|
||||
|
||||
{apiConfiguration?.clineApiKey && (
|
||||
<p
|
||||
style={{
|
||||
fontSize: "12px",
|
||||
marginTop: 3,
|
||||
color: "var(--vscode-descriptionForeground)",
|
||||
}}>
|
||||
{"apiKeyInfo"}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{!apiConfiguration?.clineApiKey && (
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<VSCodeButton appearance="primary" onClick={handleClineLogin}>
|
||||
Get Cline API Key
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginBottom: 8, marginTop: 4 }}>
|
||||
<ClineAccountView />
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -45,37 +45,40 @@ const WelcomeView = () => {
|
||||
overflow: "auto",
|
||||
}}>
|
||||
<h2>Hi, I'm Cline</h2>
|
||||
<div style={{ display: "flex", justifyContent: "center", margin: "20px 0" }}>
|
||||
<ClineLogo />
|
||||
</div>
|
||||
<p>
|
||||
I can do all kinds of tasks thanks to breakthroughs in Claude 3.7 Sonnet's agentic coding capabilities and
|
||||
access to tools that let me create & edit files, explore complex projects, use the browser, and execute
|
||||
terminal commands (with your permission, of course). I can even use MCP to create new tools and extend my own
|
||||
capabilities.
|
||||
I can do all kinds of tasks thanks to breakthroughs in{" "}
|
||||
<VSCodeLink href="https://www.anthropic.com/claude/sonnet" style={{ display: "inline" }}>
|
||||
Claude 3.7 Sonnet's
|
||||
</VSCodeLink>
|
||||
agentic coding capabilities and access to tools that let me create & edit files, explore complex projects, use
|
||||
a browser, and execute terminal commands <i>(with your permission, of course)</i>. I can even use MCP to
|
||||
create new tools and extend my own capabilities.
|
||||
</p>
|
||||
|
||||
<div style={{ marginTop: "20px", marginBottom: "20px" }}>
|
||||
<VSCodeButton appearance="primary" onClick={handleLogin}>
|
||||
Sign Up with Cline
|
||||
<p style={{ color: "var(--vscode-descriptionForeground)" }}>
|
||||
Sign up for an account to get started for free, or use an API key that provides access to models like Claude
|
||||
3.7 Sonnet.
|
||||
</p>
|
||||
|
||||
<VSCodeButton appearance="primary" onClick={handleLogin} style={{ width: "100%" }}>
|
||||
Get Started for Free
|
||||
</VSCodeButton>
|
||||
|
||||
{!showApiOptions && (
|
||||
<VSCodeButton
|
||||
appearance="secondary"
|
||||
onClick={() => setShowApiOptions(!showApiOptions)}
|
||||
style={{ marginTop: 10, width: "100%" }}>
|
||||
Use your own API key
|
||||
</VSCodeButton>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<ul style={{ paddingLeft: "20px", margin: "10px 0" }}>
|
||||
<li>Choose from hundreds of models like Claude 3.5 Sonnet and DeepSeek V3</li>
|
||||
<li>Get started for free with no credit card required</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VSCodeDivider />
|
||||
|
||||
<div style={{ marginTop: "20px" }}>
|
||||
{!showApiOptions && (
|
||||
<VSCodeButton appearance="secondary" onClick={() => setShowApiOptions(!showApiOptions)}>
|
||||
Use your own API key
|
||||
</VSCodeButton>
|
||||
)}
|
||||
|
||||
<div style={{ marginTop: "18px" }}>
|
||||
{showApiOptions && (
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<div>
|
||||
<ApiOptions showModelOptions={false} />
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} style={{ marginTop: "3px" }}>
|
||||
Let's go!
|
||||
@@ -88,4 +91,22 @@ const WelcomeView = () => {
|
||||
)
|
||||
}
|
||||
|
||||
const ClineLogo: React.FC<{ style?: React.CSSProperties }> = ({ style }) => {
|
||||
// (can't use svgs in vsc extensions)
|
||||
const logoBase64 =
|
||||
"data:image/png;base64,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"
|
||||
|
||||
return (
|
||||
<img
|
||||
src={logoBase64}
|
||||
style={{
|
||||
width: "57px",
|
||||
height: "60px",
|
||||
...style,
|
||||
}}
|
||||
alt="Cline Logo"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default WelcomeView
|
||||
|
||||
Reference in New Issue
Block a user