Skip to content

Commit 3cf35bb

Browse files
committed
Enhancement: Add 'Show all workspaces' feature to task history and update translations
1 parent 2c8304e commit 3cf35bb

File tree

18 files changed

+160
-71
lines changed

18 files changed

+160
-71
lines changed

webview-ui/src/components/history/HistoryPreview.tsx

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,61 @@ import { memo } from "react"
33
import { vscode } from "@/utils/vscode"
44
import { formatLargeNumber, formatDate } from "@/utils/format"
55
import { Button } from "@/components/ui"
6+
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
67

7-
import { useExtensionState } from "../../context/ExtensionStateContext"
88
import { useAppTranslation } from "../../i18n/TranslationContext"
99
import { CopyButton } from "./CopyButton"
10+
import { useTaskSearch } from "./useTaskSearch"
1011

1112
type HistoryPreviewProps = {
1213
showHistoryView: () => void
1314
}
1415
const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
15-
const { taskHistory } = useExtensionState()
16+
const { tasks, showAllWorkspaces, setShowAllWorkspaces } = useTaskSearch()
1617
const { t } = useAppTranslation()
1718

1819
return (
1920
<div className="flex flex-col gap-3 shrink-0 mx-5">
2021
<div className="flex items-center justify-between text-vscode-descriptionForeground">
21-
<div className="flex items-center gap-1">
22-
<span className="codicon codicon-comment-discussion scale-90 mr-1" />
23-
<span className="font-medium text-xs uppercase">{t("history:recentTasks")}</span>
22+
<div className="flex items-center gap-4">
23+
<div className="flex items-center gap-1">
24+
<span className="codicon codicon-comment-discussion scale-90 mr-1" />
25+
<span className="font-medium text-xs uppercase">{t("history:recentTasks")}</span>
26+
</div>
27+
<div
28+
className="flex items-center gap-1 text-xs opacity-80 hover:opacity-100 cursor-pointer"
29+
onClick={() => setShowAllWorkspaces(!showAllWorkspaces)}>
30+
<VSCodeCheckbox
31+
checked={showAllWorkspaces}
32+
onChange={(e) => setShowAllWorkspaces((e.target as HTMLInputElement).checked)}
33+
/>
34+
<span className="text-vscode-foreground select-none">{t("history:showAllWorkspaces")}</span>
35+
</div>
2436
</div>
2537
<Button variant="ghost" size="sm" onClick={() => showHistoryView()} className="uppercase">
2638
{t("history:viewAll")}
2739
</Button>
2840
</div>
29-
{taskHistory.slice(0, 3).map((item) => (
41+
{tasks.slice(0, 3).map((item) => (
3042
<div
3143
key={item.id}
3244
className="bg-vscode-toolbar-hoverBackground/50 hover:bg-vscode-toolbar-hoverBackground/75 rounded-xs relative overflow-hidden opacity-90 hover:opacity-100 cursor-pointer"
3345
onClick={() => vscode.postMessage({ type: "showTaskWithId", text: item.id })}>
3446
<div className="flex flex-col gap-2 p-3 pt-1">
3547
<div className="flex justify-between items-center">
36-
<span className="text-xs font-medium text-vscode-descriptionForeground uppercase">
37-
{formatDate(item.ts)}
38-
</span>
48+
<div className="flex items-center gap-4">
49+
<span className="text-xs font-medium text-vscode-descriptionForeground uppercase">
50+
{formatDate(item.ts)}
51+
</span>
52+
{item.workspace && (
53+
<span className="text-xs text-vscode-descriptionForeground flex items-center gap-1">
54+
<span className="codicon codicon-folder" />
55+
<span className="truncate max-w-[300px]">
56+
{item.workspace.split("/").slice(-2).join("/") || item.workspace}
57+
</span>
58+
</span>
59+
)}
60+
</div>
3961
<CopyButton itemTask={item.task} />
4062
</div>
4163
<div

webview-ui/src/components/history/HistoryView.tsx

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,16 @@ type HistoryViewProps = {
2424
type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
2525

2626
const HistoryView = ({ onDone }: HistoryViewProps) => {
27-
const { tasks, searchQuery, setSearchQuery, sortOption, setSortOption, setLastNonRelevantSort } = useTaskSearch()
27+
const {
28+
tasks,
29+
searchQuery,
30+
setSearchQuery,
31+
sortOption,
32+
setSortOption,
33+
setLastNonRelevantSort,
34+
showAllWorkspaces,
35+
setShowAllWorkspaces,
36+
} = useTaskSearch()
2837
const { t } = useAppTranslation()
2938

3039
const [deleteTaskId, setDeleteTaskId] = useState<string | null>(null)
@@ -147,21 +156,34 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
147156
</VSCodeRadio>
148157
</VSCodeRadioGroup>
149158

159+
<div className="flex items-center gap-2" onClick={() => setShowAllWorkspaces(!showAllWorkspaces)}>
160+
<VSCodeCheckbox
161+
checked={showAllWorkspaces}
162+
onChange={(e) => setShowAllWorkspaces((e.target as HTMLInputElement).checked)}
163+
/>
164+
<span className="text-vscode-foreground">{t("history:showAllWorkspaces")}</span>
165+
</div>
166+
150167
{/* Select all control in selection mode */}
151168
{isSelectionMode && tasks.length > 0 && (
152169
<div className="flex items-center py-1 px-2 bg-vscode-editor-background rounded">
153-
<VSCodeCheckbox
154-
checked={tasks.length > 0 && selectedTaskIds.length === tasks.length}
155-
onChange={(e) => toggleSelectAll((e.target as HTMLInputElement).checked)}
156-
/>
157-
<span className="ml-2 text-vscode-foreground">
158-
{selectedTaskIds.length === tasks.length
159-
? t("history:deselectAll")
160-
: t("history:selectAll")}
161-
</span>
162-
<span className="ml-auto text-vscode-descriptionForeground text-xs">
163-
{t("history:selectedItems", { selected: selectedTaskIds.length, total: tasks.length })}
164-
</span>
170+
<div className="flex items-center gap-2">
171+
<VSCodeCheckbox
172+
checked={tasks.length > 0 && selectedTaskIds.length === tasks.length}
173+
onChange={(e) => toggleSelectAll((e.target as HTMLInputElement).checked)}
174+
/>
175+
<span className="text-vscode-foreground">
176+
{selectedTaskIds.length === tasks.length
177+
? t("history:deselectAll")
178+
: t("history:selectAll")}
179+
</span>
180+
<span className="ml-auto text-vscode-descriptionForeground text-xs">
181+
{t("history:selectedItems", {
182+
selected: selectedTaskIds.length,
183+
total: tasks.length,
184+
})}
185+
</span>
186+
</div>
165187
</div>
166188
)}
167189
</div>
@@ -214,33 +236,42 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
214236

215237
<div className="flex-1">
216238
<div className="flex justify-between items-center">
217-
<span className="text-vscode-descriptionForeground font-medium text-sm uppercase">
218-
{formatDate(item.ts)}
219-
</span>
220-
<div className="flex flex-row">
221-
{!isSelectionMode && (
222-
<Button
223-
variant="ghost"
224-
size="sm"
225-
title={t("history:deleteTaskTitle")}
226-
data-testid="delete-task-button"
227-
onClick={(e) => {
228-
e.stopPropagation()
229-
230-
if (e.shiftKey) {
231-
vscode.postMessage({
232-
type: "deleteTaskWithId",
233-
text: item.id,
234-
})
235-
} else {
236-
setDeleteTaskId(item.id)
237-
}
238-
}}>
239-
<span className="codicon codicon-trash" />
240-
{item.size && prettyBytes(item.size)}
241-
</Button>
239+
<div className="flex items-center gap-4">
240+
<span className="text-vscode-descriptionForeground font-medium text-sm uppercase">
241+
{formatDate(item.ts)}
242+
</span>
243+
{item.workspace && (
244+
<span className="text-xs text-vscode-descriptionForeground flex items-center gap-1">
245+
<span className="codicon codicon-folder" />
246+
<span
247+
className="truncate max-w-[300px]"
248+
dangerouslySetInnerHTML={{ __html: item.workspace }}
249+
/>
250+
</span>
242251
)}
243252
</div>
253+
{!isSelectionMode && (
254+
<Button
255+
variant="ghost"
256+
size="sm"
257+
title={t("history:deleteTaskTitle")}
258+
data-testid="delete-task-button"
259+
onClick={(e) => {
260+
e.stopPropagation()
261+
262+
if (e.shiftKey) {
263+
vscode.postMessage({
264+
type: "deleteTaskWithId",
265+
text: item.id,
266+
})
267+
} else {
268+
setDeleteTaskId(item.id)
269+
}
270+
}}>
271+
<span className="codicon codicon-trash" />
272+
{item.size && prettyBytes(item.size)}
273+
</Button>
274+
)}
244275
</div>
245276
<div
246277
style={{

webview-ui/src/components/history/useTaskSearch.ts

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import { useExtensionState } from "@/context/ExtensionStateContext"
77
type SortOption = "newest" | "oldest" | "mostExpensive" | "mostTokens" | "mostRelevant"
88

99
export const useTaskSearch = () => {
10-
const { taskHistory } = useExtensionState()
10+
const { taskHistory, cwd } = useExtensionState()
1111
const [searchQuery, setSearchQuery] = useState("")
1212
const [sortOption, setSortOption] = useState<SortOption>("newest")
1313
const [lastNonRelevantSort, setLastNonRelevantSort] = useState<SortOption | null>("newest")
14+
const [showAllWorkspaces, setShowAllWorkspaces] = useState(false)
1415

1516
useEffect(() => {
1617
if (searchQuery && sortOption !== "mostRelevant" && !lastNonRelevantSort) {
@@ -28,22 +29,40 @@ export const useTaskSearch = () => {
2829

2930
const fzf = useMemo(() => {
3031
return new Fzf(presentableTasks, {
31-
selector: (item) => item.task,
32+
selector: (item) => `${item.task} ${item.workspace || ""}`,
3233
})
3334
}, [presentableTasks])
3435

3536
const tasks = useMemo(() => {
36-
let results = presentableTasks
37+
// First filter by workspace if enabled
38+
let results = showAllWorkspaces ? presentableTasks : presentableTasks.filter((item) => item.workspace === cwd)
39+
3740
if (searchQuery) {
3841
const searchResults = fzf.find(searchQuery)
39-
results = searchResults.map((result) => ({
40-
...result.item,
41-
task: highlightFzfMatch(result.item.task, Array.from(result.positions)),
42-
}))
42+
results = searchResults
43+
.map((result) => {
44+
const positions = Array.from(result.positions)
45+
const taskEndIndex = result.item.task.length
46+
47+
return {
48+
...result.item,
49+
task: highlightFzfMatch(
50+
result.item.task,
51+
positions.filter((p) => p < taskEndIndex),
52+
),
53+
workspace: result.item.workspace
54+
? highlightFzfMatch(
55+
result.item.workspace,
56+
positions.filter((p) => p > taskEndIndex).map((p) => p - taskEndIndex - 1),
57+
)
58+
: undefined,
59+
}
60+
})
61+
.filter((item) => (showAllWorkspaces ? true : item.workspace === cwd))
4362
}
4463

4564
// First apply search if needed
46-
const searchResults = searchQuery ? results : presentableTasks
65+
const searchResults = results
4766

4867
// Then sort the results
4968
return [...searchResults].sort((a, b) => {
@@ -64,7 +83,7 @@ export const useTaskSearch = () => {
6483
return (b.ts || 0) - (a.ts || 0)
6584
}
6685
})
67-
}, [presentableTasks, searchQuery, fzf, sortOption])
86+
}, [presentableTasks, searchQuery, fzf, sortOption, showAllWorkspaces, cwd])
6887

6988
return {
7089
tasks,
@@ -74,5 +93,7 @@ export const useTaskSearch = () => {
7493
setSortOption,
7594
lastNonRelevantSort,
7695
setLastNonRelevantSort,
96+
showAllWorkspaces,
97+
setShowAllWorkspaces,
7798
}
7899
}

webview-ui/src/i18n/locales/ca/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Eliminar tasques",
3535
"confirmDeleteTasks": "Estàs segur que vols eliminar {{count}} tasques?",
3636
"deleteTasksWarning": "Les tasques eliminades no es poden recuperar. Si us plau, assegura't que vols continuar.",
37-
"deleteItems": "Eliminar {{count}} elements"
37+
"deleteItems": "Eliminar {{count}} elements",
38+
"showAllWorkspaces": "Mostrar tasques de tots els espais de treball"
3839
}

webview-ui/src/i18n/locales/de/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Aufgaben löschen",
3535
"confirmDeleteTasks": "Bist du sicher, dass du {{count}} Aufgaben löschen möchtest?",
3636
"deleteTasksWarning": "Gelöschte Aufgaben können nicht wiederhergestellt werden. Bitte vergewissere dich, dass du fortfahren möchtest.",
37-
"deleteItems": "{{count}} Elemente löschen"
37+
"deleteItems": "{{count}} Elemente löschen",
38+
"showAllWorkspaces": "Aufgaben aus allen Arbeitsbereichen anzeigen"
3839
}

webview-ui/src/i18n/locales/en/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Delete Tasks",
3535
"confirmDeleteTasks": "Are you sure you want to delete {{count}} tasks?",
3636
"deleteTasksWarning": "Deleted tasks cannot be recovered. Please make sure you want to proceed.",
37-
"deleteItems": "Delete {{count}} Items"
37+
"deleteItems": "Delete {{count}} Items",
38+
"showAllWorkspaces": "Show tasks from all workspaces"
3839
}

webview-ui/src/i18n/locales/es/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Eliminar tareas",
3535
"confirmDeleteTasks": "¿Estás seguro de que quieres eliminar {{count}} tareas?",
3636
"deleteTasksWarning": "Las tareas eliminadas no se pueden recuperar. Por favor, asegúrate de que quieres continuar.",
37-
"deleteItems": "Eliminar {{count}} elementos"
37+
"deleteItems": "Eliminar {{count}} elementos",
38+
"showAllWorkspaces": "Mostrar tareas de todos los espacios de trabajo"
3839
}

webview-ui/src/i18n/locales/fr/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Supprimer les tâches",
3535
"confirmDeleteTasks": "Êtes-vous sûr de vouloir supprimer {{count}} tâches ?",
3636
"deleteTasksWarning": "Les tâches supprimées ne peuvent pas être récupérées. Veuillez confirmer que vous souhaitez continuer.",
37-
"deleteItems": "Supprimer {{count}} éléments"
37+
"deleteItems": "Supprimer {{count}} éléments",
38+
"showAllWorkspaces": "Afficher les tâches de tous les espaces de travail"
3839
}

webview-ui/src/i18n/locales/hi/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "कार्य हटाएं",
3535
"confirmDeleteTasks": "क्या आप वाकई {{count}} कार्य हटाना चाहते हैं?",
3636
"deleteTasksWarning": "हटाए गए कार्य पुनर्प्राप्त नहीं किए जा सकते। कृपया सुनिश्चित करें कि आप आगे बढ़ना चाहते हैं।",
37-
"deleteItems": "{{count}} आइटम हटाएं"
37+
"deleteItems": "{{count}} आइटम हटाएं",
38+
"showAllWorkspaces": "सभी वर्कस्पेस से कार्य दिखाएं"
3839
}

webview-ui/src/i18n/locales/it/history.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,6 @@
3434
"deleteTasks": "Elimina attività",
3535
"confirmDeleteTasks": "Sei sicuro di voler eliminare {{count}} attività?",
3636
"deleteTasksWarning": "Le attività eliminate non possono essere recuperate. Assicurati di voler continuare.",
37-
"deleteItems": "Elimina {{count}} elementi"
37+
"deleteItems": "Elimina {{count}} elementi",
38+
"showAllWorkspaces": "Mostra attività da tutti gli spazi di lavoro"
3839
}

0 commit comments

Comments
 (0)