mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 04:11:10 -05:00
Replace event listeners with react-use useEvent; fix bugs with task text truncation, stale effects, and 'visible' extension TypeError
This commit is contained in:
@@ -44,7 +44,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
||||
// Listen for when the panel becomes visible
|
||||
// https://github.com/microsoft/vscode-discussions/discussions/840
|
||||
webviewView.onDidChangeVisibility((e: any) => {
|
||||
if (e.visible) {
|
||||
if (e && e.visible) {
|
||||
// Your view is visible
|
||||
this.postMessageToWebview({ type: "action", action: "didBecomeVisible" })
|
||||
} else {
|
||||
|
||||
223
webview-ui/package-lock.json
generated
223
webview-ui/package-lock.json
generated
@@ -23,6 +23,7 @@
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-text-truncate": "^0.19.0",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
"react-use": "^17.5.1",
|
||||
"rewire": "^7.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
@@ -4489,6 +4490,11 @@
|
||||
"pretty-format": "^27.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/js-cookie": {
|
||||
"version": "2.2.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz",
|
||||
"integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="
|
||||
},
|
||||
"node_modules/@types/json-schema": {
|
||||
"version": "7.0.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
|
||||
@@ -5121,6 +5127,11 @@
|
||||
"@xtuc/long": "4.2.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@xobotyi/scrollbar-width": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz",
|
||||
"integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="
|
||||
},
|
||||
"node_modules/@xtuc/ieee754": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||
@@ -6718,6 +6729,14 @@
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/copy-to-clipboard": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
||||
"integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
|
||||
"dependencies": {
|
||||
"toggle-selection": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/core-js": {
|
||||
"version": "3.37.1",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz",
|
||||
@@ -6846,6 +6865,14 @@
|
||||
"postcss": "^8.4"
|
||||
}
|
||||
},
|
||||
"node_modules/css-in-js-utils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz",
|
||||
"integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==",
|
||||
"dependencies": {
|
||||
"hyphenate-style-name": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/css-loader": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz",
|
||||
@@ -8895,6 +8922,16 @@
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-shallow-equal": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz",
|
||||
"integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="
|
||||
},
|
||||
"node_modules/fastest-stable-stringify": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz",
|
||||
"integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||
@@ -10120,6 +10157,11 @@
|
||||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/hyphenate-style-name": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
|
||||
"integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
@@ -10266,6 +10308,14 @@
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/inline-style-prefixer": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz",
|
||||
"integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==",
|
||||
"dependencies": {
|
||||
"css-in-js-utils": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
|
||||
@@ -13116,6 +13166,11 @@
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
},
|
||||
"node_modules/js-cookie": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
|
||||
"integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
|
||||
},
|
||||
"node_modules/js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
@@ -13786,6 +13841,50 @@
|
||||
"thenify-all": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nano-css": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz",
|
||||
"integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==",
|
||||
"dependencies": {
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15",
|
||||
"css-tree": "^1.1.2",
|
||||
"csstype": "^3.1.2",
|
||||
"fastest-stable-stringify": "^2.0.2",
|
||||
"inline-style-prefixer": "^7.0.1",
|
||||
"rtl-css-js": "^1.16.1",
|
||||
"stacktrace-js": "^2.0.2",
|
||||
"stylis": "^4.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/nano-css/node_modules/css-tree": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
|
||||
"integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
|
||||
"dependencies": {
|
||||
"mdn-data": "2.0.14",
|
||||
"source-map": "^0.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nano-css/node_modules/mdn-data": {
|
||||
"version": "2.0.14",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
|
||||
"integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
|
||||
},
|
||||
"node_modules/nano-css/node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.7",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
|
||||
@@ -16455,6 +16554,40 @@
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-universal-interface": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz",
|
||||
"integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==",
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"tslib": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-use": {
|
||||
"version": "17.5.1",
|
||||
"resolved": "https://registry.npmjs.org/react-use/-/react-use-17.5.1.tgz",
|
||||
"integrity": "sha512-LG/uPEVRflLWMwi3j/sZqR00nF6JGqTTDblkXK2nzXsIvij06hXl1V/MZIlwj1OKIQUtlh1l9jK8gLsRyCQxMg==",
|
||||
"dependencies": {
|
||||
"@types/js-cookie": "^2.2.6",
|
||||
"@xobotyi/scrollbar-width": "^1.9.5",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-shallow-equal": "^1.0.0",
|
||||
"js-cookie": "^2.2.1",
|
||||
"nano-css": "^5.6.2",
|
||||
"react-universal-interface": "^0.6.2",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"screenfull": "^5.1.0",
|
||||
"set-harmonic-interval": "^1.0.1",
|
||||
"throttle-debounce": "^3.0.1",
|
||||
"ts-easing": "^0.2.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-dom": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/read-cache": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
@@ -16700,6 +16833,11 @@
|
||||
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/resize-observer-polyfill": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||
},
|
||||
"node_modules/resolve": {
|
||||
"version": "1.22.8",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
|
||||
@@ -16932,6 +17070,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/rtl-css-js": {
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
|
||||
"integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
@@ -17140,6 +17286,17 @@
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/screenfull": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz",
|
||||
"integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@@ -17350,6 +17507,14 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/set-harmonic-interval": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz",
|
||||
"integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==",
|
||||
"engines": {
|
||||
"node": ">=6.9"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
@@ -17560,6 +17725,14 @@
|
||||
"deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stack-generator": {
|
||||
"version": "2.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
|
||||
"integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
|
||||
"dependencies": {
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stack-utils": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
|
||||
@@ -17587,6 +17760,33 @@
|
||||
"integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/stacktrace-gps": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
|
||||
"integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
|
||||
"dependencies": {
|
||||
"source-map": "0.5.6",
|
||||
"stackframe": "^1.3.4"
|
||||
}
|
||||
},
|
||||
"node_modules/stacktrace-gps/node_modules/source-map": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
|
||||
"integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stacktrace-js": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
|
||||
"integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
|
||||
"dependencies": {
|
||||
"error-stack-parser": "^2.0.6",
|
||||
"stack-generator": "^2.0.5",
|
||||
"stacktrace-gps": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/static-eval": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
|
||||
@@ -17984,6 +18184,11 @@
|
||||
"postcss": "^8.2.15"
|
||||
}
|
||||
},
|
||||
"node_modules/stylis": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
|
||||
"integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
|
||||
},
|
||||
"node_modules/sucrase": {
|
||||
"version": "3.35.0",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
|
||||
@@ -18449,6 +18654,14 @@
|
||||
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/throttle-debounce": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
|
||||
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/thunky": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
|
||||
@@ -18482,6 +18695,11 @@
|
||||
"node": ">=8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toggle-selection": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
|
||||
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
@@ -18533,6 +18751,11 @@
|
||||
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ts-easing": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz",
|
||||
"integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="
|
||||
},
|
||||
"node_modules/ts-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"react-syntax-highlighter": "^15.5.0",
|
||||
"react-text-truncate": "^0.19.0",
|
||||
"react-textarea-autosize": "^8.5.3",
|
||||
"react-use": "^17.5.1",
|
||||
"rewire": "^7.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import React, { useEffect, useState } from "react"
|
||||
import React, { useEffect, useState, useCallback } from "react"
|
||||
import "./App.css"
|
||||
|
||||
import ChatView from "./components/ChatView"
|
||||
import SettingsView from "./components/SettingsView"
|
||||
import { ClaudeMessage, ExtensionMessage } from "@shared/ExtensionMessage"
|
||||
import WelcomeView from "./components/WelcomeView"
|
||||
import { vscode } from "./utilities/vscode"
|
||||
//import { mockMessages } from "./utilities/mockMessages"
|
||||
import { useEvent } from "react-use"
|
||||
|
||||
/*
|
||||
The contents of webviews however are created when the webview becomes visible and destroyed when the webview is moved into the background. Any state inside the webview will be lost when the webview is moved to a background tab.
|
||||
@@ -26,19 +25,17 @@ const App: React.FC = () => {
|
||||
|
||||
useEffect(() => {
|
||||
vscode.postMessage({ type: "webviewDidLaunch" })
|
||||
}, [])
|
||||
|
||||
const handleMessage = (e: MessageEvent) => {
|
||||
const handleMessage = useCallback((e: MessageEvent) => {
|
||||
const message: ExtensionMessage = e.data
|
||||
// switch message.type
|
||||
switch (message.type) {
|
||||
case "state":
|
||||
const shouldShowWelcome = !message.state!.didOpenOnce || !message.state!.apiKey
|
||||
setShowWelcome(shouldShowWelcome)
|
||||
setApiKey(message.state!.apiKey || "")
|
||||
setMaxRequestsPerTask(
|
||||
message.state!.maxRequestsPerTask !== undefined
|
||||
? message.state!.maxRequestsPerTask.toString()
|
||||
: ""
|
||||
message.state!.maxRequestsPerTask !== undefined ? message.state!.maxRequestsPerTask.toString() : ""
|
||||
)
|
||||
setVscodeThemeName(message.state!.themeName)
|
||||
setClaudeMessages(message.state!.claudeMessages)
|
||||
@@ -54,15 +51,11 @@ const App: React.FC = () => {
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", handleMessage)
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("message", handleMessage)
|
||||
}
|
||||
// we don't need to define any dependencies since we're not using any state in the callback. if you were to use state, you'd either have to include it in the dependency array or use the updater function `setUserText(prev => `${prev}${key}`);`. (react-use takes care of not registering the same listener multiple times even if this callback is updated.)
|
||||
}, [])
|
||||
|
||||
useEvent("message", handleMessage)
|
||||
|
||||
return (
|
||||
<>
|
||||
{showWelcome ? (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ClaudeAsk, ClaudeMessage, ExtensionMessage } from "@shared/ExtensionMessage"
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { KeyboardEvent, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { animateScroll as scroll } from "react-scroll"
|
||||
import DynamicTextArea from "react-textarea-autosize"
|
||||
import { combineApiRequests } from "../utilities/combineApiRequests"
|
||||
@@ -11,6 +11,7 @@ import ChatRow from "./ChatRow"
|
||||
import TaskHeader from "./TaskHeader"
|
||||
import { getSyntaxHighlighterStyleFromTheme } from "../utilities/getSyntaxHighlighterStyleFromTheme"
|
||||
import vsDarkPlus from "react-syntax-highlighter/dist/esm/styles/prism/vsc-dark-plus"
|
||||
import { useEvent } from "react-use"
|
||||
|
||||
interface ChatViewProps {
|
||||
messages: ClaudeMessage[]
|
||||
@@ -242,28 +243,33 @@ const ChatView = ({ messages, isHidden, vscodeThemeName }: ChatViewProps) => {
|
||||
vscode.postMessage({ type: "clearTask" })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const handleMessage = (e: MessageEvent) => {
|
||||
const handleMessage = useCallback(
|
||||
(e: MessageEvent) => {
|
||||
const message: ExtensionMessage = e.data
|
||||
switch (message.type) {
|
||||
case "action":
|
||||
switch (message.action!) {
|
||||
case "didBecomeVisible":
|
||||
if (!isHidden && !textAreaDisabled && !enableButtons) {
|
||||
textAreaRef.current?.focus()
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
// textAreaRef.current is not explicitly required here since react gaurantees that ref will be stable across re-renders, and we're not using its value but its reference.
|
||||
},
|
||||
[isHidden, textAreaDisabled, enableButtons]
|
||||
)
|
||||
|
||||
window.addEventListener("message", handleMessage)
|
||||
useEvent("message", handleMessage)
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
textAreaRef.current?.focus()
|
||||
}, 20)
|
||||
return () => {
|
||||
clearTimeout(timer)
|
||||
window.removeEventListener("message", handleMessage)
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -271,27 +277,18 @@ const ChatView = ({ messages, isHidden, vscodeThemeName }: ChatViewProps) => {
|
||||
if (textAreaRef.current && !textAreaHeight) {
|
||||
setTextAreaHeight(textAreaRef.current.offsetHeight)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [textAreaRef.current])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isHidden && !textAreaDisabled && !enableButtons) {
|
||||
textAreaRef.current?.focus()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isHidden])
|
||||
}, [textAreaHeight])
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
if (!textAreaDisabled && !enableButtons) {
|
||||
if (!isHidden && !textAreaDisabled && !enableButtons) {
|
||||
textAreaRef.current?.focus()
|
||||
}
|
||||
}, 50)
|
||||
return () => {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [textAreaDisabled])
|
||||
}, [isHidden, textAreaDisabled, enableButtons])
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -312,6 +309,7 @@ const ChatView = ({ messages, isHidden, vscodeThemeName }: ChatViewProps) => {
|
||||
tokensOut={apiMetrics.totalTokensOut}
|
||||
totalCost={apiMetrics.totalCost}
|
||||
onClose={handleTaskCloseButtonClick}
|
||||
isHidden={isHidden}
|
||||
/>
|
||||
) : (
|
||||
<div style={{ padding: "0 25px" }}>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { VSCodeTextField, VSCodeDivider, VSCodeLink, VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeButton, VSCodeDivider, VSCodeLink, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useState } from "react"
|
||||
import { useMount } from "react-use"
|
||||
import { vscode } from "../utilities/vscode"
|
||||
|
||||
type SettingsViewProps = {
|
||||
@@ -59,11 +60,20 @@ const SettingsView = ({ apiKey, setApiKey, maxRequestsPerTask, setMaxRequestsPer
|
||||
}
|
||||
|
||||
// validate as soon as the component is mounted
|
||||
/*
|
||||
useEffect will use stale values of variables if they are not included in the dependency array. so trying to use useEffect with a dependency array of only one value for example will use any other variables' old values. In most cases you don't want this, and should opt to use react-use hooks.
|
||||
|
||||
useEffect(() => {
|
||||
// uses someVar and anotherVar
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [someVar])
|
||||
|
||||
If we only want to run code once on mount we can use react-use's useEffectOnce or useMount
|
||||
*/
|
||||
useMount(() => {
|
||||
validateApiKey(apiKey)
|
||||
validateMaxRequests(maxRequestsPerTask)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [])
|
||||
})
|
||||
|
||||
return (
|
||||
<div style={{ margin: "0 auto", paddingTop: "10px" }}>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from "react"
|
||||
import TextTruncate from "react-text-truncate"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
import TextTruncate from "react-text-truncate"
|
||||
import { useWindowSize } from "react-use"
|
||||
|
||||
interface TaskHeaderProps {
|
||||
taskText: string
|
||||
@@ -8,10 +9,66 @@ interface TaskHeaderProps {
|
||||
tokensOut: number
|
||||
totalCost: number
|
||||
onClose: () => void
|
||||
isHidden: boolean
|
||||
}
|
||||
|
||||
const TaskHeader: React.FC<TaskHeaderProps> = ({ taskText, tokensIn, tokensOut, totalCost, onClose }) => {
|
||||
const TaskHeader: React.FC<TaskHeaderProps> = ({ taskText, tokensIn, tokensOut, totalCost, onClose, isHidden }) => {
|
||||
const [isExpanded, setIsExpanded] = useState(false)
|
||||
const [textTruncateKey, setTextTruncateKey] = useState(0)
|
||||
const textContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
/*
|
||||
When dealing with event listeners in React components that depend on state variables, we face a challenge. We want our listener to always use the most up-to-date version of a callback function that relies on current state, but we don't want to constantly add and remove event listeners as that function updates. This scenario often arises with resize listeners or other window events. Simply adding the listener in a useEffect with an empty dependency array risks using stale state, while including the callback in the dependencies can lead to unnecessary re-registrations of the listener. There are react hook libraries that provide a elegant solution to this problem by utilizing the useRef hook to maintain a reference to the latest callback function without triggering re-renders or effect re-runs. This approach ensures that our event listener always has access to the most current state while minimizing performance overhead and potential memory leaks from multiple listener registrations.
|
||||
Sources
|
||||
- https://usehooks-ts.com/react-hook/use-event-listener
|
||||
- https://streamich.github.io/react-use/?path=/story/sensors-useevent--docs
|
||||
- https://github.com/streamich/react-use/blob/master/src/useEvent.ts
|
||||
- https://stackoverflow.com/questions/55565444/how-to-register-event-with-useeffect-hooks
|
||||
|
||||
Before:
|
||||
|
||||
const updateMaxHeight = useCallback(() => {
|
||||
if (isExpanded && textContainerRef.current) {
|
||||
const maxHeight = window.innerHeight * (3 / 5)
|
||||
textContainerRef.current.style.maxHeight = `${maxHeight}px`
|
||||
}
|
||||
}, [isExpanded])
|
||||
|
||||
useEffect(() => {
|
||||
updateMaxHeight()
|
||||
}, [isExpanded, updateMaxHeight])
|
||||
|
||||
useEffect(() => {
|
||||
window.removeEventListener("resize", updateMaxHeight)
|
||||
window.addEventListener("resize", updateMaxHeight)
|
||||
return () => {
|
||||
window.removeEventListener("resize", updateMaxHeight)
|
||||
}
|
||||
}, [updateMaxHeight])
|
||||
|
||||
After:
|
||||
*/
|
||||
|
||||
const { height: windowHeight } = useWindowSize()
|
||||
|
||||
useEffect(() => {
|
||||
if (isExpanded && textContainerRef.current) {
|
||||
const maxHeight = windowHeight * (3 / 5)
|
||||
textContainerRef.current.style.maxHeight = `${maxHeight}px`
|
||||
}
|
||||
}, [isExpanded, windowHeight])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isHidden) {
|
||||
/*
|
||||
There's an issue with TextTruncate where it is hidden when removed from the screen. It uses canvas to measure text width and adjusts the content accordingly. However, when the component is hidden, the canvas is not rendered and the text is not measured.
|
||||
We can fix this by forcing re-render after navigation by using a key prop that changes when you navigate back to the page.
|
||||
- https://github.com/ShinyChang/React-Text-Truncate?tab=readme-ov-file#faq
|
||||
*/
|
||||
setTextTruncateKey((prev) => prev + 1)
|
||||
}
|
||||
}, [isHidden])
|
||||
|
||||
const toggleExpand = () => setIsExpanded(!isExpanded)
|
||||
|
||||
return (
|
||||
@@ -40,8 +97,15 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({ taskText, tokensIn, tokensOut,
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
<div style={{ fontSize: "var(--vscode-font-size)" }}>
|
||||
<div
|
||||
ref={textContainerRef}
|
||||
style={{
|
||||
fontSize: "var(--vscode-font-size)",
|
||||
overflowY: isExpanded ? "auto" : "hidden",
|
||||
wordBreak: "break-word",
|
||||
}}>
|
||||
<TextTruncate
|
||||
key={textTruncateKey}
|
||||
line={isExpanded ? 0 : 3}
|
||||
element="span"
|
||||
truncateText="…"
|
||||
@@ -71,22 +135,22 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({ taskText, tokensIn, tokensOut,
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "4px" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "5px" }}>
|
||||
<span style={{ fontWeight: "bold" }}>Tokens:</span>
|
||||
<span style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||
<span style={{ display: "flex", alignItems: "center", gap: "3px" }}>
|
||||
<i
|
||||
className="codicon codicon-arrow-down"
|
||||
style={{ fontSize: "12px", marginBottom: "-2px" }}
|
||||
/>
|
||||
{tokensIn.toLocaleString()}
|
||||
</span>
|
||||
<span style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||
<i
|
||||
className="codicon codicon-arrow-up"
|
||||
style={{ fontSize: "12px", marginBottom: "-2px" }}
|
||||
style={{ fontSize: "12px", fontWeight: "bold", marginBottom: "-2px" }}
|
||||
/>
|
||||
{tokensOut.toLocaleString()}
|
||||
</span>
|
||||
<span style={{ display: "flex", alignItems: "center", gap: "3px" }}>
|
||||
<i
|
||||
className="codicon codicon-arrow-up"
|
||||
style={{ fontSize: "12px", fontWeight: "bold", marginBottom: "-1.5px" }}
|
||||
/>
|
||||
{tokensIn.toLocaleString()}
|
||||
</span>
|
||||
</div>
|
||||
<div style={{ display: "flex", alignItems: "center", gap: "4px" }}>
|
||||
<span style={{ fontWeight: "bold" }}>API Cost:</span>
|
||||
|
||||
Reference in New Issue
Block a user