fix(ws): broadcast realtime page rename/icon change (#72)
handleMessage became a no-op and PageWsListener intentionally ignored PAGE_UPDATED, so a rename/icon change (client operation:updateOne) was no longer rebroadcast -> other clients saw stale title/icon in the sidebar+breadcrumbs until a reload (create/duplicate/restore were covered; updateOne regressed). Add a server-authoritative onPageUpdated handler: PageService.update detects a real title/icon change (DTO carries the field AND value differs; no-op/content- only saves excluded) and attaches a treeUpdate snapshot to PAGE_UPDATED; the listener broadcasts a tree updateOne via the restriction-aware emitTreeEvent (so a restricted page's title never leaks). Content-only saves attach nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -270,6 +270,17 @@ export class PageService {
|
||||
|
||||
const isAgent = provenance?.actor === 'agent';
|
||||
|
||||
// Detect a real title/icon change so the WS tree listener can broadcast an
|
||||
// `updateOne` to the space (rename / icon swap) WITHOUT re-broadcasting on a
|
||||
// content-only save. Only treat a field as changed when the DTO actually
|
||||
// carries it AND its value differs from what is already stored — a no-op
|
||||
// save (same title, or a content-only update where these are undefined)
|
||||
// produces no tree snapshot, so the listener stays quiet.
|
||||
const titleChanged =
|
||||
updatePageDto.title !== undefined && updatePageDto.title !== page.title;
|
||||
const iconChanged =
|
||||
updatePageDto.icon !== undefined && updatePageDto.icon !== page.icon;
|
||||
|
||||
await this.pageRepo.updatePage(
|
||||
{
|
||||
title: updatePageDto.title,
|
||||
@@ -287,6 +298,22 @@ export class PageService {
|
||||
contributorIds: contributorIds,
|
||||
},
|
||||
page.id,
|
||||
undefined,
|
||||
// Enrich PAGE_UPDATED only when title/icon actually changed. The snapshot
|
||||
// values come from the server-side data being persisted (DTO when present,
|
||||
// otherwise the unchanged stored value), never relayed from the client.
|
||||
titleChanged || iconChanged
|
||||
? {
|
||||
treeUpdate: {
|
||||
id: page.id,
|
||||
slugId: page.slugId,
|
||||
spaceId: page.spaceId,
|
||||
parentPageId: page.parentPageId ?? null,
|
||||
...(titleChanged ? { title: updatePageDto.title } : {}),
|
||||
...(iconChanged ? { icon: updatePageDto.icon } : {}),
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
);
|
||||
|
||||
this.generalQueue
|
||||
|
||||
Reference in New Issue
Block a user