mirror of
https://github.com/logancyang/obsidian-copilot.git
synced 2026-07-22 07:50:24 +00:00
fix(chat): keep status-bar clearance in sync so bottom-right banners can't cover the input
The desktop chat input reserves space for Obsidian's bottom-right status bar via the `--copilot-status-bar-clearance` variable, but `ChatViewLayout` only re-measured the overlap on `css-change`. When a core or plugin status-bar item appears or grows at runtime (update-available notice, sync status, ...) the bar can get taller without a `css-change` event, so the stale clearance let the banner overlap the chat input and its send button. Attach a ResizeObserver to the status bar so any size change re-runs the measurement. This stays generalizable: it measures the bar's geometry rather than hardcoding any specific banner or plugin, and rebinds across theme reloads that swap the element. Mobile is unaffected (the whole mechanism early-returns on mobile). Closes #99 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7261171638
commit
56c19b3aae
1 changed files with 28 additions and 0 deletions
|
|
@ -12,6 +12,8 @@ const CSS_CHANGE_DEBOUNCE_MS = 600;
|
|||
export class ChatViewLayout {
|
||||
private debounceTimer: number | null = null;
|
||||
private cssChangeRef: ReturnType<Workspace["on"]> | null = null;
|
||||
private statusBarResizeObserver: ResizeObserver | null = null;
|
||||
private observedStatusBar: HTMLElement | null = null;
|
||||
|
||||
constructor(
|
||||
private containerEl: HTMLElement,
|
||||
|
|
@ -32,6 +34,9 @@ export class ChatViewLayout {
|
|||
this.workspace.offref(this.cssChangeRef);
|
||||
this.cssChangeRef = null;
|
||||
}
|
||||
this.statusBarResizeObserver?.disconnect();
|
||||
this.statusBarResizeObserver = null;
|
||||
this.observedStatusBar = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -43,6 +48,14 @@ export class ChatViewLayout {
|
|||
* reflow so nothing flickers. Themes that already position content above
|
||||
* the status bar (no overlap) get 0 clearance automatically. Auto-hide
|
||||
* themes (opacity: 0) also get 0 since the bar is transparent.
|
||||
*
|
||||
* The desktop status bar lives in the bottom-right and hosts core and
|
||||
* plugin items (update-available notice, sync status, word count, ...).
|
||||
* When one of those appears or grows -- making the bar taller, e.g. items
|
||||
* wrap to a second line -- the overlap changes without a `css-change`
|
||||
* event, so a ResizeObserver on the bar keeps the clearance in sync and
|
||||
* the chat input from being covered. Measuring the bar's geometry stays
|
||||
* generalizable: no specific banner or plugin is hardcoded.
|
||||
*/
|
||||
private setupStatusBarClearance(): void {
|
||||
if (Platform.isMobile) return;
|
||||
|
|
@ -53,6 +66,8 @@ export class ChatViewLayout {
|
|||
const viewContent = this.containerEl.querySelector<HTMLElement>(".view-content");
|
||||
if (!statusBar || !viewContent) return;
|
||||
|
||||
this.observeStatusBar(statusBar, syncClearance);
|
||||
|
||||
// Zero out clearance and force reflow to measure natural overlap.
|
||||
// Remove any inline override left from a prior run so the CSS default
|
||||
// (0px) applies and the resulting rect reflects the natural overlap.
|
||||
|
|
@ -81,4 +96,17 @@ export class ChatViewLayout {
|
|||
this.debounceTimer = window.setTimeout(syncClearance, CSS_CHANGE_DEBOUNCE_MS);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep a single ResizeObserver pointed at the current status bar element so
|
||||
* runtime size changes re-trigger a measurement. Rebinds when the element is
|
||||
* replaced (e.g. after a theme reload swaps the DOM); a no-op otherwise.
|
||||
*/
|
||||
private observeStatusBar(statusBar: HTMLElement, onResize: () => void): void {
|
||||
if (this.observedStatusBar === statusBar) return;
|
||||
this.statusBarResizeObserver?.disconnect();
|
||||
this.statusBarResizeObserver = new ResizeObserver(() => onResize());
|
||||
this.statusBarResizeObserver.observe(statusBar);
|
||||
this.observedStatusBar = statusBar;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue