mirror of
https://github.com/pacnpal/Roo-Code.git
synced 2025-12-20 12:21:13 -05:00
Add sorting to task history
This commit is contained in:
@@ -1,17 +1,31 @@
|
||||
import { VSCodeButton, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeButton, VSCodeTextField, VSCodeRadioGroup, VSCodeRadio } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useExtensionState } from "../context/ExtensionStateContext"
|
||||
import { vscode } from "../utils/vscode"
|
||||
import { Virtuoso } from "react-virtuoso"
|
||||
import { memo, useMemo, useState } from "react"
|
||||
import { memo, useMemo, useState, useEffect } from "react"
|
||||
import Fuse, { FuseResult } from "fuse.js"
|
||||
|
||||
type HistoryViewProps = {
|
||||
onDone: () => void
|
||||
}
|
||||
|
||||
type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
|
||||
|
||||
const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
const { taskHistory } = useExtensionState()
|
||||
const [searchQuery, setSearchQuery] = useState("")
|
||||
const [sortOption, setSortOption] = useState<SortOption>("newest")
|
||||
const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
|
||||
|
||||
useEffect(() => {
|
||||
if (searchQuery && sortOption !== "mostRelevant" && !lastNonRelevantSort) {
|
||||
setLastNonRelevantSort(sortOption)
|
||||
setSortOption("mostRelevant")
|
||||
} else if (!searchQuery && sortOption === "mostRelevant" && lastNonRelevantSort) {
|
||||
setSortOption(lastNonRelevantSort)
|
||||
setLastNonRelevantSort(null)
|
||||
}
|
||||
}, [searchQuery, sortOption, lastNonRelevantSort])
|
||||
|
||||
const handleHistorySelect = (id: string) => {
|
||||
vscode.postMessage({ type: "showTaskWithId", text: id })
|
||||
@@ -43,20 +57,42 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
const fuse = useMemo(() => {
|
||||
return new Fuse(presentableTasks, {
|
||||
keys: ["task"],
|
||||
threshold: 0.4,
|
||||
threshold: 0.6,
|
||||
shouldSort: true,
|
||||
isCaseSensitive: false,
|
||||
ignoreLocation: true,
|
||||
ignoreLocation: false,
|
||||
includeMatches: true,
|
||||
minMatchCharLength: 1,
|
||||
})
|
||||
}, [presentableTasks])
|
||||
|
||||
const taskHistorySearchResults = useMemo(() => {
|
||||
if (!searchQuery) return presentableTasks
|
||||
const searchResults = fuse.search(searchQuery)
|
||||
return highlight(searchResults)
|
||||
}, [presentableTasks, searchQuery, fuse])
|
||||
let results = searchQuery ? highlight(fuse.search(searchQuery)) : presentableTasks
|
||||
|
||||
results.sort((a, b) => {
|
||||
switch (sortOption) {
|
||||
case "oldest":
|
||||
return a.ts - b.ts
|
||||
case "mostExpensive":
|
||||
return (b.totalCost || 0) - (a.totalCost || 0)
|
||||
case "mostTokens":
|
||||
return (
|
||||
(b.tokensIn || 0) +
|
||||
(b.tokensOut || 0) +
|
||||
(b.cacheWrites || 0) +
|
||||
(b.cacheReads || 0) -
|
||||
((a.tokensIn || 0) + (a.tokensOut || 0) + (a.cacheWrites || 0) + (a.cacheReads || 0))
|
||||
)
|
||||
case "mostRelevant":
|
||||
return searchQuery ? 0 : b.ts - a.ts // Keep fuse order if searching, otherwise sort by newest
|
||||
case "newest":
|
||||
default:
|
||||
return b.ts - a.ts
|
||||
}
|
||||
})
|
||||
|
||||
return results
|
||||
}, [presentableTasks, searchQuery, fuse, sortOption])
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -78,6 +114,13 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
background-color: var(--vscode-editor-findMatchHighlightBackground);
|
||||
color: inherit;
|
||||
}
|
||||
.clear-search-button {
|
||||
cursor: pointer;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.clear-search-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div
|
||||
@@ -101,26 +144,56 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
<h3 style={{ color: "var(--vscode-foreground)", margin: 0 }}>History</h3>
|
||||
<VSCodeButton onClick={onDone}>Done</VSCodeButton>
|
||||
</div>
|
||||
<div style={{ padding: "5px 17px 10px 17px" }}>
|
||||
<div style={{ padding: "5px 17px 6px 17px" }}>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "6px" }}>
|
||||
<VSCodeTextField
|
||||
style={{ width: "100%" }}
|
||||
placeholder="Search history..."
|
||||
placeholder="Fuzzy search history..."
|
||||
value={searchQuery}
|
||||
onInput={(e) => setSearchQuery((e.target as HTMLInputElement)?.value)}>
|
||||
onInput={(e) => {
|
||||
const newValue = (e.target as HTMLInputElement)?.value
|
||||
setSearchQuery(newValue)
|
||||
if (newValue && !searchQuery && sortOption !== "mostRelevant") {
|
||||
setLastNonRelevantSort(sortOption)
|
||||
setSortOption("mostRelevant")
|
||||
}
|
||||
}}>
|
||||
<div
|
||||
slot="start"
|
||||
className="codicon codicon-search"
|
||||
style={{ fontSize: 13, marginTop: 2.5, opacity: 0.8 }}></div>
|
||||
{searchQuery && (
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
<div
|
||||
className="clear-search-button"
|
||||
aria-label="Clear search"
|
||||
onClick={() => setSearchQuery("")}
|
||||
slot="end">
|
||||
slot="end"
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
height: "100%",
|
||||
}}>
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
</VSCodeTextField>
|
||||
<VSCodeRadioGroup
|
||||
style={{ display: "flex", flexWrap: "wrap" }}
|
||||
value={sortOption}
|
||||
onChange={(e) => setSortOption((e.target as HTMLInputElement).value as SortOption)}>
|
||||
<VSCodeRadio value="newest">Newest</VSCodeRadio>
|
||||
<VSCodeRadio value="oldest">Oldest</VSCodeRadio>
|
||||
<VSCodeRadio value="mostExpensive">Most Expensive</VSCodeRadio>
|
||||
<VSCodeRadio value="mostTokens">Most Tokens</VSCodeRadio>
|
||||
<VSCodeRadio
|
||||
value="mostRelevant"
|
||||
disabled={!searchQuery}
|
||||
style={{ opacity: searchQuery ? 1 : 0.5 }}>
|
||||
Most Relevant
|
||||
</VSCodeRadio>
|
||||
</VSCodeRadioGroup>
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flexGrow: 1, overflowY: "auto", margin: 0 }}>
|
||||
{presentableTasks.length === 0 && (
|
||||
@@ -139,11 +212,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
<span
|
||||
className="codicon codicon-archive"
|
||||
style={{ fontSize: "50px", marginBottom: "15px" }}></span>
|
||||
<div>
|
||||
No history found,
|
||||
<br />
|
||||
start a new task to see it here...
|
||||
</div>
|
||||
<div>No history found</div>
|
||||
</div>
|
||||
)}
|
||||
<Virtuoso
|
||||
|
||||
Reference in New Issue
Block a user