mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
feat: add optional jumping roo animation for progress indicators
- Created JumpingRoo component with CSS keyframes animation - Added useJumpingRooAnimation setting to global settings - Updated ProgressIndicator to conditionally render based on setting - Added toggle in UI Settings panel - Added translation labels for the new setting - Persisted setting in backend state management References #8747
This commit is contained in:
parent
f3a505fd36
commit
88fc49d3f3
11 changed files with 177 additions and 14 deletions
|
|
@ -148,6 +148,7 @@ export const globalSettingsSchema = z.object({
|
|||
includeTaskHistoryInEnhance: z.boolean().optional(),
|
||||
historyPreviewCollapsed: z.boolean().optional(),
|
||||
reasoningBlockCollapsed: z.boolean().optional(),
|
||||
useJumpingRooAnimation: z.boolean().optional(),
|
||||
profileThresholds: z.record(z.string(), z.number()).optional(),
|
||||
hasOpenedModeSelector: z.boolean().optional(),
|
||||
lastModeExportPath: z.string().optional(),
|
||||
|
|
|
|||
|
|
@ -1793,6 +1793,7 @@ export class ClineProvider
|
|||
terminalCompressProgressBar,
|
||||
historyPreviewCollapsed,
|
||||
reasoningBlockCollapsed,
|
||||
useJumpingRooAnimation,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
sharingEnabled,
|
||||
|
|
@ -1927,6 +1928,7 @@ export class ClineProvider
|
|||
hasSystemPromptOverride,
|
||||
historyPreviewCollapsed: historyPreviewCollapsed ?? false,
|
||||
reasoningBlockCollapsed: reasoningBlockCollapsed ?? true,
|
||||
useJumpingRooAnimation: useJumpingRooAnimation ?? false,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated: cloudIsAuthenticated ?? false,
|
||||
cloudOrganizations,
|
||||
|
|
@ -2142,6 +2144,7 @@ export class ClineProvider
|
|||
maxConcurrentFileReads: stateValues.maxConcurrentFileReads ?? 5,
|
||||
historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
|
||||
reasoningBlockCollapsed: stateValues.reasoningBlockCollapsed ?? true,
|
||||
useJumpingRooAnimation: stateValues.useJumpingRooAnimation ?? false,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
sharingEnabled,
|
||||
|
|
|
|||
|
|
@ -1621,6 +1621,10 @@ export const webviewMessageHandler = async (
|
|||
await updateGlobalState("reasoningBlockCollapsed", message.bool ?? true)
|
||||
// No need to call postStateToWebview here as the UI already updated optimistically
|
||||
break
|
||||
case "setUseJumpingRooAnimation":
|
||||
await updateGlobalState("useJumpingRooAnimation", message.bool ?? false)
|
||||
// No need to call postStateToWebview here as the UI already updated optimistically
|
||||
break
|
||||
case "toggleApiConfigPin":
|
||||
if (message.text) {
|
||||
const currentPinned = getGlobalState("pinnedApiConfigs") ?? {}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ export type ExtensionState = Pick<
|
|||
| "openRouterImageGenerationSelectedModel"
|
||||
| "includeTaskHistoryInEnhance"
|
||||
| "reasoningBlockCollapsed"
|
||||
| "useJumpingRooAnimation"
|
||||
> & {
|
||||
version: string
|
||||
clineMessages: ClineMessage[]
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ export interface WebviewMessage {
|
|||
| "profileThresholds"
|
||||
| "setHistoryPreviewCollapsed"
|
||||
| "setReasoningBlockCollapsed"
|
||||
| "setUseJumpingRooAnimation"
|
||||
| "openExternal"
|
||||
| "filterMarketplaceItems"
|
||||
| "marketplaceButtonClicked"
|
||||
|
|
|
|||
101
webview-ui/src/components/chat/JumpingRoo.tsx
Normal file
101
webview-ui/src/components/chat/JumpingRoo.tsx
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import React from "react"
|
||||
|
||||
export const JumpingRoo = () => (
|
||||
<div
|
||||
style={{
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
position: "relative",
|
||||
}}>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={{
|
||||
animation: "jumpingRoo 0.8s ease-in-out infinite",
|
||||
}}>
|
||||
{/* Kangaroo body */}
|
||||
<ellipse cx="8" cy="10" rx="3.5" ry="4" fill="currentColor" opacity="0.9" />
|
||||
{/* Kangaroo head */}
|
||||
<circle cx="8" cy="5" r="2.5" fill="currentColor" opacity="0.9" />
|
||||
{/* Kangaroo ears */}
|
||||
<ellipse
|
||||
cx="6.5"
|
||||
cy="3.5"
|
||||
rx="0.8"
|
||||
ry="1.5"
|
||||
fill="currentColor"
|
||||
opacity="0.9"
|
||||
transform="rotate(-15 6.5 3.5)"
|
||||
/>
|
||||
<ellipse
|
||||
cx="9.5"
|
||||
cy="3.5"
|
||||
rx="0.8"
|
||||
ry="1.5"
|
||||
fill="currentColor"
|
||||
opacity="0.9"
|
||||
transform="rotate(15 9.5 3.5)"
|
||||
/>
|
||||
{/* Kangaroo tail */}
|
||||
<path
|
||||
d="M5 11 Q2 12 1 14"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
fill="none"
|
||||
opacity="0.9"
|
||||
/>
|
||||
{/* Kangaroo legs */}
|
||||
<rect x="6" y="12" width="1.5" height="3" rx="0.5" fill="currentColor" opacity="0.9" />
|
||||
<rect x="8.5" y="12" width="1.5" height="3" rx="0.5" fill="currentColor" opacity="0.9" />
|
||||
{/* Kangaroo arms */}
|
||||
<rect
|
||||
x="5"
|
||||
y="8"
|
||||
width="1"
|
||||
height="2.5"
|
||||
rx="0.5"
|
||||
fill="currentColor"
|
||||
opacity="0.9"
|
||||
transform="rotate(-20 5.5 9.25)"
|
||||
/>
|
||||
<rect
|
||||
x="10"
|
||||
y="8"
|
||||
width="1"
|
||||
height="2.5"
|
||||
rx="0.5"
|
||||
fill="currentColor"
|
||||
opacity="0.9"
|
||||
transform="rotate(20 10.5 9.25)"
|
||||
/>
|
||||
{/* Kangaroo pouch */}
|
||||
<path d="M6.5 11 Q8 12 9.5 11" stroke="currentColor" strokeWidth="0.5" fill="none" opacity="0.5" />
|
||||
</svg>
|
||||
<style>{`
|
||||
@keyframes jumpingRoo {
|
||||
0%, 100% {
|
||||
transform: translateY(0) scaleY(1);
|
||||
}
|
||||
20% {
|
||||
transform: translateY(0) scaleY(0.9);
|
||||
}
|
||||
40% {
|
||||
transform: translateY(-4px) scaleY(1.1);
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-4px) scaleY(1.1);
|
||||
}
|
||||
80% {
|
||||
transform: translateY(0) scaleY(0.95);
|
||||
}
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -1,16 +1,26 @@
|
|||
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { JumpingRoo } from "./JumpingRoo"
|
||||
|
||||
export const ProgressIndicator = () => (
|
||||
<div
|
||||
style={{
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}>
|
||||
<div style={{ transform: "scale(0.55)", transformOrigin: "center" }}>
|
||||
<VSCodeProgressRing />
|
||||
export const ProgressIndicator = () => {
|
||||
const { useJumpingRooAnimation } = useExtensionState()
|
||||
|
||||
if (useJumpingRooAnimation) {
|
||||
return <JumpingRoo />
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}>
|
||||
<div style={{ transform: "scale(0.55)", transformOrigin: "center" }}>
|
||||
<VSCodeProgressRing />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -782,6 +782,7 @@ const SettingsView = forwardRef<SettingsViewRef, SettingsViewProps>(({ onDone, t
|
|||
{activeTab === "ui" && (
|
||||
<UISettings
|
||||
reasoningBlockCollapsed={reasoningBlockCollapsed ?? true}
|
||||
useJumpingRooAnimation={extensionState.useJumpingRooAnimation}
|
||||
setCachedStateField={setCachedStateField}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,16 @@ import { ExtensionStateContextType } from "@/context/ExtensionStateContext"
|
|||
|
||||
interface UISettingsProps extends HTMLAttributes<HTMLDivElement> {
|
||||
reasoningBlockCollapsed: boolean
|
||||
useJumpingRooAnimation?: boolean
|
||||
setCachedStateField: SetCachedStateField<keyof ExtensionStateContextType>
|
||||
}
|
||||
|
||||
export const UISettings = ({ reasoningBlockCollapsed, setCachedStateField, ...props }: UISettingsProps) => {
|
||||
export const UISettings = ({
|
||||
reasoningBlockCollapsed,
|
||||
useJumpingRooAnimation,
|
||||
setCachedStateField,
|
||||
...props
|
||||
}: UISettingsProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const handleReasoningBlockCollapsedChange = (value: boolean) => {
|
||||
|
|
@ -26,6 +32,15 @@ export const UISettings = ({ reasoningBlockCollapsed, setCachedStateField, ...pr
|
|||
})
|
||||
}
|
||||
|
||||
const handleJumpingRooAnimationChange = (value: boolean) => {
|
||||
setCachedStateField("useJumpingRooAnimation", value)
|
||||
|
||||
// Track telemetry event
|
||||
telemetryClient.capture("ui_settings_jumping_roo_changed", {
|
||||
enabled: value,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div {...props}>
|
||||
<SectionHeader>
|
||||
|
|
@ -49,6 +64,19 @@ export const UISettings = ({ reasoningBlockCollapsed, setCachedStateField, ...pr
|
|||
{t("settings:ui.collapseThinking.description")}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Jumping Roo Animation Setting */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<VSCodeCheckbox
|
||||
checked={useJumpingRooAnimation ?? false}
|
||||
onChange={(e: any) => handleJumpingRooAnimationChange(e.target.checked)}
|
||||
data-testid="jumping-roo-animation-checkbox">
|
||||
<span className="font-medium">{t("settings:ui.jumpingRooAnimation.label")}</span>
|
||||
</VSCodeCheckbox>
|
||||
<div className="text-vscode-descriptionForeground text-sm ml-5 mt-1">
|
||||
{t("settings:ui.jumpingRooAnimation.description")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Section>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -145,6 +145,8 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
setTerminalCompressProgressBar: (value: boolean) => void
|
||||
setHistoryPreviewCollapsed: (value: boolean) => void
|
||||
setReasoningBlockCollapsed: (value: boolean) => void
|
||||
useJumpingRooAnimation?: boolean
|
||||
setUseJumpingRooAnimation: (value: boolean) => void
|
||||
autoCondenseContext: boolean
|
||||
setAutoCondenseContext: (value: boolean) => void
|
||||
autoCondenseContextPercent: number
|
||||
|
|
@ -285,6 +287,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
global: {},
|
||||
})
|
||||
const [includeTaskHistoryInEnhance, setIncludeTaskHistoryInEnhance] = useState(true)
|
||||
const [useJumpingRooAnimation, setUseJumpingRooAnimation] = useState(false)
|
||||
|
||||
const setListApiConfigMeta = useCallback(
|
||||
(value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
|
||||
|
|
@ -322,6 +325,10 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
if ((newState as any).includeTaskHistoryInEnhance !== undefined) {
|
||||
setIncludeTaskHistoryInEnhance((newState as any).includeTaskHistoryInEnhance)
|
||||
}
|
||||
// Update useJumpingRooAnimation if present in state message
|
||||
if ((newState as any).useJumpingRooAnimation !== undefined) {
|
||||
setUseJumpingRooAnimation((newState as any).useJumpingRooAnimation)
|
||||
}
|
||||
// Handle marketplace data if present in state message
|
||||
if (newState.marketplaceItems !== undefined) {
|
||||
setMarketplaceItems(newState.marketplaceItems)
|
||||
|
|
@ -537,6 +544,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setState((prevState) => ({ ...prevState, historyPreviewCollapsed: value })),
|
||||
setReasoningBlockCollapsed: (value) =>
|
||||
setState((prevState) => ({ ...prevState, reasoningBlockCollapsed: value })),
|
||||
useJumpingRooAnimation,
|
||||
setUseJumpingRooAnimation,
|
||||
setHasOpenedModeSelector: (value) => setState((prevState) => ({ ...prevState, hasOpenedModeSelector: value })),
|
||||
setAutoCondenseContext: (value) => setState((prevState) => ({ ...prevState, autoCondenseContext: value })),
|
||||
setAutoCondenseContextPercent: (value) =>
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@
|
|||
"collapseThinking": {
|
||||
"label": "Collapse Thinking messages by default",
|
||||
"description": "When enabled, thinking blocks will be collapsed by default until you interact with them"
|
||||
},
|
||||
"jumpingRooAnimation": {
|
||||
"label": "Use Jumping Roo Animation",
|
||||
"description": "Replace the standard spinner with a jumping kangaroo animation for progress indicators"
|
||||
}
|
||||
},
|
||||
"prompts": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue