refactor: introduce RevealManager and Article DOM context

Decouple the reveal logic from the `Article` component by introducing
a `RevealManager` component and an `ArticleDomCtx`. This allows the
reveal logic to reactively manage DOM injections and classes without
polluting the `Article` component's props or lifecycle.

Additionally, implements a robust `cleanupInjections` mechanism to
ensure that injected buttons and styling artifacts are properly removed
during navigation, role changes, or disconnections.
This commit is contained in:
2026-07-07 22:19:04 +08:00
parent 1ef2560faa
commit aa326f38a0
5 changed files with 117 additions and 19 deletions
+40
View File
@@ -0,0 +1,40 @@
/**
* RevealManager — mounts as a child of <Article> and reactively applies
* reveal classes (non-GM) or injects action buttons (GM) whenever the
* content DOM, stream connection state, role, or completions change.
*/
import { Component, createEffect, onCleanup } from "solid-js";
import { useLocation } from "@solidjs/router";
import { useArticleDom } from "./Article";
import { journalStreamState } from "./stores/journalStream";
import { useJournalCompletions } from "./journal/completions";
import { addRevealedClasses, cleanupInjections } from "./stores/reveal";
export const RevealManager: Component = () => {
const contentDom = useArticleDom();
const location = useLocation();
const comp = useJournalCompletions();
createEffect(() => {
const dom = contentDom();
if (!dom) return;
// Access stream state reactively so the effect re-runs whenever
// connection status or role changes.
const state = journalStreamState;
void state.connected;
void state.myRole;
addRevealedClasses(dom, location.pathname, comp.data);
});
onCleanup(() => {
const dom = contentDom();
if (dom) cleanupInjections(dom);
});
return null;
};
export default RevealManager;