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 currentReferences: FileReference[] = [];
|
||||||
private isProcessingReference = false;
|
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) {
|
constructor(container: HTMLElement, props: ChatPanelProps) {
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.props = props;
|
this.props = props;
|
||||||
|
|
@ -429,6 +435,11 @@ export class ChatPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
|
if (this.scrollDebounceTimer !== null) {
|
||||||
|
window.clearTimeout(this.scrollDebounceTimer);
|
||||||
|
}
|
||||||
|
if (this.resizeObserver) this.resizeObserver.disconnect();
|
||||||
|
|
||||||
if (this.referenceAutocomplete) {
|
if (this.referenceAutocomplete) {
|
||||||
this.referenceAutocomplete.destroy();
|
this.referenceAutocomplete.destroy();
|
||||||
}
|
}
|
||||||
|
|
@ -652,6 +663,8 @@ export class ChatPanel {
|
||||||
|
|
||||||
// Обработчики Drag-n-Drop для внешних файлов
|
// Обработчики Drag-n-Drop для внешних файлов
|
||||||
this.setupDragAndDrop();
|
this.setupDragAndDrop();
|
||||||
|
|
||||||
|
this.setupScrollObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------- Reference Processing ---------------------------------------------------------------
|
// ----------------------------------------------- Reference Processing ---------------------------------------------------------------
|
||||||
|
|
@ -1360,4 +1373,64 @@ export class ChatPanel {
|
||||||
new Notice(`Прикреплено файлов: ${addedCount}`, 2000);
|
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 {
|
.stop-button, .submit-button {
|
||||||
padding: 4px 8px; /* Восстанавливаем паддинг */
|
padding: 4px 10px; /* Восстанавливаем паддинг */
|
||||||
border: none; /* Убираем рамку */
|
border: none; /* Убираем рамку */
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -518,6 +518,17 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
flex-shrink: 0;
|
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