Skip to content

feat: paginate project conversation history#3564

Open
JAVA-LW wants to merge 3 commits into
iOfficeAI:mainfrom
JAVA-LW:codex/project-conversation-pagination
Open

feat: paginate project conversation history#3564
JAVA-LW wants to merge 3 commits into
iOfficeAI:mainfrom
JAVA-LW:codex/project-conversation-pagination

Conversation

@JAVA-LW

@JAVA-LW JAVA-LW commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Summary

  • query project summaries separately from the global conversation history
  • load the latest 5 conversations per project
  • fetch 5 more conversations each time Show more is selected
  • reset expanded projects to the latest 5 conversations with Collapse
  • keep project folder collapse state independent from pagination state
  • preserve pinned conversations and separate legacy project conversations from the general conversation section
  • refresh loaded projects after conversation mutations

Closes #3563

Backend dependency

Requires: iOfficeAI/AionCore#606

UI

Project conversation pagination

Validation

  • targeted Oxfmt and Oxlint checks
  • TypeScript typecheck
  • project pagination unit tests
  • i18n key/type validation

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

if (timelineSections.length === 0 && pinnedConversations.length === 0) {

P1 Badge Include projects in the empty-state gate

When the history consists only of custom-workspace conversations, refreshConversations now filters those rows out of timelineSections and the Projects section is populated separately via projectGroups. This condition still ignores projectGroups, so the component returns the No history view before rendering any project folders, even after the project summaries load. Include projectGroups.length in the check or move the empty state after project rendering.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const cursor = reset ? undefined : current.items.at(-1)?.id;
const result = await ipcBridge.database.getUserConversations.invoke({
workspace,
limit: PROJECT_PAGE_SIZE,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Load the active project conversation before locating it

For a direct URL to a project conversation that is older than the first page, this hook only fetches the latest five project rows, while locateConversation searches only the loaded project rows. The active conversation is therefore never found, so the sidebar does not expand, scroll to, or highlight the current conversation until the user manually pages through the project. When an id is present, load the page containing that conversation or fetch its workspace before giving up.

Useful? React with 👍 / 👎.

extra?.is_health_check !== true &&
!extra?.team_id &&
!extra?.teamId &&
(isPinned || belongsInConversationSection)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep project conversations in shortcut ordering

This filter removes unpinned custom-workspace conversations from groupedHistory, but useVisibleConversationIds still builds the Ctrl+Tab conversation order solely from that grouped history. As a result, project conversations rendered from useProjectConversations are skipped by the conversation-switching shortcut even when they are visible. The shortcut source needs to include the loaded project rows too.

Useful? React with 👍 / 👎.

Comment on lines +265 to +269
const page = await ipcBridge.database.getUserConversations.invoke({
workspace: removeProjectTarget.workspace,
limit: 100,
cursor,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid deleting hidden team-owned project rows

When a team-owned conversation shares the same workspace as a personal project, this workspace-wide fetch returns rows that were never shown in the project folder, and the subsequent removeConversation call deletes all of them. The old implementation deleted only group.conversations, which had already gone through the regular history filters; this path should apply the same team/health visibility filter or ask the backend for only removable project conversations.

Useful? React with 👍 / 👎.

}));

try {
const cursor = reset ? undefined : current.items.at(-1)?.id;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Advance pagination past filtered rows

If a project page contains only rows that filterVisibleConversations removes, such as legacy health-check or team-owned conversations, current.items does not grow and this cursor stays on the same last visible conversation. Every later Show more request then refetches the same hidden page and the user can never reach older visible conversations. Track the raw page's last id as the next cursor, or have the API exclude the hidden rows before paginating.

Useful? React with 👍 / 👎.

}, [expandedWorkspaces.length, projects]);

useEffect(() => {
expandedWorkspaces.forEach(ensureLoaded);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Load project pages when the sidebar is collapsed

When a project is collapsed in the persisted folder state and the whole sidebar is collapsed, WorkspaceCollapse still forces its children visible for the icon-only sidebar, but this hook only loads pages for expandedWorkspaces. That leaves those visible collapsed-sidebar project slots empty until the user changes expansion state; load all visible projects in collapsed sidebar mode or decouple first-page loading from folder expansion.

Useful? React with 👍 / 👎.

Comment on lines +170 to +172
return ipcBridge.conversation.listChanged.on(() => {
void refresh();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh project pages on completed turns

Project conversations are now populated by useProjectConversations, so useConversationListSync's existing turnCompleted refresh no longer updates those rows. For background or scheduled project conversations that emit conversation.turnCompleted without a separate list-change or manual history refresh, the project folder can keep stale titles, timestamps, and ordering until another mutation happens. Subscribe to turnCompleted here and call refresh just like the main history store does.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Paginate conversation history per project in the sidebar

1 participant