Skip to content

Commit 903e900

Browse files
committed
fix(history): 保留分页历史并修正作用域刷新
修复历史面板在“加载更多”后被首屏刷新覆盖的问题。 - 首屏刷新命中已分页缓存时合并第一页与已加载结果,避免列表回退到第一页 - “全部会话”范围改为通过 ref 读取最新作用域,避免仅同步左侧项目时误触发整页重载 - 历史缓存键补充作用域路径,保证同一项目 ID 的路径上下文更新后仍会正确刷新 产品层面上,用户在“全部会话”中浏览较老历史并点击详情后,右侧历史列表不会因后台刷新突然收缩;项目路径或归属上下文更新时,历史范围也能继续保持正确。 Signed-off-by: Lulu <58587930+lulu-sk@users.noreply.github.com>
1 parent e607d5d commit 903e900

File tree

1 file changed

+37
-21
lines changed

1 file changed

+37
-21
lines changed

web/src/App.tsx

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2944,7 +2944,9 @@ export default function CodexFlowManagerUI() {
29442944
canonicalizePath(project.wslPath || ""),
29452945
canonicalizePath(project.winPath || ""),
29462946
].filter(Boolean))));
2947-
const baseCacheKey = effectiveScope === "all_sessions" ? "all_sessions" : projectIds.join("|");
2947+
const baseCacheKey = effectiveScope === "all_sessions"
2948+
? "all_sessions"
2949+
: `${projectIds.join("|")}::${projectNeedles.join("|")}`;
29482950
return {
29492951
requestedScope,
29502952
effectiveScope,
@@ -4484,7 +4486,8 @@ export default function CodexFlowManagerUI() {
44844486
let cancelled = false;
44854487

44864488
(async () => {
4487-
const descriptor = historyScopeDescriptor;
4489+
// 中文说明:通过 ref 读取最新范围描述,避免“全部会话”下仅同步左侧项目时误触发整页历史重载。
4490+
const descriptor = historyScopeDescriptorRef.current;
44884491
if (!descriptor.primaryProject && descriptor.effectiveScope !== "all_sessions") {
44894492
setHistorySessions([]);
44904493
applyHistoryPagination({ hasMore: false, nextOffset: 0 });
@@ -4533,26 +4536,39 @@ export default function CodexFlowManagerUI() {
45334536
try {
45344537
const mapped = await fetchHistoryPage(descriptor, 0, HISTORY_PAGE_INITIAL_LIMIT);
45354538
if (cancelled) return;
4536-
const hasMore = mapped.length >= HISTORY_PAGE_INITIAL_LIMIT;
4537-
const nextOffset = mapped.length;
4538-
applyHistoryPagination({ hasMore, nextOffset });
4539-
setHistorySessions(mapped as any);
4540-
setHistoryCache(projectKey, { sessions: mapped, hasMore, nextOffset });
4539+
const fetchedHasMore = mapped.length >= HISTORY_PAGE_INITIAL_LIMIT;
4540+
const fetchedNextOffset = mapped.length;
4541+
const shouldPreservePagedCache = hasCache && cachedSessions.length > mapped.length;
4542+
const nextSessions = shouldPreservePagedCache
4543+
? mergeHistorySessions(cachedSessions, mapped)
4544+
: mapped;
4545+
const nextHasMore = shouldPreservePagedCache
4546+
? (!!cached?.hasMore || fetchedHasMore)
4547+
: fetchedHasMore;
4548+
const nextOffset = shouldPreservePagedCache
4549+
? Math.max(
4550+
Math.max(0, Number(cached?.nextOffset || cachedSessions.length)),
4551+
fetchedNextOffset,
4552+
)
4553+
: fetchedNextOffset;
4554+
applyHistoryPagination({ hasMore: nextHasMore, nextOffset });
4555+
setHistorySessions(nextSessions as any);
4556+
setHistoryCache(projectKey, { sessions: nextSessions, hasMore: nextHasMore, nextOffset });
45414557
// 校验并修正当前选择,避免缓存残留导致的空白详情
45424558
if (!skipAuto) {
4543-
const ids = new Set(mapped.map((x) => x.id));
4544-
const nowRef = new Date();
4545-
const keyOf = (item?: HistorySession) => historyTimelineGroupKey(item, nowRef);
4546-
const dirs = new Set(mapped.map((x) => keyOf(x)));
4547-
const needResetId = !selectedHistoryId || !ids.has(selectedHistoryId);
4548-
const needResetDir = !selectedHistoryDir || !dirs.has(selectedHistoryDir);
4549-
if ((needResetId || needResetDir) && mapped.length > 0) {
4550-
const firstKey = keyOf(mapped[0]);
4551-
// 仅优化默认 UI:展开最新分组,不自动选择会话,也不切换到详情
4552-
setSelectedHistoryDir(null);
4553-
setSelectedHistoryId(null);
4554-
setExpandedGroups({ [firstKey]: true });
4555-
}
4559+
const ids = new Set(nextSessions.map((x) => x.id));
4560+
const nowRef = new Date();
4561+
const keyOf = (item?: HistorySession) => historyTimelineGroupKey(item, nowRef);
4562+
const dirs = new Set(nextSessions.map((x) => keyOf(x)));
4563+
const needResetId = !selectedHistoryId || !ids.has(selectedHistoryId);
4564+
const needResetDir = !selectedHistoryDir || !dirs.has(selectedHistoryDir);
4565+
if ((needResetId || needResetDir) && nextSessions.length > 0) {
4566+
const firstKey = keyOf(nextSessions[0]);
4567+
// 仅优化默认 UI:展开最新分组,不自动选择会话,也不切换到详情
4568+
setSelectedHistoryDir(null);
4569+
setSelectedHistoryId(null);
4570+
setExpandedGroups({ [firstKey]: true });
4571+
}
45564572
}
45574573
// 如果抑制了自动选择,需要在处理完加载后重置抑制标志
45584574
if (skipAuto) suppressAutoSelectRef.current = false;
@@ -4566,7 +4582,7 @@ export default function CodexFlowManagerUI() {
45664582
return () => {
45674583
cancelled = true;
45684584
};
4569-
}, [historyScopeDescriptor, historyInvalidateNonce, getHistoryCache, fetchHistoryPage, HISTORY_PAGE_INITIAL_LIMIT, applyHistoryPagination, setHistoryCache]);
4585+
}, [historyScopeDescriptor.cacheKey, historyScopeDescriptor.effectiveScope, historyInvalidateNonce, getHistoryCache, fetchHistoryPage, HISTORY_PAGE_INITIAL_LIMIT, applyHistoryPagination, mergeHistorySessions, setHistoryCache]);
45704586

45714587
// 订阅索引器事件:新增/更新/删除时,若属于当前历史范围则立即更新 UI
45724588
useEffect(() => {

0 commit comments

Comments
 (0)