Skip to content

Commit db84a07

Browse files
committed
feat: Add Code Supernova stealth model promotion and pro trial buttons
- Adds new UI message promoting stealth model Code Supernova - Adds pro trial buttons to the provider page when Roo Code Cloud is selected - Adds pro trial buttons to the Cloud page - Updates internationalization files across all supported languages
1 parent d34aad4 commit db84a07

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+183
-93
lines changed

src/core/webview/webviewMessageHandler.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3035,5 +3035,10 @@ export const webviewMessageHandler = async (
30353035
})
30363036
break
30373037
}
3038+
case "openSettings": {
3039+
// Execute the settings command to open the settings panel
3040+
await vscode.commands.executeCommand(getCommand("settingsButtonClicked"))
3041+
break
3042+
}
30383043
}
30393044
}

src/shared/WebviewMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ export interface WebviewMessage {
225225
| "editQueuedMessage"
226226
| "dismissUpsell"
227227
| "getDismissedUpsells"
228+
| "openSettings"
228229
text?: string
229230
editedMessageContent?: string
230231
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "cloud"

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ import { CheckpointWarning } from "./CheckpointWarning"
5757
import { QueuedMessages } from "./QueuedMessages"
5858
import DismissibleUpsell from "../common/DismissibleUpsell"
5959
import { useCloudUpsell } from "@src/hooks/useCloudUpsell"
60-
import { Cloud } from "lucide-react"
6160

6261
export interface ChatViewProps {
6362
isHidden: boolean
@@ -131,7 +130,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
131130
messagesRef.current = messages
132131
}, [messages])
133132

134-
const { tasks } = useTaskSearch()
133+
const { tasks, recentTasks } = useTaskSearch()
134+
const hasTaskHistory = recentTasks.length > 0
135135

136136
// Initialize expanded state based on the persisted setting (default to expanded if undefined)
137137
const [isExpanded, setIsExpanded] = useState(
@@ -212,7 +212,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
212212

213213
const {
214214
isOpen: isUpsellOpen,
215-
openUpsell,
215+
openUpsell: _openUpsell,
216216
closeUpsell,
217217
handleConnect,
218218
} = useCloudUpsell({
@@ -1819,10 +1819,10 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
18191819
) : (
18201820
<div className="flex-1 min-h-0 overflow-y-auto flex flex-col gap-4 relative">
18211821
{/* Moved Task Bar Header Here */}
1822-
{tasks.length !== 0 && (
1822+
{hasTaskHistory && (
18231823
<div className="flex text-vscode-descriptionForeground w-full mx-auto px-5 pt-3">
18241824
<div className="flex items-center gap-1 cursor-pointer" onClick={toggleExpanded}>
1825-
{tasks.length < 10 && (
1825+
{recentTasks.length < 10 && (
18261826
<span className={`font-medium text-xs `}>{t("history:recentTasks")}</span>
18271827
)}
18281828
<span
@@ -1847,23 +1847,29 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
18471847
) : (
18481848
<>
18491849
<DismissibleUpsell
1850-
upsellId="taskList"
1851-
icon={<Cloud className="size-4 mt-0.5 shrink-0" />}
1852-
onClick={() => openUpsell()}
1850+
upsellId="taskListSupernova"
18531851
dismissOnClick={false}
18541852
className="bg-vscode-editor-background p-4 !text-base">
1855-
<Trans
1856-
i18nKey="cloud:upsell.taskList"
1857-
components={{
1858-
learnMoreLink: <VSCodeLink href="#" />,
1859-
}}
1860-
/>
1853+
<div className="w-full text-center leading-relaxed">
1854+
<Trans
1855+
i18nKey="cloud:upsell.taskList"
1856+
components={{
1857+
lineBreak: <br />,
1858+
providersLink: (
1859+
<VSCodeLink
1860+
href="#"
1861+
onClick={() => vscode.postMessage({ type: "openSettings" })}
1862+
/>
1863+
),
1864+
}}
1865+
/>
1866+
</div>
18611867
</DismissibleUpsell>
18621868
</>
18631869
)}
18641870
</div>
18651871
{/* Show the task history preview if expanded and tasks exist */}
1866-
{taskHistory.length > 0 && isExpanded && <HistoryPreview />}
1872+
{hasTaskHistory && isExpanded && <HistoryPreview />}
18671873
</div>
18681874
</div>
18691875
)}

webview-ui/src/components/cloud/CloudView.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone }: Cl
136136
vscode.postMessage({ type: "openExternal", url: cloudUrl })
137137
}
138138

139+
const handleStartFreeTrial = () => {
140+
vscode.postMessage({ type: "openExternal", url: "https://app.roocode.com/billing" })
141+
}
142+
139143
const handleOpenCloudUrl = () => {
140144
if (cloudApiUrl) {
141145
vscode.postMessage({ type: "openExternal", url: cloudApiUrl })
@@ -272,9 +276,20 @@ export const CloudView = ({ userInfo, isAuthenticated, cloudApiUrl, onDone }: Cl
272276
<div className={cn(authInProgress && "opacity-50")}>{renderCloudBenefitsContent(t)}</div>
273277

274278
{!authInProgress && (
275-
<VSCodeButton appearance="primary" onClick={handleConnectClick} className="w-full">
276-
{t("cloud:connect")}
277-
</VSCodeButton>
279+
<>
280+
<VSCodeButton
281+
appearance="primary"
282+
onClick={handleStartFreeTrial}
283+
className="w-full">
284+
{t("cloud:startFreeTrial")}
285+
</VSCodeButton>
286+
<VSCodeButton
287+
appearance="secondary"
288+
onClick={handleConnectClick}
289+
className="w-full">
290+
{t("cloud:connect")}
291+
</VSCodeButton>
292+
</>
278293
)}
279294

280295
{/* Manual entry section */}

webview-ui/src/components/history/HistoryPreview.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@ import { useTaskSearch } from "./useTaskSearch"
77
import TaskItem from "./TaskItem"
88

99
const HistoryPreview = () => {
10-
const { tasks } = useTaskSearch()
10+
const { tasks, recentTasks } = useTaskSearch()
1111
const { t } = useAppTranslation()
1212

1313
const handleViewAllHistory = () => {
1414
vscode.postMessage({ type: "switchTab", tab: "history" })
1515
}
1616

17+
const previewSource = tasks.length > 0 ? tasks : recentTasks
18+
const previewTasks = previewSource.slice(0, 3)
19+
const hasAnyTasks = recentTasks.length > 0
20+
1721
return (
1822
<div className="flex flex-col gap-3">
19-
{tasks.length !== 0 && (
23+
{hasAnyTasks && (
2024
<>
21-
{tasks.slice(0, 3).map((item) => (
25+
{previewTasks.map((item) => (
2226
<TaskItem key={item.id} item={item} variant="compact" />
2327
))}
2428
<button

webview-ui/src/components/history/__tests__/HistoryPreview.spec.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ describe("HistoryPreview", () => {
8787
it("renders nothing when no tasks are available", () => {
8888
mockUseTaskSearch.mockReturnValue({
8989
tasks: [],
90+
recentTasks: [],
9091
searchQuery: "",
9192
setSearchQuery: vi.fn(),
9293
sortOption: "newest",
@@ -107,6 +108,7 @@ describe("HistoryPreview", () => {
107108
it("renders up to 3 tasks when tasks are available", () => {
108109
mockUseTaskSearch.mockReturnValue({
109110
tasks: mockTasks,
111+
recentTasks: mockTasks,
110112
searchQuery: "",
111113
setSearchQuery: vi.fn(),
112114
sortOption: "newest",
@@ -132,6 +134,7 @@ describe("HistoryPreview", () => {
132134
const threeTasks = mockTasks.slice(0, 3)
133135
mockUseTaskSearch.mockReturnValue({
134136
tasks: threeTasks,
137+
recentTasks: threeTasks,
135138
searchQuery: "",
136139
setSearchQuery: vi.fn(),
137140
sortOption: "newest",
@@ -156,6 +159,7 @@ describe("HistoryPreview", () => {
156159
const oneTask = mockTasks.slice(0, 1)
157160
mockUseTaskSearch.mockReturnValue({
158161
tasks: oneTask,
162+
recentTasks: oneTask,
159163
searchQuery: "",
160164
setSearchQuery: vi.fn(),
161165
sortOption: "newest",
@@ -175,6 +179,7 @@ describe("HistoryPreview", () => {
175179
it("passes correct props to TaskItem components", () => {
176180
mockUseTaskSearch.mockReturnValue({
177181
tasks: mockTasks.slice(0, 3),
182+
recentTasks: mockTasks.slice(0, 3),
178183
searchQuery: "",
179184
setSearchQuery: vi.fn(),
180185
sortOption: "newest",
@@ -228,4 +233,25 @@ describe("HistoryPreview", () => {
228233

229234
expect(container.firstChild).toHaveClass("flex", "flex-col", "gap-3")
230235
})
236+
237+
it("falls back to recent tasks when filtered tasks are empty", () => {
238+
mockUseTaskSearch.mockReturnValue({
239+
tasks: [],
240+
recentTasks: mockTasks,
241+
searchQuery: "",
242+
setSearchQuery: vi.fn(),
243+
sortOption: "newest",
244+
setSortOption: vi.fn(),
245+
lastNonRelevantSort: null,
246+
setLastNonRelevantSort: vi.fn(),
247+
showAllWorkspaces: false,
248+
setShowAllWorkspaces: vi.fn(),
249+
})
250+
251+
render(<HistoryPreview />)
252+
253+
expect(screen.getByTestId("task-item-task-1")).toBeInTheDocument()
254+
expect(screen.getByTestId("task-item-task-2")).toBeInTheDocument()
255+
expect(screen.getByTestId("task-item-task-3")).toBeInTheDocument()
256+
})
231257
})

webview-ui/src/components/history/useTaskSearch.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export const useTaskSearch = () => {
3131
return tasks
3232
}, [taskHistory, showAllWorkspaces, cwd])
3333

34+
const recentTasks = useMemo(
35+
() => [...presentableTasks].sort((a, b) => (b.ts || 0) - (a.ts || 0)),
36+
[presentableTasks],
37+
)
38+
3439
const fzf = useMemo(() => {
3540
return new Fzf(presentableTasks, {
3641
selector: (item) => item.task,
@@ -80,6 +85,7 @@ export const useTaskSearch = () => {
8085

8186
return {
8287
tasks,
88+
recentTasks,
8389
searchQuery,
8490
setSearchQuery,
8591
sortOption,

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,14 @@ const ApiOptions = ({
665665
<div className="flex flex-col gap-2">
666666
<VSCodeButton
667667
appearance="primary"
668+
onClick={() =>
669+
vscode.postMessage({ type: "openExternal", url: "https://app.roocode.com/billing" })
670+
}
671+
className="w-fit">
672+
{t("settings:providers.roo.startFreeTrialButton")}
673+
</VSCodeButton>
674+
<VSCodeButton
675+
appearance="secondary"
668676
onClick={() => vscode.postMessage({ type: "rooCloudSignIn" })}
669677
className="w-fit">
670678
{t("settings:providers.roo.connectButton")}

webview-ui/src/i18n/locales/ca/cloud.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)