v4: every live update reaches every page that shows what it changed — the client kept each kind of event in one "latest" slot, so two arriving before a render lost the first (two notifications of one dump going public showed one); they now go through a subscription, useWSEvent, and each reaches every subscriber. A playlist made private sent its new title and description to everyone, and kept them on a visitor's page; playlists now follow the dumps' rule, broadcastChange: others get playlist_deleted, and playlist_created when it goes public again. A dump deleted or turned private sends its playlists' dumps again, so their counts and pages follow. Comments on a private dump reach its poster's other tabs. Reading the notifications clears the bell in every tab (notifications_read), and a category change makes every client fetch the categories again (categories_changed). The dump page gives way to a notice when its dump is deleted or made private. A profile gains the user's new dumps, the followed feed those of the users followed and the playlists followed, the search results follow edits and deletions, the index's category feed drops a dump edited out of it, and a renamed user's name follows on cards and comments. After a reconnection, every live list fetches the pages it holds again (usePagedList's resync), and the playlist, the profile, the dump, the categories and the follows are fetched again. The position memory of usePositionAwareSync is now inside the list sync hooks, so a returning item is put back without depending on the order the hooks are called.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
khannurien
2026-10-10 07:34:49 +00:00
parent 1c5a449d84
commit 308a8299f3
53 changed files with 1941 additions and 1044 deletions

View File

@@ -283,8 +283,10 @@ export interface DumpDeletedMessage {
/**
* Sent by the server when a playlist is created, to every socket if it is
* public, else to its owner's. `WSProvider` passes it on to the playlist pages
* as `lastPlaylistEvent`, as it does the three messages below.
* public, else to its owner's. It also goes to everyone but the owner when a
* private playlist goes public, since to them it is new. `WSProvider` passes
* it on to the playlist pages as a `playlist` event, as it does the three
* messages below.
*/
export interface PlaylistCreatedMessage {
type: "playlist_created";
@@ -292,16 +294,18 @@ export interface PlaylistCreatedMessage {
}
/**
* Sent by the server when a playlist changes, to every socket if it is public
* or was until this change, so that a playlist gone private leaves the others'
* views.
* Sent by the server when a playlist changes, to every socket if it is public,
* else to its owner's, as when it has just gone private.
*/
export interface PlaylistUpdatedMessage {
type: "playlist_updated";
playlist: Playlist;
}
/** Sent by the server when a playlist is deleted, to those who could see it. */
/**
* Sent by the server when a playlist is deleted, to those who could see it. It
* also goes to everyone but the owner when a public playlist goes private.
*/
export interface PlaylistDeletedMessage {
type: "playlist_deleted";
playlistId: string;
@@ -310,7 +314,8 @@ export interface PlaylistDeletedMessage {
/**
* Sent by the server when dumps are added to, removed from or reordered in a
* playlist, to those who can see it.
* playlist, to those who can see it, and when one of its dumps is deleted or
* changes visibility, which changes what its viewers see of it.
*/
export interface PlaylistDumpsUpdatedMessage {
type: "playlist_dumps_updated";
@@ -325,8 +330,10 @@ export interface PlaylistDumpsUpdatedMessage {
}
/**
* Sent by the server to every socket after a profile edit, a role change or an
* avatar upload. `WSProvider` refreshes the user's avatar wherever it shows.
* Sent by the server to every socket after a profile edit, a rename, a role
* change or an avatar upload. `WSProvider` refreshes the user's avatar
* wherever it shows, and passes it on as a `user` event, which updates their
* profile and their name on the lists.
*/
export interface UserUpdatedMessage {
type: "user_updated";
@@ -334,9 +341,9 @@ export interface UserUpdatedMessage {
}
/**
* Sent by the server to every socket when a comment is posted on a public
* dump. Comments on a private dump are never broadcast. `WSProvider` passes it
* on to the dump's page as `lastCommentEvent`, as it does the two messages
* Sent by the server when a comment is posted, to every socket if its dump is
* public, else to the dump's poster's. `WSProvider` passes it on to the dump's
* page and the dump lists as a `comment` event, as it does the two messages
* below.
*/
export interface CommentCreatedMessage {
@@ -344,18 +351,13 @@ export interface CommentCreatedMessage {
comment: Comment;
}
/**
* Sent by the server to every socket when a comment on a public dump is edited.
*/
/** Sent by the server when a comment is edited, as when one is posted. */
export interface CommentUpdatedMessage {
type: "comment_updated";
comment: Comment;
}
/**
* Sent by the server to every socket when a comment on a public dump is
* deleted.
*/
/** Sent by the server when a comment is deleted, as when one is posted. */
export interface CommentDeletedMessage {
type: "comment_deleted";
commentId: string;
@@ -372,6 +374,23 @@ export interface NotificationCreatedMessage {
notification: Notification;
}
/**
* Sent by the notification service to every socket of a user who opened their
* notifications, which marks them all read. `WSProvider` zeroes the bell's
* count, in the other tabs and devices too.
*/
export interface NotificationsReadMessage {
type: "notifications_read";
}
/**
* Sent by the category service to every socket after a category is created,
* edited or deleted. `CategoriesProvider` fetches the categories again.
*/
export interface CategoriesChangedMessage {
type: "categories_changed";
}
/**
* Sent by the server to the socket whose message failed. With `dumpId` or
* `commentId`, `WSProvider` undoes that optimistic vote or like at once rather
@@ -478,6 +497,8 @@ export type ServerToClientMessage =
| CommentUpdatedMessage
| CommentDeletedMessage
| NotificationCreatedMessage
| NotificationsReadMessage
| CategoriesChangedMessage
| ErrorMessage
| ChatMessageMessage
| ChatMessageUpdatedMessage