diff options
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/transport.js | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport.js b/packages/meshbay-hub/src/meshbay_hub/static/transport.js index 3acfd20..179292e 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport.js @@ -72,13 +72,35 @@ function _aborted() { // change anything — `op` is already on every admin_challenge, and this // list is what lets a response two steps later be tied back to the right // one. -// The acks whose payload is state no caller could have predicted: they carry -// the node's whole roots table back. See the note where they are dispatched. -const ROOT_ACK_TYPES = new Set([ +// Acks the node *broadcasts* to everyone in the group, which the requester +// therefore also has to be handed. +// +// `_dispatch` resolves an admin ack against the pending request and returns, +// which is right for an op whose caller already knows the value it chose. It is +// wrong for these: every *other* connected client learns the change from the +// broadcast, and the one that asked for it is the only one that does not, +// because its own request swallowed its copy. Found twice — first on the root +// table, then on Chat's directory, where it meant the pane went on showing an +// unsaved-looking draft after a save that had worked. +const BROADCAST_ACK_TYPES = new Set([ 'root_update_ack', 'root_eject_ack', 'root_plug_ack', 'root_add_ack', 'root_remove_ack', + 'app_directories_ack', 'chat_directory_ack', 'chat_link_preview_ack', ]); +/** Hand a broadcast ack to the callback that would have had it from a peer. */ +function _replayBroadcast(transport, msg) { + if (msg.type === 'app_directories_ack' && transport._onAppDirectories) { + transport._onAppDirectories(msg.app, msg.directories || []); + } else if (msg.type === 'chat_directory_ack' && transport._onChatDirectory) { + transport._onChatDirectory(msg.path || ''); + } else if (msg.type === 'chat_link_preview_ack' && transport._onChatLinkPreview) { + transport._onChatLinkPreview(Boolean(msg.enabled)); + } else if (transport._onRootsChanged) { + transport._onRootsChanged(msg); + } +} + const ADMIN_OP_TYPES = new Set([ 'tmdb_override', 'tmdb_rematch', 'tmdb_config', 'tmdb_enabled', 'video_root', 'audio_root', 'photo_roots', @@ -2349,9 +2371,7 @@ class MeshBayTransport { // name it settled on. Returning here left the operator who clicked // Eject as the one client that never saw it happen, while every // other peer got the broadcast. So this one type is handed on. - if (ROOT_ACK_TYPES.has(msg.type) && this._onRootsChanged) { - this._onRootsChanged(msg); - } + if (BROADCAST_ACK_TYPES.has(msg.type)) _replayBroadcast(this, msg); return; } } @@ -2486,8 +2506,10 @@ class MeshBayTransport { // A root's flags changed, or one was ejected, plugged, added or removed. // Broadcast by the node to every peer, so everyone's table updates without // waiting for the next index_sync. - if (ROOT_ACK_TYPES.has(msg.type) && this._onRootsChanged) { - this._onRootsChanged(msg); + if (msg.type === 'root_update_ack' || msg.type === 'root_eject_ack' + || msg.type === 'root_plug_ack' || msg.type === 'root_add_ack' + || msg.type === 'root_remove_ack') { + if (this._onRootsChanged) this._onRootsChanged(msg); } // The operator's node is scanning — never the entries themselves, just |