mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-09 22:31:08 +00:00
[DRAFT] feat(menu): use material icons for files and folders (#2739)
feat(menu): use material icons for files and folders
This commit is contained in:
parent
0d561f8a27
commit
1a376c262e
4 changed files with 67 additions and 19 deletions
7
package-lock.json
generated
7
package-lock.json
generated
|
|
@ -61,6 +61,7 @@
|
|||
"tmp": "^0.2.3",
|
||||
"tree-sitter-wasms": "^0.1.11",
|
||||
"turndown": "^7.2.0",
|
||||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
|
@ -21550,6 +21551,12 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/vscode-material-icons": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-material-icons/-/vscode-material-icons-0.1.1.tgz",
|
||||
"integrity": "sha512-GsoEEF8Tbb0yUFQ6N6FPvh11kFkL9F95x0FkKlbbfRQN9eFms67h+L3t6b9cUv58dSn2gu8kEhNfoESVCrz4ag==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/walker": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
|
||||
|
|
|
|||
|
|
@ -453,6 +453,7 @@
|
|||
"tmp": "^0.2.3",
|
||||
"tree-sitter-wasms": "^0.1.11",
|
||||
"turndown": "^7.2.0",
|
||||
"vscode-material-icons": "^0.1.1",
|
||||
"web-tree-sitter": "^0.22.6",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -622,6 +622,13 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
"codicon.css",
|
||||
])
|
||||
|
||||
const materialIconsUri = getUri(webview, this.contextProxy.extensionUri, [
|
||||
"node_modules",
|
||||
"vscode-material-icons",
|
||||
"generated",
|
||||
"icons",
|
||||
])
|
||||
|
||||
const imagesUri = getUri(webview, this.contextProxy.extensionUri, ["assets", "images"])
|
||||
|
||||
const file = "src/index.tsx"
|
||||
|
|
@ -656,7 +663,8 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
<link rel="stylesheet" type="text/css" href="${stylesUri}">
|
||||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<script nonce="${nonce}">
|
||||
window.IMAGES_BASE_URI = "${imagesUri}"
|
||||
window.IMAGES_BASE_URI = "${imagesUri}"
|
||||
window.MATERIAL_ICONS_BASE_URI = "${materialIconsUri}"
|
||||
</script>
|
||||
<title>Roo Code</title>
|
||||
</head>
|
||||
|
|
@ -706,6 +714,14 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
"codicon.css",
|
||||
])
|
||||
|
||||
// The material icons from the React build output
|
||||
const materialIconsUri = getUri(webview, this.contextProxy.extensionUri, [
|
||||
"node_modules",
|
||||
"vscode-material-icons",
|
||||
"generated",
|
||||
"icons",
|
||||
])
|
||||
|
||||
const imagesUri = getUri(webview, this.contextProxy.extensionUri, ["assets", "images"])
|
||||
|
||||
// const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this._extensionUri, "assets", "main.js"))
|
||||
|
|
@ -742,6 +758,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<script nonce="${nonce}">
|
||||
window.IMAGES_BASE_URI = "${imagesUri}"
|
||||
window.MATERIAL_ICONS_BASE_URI = "${materialIconsUri}"
|
||||
</script>
|
||||
<title>Roo Code</title>
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react"
|
||||
import React, { useEffect, useMemo, useRef, useState } from "react"
|
||||
import { getIconForFilePath, getIconUrlByName, getIconForDirectoryPath } from "vscode-material-icons"
|
||||
import {
|
||||
ContextMenuOptionType,
|
||||
ContextMenuQueryItem,
|
||||
|
|
@ -35,6 +36,7 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||
loading = false,
|
||||
dynamicSearchResults = [],
|
||||
}) => {
|
||||
const [materialIconsBaseUri, setMaterialIconsBaseUri] = useState("")
|
||||
const menuRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const filteredOptions = useMemo(() => {
|
||||
|
|
@ -57,6 +59,12 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||
}
|
||||
}, [selectedIndex])
|
||||
|
||||
// get the icons base uri on mount
|
||||
useEffect(() => {
|
||||
const w = window as any
|
||||
setMaterialIconsBaseUri(w.MATERIAL_ICONS_BASE_URI)
|
||||
}, [])
|
||||
|
||||
const renderOptionContent = (option: ContextMenuQueryItem) => {
|
||||
switch (option.type) {
|
||||
case ContextMenuOptionType.Mode:
|
||||
|
|
@ -175,6 +183,15 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||
}
|
||||
}
|
||||
|
||||
const getMaterialIconForOption = (option: ContextMenuQueryItem): string => {
|
||||
// only take the last part of the path to handle both file and folder icons
|
||||
// since material-icons have specific folder icons, we use them if available
|
||||
const name = option.value?.split("/").filter(Boolean).at(-1) ?? ""
|
||||
const iconName =
|
||||
option.type === ContextMenuOptionType.Folder ? getIconForDirectoryPath(name) : getIconForFilePath(name)
|
||||
return getIconUrlByName(iconName, materialIconsBaseUri)
|
||||
}
|
||||
|
||||
const isOptionSelectable = (option: ContextMenuQueryItem): boolean => {
|
||||
return option.type !== ContextMenuOptionType.NoResults && option.type !== ContextMenuOptionType.URL
|
||||
}
|
||||
|
|
@ -231,17 +248,35 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||
overflow: "hidden",
|
||||
paddingTop: 0,
|
||||
}}>
|
||||
{option.type !== ContextMenuOptionType.Mode && getIconForOption(option) && (
|
||||
<i
|
||||
className={`codicon codicon-${getIconForOption(option)}`}
|
||||
{(option.type === ContextMenuOptionType.File ||
|
||||
option.type === ContextMenuOptionType.Folder ||
|
||||
option.type === ContextMenuOptionType.OpenedFile) && (
|
||||
<img
|
||||
src={getMaterialIconForOption(option)}
|
||||
alt="Mode"
|
||||
style={{
|
||||
marginRight: "6px",
|
||||
flexShrink: 0,
|
||||
fontSize: "14px",
|
||||
marginTop: 0,
|
||||
width: "16px",
|
||||
height: "16px",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{option.type !== ContextMenuOptionType.Mode &&
|
||||
option.type !== ContextMenuOptionType.File &&
|
||||
option.type !== ContextMenuOptionType.Folder &&
|
||||
option.type !== ContextMenuOptionType.OpenedFile &&
|
||||
getIconForOption(option) && (
|
||||
<i
|
||||
className={`codicon codicon-${getIconForOption(option)}`}
|
||||
style={{
|
||||
marginRight: "6px",
|
||||
flexShrink: 0,
|
||||
fontSize: "14px",
|
||||
marginTop: 0,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{renderOptionContent(option)}
|
||||
</div>
|
||||
{(option.type === ContextMenuOptionType.File ||
|
||||
|
|
@ -253,18 +288,6 @@ const ContextMenu: React.FC<ContextMenuProps> = ({
|
|||
style={{ fontSize: "10px", flexShrink: 0, marginLeft: 8 }}
|
||||
/>
|
||||
)}
|
||||
{(option.type === ContextMenuOptionType.Problems ||
|
||||
option.type === ContextMenuOptionType.Terminal ||
|
||||
((option.type === ContextMenuOptionType.File ||
|
||||
option.type === ContextMenuOptionType.Folder ||
|
||||
option.type === ContextMenuOptionType.OpenedFile ||
|
||||
option.type === ContextMenuOptionType.Git) &&
|
||||
option.value)) && (
|
||||
<i
|
||||
className="codicon codicon-add"
|
||||
style={{ fontSize: "10px", flexShrink: 0, marginLeft: 8 }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue