Simplify client hooks messaging

This commit is contained in:
Jonatan Kłosko 2024-12-09 17:16:32 +08:00
parent ab182ffecb
commit 2b6ce4a92a
4 changed files with 87 additions and 112 deletions

View file

@ -85,13 +85,23 @@ const Cell = {
this.subscriptions = [ this.subscriptions = [
globalPubsub.subscribe( globalPubsub.subscribe(
"navigation", "navigation:focus_changed",
this.handleNavigationEvent.bind(this), ({ focusableId, scroll }) =>
this.handleElementFocused(focusableId, scroll),
),
globalPubsub.subscribe("navigation:insert_mode_changed", ({ enabled }) =>
this.handleInsertModeChanged(enabled),
),
globalPubsub.subscribe("cells:cell_moved", ({ cellId }) =>
this.handleCellMoved(cellId),
), ),
globalPubsub.subscribe("cells", this.handleCellsEvent.bind(this)),
globalPubsub.subscribe( globalPubsub.subscribe(
`cells:${this.props.cellId}`, `cells:${this.props.cellId}:dispatch_queue_evaluation`,
this.handleCellEvent.bind(this), ({ dispatch }) => this.handleDispatchQueueEvaluation(dispatch),
),
globalPubsub.subscribe(
`cells:${this.props.cellId}:jump_to_line`,
({ line, offset = 0 }) => this.handleJumpToLine(line, offset),
), ),
]; ];
@ -138,30 +148,6 @@ const Cell = {
]); ]);
}, },
handleNavigationEvent(event) {
if (event.type === "element_focused") {
this.handleElementFocused(event.focusableId, event.scroll);
} else if (event.type === "insert_mode_changed") {
this.handleInsertModeChanged(event.enabled);
}
},
handleCellsEvent(event) {
if (event.type === "cell_moved") {
this.handleCellMoved(event.cellId);
}
},
handleCellEvent(event) {
if (event.type === "dispatch_queue_evaluation") {
this.handleDispatchQueueEvaluation(event.dispatch);
} else if (event.type === "jump_to_line") {
if (this.isFocused) {
this.currentEditor().moveCursorToLine(event.line, event.offset || 0);
}
}
},
handleElementFocused(focusableId, scroll) { handleElementFocused(focusableId, scroll) {
if (this.props.cellId === focusableId) { if (this.props.cellId === focusableId) {
this.isFocused = true; this.isFocused = true;
@ -355,8 +341,7 @@ const Cell = {
handleDispatchQueueEvaluation(dispatch) { handleDispatchQueueEvaluation(dispatch) {
if (this.props.type === "smart" && this.props.smartCellJsViewRef) { if (this.props.type === "smart" && this.props.smartCellJsViewRef) {
// Ensure the smart cell UI is reflected on the server, before the evaluation // Ensure the smart cell UI is reflected on the server, before the evaluation
globalPubsub.broadcast(`js_views:${this.props.smartCellJsViewRef}`, { globalPubsub.broadcast(`js_views:${this.props.smartCellJsViewRef}:sync`, {
type: "sync",
callback: dispatch, callback: dispatch,
}); });
} else { } else {
@ -364,6 +349,12 @@ const Cell = {
} }
}, },
handleJumpToLine(line, offset) {
if (this.isFocused) {
this.currentEditor().moveCursorToLine(line, offset);
}
},
scrollEditorCursorIntoViewIfNeeded() { scrollEditorCursorIntoViewIfNeeded() {
const element = this.currentEditor().getElementAtCursor(); const element = this.currentEditor().getElementAtCursor();
@ -381,9 +372,9 @@ const Cell = {
const cursor = this.currentEditor().getCurrentCursorPosition(); const cursor = this.currentEditor().getCurrentCursorPosition();
if (cursor === null) return; if (cursor === null) return;
globalPubsub.broadcast("history", { globalPubsub.broadcast("navigation:cursor_moved", {
...cursor, line: cursor.line,
type: "navigation", offset: cursor.offset,
cellId: this.props.cellId, cellId: this.props.cellId,
}); });
}, },

View file

@ -26,10 +26,16 @@ const Headline = {
this.initializeHeadingEl(); this.initializeHeadingEl();
this.navigationSubscription = globalPubsub.subscribe( this.subscriptions = [
"navigation", globalPubsub.subscribe(
this.handleNavigationEvent.bind(this), "navigation:focus_changed",
); ({ focusableId, scroll }) =>
this.handleElementFocused(focusableId, scroll),
),
globalPubsub.subscribe("navigation:insert_mode_changed", ({ enabled }) =>
this.handleInsertModeChanged(enabled),
),
];
}, },
updated() { updated() {
@ -38,7 +44,7 @@ const Headline = {
}, },
destroyed() { destroyed() {
this.navigationSubscription.destroy(); this.subscriptions.forEach((subscription) => subscription.destroy());
}, },
getProps() { getProps() {
@ -80,14 +86,6 @@ const Headline = {
}); });
}, },
handleNavigationEvent(event) {
if (event.type === "element_focused") {
this.handleElementFocused(event.focusableId, event.scroll);
} else if (event.type === "insert_mode_changed") {
this.handleInsertModeChanged(event.enabled);
}
},
handleElementFocused(focusableId, scroll) { handleElementFocused(focusableId, scroll) {
if (this.props.id === focusableId) { if (this.props.id === focusableId) {
this.isFocused = true; this.isFocused = true;

View file

@ -132,12 +132,15 @@ const JSView = {
this.subscriptions = [ this.subscriptions = [
globalPubsub.subscribe( globalPubsub.subscribe(
`js_views:${this.props.ref}`, `js_views:${this.props.ref}:sync`,
this.handleJSViewEvent.bind(this), ({ callback }) => this.handleSync(callback),
), ),
globalPubsub.subscribe( globalPubsub.subscribe(
"navigation", `js_views:${this.props.ref}:secret_selected`,
this.handleNavigationEvent.bind(this), ({ secretName }) => this.handleSecretSelected(secretName),
),
globalPubsub.subscribe("navigation:focus_changed", ({ focusableId }) =>
this.handleElementFocused(focusableId),
), ),
]; ];
@ -248,11 +251,10 @@ const JSView = {
// dispatched to trigger reposition. This way we don't need to // dispatched to trigger reposition. This way we don't need to
// use deep MutationObserver, which would be expensive, especially // use deep MutationObserver, which would be expensive, especially
// with code editor // with code editor
const jsViewSubscription = globalPubsub.subscribe("js_views", (event) => { const jsViewSubscription = globalPubsub.subscribe(
if (event.type === "reposition") { "js_views:reposition",
this.repositionIframe(); (event) => this.repositionIframe(),
} );
});
// Emulate mouse enter and leave on the placeholder. Note that we // Emulate mouse enter and leave on the placeholder. Note that we
// intentionally use bubbling to notify all parents that may have // intentionally use bubbling to notify all parents that may have
@ -467,36 +469,33 @@ const JSView = {
callback(); callback();
}, },
handleJSViewEvent(event) { handleSync(callback) {
if (event.type === "sync") {
// First, we invoke optional synchronization callback in the iframe, // First, we invoke optional synchronization callback in the iframe,
// that may send any deferred UI changes to the server. Then, we // that may send any deferred UI changes to the server. Then, we
// do a ping to synchronize with the server // do a ping to synchronize with the server
this.syncCallbackQueue.push(event.callback); this.syncCallbackQueue.push(callback);
this.postMessage({ type: "sync" }); this.postMessage({ type: "sync" });
} else if (event.type == "secretSelected") {
this.postMessage({
type: "secretSelected",
secretName: event.secretName,
});
}
}, },
handleNavigationEvent(event) { handleSecretSelected(secretName) {
if (event.type === "element_focused") { this.postMessage({ type: "secretSelected", secretName });
},
handleElementFocused(focusableId) {
// If a parent focusable element is focused, mirror the attribute // If a parent focusable element is focused, mirror the attribute
// to the iframe element. This way if we need to apply style rules // to the iframe element. This way if we need to apply style rules
// (such as opacity) to focused elements, we can target the iframe // (such as opacity) to focused elements, we can target the iframe
// elements placed elsewhere in the DOM // elements placed elsewhere in the DOM
const focusableEl = this.el.closest(`[data-focusable-id]`); const parentFocusableEl = this.el.closest(`[data-focusable-id]`);
const focusableId = focusableEl ? focusableEl.dataset.focusableId : null; const parentFocusableId = parentFocusableEl
? parentFocusableEl.dataset.focusableId
: null;
this.iframe.toggleAttribute( this.iframe.toggleAttribute(
"data-js-focused", "data-js-focused",
focusableId === event.focusableId, parentFocusableId === focusableId,
); );
}
}, },
}; };

View file

@ -163,7 +163,11 @@ const Session = {
globalPubsub.subscribe("jump_to_editor", ({ line, file }) => globalPubsub.subscribe("jump_to_editor", ({ line, file }) =>
this.jumpToLine(file, line), this.jumpToLine(file, line),
), ),
globalPubsub.subscribe("history", this.handleHistoryEvent.bind(this)), globalPubsub.subscribe(
"navigation:cursor_moved",
({ cellId, line, offset }) =>
this.cursorHistory.push(cellId, line, offset),
),
]; ];
this.initializeDragAndDrop(); this.initializeDragAndDrop();
@ -951,10 +955,10 @@ const Session = {
// If an evaluable cell is focused, we forward the evaluation // If an evaluable cell is focused, we forward the evaluation
// request to that cell, so it can synchronize itself before // request to that cell, so it can synchronize itself before
// sending the request to the server // sending the request to the server
globalPubsub.broadcast(`cells:${this.focusedId}`, { globalPubsub.broadcast(
type: "dispatch_queue_evaluation", `cells:${this.focusedId}:dispatch_queue_evaluation`,
dispatch, { dispatch },
}); );
} else { } else {
dispatch(); dispatch();
} }
@ -1085,8 +1089,7 @@ const Session = {
} }
} }
globalPubsub.broadcast("navigation", { globalPubsub.broadcast("navigation:focus_changed", {
type: "element_focused",
focusableId: focusableId, focusableId: focusableId,
scroll, scroll,
}); });
@ -1105,8 +1108,7 @@ const Session = {
this.el.removeAttribute("data-js-insert-mode"); this.el.removeAttribute("data-js-insert-mode");
} }
globalPubsub.broadcast("navigation", { globalPubsub.broadcast("navigation:insert_mode_changed", {
type: "insert_mode_changed",
enabled: insertModeEnabled, enabled: insertModeEnabled,
}); });
}, },
@ -1265,7 +1267,7 @@ const Session = {
this.repositionJSViews(); this.repositionJSViews();
if (this.focusedId === cellId) { if (this.focusedId === cellId) {
globalPubsub.broadcast("cells", { type: "cell_moved", cellId }); globalPubsub.broadcast("cells:cell_moved", { cellId });
} }
}, },
@ -1323,8 +1325,7 @@ const Session = {
}, },
handleSecretSelected(select_secret_ref, secretName) { handleSecretSelected(select_secret_ref, secretName) {
globalPubsub.broadcast(`js_views:${select_secret_ref}`, { globalPubsub.broadcast(`js_views:${select_secret_ref}:secret_selected`, {
type: "secretSelected",
secretName, secretName,
}); });
}, },
@ -1344,14 +1345,8 @@ const Session = {
} }
}, },
handleHistoryEvent(event) {
if (event.type === "navigation") {
this.cursorHistory.push(event.cellId, event.line, event.offset);
}
},
repositionJSViews() { repositionJSViews() {
globalPubsub.broadcast("js_views", { type: "reposition" }); globalPubsub.broadcast("js_views:reposition", {});
}, },
/** /**
@ -1476,7 +1471,7 @@ const Session = {
this.setFocusedEl(cellId, { scroll: false }); this.setFocusedEl(cellId, { scroll: false });
this.setInsertMode(true); this.setInsertMode(true);
globalPubsub.broadcast(`cells:${cellId}`, { type: "jump_to_line", line }); globalPubsub.broadcast(`cells:${cellId}:jump_to_line`, { line });
}, },
cursorHistoryGoBack() { cursorHistoryGoBack() {
@ -1485,11 +1480,7 @@ const Session = {
this.setFocusedEl(cellId, { scroll: false }); this.setFocusedEl(cellId, { scroll: false });
this.setInsertMode(true); this.setInsertMode(true);
globalPubsub.broadcast(`cells:${cellId}`, { globalPubsub.broadcast(`cells:${cellId}:jump_to_line`, { line, offset });
type: "jump_to_line",
line,
offset,
});
} }
}, },
@ -1499,11 +1490,7 @@ const Session = {
this.setFocusedEl(cellId, { scroll: false }); this.setFocusedEl(cellId, { scroll: false });
this.setInsertMode(true); this.setInsertMode(true);
globalPubsub.broadcast(`cells:${cellId}`, { globalPubsub.broadcast(`cells:${cellId}:jump_to_line`, { line, offset });
type: "jump_to_line",
line,
offset,
});
} }
}, },
}; };