fix: distinguish Magic Notes loading state
Cross-platform packages / Validate source (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub Release (push) Canceled after 0s

The AI comments pane reused its final empty-state title while the selected note detail was still loading. Slow CI runners could therefore satisfy the title wait before the final hint existed, causing the immutable v0.10.0 release validation to fail repeatedly.

The pane now presents a distinct loading state until note data is ready, and regression coverage controls the delayed detail response before asserting the final empty state. Recovery metadata moves the unpublished 0.10.0 notes forward to 0.10.1 so upgrading users see the cumulative release once.

Release note: 魔法笔记的 AI 评论区在笔记详情加载期间会明确显示加载状态,不再短暂显示空评论提示。
This commit is contained in:
mesalogo
2026-08-17 13:54:12 +08:00
parent 98fabe9e2e
commit 47214ef87f
6 changed files with 42 additions and 12 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ describe('packaged release notes', () => {
}
const currentRelease = parsed.releases.find(
(release) => release.version === '0.10.0'
(release) => release.version === '0.10.1'
)
expect(currentRelease).toBeDefined()
expect(currentRelease?.releasedAt).toBe('2026-08-17')
+25 -3
View File
@@ -4,6 +4,7 @@ import {
fireEvent,
render,
screen,
within,
waitFor
} from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
@@ -449,14 +450,35 @@ describe('MagicNotesWorkspace', () => {
})
it('shows a concise empty state before a note has AI comments', async () => {
get.mockResolvedValueOnce(alternateDetail(noteId, detail.title))
let resolveDetail:
| ((value: MagicNoteDetail) => void)
| undefined
const delayedDetail = new Promise<MagicNoteDetail>((resolve) => {
resolveDetail = resolve
})
get.mockReturnValueOnce(delayedDetail)
render(<MagicNotesWorkspace onNotify={onNotify} />)
expect(await screen.findByText('暂无 AI 评论')).toBeInTheDocument()
const pane = await screen.findByLabelText('AI 评论')
expect(within(pane).getByText('正在加载')).toBeInTheDocument()
expect(within(pane).getByText('正在加载笔记…')).toBeInTheDocument()
expect(
screen.getByText('写完一句并停止输入 5 秒后,评论会显示在这里。')
within(pane).queryByText('暂无 AI 评论')
).not.toBeInTheDocument()
await act(async () => {
resolveDetail?.(alternateDetail(noteId, detail.title))
await delayedDetail
})
expect(
await within(pane).findByText(
'写完一句并停止输入 5 秒后,评论会显示在这里。'
)
).toBeInTheDocument()
expect(within(pane).getByText('暂无 AI 评论')).toBeInTheDocument()
expect(within(pane).queryByText('正在加载')).not.toBeInTheDocument()
})
it('resizes the AI comments pane with pointer and keyboard controls', async () => {
+10 -2
View File
@@ -2155,9 +2155,17 @@ export function MagicNotesWorkspace({
)
) : !detail ? (
<EmptyState
description={t('comments.selectNote')}
description={
loadStatus === 'loading'
? t('status.loadingNotes')
: t('comments.selectNote')
}
icon={<Bot size={20} />}
title={t('comments.emptyTitle')}
title={
loadStatus === 'loading'
? t('status.loading')
: t('comments.emptyTitle')
}
/>
) : aiEntries.length === 0 &&
draftAnalyses.length === 0 &&