The reactions primitive (MICA-98): one keyed cache, one batched read, one optimistic
toggle, for every surface that lets a player react to something.
Blabber's DMs had all of this written out inside the app — a writable map, an empty
constant, a batched loader and a toggle whose optimism and rollback are the fiddly part.
Messages wants the same behaviour (MICA-68) and Blabs themselves plausibly will, and
three copies of an optimistic update is three places for one of them to forget the
rollback. An optimistic update that survives a refused write is a lie the UI tells.
Kept out of the map rather than merged onto the rows it describes, mirroring Blabber's
engagement: a reaction landing must not replace a row object and cost it its identity in
a keyed {#each}.
It lives in kit/ and not services/ deliberately: it names no route and touches no
shell, so it bundles into a sandboxed add-on unchanged — which matters, because Blabber
is one (core: false).
The reactions primitive (MICA-98): one keyed cache, one batched read, one optimistic toggle, for every surface that lets a player react to something.
Blabber's DMs had all of this written out inside the app — a
writablemap, an empty constant, a batched loader and a toggle whose optimism and rollback are the fiddly part. Messages wants the same behaviour (MICA-68) and Blabs themselves plausibly will, and three copies of an optimistic update is three places for one of them to forget the rollback. An optimistic update that survives a refused write is a lie the UI tells.Kept out of the map rather than merged onto the rows it describes, mirroring Blabber's
engagement: a reaction landing must not replace a row object and cost it its identity in a keyed{#each}.It lives in
kit/and notservices/deliberately: it names no route and touches no shell, so it bundles into a sandboxed add-on unchanged — which matters, because Blabber is one (core: false).