Files
beaver-plugin-obsidian/preview/entry.ts
T

141 lines
4.0 KiB
TypeScript

import { Component } from "obsidian";
import { mount } from "svelte";
import { PanelState } from "../src/state.svelte";
import App from "../src/ui/app.svelte";
import { BRANCH_BLASTER, DEEP_PANEL, FakeClient, MASTER } from "./fake-client";
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
// bits-ui opens menus on pointerdown and tabs on pointer or click: send both.
function press(element: Element | null | undefined): void {
if (!element) {
return;
}
element.dispatchEvent(
new PointerEvent("pointerdown", {
bubbles: true,
button: 0,
cancelable: true,
pointerType: "mouse",
})
);
(element as HTMLElement).focus();
(element as HTMLElement).click();
}
// Scenes for screenshots: open the page with a hash to land in a state.
// Width comes from the window (``--window-size``), the state from here.
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one flat scene list
async function main(): Promise<void> {
const client = new FakeClient();
const state = new PanelState();
const scene = location.hash.slice(1) || "thread";
state.selected = MASTER;
if (scene === "empty") {
state.selected = null;
}
if (scene === "question" || scene === "toggle") {
state.selected = BRANCH_BLASTER;
}
if (scene === "deep") {
state.selected = DEEP_PANEL;
}
if (scene === "offline") {
state.selected = MASTER;
}
document.body.classList.toggle("theme-light", scene.endsWith("-light"));
document.body.classList.toggle("theme-dark", !scene.endsWith("-light"));
const app = {
workspace: {
openLinkText: (target: string) => console.log("open", target),
},
};
mount(App, {
props: {
app: app as never,
chatsFolder: () => "💬 чаты",
client: scene === "offline" ? null : client,
component: new Component() as never,
onOpenSettings: () => console.log("settings"),
state,
},
target: document.getElementById("app") as HTMLElement,
});
await wait(80);
if (scene.startsWith("switcher")) {
document
.querySelector<HTMLButtonElement>('[aria-label="Switch conversation"]')
?.click();
}
if (scene.startsWith("menu")) {
const row =
document.querySelector<HTMLElement>(`[data-row="${BRANCH_BLASTER}"]`) ??
(await (async () => {
document
.querySelector<HTMLButtonElement>(
'[aria-label="Switch conversation"]'
)
?.click();
await wait(60);
return document.querySelector<HTMLElement>(
`[data-row="${BRANCH_BLASTER}"]`
);
})());
row?.dispatchEvent(
new MouseEvent("contextmenu", {
bubbles: true,
clientX: row.getBoundingClientRect().left + 120,
clientY: row.getBoundingClientRect().top + 16,
})
);
}
if (scene.startsWith("toggle")) {
press(document.querySelector('[data-slot="switch"]'));
}
if (scene.startsWith("actions")) {
press(document.querySelector('[aria-label="Conversation actions"]'));
}
if (scene.startsWith("activity")) {
for (const trigger of document.querySelectorAll<HTMLButtonElement>(
".rule-word"
)) {
if (trigger.textContent?.trim() === "Activity") {
press(trigger);
}
}
}
if (scene.startsWith("context")) {
for (const trigger of document.querySelectorAll<HTMLButtonElement>(
".rule-word"
)) {
if (trigger.textContent?.trim() === "Context") {
press(trigger);
}
}
}
if (scene.startsWith("branch")) {
document
.querySelector<HTMLButtonElement>(
'[aria-label="Branch off this conversation"]'
)
?.click();
}
await wait(60);
if (scene.startsWith("stream")) {
// A tool lands while you watch: the tree grows without a reload.
client.emit({
conversation_id: MASTER,
input: { command: "curl -sI https://b.hhhhh.dev/healthz" },
name: "Bash",
parent_tool_use_id: null,
tool_use_id: "tu_live",
turn_id: "t-run",
type: "tool",
});
}
}
main().catch(console.error);