Fix model selection dropdown
This commit is contained in:
parent
29cddbcb57
commit
23b4ca4571
|
|
@ -4,7 +4,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ChatHistoryItem } from './models/ChatHistoryItem';
|
import { ChatHistoryItem } from './models/ChatHistoryItem';
|
||||||
|
|
||||||
import { AutocompleteManager } from '../references/AutocompleteManager';
|
import { AutocompleteManager } from '../references/AutocompleteManager';
|
||||||
import { ReferenceAutocomplete } from '../references/ReferenceAutocomplete';
|
import { ReferenceAutocomplete } from '../references/ReferenceAutocomplete';
|
||||||
import { ReferenceExpander } from '../references/ReferenceExpander';
|
import { ReferenceExpander } from '../references/ReferenceExpander';
|
||||||
|
|
@ -81,30 +80,35 @@ export class ChatPanel {
|
||||||
// Показываем дропдаун, чтобы получить его размеры и положение
|
// Показываем дропдаун, чтобы получить его размеры и положение
|
||||||
this.modelDropdown.style.display = 'block';
|
this.modelDropdown.style.display = 'block';
|
||||||
|
|
||||||
const modelSelectButtonRect = this.modelSelectButton.getBoundingClientRect();
|
const container = this.modelSelectButton.closest('.chat-input-container') as HTMLElement;
|
||||||
const modelDropdownRect = this.modelDropdown.getBoundingClientRect();
|
|
||||||
const chatPanelRect = this.container.getBoundingClientRect(); // Общие границы чат-панели
|
|
||||||
const viewportHeight = window.innerHeight || document.documentElement.clientHeight;
|
|
||||||
|
|
||||||
// ----------------------------------------------- Секция логики позиционирования дропдауна ----------------------------------------------------
|
const modelSelectButtonRect = this.modelSelectButton.getBoundingClientRect();
|
||||||
// Позиция относительно контейнера chatPanel (или inputElement)
|
const containerRect = container.getBoundingClientRect(); // Общие границы чат-панели
|
||||||
let top = modelSelectButtonRect.bottom - chatPanelRect.top + 4; // Отступ 4px от кнопки
|
const dropdownRect = this.modelDropdown.getBoundingClientRect();
|
||||||
let left = modelSelectButtonRect.left - chatPanelRect.left;
|
const viewportHeight = window.innerHeight;
|
||||||
|
|
||||||
|
// Позиция относительно контейнера chatPanel
|
||||||
|
// Левый край дропдауна совпадает с левым краем кнопки выбора модели
|
||||||
|
let left = modelSelectButtonRect.left - containerRect.left - 5;
|
||||||
|
|
||||||
|
// Дефолтное положение - под кнопкой
|
||||||
|
let top = modelSelectButtonRect.height;
|
||||||
|
|
||||||
// Проверяем, помещается ли dropdown снизу
|
// Проверяем, помещается ли dropdown снизу
|
||||||
const spaceBelow = viewportHeight - modelSelectButtonRect.bottom;
|
const spaceBelow = viewportHeight - modelSelectButtonRect.bottom;
|
||||||
const spaceAbove = modelSelectButtonRect.top;
|
const spaceAbove = modelSelectButtonRect.top;
|
||||||
|
|
||||||
if (spaceBelow < modelDropdownRect.height + 10 && spaceAbove > modelDropdownRect.height + 10) {
|
if (spaceBelow < dropdownRect.height + 10 && spaceAbove > dropdownRect.height + 10) {
|
||||||
// Если снизу мало места и сверху достаточно, размещаем сверху
|
// Если снизу мало места и сверху достаточно, размещаем сверху
|
||||||
top = modelSelectButtonRect.top - chatPanelRect.top - modelDropdownRect.height - 4; // Отступ 4px от кнопки
|
top = - dropdownRect.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Убедимся, что дропдаун не выходит за границы контейнера справа
|
// Убедимся, что дропдаун не выходит за границы контейнера справа
|
||||||
const maxRight = chatPanelRect.width;
|
const maxRight = containerRect.right - containerRect.left;
|
||||||
if (left + modelDropdownRect.width > maxRight) {
|
if (left + dropdownRect.width > maxRight) {
|
||||||
left = maxRight - modelDropdownRect.width;
|
left = maxRight - dropdownRect.width - 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Убедимся, что дропдаун не выходит за границы контейнера слева
|
// Убедимся, что дропдаун не выходит за границы контейнера слева
|
||||||
if (left < 0) {
|
if (left < 0) {
|
||||||
left = 0;
|
left = 0;
|
||||||
|
|
@ -113,7 +117,11 @@ export class ChatPanel {
|
||||||
this.modelDropdown.style.top = `${top}px`;
|
this.modelDropdown.style.top = `${top}px`;
|
||||||
this.modelDropdown.style.left = `${left}px`;
|
this.modelDropdown.style.left = `${left}px`;
|
||||||
this.modelDropdown.style.right = 'auto'; // Сброс right, чтобы left работал корректно
|
this.modelDropdown.style.right = 'auto'; // Сброс right, чтобы left работал корректно
|
||||||
// ----------------------------------------------- End of Секция логики позиционирования дропдауна ---------------------------------------------
|
|
||||||
|
// ДОБАВЛЕНО: Устанавливаем минимальную ширину дропдауна, равную ширине кнопки
|
||||||
|
let minWidth = Math.min(containerRect.width / 2, dropdownRect.width);
|
||||||
|
this.modelDropdown.style.minWidth = `${minWidth}px`;
|
||||||
|
this.modelDropdown.style.width = 'auto'; // Позволяем контенту определить ширину, но не меньше minWidth
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModelDropdown(): void {
|
updateModelDropdown(): void {
|
||||||
|
|
@ -462,7 +470,7 @@ export class ChatPanel {
|
||||||
const { startNode, startOffset, endNode, endOffset } = this.findNodesAndOffsetsForMatch(match);
|
const { startNode, startOffset, endNode, endOffset } = this.findNodesAndOffsetsForMatch(match);
|
||||||
|
|
||||||
if (!startNode || !endNode) {
|
if (!startNode || !endNode) {
|
||||||
console.error("Не удалось найти узлы для замены ссылки", match);
|
console.error('Не удалось найти узлы для замены ссылки', match);
|
||||||
this.isProcessingReference = false;
|
this.isProcessingReference = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -492,10 +500,10 @@ export class ChatPanel {
|
||||||
* @returns Объект с startNode, startOffset, endNode, endOffset.
|
* @returns Объект с startNode, startOffset, endNode, endOffset.
|
||||||
*/
|
*/
|
||||||
private findNodesAndOffsetsForMatch(match: ReferenceMatch): {
|
private findNodesAndOffsetsForMatch(match: ReferenceMatch): {
|
||||||
startNode: Node | null,
|
startNode: Node | null;
|
||||||
startOffset: number,
|
startOffset: number;
|
||||||
endNode: Node | null,
|
endNode: Node | null;
|
||||||
endOffset: number
|
endOffset: number;
|
||||||
} {
|
} {
|
||||||
let startNode: Node | null = null;
|
let startNode: Node | null = null;
|
||||||
let startOffset = 0;
|
let startOffset = 0;
|
||||||
|
|
@ -531,7 +539,6 @@ export class ChatPanel {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
currentLength += nodeTextLength;
|
currentLength += nodeTextLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,7 +550,6 @@ export class ChatPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return { startNode, startOffset, endNode, endOffset };
|
return { startNode, startOffset, endNode, endOffset };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -591,7 +597,6 @@ export class ChatPanel {
|
||||||
selection.addRange(range);
|
selection.addRange(range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Заменяет текст на HTML элемент
|
* Заменяет текст на HTML элемент
|
||||||
*/
|
*/
|
||||||
|
|
@ -624,7 +629,7 @@ export class ChatPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nodeBeforeMatch) {
|
if (!nodeBeforeMatch) {
|
||||||
console.warn("Не удалось найти текстовый узел для начала замены.");
|
console.warn('Не удалось найти текстовый узел для начала замены.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -652,7 +657,6 @@ export class ChatPanel {
|
||||||
deleteRange.setEnd(currentNode || nodeBeforeMatch, currentOffset);
|
deleteRange.setEnd(currentNode || nodeBeforeMatch, currentOffset);
|
||||||
deleteRange.deleteContents();
|
deleteRange.deleteContents();
|
||||||
|
|
||||||
|
|
||||||
// Вставляем новый элемент на место удаленного текста
|
// Вставляем новый элемент на место удаленного текста
|
||||||
deleteRange.insertNode(element);
|
deleteRange.insertNode(element);
|
||||||
|
|
||||||
|
|
@ -778,9 +782,7 @@ export class ChatPanel {
|
||||||
} else if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).classList.contains('reference-box')) {
|
} else if (node.nodeType === Node.ELEMENT_NODE && (node as HTMLElement).classList.contains('reference-box')) {
|
||||||
const reference = ReferenceBox.extractReference(node as HTMLElement);
|
const reference = ReferenceBox.extractReference(node as HTMLElement);
|
||||||
if (reference) {
|
if (reference) {
|
||||||
const prefix = reference.permanent
|
const prefix = reference.permanent ? (reference.type === 'file' ? '@@' : '##') : reference.type === 'file' ? '@' : '#';
|
||||||
? reference.type === 'file' ? '@@' : '##'
|
|
||||||
: reference.type === 'file' ? '@' : '#';
|
|
||||||
result += prefix + reference.name;
|
result += prefix + reference.name;
|
||||||
}
|
}
|
||||||
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
} else if (node.nodeType === Node.ELEMENT_NODE) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user