Add scroll buttons to chat panel
This commit is contained in:
parent
526db6feb0
commit
89e57198ad
|
|
@ -39,6 +39,8 @@ export class ChatPanel {
|
||||||
customPromptIndicator: HTMLSpanElement | null = null;
|
customPromptIndicator: HTMLSpanElement | null = null;
|
||||||
currentStreamingNodeId: string | null;
|
currentStreamingNodeId: string | null;
|
||||||
stopButton: HTMLButtonElement;
|
stopButton: HTMLButtonElement;
|
||||||
|
scrollToBottomBtn: HTMLButtonElement;
|
||||||
|
scrollToTopBtn: HTMLButtonElement;
|
||||||
|
|
||||||
maxTokensInput: HTMLInputElement;
|
maxTokensInput: HTMLInputElement;
|
||||||
maxTokensResetBtn: HTMLButtonElement;
|
maxTokensResetBtn: HTMLButtonElement;
|
||||||
|
|
@ -446,6 +448,16 @@ export class ChatPanel {
|
||||||
init(): void {
|
init(): void {
|
||||||
this.container.innerHTML = `
|
this.container.innerHTML = `
|
||||||
<div class="llm-agent-chat-panel">
|
<div class="llm-agent-chat-panel">
|
||||||
|
|
||||||
|
<div class="sticky-btn-wrapper">
|
||||||
|
<button class="scroll-to-top-btn" id="scroll-to-top-btn" title="Прокрутить вверх" aria-label="Прокрутить к первому сообщению">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="19" x2="12" y2="5"></line><polyline points="5 12 12 5 19 12"></polyline></svg>
|
||||||
|
</button>
|
||||||
|
<button class="scroll-to-bottom-btn" id="scroll-to-bottom-btn" title="Прокрутить вниз" aria-label="Прокрутить к последнему сообщению">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><polyline points="19 12 12 19 5 12"></polyline></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="chat-history" id="chat-history"></div>
|
<div class="chat-history" id="chat-history"></div>
|
||||||
<div class="chat-input-container">
|
<div class="chat-input-container">
|
||||||
<div class="scroll-container">
|
<div class="scroll-container">
|
||||||
|
|
@ -506,6 +518,9 @@ export class ChatPanel {
|
||||||
this.customPromptIndicator = this.container.querySelector('#custom-prompt-indicator') as HTMLSpanElement;
|
this.customPromptIndicator = this.container.querySelector('#custom-prompt-indicator') as HTMLSpanElement;
|
||||||
this.stopButton = this.container.querySelector('#stop-button') as HTMLButtonElement;
|
this.stopButton = this.container.querySelector('#stop-button') as HTMLButtonElement;
|
||||||
|
|
||||||
|
this.scrollToTopBtn = this.container.querySelector('#scroll-to-top-btn') as HTMLButtonElement;
|
||||||
|
this.scrollToBottomBtn = this.container.querySelector('#scroll-to-bottom-btn') as HTMLButtonElement;
|
||||||
|
|
||||||
this.attachedFilesContainer = this.container.querySelector('#attached-files-container') as HTMLDivElement;
|
this.attachedFilesContainer = this.container.querySelector('#attached-files-container') as HTMLDivElement;
|
||||||
|
|
||||||
this.tempInput = this.container.querySelector('#temp-input') as HTMLInputElement;
|
this.tempInput = this.container.querySelector('#temp-input') as HTMLInputElement;
|
||||||
|
|
@ -513,7 +528,7 @@ export class ChatPanel {
|
||||||
this.maxTokensInput = this.container.querySelector('#max-tokens-input') as HTMLInputElement;
|
this.maxTokensInput = this.container.querySelector('#max-tokens-input') as HTMLInputElement;
|
||||||
this.maxTokensResetBtn = this.container.querySelector('#max-tokens-reset') as HTMLButtonElement;
|
this.maxTokensResetBtn = this.container.querySelector('#max-tokens-reset') as HTMLButtonElement;
|
||||||
|
|
||||||
const defaultTemp = (this.props.plugin.settings as any).temperatureChat ?? DEFAULT_TEMPERATURE;
|
const defaultTemp = (this.props.plugin.settings as any).temperatureChat ?? LLM_DEFAULTS.TEMPERATURE;
|
||||||
this.tempInput.value = defaultTemp.toString();
|
this.tempInput.value = defaultTemp.toString();
|
||||||
|
|
||||||
// Устанавливаем дефолтное значение для токенов
|
// Устанавливаем дефолтное значение для токенов
|
||||||
|
|
@ -597,7 +612,7 @@ export class ChatPanel {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.tempResetBtn.addEventListener('click', () => {
|
this.tempResetBtn.addEventListener('click', () => {
|
||||||
const def = (this.props.plugin.settings as any).temperatureChat ?? DEFAULT_TEMPERATURE;
|
const def = (this.props.plugin.settings as any).temperatureChat ?? LLM_DEFAULTS.TEMPERATURE;
|
||||||
this.tempInput.value = def.toString();
|
this.tempInput.value = def.toString();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -611,6 +626,22 @@ export class ChatPanel {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Логика прокрутки вверх и вниз при клике
|
||||||
|
this.scrollToTopBtn.addEventListener('click', () => {
|
||||||
|
const scrollContainer = this.container.closest('.view-content') as HTMLElement;
|
||||||
|
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
||||||
|
|
||||||
|
if (scrollContainer) scrollContainer.scrollTop = 0;
|
||||||
|
if (historyContainer) historyContainer.scrollTop = 0;
|
||||||
|
});
|
||||||
|
this.scrollToBottomBtn.addEventListener('click', () => {
|
||||||
|
const scrollContainer = this.container.closest('.view-content') as HTMLElement;
|
||||||
|
const historyContainer = this.container.querySelector('#chat-history') as HTMLElement;
|
||||||
|
|
||||||
|
if (scrollContainer) scrollContainer.scrollTop = scrollContainer.scrollHeight;
|
||||||
|
if (historyContainer) historyContainer.scrollTop = historyContainer.scrollHeight;
|
||||||
|
});
|
||||||
|
|
||||||
// Обработчики Drag-n-Drop для внешних файлов
|
// Обработчики Drag-n-Drop для внешних файлов
|
||||||
this.setupDragAndDrop();
|
this.setupDragAndDrop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-history {
|
.chat-history {
|
||||||
|
|
@ -501,6 +502,75 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------- Кнопка прокрутки чат-панели до низа --------------------------------------------------- */
|
||||||
|
|
||||||
|
/* "Липкая" обертка, которая зависает в самом верху контейнера */
|
||||||
|
.sticky-btn-wrapper {
|
||||||
|
position: sticky;
|
||||||
|
top: 14px;
|
||||||
|
z-index: 100;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column; /* Кнопки в колонку */
|
||||||
|
align-items: flex-end; /* Прижать к правому краю */
|
||||||
|
gap: 8px; /* Расстояние между кнопками */
|
||||||
|
padding-right: 14px;
|
||||||
|
height: 0;
|
||||||
|
width: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Добавить общий стиль для обеих кнопок и специфичный для новой */
|
||||||
|
.scroll-to-bottom-btn,
|
||||||
|
.scroll-to-top-btn {
|
||||||
|
pointer-events: auto;
|
||||||
|
border: 2px solid var(--background-primary);
|
||||||
|
border-radius: 50%;
|
||||||
|
|
||||||
|
/* Жестко задаем размеры (например, 40px) */
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
min-width: 40px;
|
||||||
|
min-height: 40px;
|
||||||
|
|
||||||
|
/* Запрещаем flexbox сжимать эти элементы */
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
|
/* Сбрасываем стандартные паддинги Obsidian */
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
color: white;
|
||||||
|
background-color: var(--button-secondary-background); /* По умолчанию тусклее */
|
||||||
|
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-to-bottom-btn:hover,
|
||||||
|
.scroll-to-top-btn:hover {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1.1);
|
||||||
|
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
|
||||||
|
background-color: var(--button-primary-background) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scroll-to-bottom-btn:active,
|
||||||
|
.scroll-to-top-btn:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Иконки кнопок */
|
||||||
|
.scroll-to-bottom-btn svg,
|
||||||
|
.scroll-to-top-btn svg {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
stroke-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------- Reference System Styles --------------------------------------------------- */
|
/* ----------------------------------------------- Reference System Styles --------------------------------------------------- */
|
||||||
|
|
||||||
/* Reference Boxes */
|
/* Reference Boxes */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user