You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Activity
xuyushun441-sys commentedon Aug 3, 2026
认领:PM 循环第 3 轮
会话:
session_01NVPjPzmmAJ2Ngtvgg5MSRa(objectui 分片 PM,账号xuyushun441-sys,已在 objectstack#4604 登记)分支:
claude/issue-3209-chatter-loading-signalWorktree:
objectui-issue-3209分诊:无需拍板,直接派
本单已经把该定的都定了 —— 信号由拥有取数的宿主产出,这是 #3165 / #3205 已确立的形状,而且原单明确写了不要在消费端加宽容兜底(不许在 timeline 里猜"items 为空且刚挂载就算 loading")。这与本轮已合并的 #3232 是同一条仓规:分歧在生产者收敛,不在消费者用启发式兜住。没有可选方案需要维护者选。
两处容易做错的地方,派发时先钉住
1. 两个
find是并行 promise,收口要收全。 原单已经点出这点。feedLoading必须在两条都 settle 之后才转 false,且.catch(() => {})那条路径也要计入 —— 失败也是 settle,不能让一个 reject 把面板永久钉在 loading 态。这是最容易写出"永远转圈"的地方。2. 三处都要接,少一处就等于没修。 原单列的三个落点是一条链:
RecordDetailView里新增 loading state;<DiscussionContextProvider loading={feedLoading} …>;<RecordChatterPanel loading={feedLoading} …>;plugin-detail/src/renderers/record-chatter.tsx补loading={discussion?.loading},让作者手工摆放的record:chatter/record:discussion走同一条链。record:activity(renderers/record-activity.tsx)已经在读discussion?.loading,照它抄,不要发明第二种写法。验收要求
要有测试钉住"取数期间渲染 loading 而不是
No comments yet",并且 mutation 验证:把loading传递摘掉后测试必须转红。#3205 修的是渲染分支、本单修的是信号源,两者合起来才是完整链路 —— 只断言"panel 收到了 loading prop"不够,要断言用户看到的是加载态而不是空态。Generated by Claude Code
xuyushun441-sys commentedon Aug 3, 2026
PM 验收:ACCEPT — PR #3270,已入合并队列
main、Fixes objectstack-ai/objectui#3209packages/app-shell+packages/plugin-detail+ changesetcontent/docs/releases/零改动我派发时钉的两处易错点,都处理到位了
1. 两个并行 promise 的收口。 用
Promise.allSettled(inFlight),而两条链各自已有.catch(() => {})—— 所以 rejected 也计入 settled。这正是要点:没有部署 audit 插件的环境sys_activity会 404、对象关了enable.feeds时sys_comment会 403,这两种情况必须落到空态而不是永久转圈。changeset 里那句话说得对:「那会把"错说成空"换成"永远转圈",是更糟的 bug」。清理函数里还有cancelled守卫。2. 四个接入点一个不少 —— 新 state、
DiscussionContextProvider、自动追加的RecordChatterPanel、以及record-chatter.tsx的loading={discussion?.loading}。一处超出我要求、而且是对的设计
flag 没做成朴素布尔,而是按
object:recordId键控:理由写在注释里,两条我都认同:
useState(false)+ effect 里setFeedLoading(true)会让 effect 跑之前那一帧先画出空态(一闪而过的 "No comments yet");而切换记录时,朴素布尔会在新 effect 触发前显示上一条记录的已结算状态。派生式写法让一条记录的第一帧就是 loading,且不需要额外的 reset effect。并且它明说这是抄record:activity的canSelfFetch && fetched === null同一套写法 —— 一个惯例,不是两个,正是我要求的。测试断言的是用户看到什么
我要求"不能只断言 panel 收到了 loading prop"。它做到了:全部断言落在
getByTestId('activity-loading')在场 /queryByText('No comments yet')为 null。而且两条投递路径都覆盖了 —— 合成页面(走record:discussion→ DiscussionContext)与作者页面无 discussion 槽(走宿主底部自动追加,没有 context 中转,是独立的一条线)。少测一条,另一条仍然带着 bug 上线。五处独立 mutation 验证,每处只摘一根线:
DiscussionContextProvider的loadingrecord-chatter.tsx的转发loadingallSettled(inFlight)→ 只取第一个allSettled→Promise.all且去掉.catch后两条恰好证明了我担心的两个失效方向都真的被拦住。
needs-user-decisionRecordDetailView在记录切换时从不重置feedItems—— 两个取数回调都是按 id 并入prev,没有任何地方把它设回[],而该视图在记录间不会重新挂载(所有挂载点都没有key)。结果:记录 A 的评论和活动会留在屏幕上,显示在记录 B 下面。 已在本单的测试夹具上复现(rerender 到recordIdOverride="rec-B"后 rec-A 的评论仍在)。它同时掩盖了本单的修复:timeline 的分支是
loading && filtered.length === 0,而残留行让filtered非空,所以记录间导航时 loading 态不显示。我没有让它顺手修,标了
needs-user-decision,因为形态需要维护者定:清空 vs 按objectName:recordId给 feed state 加键,而乐观更新的行(用户刚发的评论)让这个选择有实际后果。Generated by Claude Code
fix(app-shell,plugin-detail): the chatter chain gets a loading signal…
fix(app-shell): key the record feed state by objectName:recordId (obj…