From fd88260ce6ad1f8801fd5dd36f0ec527467b4202 Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Fri, 21 Aug 2026 16:50:54 +0800 Subject: [PATCH] fix(sheets-thread-comment): preserve cell thread selection (#7571) --- .../src/views/SheetsThreadCommentCell.tsx | 18 ++++++++-- .../SheetsThreadCommentPanel.spec.tsx | 36 +++++++++++++++++++ .../sheets-thread-comment.model.spec.ts | 36 +++++++++++++++++++ .../src/models/sheets-thread-comment.model.ts | 2 +- 4 files changed, 89 insertions(+), 3 deletions(-) diff --git a/packages/sheets-thread-comment-ui/src/views/SheetsThreadCommentCell.tsx b/packages/sheets-thread-comment-ui/src/views/SheetsThreadCommentCell.tsx index 138593d52e..5d12bff915 100644 --- a/packages/sheets-thread-comment-ui/src/views/SheetsThreadCommentCell.tsx +++ b/packages/sheets-thread-comment-ui/src/views/SheetsThreadCommentCell.tsx @@ -27,11 +27,25 @@ export const SheetsThreadCommentCell = () => { const sheetsThreadCommentPopupService = useDependency(SheetsThreadCommentPopupService); const activePopup = useObservable(sheetsThreadCommentPopupService.activePopup$); const sheetThreadCommentModel = useDependency(SheetsThreadCommentModel); + const getRootId = () => { + if (!activePopup) { + return undefined; + } + + const { unitId, subUnitId, row, col, commentId } = activePopup; + const activeComment = commentId + ? sheetThreadCommentModel.getAllByLocation(unitId, subUnitId, row, col).find((comment) => comment.id === commentId) + : undefined; + + return activeComment && !activeComment.resolved + ? activeComment.id + : sheetThreadCommentModel.getByLocation(unitId, subUnitId, row, col); + }; const rootId = useObservable( activePopup ? () => sheetThreadCommentModel.commentUpdate$.pipe( - map(() => sheetThreadCommentModel.getByLocation(activePopup.unitId, activePopup.subUnitId, activePopup.row, activePopup.col)), - startWith(sheetThreadCommentModel.getByLocation(activePopup.unitId, activePopup.subUnitId, activePopup.row, activePopup.col)) + map(() => getRootId()), + startWith(getRootId()) ) : null, undefined, diff --git a/packages/sheets-thread-comment-ui/src/views/__tests__/SheetsThreadCommentPanel.spec.tsx b/packages/sheets-thread-comment-ui/src/views/__tests__/SheetsThreadCommentPanel.spec.tsx index 7970c03f9d..e32a1b487e 100644 --- a/packages/sheets-thread-comment-ui/src/views/__tests__/SheetsThreadCommentPanel.spec.tsx +++ b/packages/sheets-thread-comment-ui/src/views/__tests__/SheetsThreadCommentPanel.spec.tsx @@ -1047,6 +1047,42 @@ describe('SheetsThreadCommentPanel', () => { })); }); + it('switches the cell thread when the active popup selects another thread at the same location', () => { + const testBed = createTestBed(); + univer = testBed.univer; + testBed.threadCommentModel.addComment(unitId, sheet1, createComment('first-thread', sheet1, 'B2', 'First B2 thread')); + testBed.threadCommentModel.addComment(unitId, sheet1, createComment('second-thread', sheet1, 'B2', 'Second B2 thread')); + testBed.popupService.showPopup({ + unitId, + subUnitId: sheet1, + row: 1, + col: 1, + commentId: 'first-thread', + }); + + const rendered = renderCell(testBed.injector); + root = rendered.root; + container = rendered.container; + + expect(container.querySelector(`#CELL-${unitId}-${sheet1}-first-thread`)).toBeInstanceOf(HTMLElement); + expect(container.textContent).toContain('First B2 thread'); + expect(container.textContent).not.toContain('Second B2 thread'); + + act(() => { + testBed.popupService.showPopup({ + unitId, + subUnitId: sheet1, + row: 1, + col: 1, + commentId: 'second-thread', + }); + }); + + expect(container.querySelector(`#CELL-${unitId}-${sheet1}-second-thread`)).toBeInstanceOf(HTMLElement); + expect(container.textContent).toContain('Second B2 thread'); + expect(container.textContent).not.toContain('First B2 thread'); + }); + it('updates an open cell popup when a thread is added at that cell location', () => { const testBed = createTestBed(); univer = testBed.univer; diff --git a/packages/sheets-thread-comment/src/models/__tests__/sheets-thread-comment.model.spec.ts b/packages/sheets-thread-comment/src/models/__tests__/sheets-thread-comment.model.spec.ts index b9c61e091e..83d2ba7e95 100644 --- a/packages/sheets-thread-comment/src/models/__tests__/sheets-thread-comment.model.spec.ts +++ b/packages/sheets-thread-comment/src/models/__tests__/sheets-thread-comment.model.spec.ts @@ -36,6 +36,42 @@ function createComment(overrides: Record = {}) { } describe('SheetsThreadCommentModel', () => { + it('keeps the newer unresolved thread as the default when an older thread is reopened', () => { + const olderComment = createComment({ id: 'older-comment', threadId: 'older-thread', resolved: true }); + const newerComment = createComment({ id: 'newer-comment', threadId: 'newer-thread' }); + const comments = new Map([ + [olderComment.id, olderComment], + [newerComment.id, newerComment], + ]); + const updates$ = new Subject(); + const threadCommentModel = { + getAll: () => [{ threads: [ + { unitId: 'unit-1', subUnitId: 'sheet-1', root: olderComment }, + { unitId: 'unit-1', subUnitId: 'sheet-1', root: newerComment }, + ] }], + commentUpdate$: updates$, + getComment: (_unitId: string, _subUnitId: string, commentId: string) => comments.get(commentId), + }; + const univerInstanceService = { + getUnitType: () => UniverInstanceType.UNIVER_SHEET, + }; + const model = new SheetsThreadCommentModel(threadCommentModel as never, univerInstanceService as never); + + expect(model.getByLocation('unit-1', 'sheet-1', 0, 0)).toBe(newerComment.id); + + olderComment.resolved = false; + updates$.next({ + type: 'resolve', + unitId: 'unit-1', + subUnitId: 'sheet-1', + payload: { commentId: olderComment.id, resolved: false }, + }); + + expect(model.getByLocation('unit-1', 'sheet-1', 0, 0)).toBe(newerComment.id); + + model.dispose(); + }); + it('should build location indexes from existing root comments and expose thread data', () => { const root = createComment(); const reply = createComment({ id: 'reply-1', parentId: root.id, ref: '', resolved: false }); diff --git a/packages/sheets-thread-comment/src/models/sheets-thread-comment.model.ts b/packages/sheets-thread-comment/src/models/sheets-thread-comment.model.ts index 359e46c8b2..44401a365f 100644 --- a/packages/sheets-thread-comment/src/models/sheets-thread-comment.model.ts +++ b/packages/sheets-thread-comment/src/models/sheets-thread-comment.model.ts @@ -230,7 +230,7 @@ export class SheetsThreadCommentModel extends Disposable { getByLocation(unitId: string, subUnitId: string, row: number, column: number): string | undefined { const comments = this.getAllByLocation(unitId, subUnitId, row, column); const activeComments = comments.filter((comment) => !comment.resolved); - return activeComments[0]?.id; + return activeComments[activeComments.length - 1]?.id; } getAllByLocation(unitId: string, subUnitId: string, row: number, column: number): IThreadComment[] {