history ux

This commit is contained in:
Mathew Pareles 2025-04-17 22:41:40 -07:00
parent c921059690
commit b7db527866
6 changed files with 62 additions and 23 deletions

View file

@ -295,12 +295,13 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx }: { pas
const numMessages = pastThread.messages.filter((msg) => msg.role === 'assistant' || msg.role === 'user').length;
const dateHTML = <span
className='inline-flex items-center'
data-tooltip-id='void-tooltip'
data-tooltip-content={`Last modified ${formatTime(new Date(pastThread.lastModified))}`}
data-tooltip-place='top'
const optionsHTML = <span
className='gap-1 inline-flex items-center'
// data-tooltip-id='void-tooltip'
// data-tooltip-content={`Last modified ${formatTime(new Date(pastThread.lastModified))}`}
// data-tooltip-place='top'
>
{/* <span>{numMessages}</span> */}
{formatDate(new Date(pastThread.lastModified))}
</span>
@ -315,10 +316,6 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx }: { pas
}}
onMouseEnter={() => setHoveredIdx(idx)}
onMouseLeave={() => setHoveredIdx(null)}
data-tooltip-id='void-tooltip'
data-tooltip-content={`${numMessages} messages`}
data-tooltip-place='top'
data-tooltip-delay-show={500}
>
<div className="flex items-center justify-between gap-1">
<span className="flex items-center gap-2 min-w-0 overflow-hidden">
@ -328,7 +325,7 @@ const PastThreadElement = ({ pastThread, idx, hoveredIdx, setHoveredIdx }: { pas
<div className="flex items-center gap-2 opacity-60">
{idx === hoveredIdx ?
<TrashButton threadId={pastThread.id} />
: dateHTML
: optionsHTML
}
</div>
</div>

View file

@ -12,7 +12,7 @@
--void-bg-1-alt: var(--vscode-badge-background);
--void-bg-2: var(--vscode-sideBar-background);
--void-bg-2-alt: color-mix(in srgb, var(--vscode-editor-background) 30%, var(--vscode-sideBar-background) 70%);
--void-bg-2-hover: color-mix(in srgb, var(--vscode-editor-foreground) 5%, var(--vscode-sideBar-background) 95%);
--void-bg-2-hover: color-mix(in srgb, var(--vscode-editor-foreground) 2%, var(--vscode-sideBar-background) 98%);
--void-bg-3: var(--vscode-editor-background);
--void-fg-0: color-mix(in srgb, var(--vscode-tab-activeForeground) 90%, black 10%);

View file

@ -689,7 +689,7 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
key={optionName}
className={`flex items-center px-2 py-1 pr-4 cursor-pointer whitespace-nowrap
transition-all duration-100
${thisOptionIsSelected ? 'bg-void-bg-2-hover' : 'bg-void-bg-2 hover:bg-void-bg-2-hover'}
${thisOptionIsSelected ? 'bg-void-bg-2-hover' : 'bg-void-bg-2-alt hover:bg-void-bg-2-hover'}
`}
onClick={() => {
onChangeOption(option);

View file

@ -686,7 +686,7 @@ const transferTheseFilesOfOS = (os: 'mac' | 'windows' | 'linux' | null, fromEdit
}, {
from: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.cursor', 'extensions'),
to: URI.joinPath(URI.from({ scheme: 'file' }), userprofile, '.void-editor', 'extensions'),
}]
}]
} else if (fromEditor === 'Windsurf') {
return [{
from: URI.joinPath(URI.from({ scheme: 'file' }), appdata, 'Windsurf', 'User', 'settings.json'),

View file

@ -202,7 +202,19 @@ registerAction2(class extends Action2 {
})
const openNewThreadAndFireFocus = (accessor: ServicesAccessor) => {
const stateService = accessor.get(ISidebarStateService)
stateService.setState({ isHistoryOpen: false, currentTab: 'chat' })
const chatThreadService = accessor.get(IChatThreadService)
chatThreadService.openNewThread()
// focus
stateService.fireFocusChat()
const window = getActiveWindow()
window.requestAnimationFrame(() => stateService.fireFocusChat())
}
// New chat menu button
@ -213,6 +225,25 @@ registerAction2(class extends Action2 {
title: 'New Chat',
icon: { id: 'add' },
menu: [{ id: MenuId.ViewTitle, group: 'navigation', when: ContextKeyExpr.equals('view', VOID_VIEW_ID), }],
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const metricsService = accessor.get(IMetricsService)
metricsService.capture('Chat Navigation', { type: 'New Chat' })
openNewThreadAndFireFocus(accessor)
}
})
// New chat keybind
registerAction2(class extends Action2 {
constructor() {
super({
id: 'void.newChatKeybindAction',
title: 'New Chat Keybind',
keybinding: {
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyL,
weight: KeybindingWeight.VoidExtension,
@ -220,19 +251,16 @@ registerAction2(class extends Action2 {
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const stateService = accessor.get(ISidebarStateService)
const metricsService = accessor.get(IMetricsService)
const commandService = accessor.get(ICommandService)
metricsService.capture('Chat Navigation', { type: 'New Chat Keybind' })
metricsService.capture('Chat Navigation', { type: 'New Chat' })
openNewThreadAndFireFocus(accessor)
stateService.setState({ isHistoryOpen: false, currentTab: 'chat' })
const chatThreadService = accessor.get(IChatThreadService)
chatThreadService.openNewThread()
// add user's selection to chat
await commandService.executeCommand(VOID_CTRL_L_ACTION_ID)
// focus
stateService.fireFocusChat()
const window = getActiveWindow()
window.requestAnimationFrame(() => stateService.fireFocusChat())
}
})
@ -247,13 +275,27 @@ registerAction2(class extends Action2 {
});
}
async run(accessor: ServicesAccessor): Promise<void> {
// do not do anything if there are no messages (without this it clears all of the user's selections if the button is pressed)
// TODO the history button should be disabled in this case so we can remove this logic
const thread = accessor.get(IChatThreadService).getCurrentThread()
if (thread.messages.length === 0) {
return;
}
const stateService = accessor.get(ISidebarStateService)
const metricsService = accessor.get(IMetricsService)
metricsService.capture('Chat Navigation', { type: 'History' })
openNewThreadAndFireFocus(accessor)
// doesnt do anything right now
stateService.setState({ isHistoryOpen: !stateService.state.isHistoryOpen, currentTab: 'chat' })
stateService.fireBlurChat()
}
})

View file

@ -13,7 +13,7 @@ import { VOID_OPEN_SIDEBAR_ACTION_ID } from './sidebarPane.js';
// service that manages sidebar's state
export type VoidSidebarState = {
isHistoryOpen: boolean;
isHistoryOpen: boolean; // this isn't doing anything right now
currentTab: 'chat';
}