mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import { Platform } from "obsidian";
|
|
|
|
/**
|
|
* Mobile-keyboard + drawer-hide observers shared by chat views (regular and
|
|
* agent). Pure DOM/lifecycle utilities — no chat-specific state.
|
|
*
|
|
* On mobile, when the soft keyboard opens we want to hide drawer chrome
|
|
* (header/tab options) by toggling a class on the surrounding workspace
|
|
* drawer; and when the drawer is hidden by Obsidian (e.g. user pressed back),
|
|
* any open Radix popover anchored inside this view needs to close so it
|
|
* doesn't jump to (0,0).
|
|
*
|
|
* Returns:
|
|
* - `dispose`: call from the view's `onClose` to unbind everything.
|
|
* - `rebindDrawerObserver`: the view can be moved between drawers without
|
|
* `onOpen` firing again; call this from a `layout-change` handler so the
|
|
* drawer-hide observer always watches the correct drawer.
|
|
*/
|
|
export function attachChatViewLayoutObservers(containerEl: HTMLElement): {
|
|
dispose: () => void;
|
|
rebindDrawerObserver: () => void;
|
|
} {
|
|
if (!Platform.isMobile) {
|
|
return { dispose: () => {}, rebindDrawerObserver: () => {} };
|
|
}
|
|
|
|
let lastDrawerEl: HTMLElement | null = null;
|
|
let drawerHideObserver: MutationObserver | null = null;
|
|
|
|
const syncKeyboardClass = () => {
|
|
const drawer = containerEl.closest<HTMLElement>(".workspace-drawer");
|
|
if (lastDrawerEl && lastDrawerEl !== drawer) {
|
|
lastDrawerEl.classList.remove("copilot-keyboard-open");
|
|
}
|
|
lastDrawerEl = drawer;
|
|
if (!drawer) return;
|
|
|
|
const isCopilotActive = !!containerEl.closest(".workspace-drawer-active-tab-content");
|
|
const kbHeight = parseFloat(
|
|
containerEl.doc.documentElement.style.getPropertyValue("--keyboard-height") || "0"
|
|
);
|
|
drawer.classList.toggle("copilot-keyboard-open", isCopilotActive && kbHeight > 0);
|
|
};
|
|
|
|
const keyboardObserver = new MutationObserver(syncKeyboardClass);
|
|
keyboardObserver.observe(containerEl.doc.documentElement, {
|
|
attributes: true,
|
|
attributeFilter: ["style"],
|
|
});
|
|
syncKeyboardClass();
|
|
|
|
const rebindDrawerObserver = () => {
|
|
drawerHideObserver?.disconnect();
|
|
const drawer = containerEl.closest(".workspace-drawer");
|
|
if (!drawer) return;
|
|
|
|
let wasHidden = drawer.classList.contains("is-hidden");
|
|
drawerHideObserver = new MutationObserver(() => {
|
|
const isHidden = drawer.classList.contains("is-hidden");
|
|
if (isHidden && !wasHidden) {
|
|
containerEl.dispatchEvent(
|
|
new KeyboardEvent("keydown", { key: "Escape", bubbles: true, cancelable: true })
|
|
);
|
|
}
|
|
wasHidden = isHidden;
|
|
});
|
|
drawerHideObserver.observe(drawer, { attributes: true, attributeFilter: ["class"] });
|
|
};
|
|
rebindDrawerObserver();
|
|
|
|
const dispose = () => {
|
|
keyboardObserver.disconnect();
|
|
drawerHideObserver?.disconnect();
|
|
lastDrawerEl?.classList.remove("copilot-keyboard-open");
|
|
lastDrawerEl = null;
|
|
};
|
|
|
|
return { dispose, rebindDrawerObserver };
|
|
}
|