feat(vscode-ide-companion): enhance session management with pagination support

Implement cursor-based pagination for session listing and improve session handling

- Add pagination state management in useSessionManagement hook

- Implement handleLoadMoreSessions for infinite scrolling

- Update SessionMessageHandler to support paged session requests

- Add ChatHeader component for improved UI layout

- Fix session title duplication issue

- Improve error handling in session operations
This commit is contained in:
yiliang114
2025-12-06 21:45:36 +08:00
parent e538a3d1bf
commit ad301963a6
5 changed files with 298 additions and 71 deletions

View File

@@ -21,6 +21,11 @@ export const useSessionManagement = (vscode: VSCodeAPI) => {
const [showSessionSelector, setShowSessionSelector] = useState(false);
const [sessionSearchQuery, setSessionSearchQuery] = useState('');
const [savedSessionTags, setSavedSessionTags] = useState<string[]>([]);
const [nextCursor, setNextCursor] = useState<number | undefined>(undefined);
const [hasMore, setHasMore] = useState<boolean>(true);
const [isLoading, setIsLoading] = useState<boolean>(false);
const PAGE_SIZE = 20;
/**
* Filter session list
@@ -44,10 +49,24 @@ export const useSessionManagement = (vscode: VSCodeAPI) => {
* Load session list
*/
const handleLoadQwenSessions = useCallback(() => {
vscode.postMessage({ type: 'getQwenSessions', data: {} });
// Reset pagination state and load first page
setQwenSessions([]);
setNextCursor(undefined);
setHasMore(true);
setIsLoading(true);
vscode.postMessage({ type: 'getQwenSessions', data: { size: PAGE_SIZE } });
setShowSessionSelector(true);
}, [vscode]);
const handleLoadMoreSessions = useCallback(() => {
if (!hasMore || isLoading || nextCursor === undefined) return;
setIsLoading(true);
vscode.postMessage({
type: 'getQwenSessions',
data: { cursor: nextCursor, size: PAGE_SIZE },
});
}, [hasMore, isLoading, nextCursor, vscode]);
/**
* Create new session
*/
@@ -117,6 +136,9 @@ export const useSessionManagement = (vscode: VSCodeAPI) => {
sessionSearchQuery,
filteredSessions,
savedSessionTags,
nextCursor,
hasMore,
isLoading,
// State setters
setQwenSessions,
@@ -125,6 +147,9 @@ export const useSessionManagement = (vscode: VSCodeAPI) => {
setShowSessionSelector,
setSessionSearchQuery,
setSavedSessionTags,
setNextCursor,
setHasMore,
setIsLoading,
// Operations
handleLoadQwenSessions,
@@ -132,5 +157,6 @@ export const useSessionManagement = (vscode: VSCodeAPI) => {
handleSwitchSession,
handleSaveSession,
handleSaveSessionResponse,
handleLoadMoreSessions,
};
};

View File

@@ -10,18 +10,27 @@ import type { Conversation } from '../../storage/conversationStore.js';
import type {
PermissionOption,
ToolCall as PermissionToolCall,
} from '../components/PermissionRequest.js';
import type { PlanEntry } from '../components/PlanDisplay.js';
} from '../components/PermissionDrawer/PermissionRequest.js';
import type { ToolCallUpdate } from '../types/toolCall.js';
import type { PlanEntry } from '../../agents/qwenTypes.js';
interface UseWebViewMessagesProps {
// Session management
sessionManagement: {
currentSessionId: string | null;
setQwenSessions: (sessions: Array<Record<string, unknown>>) => void;
setQwenSessions: (
sessions:
| Array<Record<string, unknown>>
| ((
prev: Array<Record<string, unknown>>,
) => Array<Record<string, unknown>>),
) => void;
setCurrentSessionId: (id: string | null) => void;
setCurrentSessionTitle: (title: string) => void;
setShowSessionSelector: (show: boolean) => void;
setNextCursor: (cursor: number | undefined) => void;
setHasMore: (hasMore: boolean) => void;
setIsLoading: (loading: boolean) => void;
handleSaveSessionResponse: (response: {
success: boolean;
message?: string;
@@ -487,8 +496,19 @@ export const useWebViewMessages = ({
}
case 'qwenSessionList': {
const sessions = message.data.sessions || [];
handlers.sessionManagement.setQwenSessions(sessions);
const sessions =
(message.data.sessions as Array<Record<string, unknown>>) || [];
const append = Boolean(message.data.append);
const nextCursor = message.data.nextCursor as number | undefined;
const hasMore = Boolean(message.data.hasMore);
handlers.sessionManagement.setQwenSessions(
(prev: Array<Record<string, unknown>>) =>
append ? [...prev, ...sessions] : sessions,
);
handlers.sessionManagement.setNextCursor(nextCursor);
handlers.sessionManagement.setHasMore(hasMore);
handlers.sessionManagement.setIsLoading(false);
if (
handlers.sessionManagement.currentSessionId &&
sessions.length > 0
@@ -533,8 +553,26 @@ export const useWebViewMessages = ({
} else {
handlers.messageHandling.clearMessages();
}
// Clear and restore tool calls if provided in session data
handlers.clearToolCalls();
handlers.setPlanEntries([]);
if (message.data.toolCalls && Array.isArray(message.data.toolCalls)) {
message.data.toolCalls.forEach((toolCall: unknown) => {
if (toolCall && typeof toolCall === 'object') {
handlers.handleToolCallUpdate(toolCall as ToolCallUpdate);
}
});
}
// Restore plan entries if provided
if (
message.data.planEntries &&
Array.isArray(message.data.planEntries)
) {
handlers.setPlanEntries(message.data.planEntries);
} else {
handlers.setPlanEntries([]);
}
lastPlanSnapshotRef.current = null;
break;