Fix hero-canvas navigation race; style the prosekit editor and add a toolbar
Deploy / deploy (push) Successful in 28s
Deploy / deploy (push) Successful in 28s
- Hero: gate RasterizedYES construction on a NodeRef resolving, not just "the Effect ran". Root cause of the reported "loading..." stall + "RefCell already borrowed" panic - navigating back to / client-side could run the Effect before the new <canvas> was actually in the DOM, yes.js did an unchecked getElementById(...).getContext() on null and threw mid-reactive-update, corrupting wasm_bindgen_futures' executor badly enough to panic on the next tick. Same NodeRef-gating pattern the prosekit editor's own mount already used. - style/main.css: .prosekit-wrap/.prosekit-toolbar/.prosekit-editor to match the existing input/textarea look (border, background, focus ring). - prosekit-editor.js: a real toolbar (Bold, Italic, H1, H2, Link, and a dedicated Gitea-repo-embed button reusing the paste rule's own insert logic) with active-state highlighting via the standard ProseMirror markActive/nodeActive idiom.
This commit is contained in:
+21
-7
@@ -232,11 +232,11 @@ fn Hero(title: String, description: String, show_yes: bool) -> impl IntoView {
|
||||
// Only the landing page gets the full interactive piece - it's the
|
||||
// one page this is actually "the" hero for; other pages (thank-you
|
||||
// pages, /review) get the plain dark header below. Starts the
|
||||
// animation once the canvas elements exist (post-mount, via
|
||||
// Effect), and explicitly stops the requestAnimationFrame loop on
|
||||
// unmount - the original page-owning script never needed this since
|
||||
// navigating away meant a full document unload, which doesn't
|
||||
// happen in an SPA.
|
||||
// animation once the canvas elements exist, and explicitly stops
|
||||
// the requestAnimationFrame loop on unmount - the original
|
||||
// page-owning script never needed this since navigating away meant
|
||||
// a full document unload, which doesn't happen in an SPA.
|
||||
let raster_ref: NodeRef<leptos::html::Canvas> = NodeRef::new();
|
||||
#[cfg(feature = "hydrate")]
|
||||
if show_yes {
|
||||
// `on_cleanup` requires Send + Sync (even single-threaded, wasm),
|
||||
@@ -245,7 +245,21 @@ fn Hero(title: String, description: String, show_yes: bool) -> impl IntoView {
|
||||
// cnats' WebRTC call state uses for its own non-Send peer map).
|
||||
let instance: StoredValue<Option<yes::RasterizedYes>, LocalStorage> =
|
||||
StoredValue::new_local(None);
|
||||
// Gated on the canvas NodeRef resolving, not just "the Effect
|
||||
// ran" - on a fresh page load the DOM is already there by the
|
||||
// time this fires, but navigating back to `/` client-side hit a
|
||||
// real race: the Effect ran before the new view's <canvas> was
|
||||
// actually inserted, RasterizedYES::new() (yes.js) did an
|
||||
// unchecked `document.getElementById(...).getContext(...)` on
|
||||
// null and threw mid-reactive-update - which then corrupted
|
||||
// wasm_bindgen_futures' single-threaded executor state badly
|
||||
// enough to panic ("RefCell already borrowed") on the next
|
||||
// tick. Waiting for the NodeRef itself guarantees DOM presence
|
||||
// the same way the prosekit editor's own mount Effect does.
|
||||
Effect::new(move |_| {
|
||||
if raster_ref.get().is_none() {
|
||||
return;
|
||||
}
|
||||
instance.set_value(Some(yes::RasterizedYes::new()));
|
||||
});
|
||||
on_cleanup(move || {
|
||||
@@ -264,7 +278,7 @@ fn Hero(title: String, description: String, show_yes: bool) -> impl IntoView {
|
||||
view! {
|
||||
<div class="hero-canvas" aria-hidden="true">
|
||||
<canvas id="lineCanvas"></canvas>
|
||||
<canvas id="rasterCanvas"></canvas>
|
||||
<canvas id="rasterCanvas" node_ref=raster_ref></canvas>
|
||||
</div>
|
||||
}
|
||||
})}
|
||||
@@ -502,7 +516,7 @@ fn AlternativeCard(
|
||||
prop:value=move || sig.get()
|
||||
on:input=move |ev| sig.set(event_target_value(&ev))
|
||||
/>
|
||||
<div class="prosekit-editor" node_ref=container_ref></div>
|
||||
<div class="prosekit-wrap" node_ref=container_ref></div>
|
||||
</label>
|
||||
}
|
||||
.into_any();
|
||||
|
||||
Reference in New Issue
Block a user