Add new branch button to chat panel

This commit is contained in:
dimitrievgs 2026-06-03 23:25:25 +03:00
parent 0acd67ee57
commit f1dff8f855
2 changed files with 24 additions and 6 deletions

View File

@ -38,6 +38,8 @@ export class ChatPanel {
selectedModel: string;
customPromptIndicator: HTMLSpanElement | null = null;
currentStreamingNodeId: string | null;
branchChatBtn: HTMLButtonElement;
stopButton: HTMLButtonElement;
scrollToBottomBtn: HTMLButtonElement;
scrollToTopBtn: HTMLButtonElement;
@ -457,6 +459,7 @@ export class ChatPanel {
async updateHistory(newHistory: ChatHistoryItem[]): Promise<void> {
this.chatHistory = newHistory;
await this.renderHistory();
this.updateScrollButtonsVisibility(); // НОВОЕ: проверяем видимость кнопок
}
/**
@ -614,6 +617,10 @@ export class ChatPanel {
<div class="llm-agent-chat-panel">
<div class="sticky-btn-wrapper">
<button class="branch-chat-btn" id="branch-chat-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" class="lucide lucide-git-branch"><line x1="6" x2="6" y1="3" y2="15"></line><circle cx="18" cy="6" r="3"></circle><circle cx="6" cy="18" r="3"></circle><path d="M18 9a9 9 0 0 1-9 9"></path></svg>
</button>
<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>
@ -698,8 +705,9 @@ export class ChatPanel {
this.modelSelectButton = this.container.querySelector('#model-select-button') as HTMLButtonElement;
this.modelDropdown = this.container.querySelector('#model-dropdown') as HTMLDivElement;
this.customPromptIndicator = this.container.querySelector('#custom-prompt-indicator') as HTMLSpanElement;
this.stopButton = this.container.querySelector('#stop-button') as HTMLButtonElement;
this.branchChatBtn = this.container.querySelector('#branch-chat-btn') 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;
@ -813,6 +821,10 @@ export class ChatPanel {
this.props.plugin.eventBus.emit('stop-all-streams');
});
this.branchChatBtn.addEventListener('click', () => {
this.props.plugin.eventBus.emit('start-new-independent-chat');
});
// Подписка на изменение стримов
this.props.plugin.eventBus.on('global-stream-state-changed', (isStreaming: boolean) => {
this.hasGlobalStreams = isStreaming;
@ -1730,14 +1742,16 @@ export class ChatPanel {
if (!this.cachedScrollContainer || !this.cachedBtnWrapper) return;
const hasScrollbar = this.cachedScrollContainer.scrollHeight > (this.cachedScrollContainer.clientHeight + 2);
const hasHistory = this.chatHistory && this.chatHistory.length > 0;
// Управляем видимостью кнопок скролла (скрываем их индивидуально)
this.scrollToTopBtn.style.display = hasScrollbar ? 'flex' : 'none';
this.scrollToBottomBtn.style.display = hasScrollbar ? 'flex' : 'none';
this.globalStopBtn.style.display = this.hasGlobalStreams ? 'flex' : 'none';
this.branchChatBtn.style.display = hasHistory ? 'flex' : 'none';
// Обертка видна, если есть либо скроллбар, либо активный стрим
if (hasScrollbar || this.hasGlobalStreams) {
if (hasScrollbar || this.hasGlobalStreams || hasHistory) {
this.cachedBtnWrapper.classList.add('is-visible');
} else {
this.cachedBtnWrapper.classList.remove('is-visible');

View File

@ -528,7 +528,8 @@
/* Добавить общий стиль для обеих кнопок и специфичный для новой */
.scroll-to-bottom-btn,
.scroll-to-top-btn {
.scroll-to-top-btn,
.branch-chat-btn {
pointer-events: auto;
border: 2px solid var(--background-primary);
border-radius: 50%;
@ -557,7 +558,8 @@
}
.scroll-to-bottom-btn:hover,
.scroll-to-top-btn:hover {
.scroll-to-top-btn:hover,
.branch-chat-btn:hover {
opacity: 1;
transform: scale(1.1);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
@ -565,13 +567,15 @@
}
.scroll-to-bottom-btn:active,
.scroll-to-top-btn:active {
.scroll-to-top-btn:active,
.branch-chat-btn:active {
transform: scale(0.95);
}
/* Иконки кнопок */
.scroll-to-bottom-btn svg,
.scroll-to-top-btn svg {
.scroll-to-top-btn svg,
.branch-chat-btn svg {
width: 18px;
height: 18px;
stroke-width: 3px;