11import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
22import deepEqual from "fast-deep-equal"
3- import React , { memo , useEffect , useMemo , useRef , useState } from "react"
3+ import React , { CSSProperties , memo , useEffect , useMemo , useRef , useState } from "react"
44import { useSize } from "react-use"
55import styled from "styled-components"
66import { BROWSER_VIEWPORT_PRESETS } from "../../../../src/shared/BrowserSettings"
@@ -21,6 +21,93 @@ interface BrowserSessionRowProps {
2121 onHeightChange : ( isTaller : boolean ) => void
2222}
2323
24+ const browserSessionRowContainerInnerStyle : CSSProperties = {
25+ display : "flex" ,
26+ alignItems : "center" ,
27+ gap : "10px" ,
28+ marginBottom : "10px" ,
29+ }
30+ const browserIconStyle : CSSProperties = {
31+ color : "var(--vscode-foreground)" ,
32+ marginBottom : "-1.5px" ,
33+ }
34+ const approveTextStyle : CSSProperties = { fontWeight : "bold" }
35+ const urlBarContainerStyle : CSSProperties = {
36+ margin : "5px auto" ,
37+ width : "calc(100% - 10px)" ,
38+ display : "flex" ,
39+ alignItems : "center" ,
40+ gap : "4px" ,
41+ }
42+ const urlTextStyle : CSSProperties = {
43+ textOverflow : "ellipsis" ,
44+ overflow : "hidden" ,
45+ whiteSpace : "nowrap" ,
46+ width : "100%" ,
47+ textAlign : "center" ,
48+ }
49+ const imgScreenshotStyle : CSSProperties = {
50+ position : "absolute" ,
51+ top : 0 ,
52+ left : 0 ,
53+ width : "100%" ,
54+ height : "100%" ,
55+ objectFit : "contain" ,
56+ cursor : "pointer" ,
57+ }
58+ const noScreenshotContainerStyle : CSSProperties = {
59+ position : "absolute" ,
60+ top : "50%" ,
61+ left : "50%" ,
62+ transform : "translate(-50%, -50%)" ,
63+ }
64+ const noScreenshotIconStyle : CSSProperties = {
65+ fontSize : "80px" ,
66+ color : "var(--vscode-descriptionForeground)" ,
67+ }
68+ const consoleLogsContainerStyle : CSSProperties = { width : "100%" }
69+ const consoleLogsTextStyle : CSSProperties = { fontSize : "0.8em" }
70+ const paginationContainerStyle : CSSProperties = {
71+ display : "flex" ,
72+ justifyContent : "space-between" ,
73+ alignItems : "center" ,
74+ padding : "8px 0px" ,
75+ marginTop : "15px" ,
76+ borderTop : "1px solid var(--vscode-editorGroup-border)" ,
77+ }
78+ const paginationButtonGroupStyle : CSSProperties = { display : "flex" , gap : "4px" }
79+ const browserSessionStartedTextStyle : CSSProperties = { fontWeight : "bold" }
80+ const codeBlockContainerStyle : CSSProperties = {
81+ borderRadius : 3 ,
82+ border : "1px solid var(--vscode-editorGroup-border)" ,
83+ overflow : "hidden" ,
84+ backgroundColor : CODE_BLOCK_BG_COLOR ,
85+ }
86+ const browserActionBoxContainerStyle : CSSProperties = { padding : "10px 0 0 0" }
87+ const browserActionBoxContainerInnerStyle : CSSProperties = {
88+ borderRadius : 3 ,
89+ backgroundColor : CODE_BLOCK_BG_COLOR ,
90+ overflow : "hidden" ,
91+ border : "1px solid var(--vscode-editorGroup-border)" ,
92+ }
93+ const browseActionRowContainerStyle : CSSProperties = {
94+ display : "flex" ,
95+ alignItems : "center" ,
96+ padding : "9px 10px" ,
97+ }
98+ const browseActionRowStyle : CSSProperties = {
99+ whiteSpace : "normal" ,
100+ wordBreak : "break-word" ,
101+ }
102+ const browseActionTextStyle : CSSProperties = { fontWeight : 500 }
103+ const chatRowContentContainerStyle : CSSProperties = { padding : "10px 0 10px 0" }
104+ const headerStyle : CSSProperties = {
105+ display : "flex" ,
106+ alignItems : "center" ,
107+ gap : "10px" ,
108+ marginBottom : "10px" ,
109+ }
110+
24111const BrowserSessionRow = memo ( ( props : BrowserSessionRowProps ) => {
25112 const { messages, isLast, onHeightChange, lastModifiedMessage } = props
26113 const { browserSettings } = useExtensionState ( )
@@ -244,25 +331,12 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
244331 const maxWidth = browserSettings . viewport . width < BROWSER_VIEWPORT_PRESETS [ "Small Desktop (900x600)" ] . width ? 200 : undefined
245332
246333 const [ browserSessionRow , { height } ] = useSize (
334+ // We don't declare a constant for the inline style here because `useSize` will try to modify the style object
335+ // Which will cause `Uncaught TypeError: Cannot assign to read only property 'position' of object '#<Object>'`
247336 < BrowserSessionRowContainer style = { { marginBottom : - 10 } } >
248- < div
249- style = { {
250- display : "flex" ,
251- alignItems : "center" ,
252- gap : "10px" ,
253- marginBottom : "10px" ,
254- } } >
255- { isBrowsing ? (
256- < ProgressIndicator />
257- ) : (
258- < span
259- className = { `codicon codicon-inspect` }
260- style = { {
261- color : "var(--vscode-foreground)" ,
262- marginBottom : "-1.5px" ,
263- } } > </ span >
264- ) }
265- < span style = { { fontWeight : "bold" } } >
337+ < div style = { browserSessionRowContainerInnerStyle } >
338+ { isBrowsing ? < ProgressIndicator /> : < span className = "codicon codicon-inspect" style = { browserIconStyle } > </ span > }
339+ < span style = { approveTextStyle } >
266340 < > { isAutoApproved ? "Cline is using the browser:" : "Cline wants to use the browser:" } </ >
267341 </ span >
268342 </ div >
@@ -277,14 +351,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
277351 margin : "0 auto 10px auto" , // Center the container
278352 } } >
279353 { /* URL Bar */ }
280- < div
281- style = { {
282- margin : "5px auto" ,
283- width : "calc(100% - 10px)" ,
284- display : "flex" ,
285- alignItems : "center" ,
286- gap : "4px" ,
287- } } >
354+ < div style = { urlBarContainerStyle } >
288355 < div
289356 style = { {
290357 flex : 1 ,
@@ -296,16 +363,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
296363 color : displayState . url ? "var(--vscode-input-foreground)" : "var(--vscode-descriptionForeground)" ,
297364 fontSize : "12px" ,
298365 } } >
299- < div
300- style = { {
301- textOverflow : "ellipsis" ,
302- overflow : "hidden" ,
303- whiteSpace : "nowrap" ,
304- width : "100%" ,
305- textAlign : "center" ,
306- } } >
307- { displayState . url || "http" }
308- </ div >
366+ < div style = { urlTextStyle } > { displayState . url || "http" } </ div >
309367 </ div >
310368 < BrowserSettingsMenu disabled = { ! shouldShowSettings } maxWidth = { maxWidth } />
311369 </ div >
@@ -322,15 +380,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
322380 < img
323381 src = { displayState . screenshot }
324382 alt = "Browser screenshot"
325- style = { {
326- position : "absolute" ,
327- top : 0 ,
328- left : 0 ,
329- width : "100%" ,
330- height : "100%" ,
331- objectFit : "contain" ,
332- cursor : "pointer" ,
333- } }
383+ style = { imgScreenshotStyle }
334384 onClick = { ( ) =>
335385 vscode . postMessage ( {
336386 type : "openImage" ,
@@ -339,20 +389,8 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
339389 }
340390 />
341391 ) : (
342- < div
343- style = { {
344- position : "absolute" ,
345- top : "50%" ,
346- left : "50%" ,
347- transform : "translate(-50%, -50%)" ,
348- } } >
349- < span
350- className = "codicon codicon-globe"
351- style = { {
352- fontSize : "80px" ,
353- color : "var(--vscode-descriptionForeground)" ,
354- } }
355- />
392+ < div style = { noScreenshotContainerStyle } >
393+ < span className = "codicon codicon-globe" style = { noScreenshotIconStyle } />
356394 </ div >
357395 ) }
358396 { displayState . mousePosition && (
@@ -367,7 +405,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
367405 ) }
368406 </ div >
369407
370- < div style = { { width : "100%" } } >
408+ < div style = { consoleLogsContainerStyle } >
371409 < div
372410 onClick = { ( ) => {
373411 setConsoleLogsExpanded ( ! consoleLogsExpanded )
@@ -382,7 +420,7 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
382420 padding : `9px 8px ${ consoleLogsExpanded ? 0 : 8 } px 8px` ,
383421 } } >
384422 < span className = { `codicon codicon-chevron-${ consoleLogsExpanded ? "down" : "right" } ` } > </ span >
385- < span style = { { fontSize : "0.8em" } } > Console Logs</ span >
423+ < span style = { consoleLogsTextStyle } > Console Logs</ span >
386424 </ div >
387425 { consoleLogsExpanded && (
388426 < CodeBlock source = { `${ "```" } shell\n${ displayState . consoleLogs || "(No new logs)" } \n${ "```" } ` } />
@@ -395,19 +433,11 @@ const BrowserSessionRow = memo((props: BrowserSessionRowProps) => {
395433
396434 { /* Pagination moved to bottom */ }
397435 { pages . length > 1 && (
398- < div
399- style = { {
400- display : "flex" ,
401- justifyContent : "space-between" ,
402- alignItems : "center" ,
403- padding : "8px 0px" ,
404- marginTop : "15px" ,
405- borderTop : "1px solid var(--vscode-editorGroup-border)" ,
406- } } >
436+ < div style = { paginationContainerStyle } >
407437 < div >
408438 Step { currentPageIndex + 1 } of { pages . length }
409439 </ div >
410- < div style = { { display : "flex" , gap : "4px" } } >
440+ < div style = { paginationButtonGroupStyle } >
411441 < VSCodeButton
412442 disabled = { currentPageIndex === 0 || isBrowsing }
413443 onClick = { ( ) => setCurrentPageIndex ( ( i ) => i - 1 ) } >
@@ -453,26 +483,13 @@ const BrowserSessionRowContent = ({
453483 isLast,
454484 setMaxActionHeight,
455485} : BrowserSessionRowContentProps ) => {
456- const headerStyle : React . CSSProperties = {
457- display : "flex" ,
458- alignItems : "center" ,
459- gap : "10px" ,
460- marginBottom : "10px" ,
461- }
462-
463486 if ( message . ask === "browser_action_launch" || message . say === "browser_action_launch" ) {
464487 return (
465488 < >
466489 < div style = { headerStyle } >
467- < span style = { { fontWeight : "bold" } } > Browser Session Started</ span >
490+ < span style = { browserSessionStartedTextStyle } > Browser Session Started</ span >
468491 </ div >
469- < div
470- style = { {
471- borderRadius : 3 ,
472- border : "1px solid var(--vscode-editorGroup-border)" ,
473- overflow : "hidden" ,
474- backgroundColor : CODE_BLOCK_BG_COLOR ,
475- } } >
492+ < div style = { codeBlockContainerStyle } >
476493 < CodeBlock source = { `${ "```" } shell\n${ message . text } \n${ "```" } ` } forceWrap = { true } />
477494 </ div >
478495 </ >
@@ -485,7 +502,7 @@ const BrowserSessionRowContent = ({
485502 case "api_req_started" :
486503 case "text" :
487504 return (
488- < div style = { { padding : "10px 0 10px 0" } } >
505+ < div style = { chatRowContentContainerStyle } >
489506 < ChatRowContent
490507 message = { message }
491508 isExpanded = { isExpanded ( message . ts ) }
@@ -543,26 +560,11 @@ const BrowserActionBox = ({ action, coordinate, text }: { action: BrowserAction;
543560 }
544561 }
545562 return (
546- < div style = { { padding : "10px 0 0 0" } } >
547- < div
548- style = { {
549- borderRadius : 3 ,
550- backgroundColor : CODE_BLOCK_BG_COLOR ,
551- overflow : "hidden" ,
552- border : "1px solid var(--vscode-editorGroup-border)" ,
553- } } >
554- < div
555- style = { {
556- display : "flex" ,
557- alignItems : "center" ,
558- padding : "9px 10px" ,
559- } } >
560- < span
561- style = { {
562- whiteSpace : "normal" ,
563- wordBreak : "break-word" ,
564- } } >
565- < span style = { { fontWeight : 500 } } > Browse Action: </ span >
563+ < div style = { browserActionBoxContainerStyle } >
564+ < div style = { browserActionBoxContainerInnerStyle } >
565+ < div style = { browseActionRowContainerStyle } >
566+ < span style = { browseActionRowStyle } >
567+ < span style = { browseActionTextStyle } > Browse Action: </ span >
566568 { getBrowserActionText ( action , coordinate , text ) }
567569 </ span >
568570 </ div >
@@ -571,7 +573,7 @@ const BrowserActionBox = ({ action, coordinate, text }: { action: BrowserAction;
571573 )
572574}
573575
574- const BrowserCursor : React . FC < { style ?: React . CSSProperties } > = ( { style } ) => {
576+ const BrowserCursor : React . FC < { style ?: CSSProperties } > = ( { style } ) => {
575577 // (can't use svgs in vsc extensions)
576578 const cursorBase64 =
577579 "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAYCAYAAAAVibZIAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFaADAAQAAAABAAAAGAAAAADwi9a/AAADGElEQVQ4EZ2VbUiTURTH772be/PxZdsz3cZwC4RVaB8SAjMpxQwSWZbQG/TFkN7oW1Df+h6IRV9C+hCpKUSIZUXOfGM5tAKViijFFEyfZ7Ol29S1Pbdzl8Uw9+aBu91zzv3/nt17zt2DEZjBYOAkKrtFMXIghAWM8U2vMN/FctsxGRMpM7NbEEYNMM2CYUSInlJx3OpawO9i+XSNQYkmk2uFb9njzkcfVSr1p/GJiQKMULVaw2WuBv296UKRxWJR6wxGCmM1EAhSNppv33GBH9qI32cPTAtss9lUm6EM3N7R+RbigT+5/CeosFCZKpjEW+iorS1pb30wDUXzQfHqtD/9L3ieZ2ee1OJCmbL8QHnRs+4uj0wmW4QzrpCwvJ8zGg3JqAmhTLynuLiwv8/5KyND8Q3cEkUEDWu15oJE4KRQJt5hs1rcriGNRqP+DK4dyyWXXm/aFQ+cEpSJ8/LyDGPuEZNOmzsOroUSOqzXG/dtBU4ZysTZYKNut91sNo2Cq6cE9enz86s2g9OCMrFSqVC5hgb32u072W3jKMU90Hb1seC0oUwsB+t92bO/rKx0EFGkgFCnjjc1/gVvC8rE0L+4o63t4InjxwbAJQjTe3qD8QrLkXA4DC24fWtuajp06cLFYSBIFKGmXKPRRmAnME9sPt+yLwIWb9WN69fKoTneQz4Dh2mpPNkvfeV0jjecb9wNAkwIEVQq5VJOds4Kb+DXoAsiVquVwI1Dougpij6UyGYx+5cKroeDEFibm5lWRRMbH1+npmYrq6qhwlQHIbajZEf1fElcqGGFpGg9HMuKzpfBjhytCTMgkJ56RX09zy/ysENTBElmjIgJnmNChJqohDVQqpEfwkILE8v/o0GAnV9F1eEvofVQCbiTBEXOIPQh5PGgefDZeAcjrpGZjULBr/m3tZOnz7oEQWRAQZLjWlEU/XEJWySiILgRc5Cz1DkcAyuBFcnpfF0JiXWKpcolQXizhS5hKAqFpr0MVbgbuxJ6+5xX+P4wNpbqPPrugZfbmIbLmgQR3Aw8QSi66hUXulOFbF73GxqjE5BNXWNeAAAAAElFTkSuQmCC"
0 commit comments