Add buttons to scroll to start of message and copy text of message
This commit is contained in:
parent
58eff747a4
commit
9ae3256c35
|
|
@ -1,5 +1,5 @@
|
||||||
import LLMAgentPlugin from 'main';
|
import LLMAgentPlugin from 'main';
|
||||||
import { MarkdownRenderer } from 'obsidian';
|
import { MarkdownRenderer, setIcon, Notice } from 'obsidian';
|
||||||
|
|
||||||
export class VoicePanel {
|
export class VoicePanel {
|
||||||
private activeTab: 'res1' | 'res2' | 'trans' = 'res1';
|
private activeTab: 'res1' | 'res2' | 'trans' = 'res1';
|
||||||
|
|
@ -77,6 +77,7 @@ export class VoicePanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.activeTab === 'trans') {
|
if (this.activeTab === 'trans') {
|
||||||
|
// Для транскрибации оставляем простой текст, так как она меняется постоянно
|
||||||
if (body.innerText !== data.transcription) {
|
if (body.innerText !== data.transcription) {
|
||||||
body.innerText = data.transcription || '';
|
body.innerText = data.transcription || '';
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +108,7 @@ export class VoicePanel {
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
// Создаем контейнер
|
// Создаем контейнер
|
||||||
const msgContainer = document.createElement('div');
|
const msgContainer = document.createElement('div');
|
||||||
msgContainer.addClass('voice-message-block', 'markdown-rendered');
|
msgContainer.addClass('voice-message-block', 'markdown-rendered', 'group/turn-messages'); // Добавлен класс group для hover-эффекта
|
||||||
msgContainer.setAttr('data-id', entry.id);
|
msgContainer.setAttr('data-id', entry.id);
|
||||||
|
|
||||||
// Добавляем В НАЧАЛО контейнера
|
// Добавляем В НАЧАЛО контейнера
|
||||||
|
|
@ -116,9 +117,49 @@ export class VoicePanel {
|
||||||
// Рендерим Markdown
|
// Рендерим Markdown
|
||||||
await MarkdownRenderer.renderMarkdown(entry.content, msgContainer, '', this.plugin);
|
await MarkdownRenderer.renderMarkdown(entry.content, msgContainer, '', this.plugin);
|
||||||
|
|
||||||
// Если нужно добавить разделитель (hr), в такой логике его проще
|
// ДОБАВЛЯЕМ КНОПКИ (Copy и Scroll to Top)
|
||||||
// добавить стилями CSS (border-bottom), либо вставлять внутрь msgContainer
|
this.createVoiceMessageToolset(msgContainer, entry.content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createVoiceMessageToolset(messageElement: HTMLElement, content: string): void {
|
||||||
|
const toolsetContainer = messageElement.createDiv({
|
||||||
|
cls: 'voice-message-toolset'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Кнопка "Копировать"
|
||||||
|
const copyButton = toolsetContainer.createEl('button', {
|
||||||
|
cls: 'voice-tool-btn',
|
||||||
|
attr: { 'aria-label': 'Копировать всё' }
|
||||||
|
});
|
||||||
|
const copyIconContainer = copyButton.createSpan();
|
||||||
|
setIcon(copyIconContainer, 'copy');
|
||||||
|
|
||||||
|
copyButton.addEventListener('click', async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(content);
|
||||||
|
setIcon(copyIconContainer, 'check');
|
||||||
|
setTimeout(() => setIcon(copyIconContainer, 'copy'), 1000);
|
||||||
|
} catch (err) {
|
||||||
|
new Notice('Ошибка копирования');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Кнопка "Наверх" (перемотка к началу сообщения)
|
||||||
|
const scrollToTopButton = toolsetContainer.createEl('button', {
|
||||||
|
cls: 'voice-tool-btn',
|
||||||
|
attr: { 'aria-label': 'К началу сообщения' }
|
||||||
|
});
|
||||||
|
const scrollIconContainer = scrollToTopButton.createSpan();
|
||||||
|
setIcon(scrollIconContainer, 'arrow-up');
|
||||||
|
|
||||||
|
scrollToTopButton.addEventListener('click', () => {
|
||||||
|
// Используем встроенный метод scrollIntoView для точного позиционирования
|
||||||
|
messageElement.scrollIntoView({
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'start' // Прокрутить так, чтобы начало элемента совпало с верхом контейнера
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -833,12 +833,43 @@
|
||||||
border-bottom: 1px solid var(--background-modifier-border);
|
border-bottom: 1px solid var(--background-modifier-border);
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
position: relative; /* Для позиционирования тулсета */
|
||||||
|
scroll-margin-top: 10px;
|
||||||
}
|
}
|
||||||
/* Чтобы у последнего сообщения (самого нижнего) не было линии */
|
/* Чтобы у последнего сообщения (самого нижнего) не было линии */
|
||||||
.voice-message-block:last-child {
|
.voice-message-block:last-child {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.voice-message-toolset {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
margin-top: 8px;
|
||||||
|
transition: opacity 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.voice-tool-btn {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: var(--text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.voice-tool-btn:hover {
|
||||||
|
background-color: var(--background-modifier-hover);
|
||||||
|
color: var(--text-normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
.voice-tool-btn svg {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
.v-tabs {
|
.v-tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2px;
|
gap: 2px;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user