Add parameters for visible and total items of autocomplete dropdown for @ and #
This commit is contained in:
parent
bc9424877c
commit
29cddbcb57
|
|
@ -671,13 +671,17 @@
|
||||||
|
|
||||||
/* Reference Autocomplete */
|
/* Reference Autocomplete */
|
||||||
.reference-autocomplete {
|
.reference-autocomplete {
|
||||||
|
/* 200px для 5 элементов, возможно, нужно заменить на расчёт с помощью padding и размером шрифта */
|
||||||
|
--item-height: 33px; /* высота одного элемента */
|
||||||
|
--visible-items: 10; /* количество видимых элементов */
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: var(--background-primary);
|
background: var(--background-primary);
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
max-height: 200px;
|
max-height: calc(var(--item-height) * var(--visible-items));
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
min-width: 250px;
|
min-width: 250px;
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,11 @@ export class AutocompleteManager {
|
||||||
private lastCacheUpdate = 0;
|
private lastCacheUpdate = 0;
|
||||||
private readonly CACHE_TTL = 30000; // 30 секунд
|
private readonly CACHE_TTL = 30000; // 30 секунд
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property {number} MAX_TOTAL_ITEMS Максимальное количество элементов для поиска и кэширования.
|
||||||
|
*/
|
||||||
|
static MAX_TOTAL_ITEMS = 20;
|
||||||
|
|
||||||
constructor(plugin: LLMAgentPlugin) {
|
constructor(plugin: LLMAgentPlugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.setupFileWatcher();
|
this.setupFileWatcher();
|
||||||
|
|
@ -49,13 +54,13 @@ export class AutocompleteManager {
|
||||||
const allFiles = this.fileCache.get('all') || [];
|
const allFiles = this.fileCache.get('all') || [];
|
||||||
|
|
||||||
if (!query.trim()) {
|
if (!query.trim()) {
|
||||||
return allFiles.slice(0, 10); // Показываем первые 10 файлов
|
return allFiles.slice(0, AutocompleteManager.MAX_TOTAL_ITEMS); // Показываем первые 10 файлов
|
||||||
}
|
}
|
||||||
|
|
||||||
const lowercaseQuery = query.toLowerCase();
|
const lowercaseQuery = query.toLowerCase();
|
||||||
return allFiles
|
return allFiles
|
||||||
.filter((item) => item.name.toLowerCase().includes(lowercaseQuery) || item.path.toLowerCase().includes(lowercaseQuery))
|
.filter((item) => item.name.toLowerCase().includes(lowercaseQuery) || item.path.toLowerCase().includes(lowercaseQuery))
|
||||||
.slice(0, 10);
|
.slice(0, AutocompleteManager.MAX_TOTAL_ITEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -73,13 +78,13 @@ export class AutocompleteManager {
|
||||||
const allPrompts = this.promptCache.get('all') || [];
|
const allPrompts = this.promptCache.get('all') || [];
|
||||||
|
|
||||||
if (!query.trim()) {
|
if (!query.trim()) {
|
||||||
return allPrompts.slice(0, 10);
|
return allPrompts.slice(0, AutocompleteManager.MAX_TOTAL_ITEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
const lowercaseQuery = query.toLowerCase();
|
const lowercaseQuery = query.toLowerCase();
|
||||||
return allPrompts
|
return allPrompts
|
||||||
.filter((item) => item.name.toLowerCase().includes(lowercaseQuery) || item.path.toLowerCase().includes(lowercaseQuery))
|
.filter((item) => item.name.toLowerCase().includes(lowercaseQuery) || item.path.toLowerCase().includes(lowercaseQuery))
|
||||||
.slice(0, 10);
|
.slice(0, AutocompleteManager.MAX_TOTAL_ITEMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -107,59 +112,58 @@ export class AutocompleteManager {
|
||||||
/**
|
/**
|
||||||
* Обновляет кеш файлов и промптов
|
* Обновляет кеш файлов и промптов
|
||||||
*/
|
*/
|
||||||
private async updateCache(): Promise<void> {
|
private async updateCache(): Promise<void> {
|
||||||
const files = this.plugin.app.vault.getMarkdownFiles();
|
const files = this.plugin.app.vault.getMarkdownFiles();
|
||||||
const fileItems: AutocompleteItem[] = [];
|
const fileItems: AutocompleteItem[] = [];
|
||||||
const promptItems: AutocompleteItem[] = [];
|
const promptItems: AutocompleteItem[] = [];
|
||||||
|
|
||||||
// Нормализуем пути исключенных папок
|
// Нормализуем пути исключенных папок
|
||||||
const normalizedExcludedFolders = this.plugin.settings.excludedFolders
|
const normalizedExcludedFolders = this.plugin.settings.excludedFolders
|
||||||
.filter(folder => folder.trim() !== '')
|
.filter((folder) => folder.trim() !== '')
|
||||||
.map(folder => folder.endsWith('/') ? folder : folder + '/') // Убедимся, что заканчивается на слэш
|
.map((folder) => (folder.endsWith('/') ? folder : folder + '/')) // Убедимся, что заканчивается на слэш
|
||||||
.map(folder => folder.startsWith('/') ? folder.substring(1) : folder); // Удаляем начальный слэш
|
.map((folder) => (folder.startsWith('/') ? folder.substring(1) : folder)); // Удаляем начальный слэш
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
// Пропускаем файлы из исключенных папок
|
// Пропускаем файлы из исключенных папок
|
||||||
if (this.isFileInExcludedFolder(file, normalizedExcludedFolders)) {
|
if (this.isFileInExcludedFolder(file, normalizedExcludedFolders)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const item: AutocompleteItem = {
|
const item: AutocompleteItem = {
|
||||||
name: file.basename,
|
name: file.basename,
|
||||||
path: file.path,
|
path: file.path,
|
||||||
type: this.isPromptFile(file) ? 'prompt' : 'file',
|
type: this.isPromptFile(file) ? 'prompt' : 'file',
|
||||||
icon: this.getFileIcon(file),
|
icon: this.getFileIcon(file),
|
||||||
file: file
|
file: file
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.type === 'prompt') {
|
if (item.type === 'prompt') {
|
||||||
promptItems.push(item);
|
promptItems.push(item);
|
||||||
} else {
|
} else {
|
||||||
fileItems.push(item);
|
fileItems.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сортируем по имени
|
// Сортируем по имени
|
||||||
fileItems.sort((a, b) => a.name.localeCompare(b.name));
|
fileItems.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
promptItems.sort((a, b) => a.name.localeCompare(b.name));
|
promptItems.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
|
||||||
|
this.fileCache.set('all', fileItems);
|
||||||
|
this.promptCache.set('all', promptItems);
|
||||||
|
}
|
||||||
|
|
||||||
this.fileCache.set('all', fileItems);
|
|
||||||
this.promptCache.set('all', promptItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверяет, является ли файл промптом
|
* Проверяет, является ли файл промптом
|
||||||
*/
|
*/
|
||||||
private isPromptFile(file: TFile): boolean {
|
private isPromptFile(file: TFile): boolean {
|
||||||
const promptsFolder = this.plugin.settings.promptsFolder;
|
const promptsFolder = this.plugin.settings.promptsFolder;
|
||||||
if (!promptsFolder) return false;
|
if (!promptsFolder) return false;
|
||||||
|
|
||||||
// Нормализуем путь к папке промптов
|
// Нормализуем путь к папке промптов
|
||||||
const normalizedPromptsPath = promptsFolder.replace(/^\/+|\/+$/g, '');
|
const normalizedPromptsPath = promptsFolder.replace(/^\/+|\/+$/g, '');
|
||||||
|
|
||||||
return file.path.startsWith(normalizedPromptsPath + '/') ||
|
return file.path.startsWith(normalizedPromptsPath + '/') || file.path === normalizedPromptsPath;
|
||||||
file.path === normalizedPromptsPath;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Возвращает иконку для файла на основе Obsidian иконок
|
* Возвращает иконку для файла на основе Obsidian иконок
|
||||||
|
|
@ -214,23 +218,23 @@ export class AutocompleteManager {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Проверяет, находится ли файл в одной из исключенных папок.
|
* Проверяет, находится ли файл в одной из исключенных папок.
|
||||||
* @param file - файл Obsidian.
|
* @param file - файл Obsidian.
|
||||||
* @param excludedFolders - массив нормализованных путей исключенных папок.
|
* @param excludedFolders - массив нормализованных путей исключенных папок.
|
||||||
* @returns true, если файл находится в исключенной папке.
|
* @returns true, если файл находится в исключенной папке.
|
||||||
*/
|
*/
|
||||||
private isFileInExcludedFolder(file: TFile, excludedFolders: string[]): boolean {
|
private isFileInExcludedFolder(file: TFile, excludedFolders: string[]): boolean {
|
||||||
const filePath = file.path.toLowerCase(); // Для регистронезависимого сравнения
|
const filePath = file.path.toLowerCase(); // Для регистронезависимого сравнения
|
||||||
|
|
||||||
for (const folder of excludedFolders) {
|
for (const folder of excludedFolders) {
|
||||||
const normalizedFolder = folder.toLowerCase();
|
const normalizedFolder = folder.toLowerCase();
|
||||||
// Проверяем, начинается ли путь файла с пути исключенной папки
|
// Проверяем, начинается ли путь файла с пути исключенной папки
|
||||||
// Или если файл находится прямо в корне исключенной папки (н.п. "folder/file.md")
|
// Или если файл находится прямо в корне исключенной папки (н.п. "folder/file.md")
|
||||||
if (filePath.startsWith(normalizedFolder) ) {
|
if (filePath.startsWith(normalizedFolder)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user