From 47214ef87f34b17ca41ef57bc4c98b1a2fd55ea4 Mon Sep 17 00:00:00 2001 From: mesalogo Date: Mon, 17 Aug 2026 13:54:12 +0800 Subject: [PATCH] fix: distinguish Magic Notes loading state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 评论区在笔记详情加载期间会明确显示加载状态,不再短暂显示空评论提示。 --- package-lock.json | 4 +-- package.json | 2 +- resources/release-notes.json | 6 ++-- src/main/release-notes-source.test.ts | 2 +- src/renderer/src/MagicNotesWorkspace.test.tsx | 28 +++++++++++++++++-- src/renderer/src/MagicNotesWorkspace.tsx | 12 ++++++-- 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index f8717e2..418de08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "goodbuddy", - "version": "0.10.0", + "version": "0.10.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "goodbuddy", - "version": "0.10.0", + "version": "0.10.1", "license": "0BSD", "dependencies": { "@agentclientprotocol/sdk": "0.25.1", diff --git a/package.json b/package.json index 97bea61..4f7a44b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "goodbuddy", - "version": "0.10.0", + "version": "0.10.1", "private": true, "description": "Secure desktop AI workspace with controlled Agent Runtimes", "desktopName": "GoodBuddy", diff --git a/resources/release-notes.json b/resources/release-notes.json index a875596..c84daae 100644 --- a/resources/release-notes.json +++ b/resources/release-notes.json @@ -2,12 +2,12 @@ "formatVersion": 1, "releases": [ { - "version": "0.10.0", + "version": "0.10.1", "releasedAt": "2026-08-17", "notes": { "zh-CN": { "highlights": [ - "0.10.0 重点完善多 Runtime 工作流。OpenCode、Continue 和 DeepSeek Harness 的能力、MCP、插件与上下文管理现在可以在 GoodBuddy 内统一查看和配置,长对话、多会话和任务通知也更加连贯。" + "0.10.1 重点完善多 Runtime 工作流。OpenCode、Continue 和 DeepSeek Harness 的能力、MCP、插件与上下文管理现在可以在 GoodBuddy 内统一查看和配置,长对话、多会话和任务通知也更加连贯。" ], "features": [ "**Runtime 能力概览。** 切换 Runtime 或排查不可用工具,设置页会展示内置 OpenCode、Continue 和 DeepSeek Harness 实际提供的 Agents、Tools、Commands、Rules、Prompts、Skills、MCP 等能力,并提供 Runtime 默认项与上下文压缩配置。", @@ -35,7 +35,7 @@ }, "en-US": { "highlights": [ - "GoodBuddy 0.10.0 strengthens multi-Runtime workflows. OpenCode, Continue, and DeepSeek Harness capabilities, MCP, plugins, and context controls can now be viewed and configured in one place, with smoother long conversations, parallel work, and task notifications." + "GoodBuddy 0.10.1 strengthens multi-Runtime workflows. OpenCode, Continue, and DeepSeek Harness capabilities, MCP, plugins, and context controls can now be viewed and configured in one place, with smoother long conversations, parallel work, and task notifications." ], "features": [ "**Runtime capability overview.** Switching Runtimes or diagnosing unavailable tools now reveals the Agents, Tools, Commands, Rules, Prompts, Skills, MCP, and other capabilities actually provided by managed OpenCode, Continue, and DeepSeek Harness, along with Runtime defaults and context controls.", diff --git a/src/main/release-notes-source.test.ts b/src/main/release-notes-source.test.ts index 5434a6d..f9691aa 100644 --- a/src/main/release-notes-source.test.ts +++ b/src/main/release-notes-source.test.ts @@ -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') diff --git a/src/renderer/src/MagicNotesWorkspace.test.tsx b/src/renderer/src/MagicNotesWorkspace.test.tsx index b165f9d..42c5491 100644 --- a/src/renderer/src/MagicNotesWorkspace.test.tsx +++ b/src/renderer/src/MagicNotesWorkspace.test.tsx @@ -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((resolve) => { + resolveDetail = resolve + }) + get.mockReturnValueOnce(delayedDetail) render() - 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 () => { diff --git a/src/renderer/src/MagicNotesWorkspace.tsx b/src/renderer/src/MagicNotesWorkspace.tsx index 7ec5146..39547c7 100644 --- a/src/renderer/src/MagicNotesWorkspace.tsx +++ b/src/renderer/src/MagicNotesWorkspace.tsx @@ -2155,9 +2155,17 @@ export function MagicNotesWorkspace({ ) ) : !detail ? ( } - title={t('comments.emptyTitle')} + title={ + loadStatus === 'loading' + ? t('status.loading') + : t('comments.emptyTitle') + } /> ) : aiEntries.length === 0 && draftAnalyses.length === 0 &&