Fix bug with scroll buttons visibility when no scroller in chat panel
This commit is contained in:
parent
9aefdaaa69
commit
cdf45430aa
|
|
@ -63,6 +63,12 @@ export class ChatPanel {
|
|||
private currentReferences: FileReference[] = [];
|
||||
private isProcessingReference = false;
|
||||
|
||||
// Свойства для обсерверов прокрутки
|
||||
private resizeObserver: ResizeObserver | null = null;
|
||||
private scrollDebounceTimer: number | null = null; // Таймер для debounce
|
||||
private cachedScrollContainer: HTMLElement | null = null;
|
||||
private cachedBtnWrapper: HTMLElement | null = null;
|
||||
|
||||
constructor(container: HTMLElement, props: ChatPanelProps) {
|
||||
this.container = container;
|
||||
this.props = props;
|
||||
|
|
@ -429,6 +435,11 @@ export class ChatPanel {
|
|||
}
|
||||
|
||||
destroy(): void {
|
||||
if (this.scrollDebounceTimer !== null) {
|
||||
window.clearTimeout(this.scrollDebounceTimer);
|
||||
}
|
||||
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||
|
||||
if (this.referenceAutocomplete) {
|
||||
this.referenceAutocomplete.destroy();
|
||||
}
|
||||
|
|
@ -652,6 +663,8 @@ export class ChatPanel {
|
|||
|
||||
// Обработчики Drag-n-Drop для внешних файлов
|
||||
this.setupDragAndDrop();
|
||||
|
||||
this.setupScrollObservers();
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Reference Processing ---------------------------------------------------------------
|
||||
|
|
@ -1360,4 +1373,64 @@ export class ChatPanel {
|
|||
new Notice(`Прикреплено файлов: ${addedCount}`, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Scroll Observers ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Настраивает наблюдатели за размерами окна и внутренним контентом чата
|
||||
*/
|
||||
private setupScrollObservers(): void {
|
||||
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
||||
this.cachedScrollContainer = this.container.closest('.view-content') as HTMLElement;
|
||||
this.cachedBtnWrapper = this.container.querySelector('.sticky-btn-wrapper') as HTMLElement;
|
||||
|
||||
if (!this.cachedScrollContainer || !this.cachedBtnWrapper) return;
|
||||
|
||||
// Оставляем только ResizeObserver.
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
this.scheduleDebouncedScrollUpdate();
|
||||
});
|
||||
|
||||
// Следим за родителем (ресайз панелей)
|
||||
this.resizeObserver.observe(this.cachedScrollContainer);
|
||||
|
||||
// Следим за контентом (чтобы поймать появление overlay-скроллбаров на Mac)
|
||||
if (historyContainer) {
|
||||
this.resizeObserver.observe(historyContainer);
|
||||
}
|
||||
|
||||
// Проверяем состояние при инициализации
|
||||
setTimeout(() => this.updateScrollButtonsVisibility(), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Схлопывает частые вызовы событий (debounce)
|
||||
*/
|
||||
private scheduleDebouncedScrollUpdate(): void {
|
||||
if (this.scrollDebounceTimer !== null) {
|
||||
window.clearTimeout(this.scrollDebounceTimer);
|
||||
}
|
||||
|
||||
// Запускаем перерасчет только если изменения "затихли" на 200мс
|
||||
this.scrollDebounceTimer = window.setTimeout(() => {
|
||||
this.updateScrollButtonsVisibility();
|
||||
this.scrollDebounceTimer = null;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет наличие скроллбара на родительском элементе и скрывает/показывает кнопки
|
||||
*/
|
||||
private updateScrollButtonsVisibility(): void {
|
||||
if (!this.cachedScrollContainer || !this.cachedBtnWrapper) return;
|
||||
|
||||
// DOM больше не сканируется через closest/querySelector, элементы закэшированы
|
||||
const hasScrollbar = this.cachedScrollContainer.scrollHeight > (this.cachedScrollContainer.clientHeight + 2);
|
||||
|
||||
if (hasScrollbar) {
|
||||
this.cachedBtnWrapper.classList.add('is-visible');
|
||||
} else {
|
||||
this.cachedBtnWrapper.classList.remove('is-visible');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@
|
|||
}
|
||||
|
||||
.stop-button, .submit-button {
|
||||
padding: 4px 8px; /* Восстанавливаем паддинг */
|
||||
padding: 4px 10px; /* Восстанавливаем паддинг */
|
||||
border: none; /* Убираем рамку */
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
|
|
@ -518,6 +518,17 @@
|
|||
width: 100%;
|
||||
pointer-events: none;
|
||||
flex-shrink: 0;
|
||||
|
||||
/* Скрываем по умолчанию */
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease;
|
||||
}
|
||||
|
||||
/* Класс, который добавляется JS, когда есть скролл */
|
||||
.sticky-btn-wrapper.is-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* Добавить общий стиль для обеих кнопок и специфичный для новой */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user