feat(Index.tsx): implement debounced tag generation for improved user experience
This commit is contained in:
@@ -98,6 +98,7 @@ const Index = () => {
|
||||
const [autoGenerateTags, setAutoGenerateTags] = useState(true);
|
||||
const [ollamaStatus, setOllamaStatus] = useState<'unknown' | 'online' | 'offline'>('unknown');
|
||||
const [includeTagsInSearch, setIncludeTagsInSearch] = useState(true);
|
||||
const [tagGenerationTimeout, setTagGenerationTimeout] = useState<NodeJS.Timeout>();
|
||||
|
||||
const { resolvedTheme, setTheme } = useTheme();
|
||||
|
||||
@@ -240,12 +241,46 @@ const Index = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Debounced tag generation
|
||||
const debouncedGenerateTags = (content: string, noteIndex?: number) => {
|
||||
if (tagGenerationTimeout) {
|
||||
clearTimeout(tagGenerationTimeout);
|
||||
}
|
||||
|
||||
const timeout = setTimeout(async () => {
|
||||
if (content.trim() && autoGenerateTags) {
|
||||
try {
|
||||
addDebugInfo('Auto-generating tags...');
|
||||
const tags = await generateTags(content, noteIndex);
|
||||
if (noteIndex !== undefined) {
|
||||
// For existing notes
|
||||
const note = noteCache[noteIndex];
|
||||
if (note) {
|
||||
const updatedNote = { ...note, tags };
|
||||
setPreviousNote(updatedNote);
|
||||
setIsPreviousNoteModified(true);
|
||||
}
|
||||
} else {
|
||||
// For current note
|
||||
setCurrentNoteTags(tags);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auto tag generation failed:', error);
|
||||
}
|
||||
}
|
||||
}, 200);
|
||||
|
||||
setTagGenerationTimeout(timeout);
|
||||
};
|
||||
|
||||
// Generate tags using Ollama
|
||||
const generateTags = async (content: string, noteIndex?: number): Promise<string[]> => {
|
||||
try {
|
||||
const systemPrompt = `You are a helpful assistant that generates searchable tags for journal entries.
|
||||
|
||||
Your task is to analyze the content and generate 3-8 relevant tags that would help the author find this note later.
|
||||
Your task is to analyze the content and generate 1-3 relevant tags that would help the author find this note later.
|
||||
Focus on the quality of tags, not the quantity.
|
||||
|
||||
Focus on:
|
||||
- Programming languages, frameworks, libraries mentioned
|
||||
- Technical concepts and methodologies
|
||||
@@ -468,7 +503,7 @@ ${content}${context}`;
|
||||
// Use current note tags or generate tags using Ollama if enabled
|
||||
let tags: string[] = currentNoteTags;
|
||||
if (autoGenerateTags && tags.length === 0) {
|
||||
addDebugInfo('Generating tags for new note...');
|
||||
addDebugInfo('Generating tags for new note before saving...');
|
||||
tags = await generateTags(trimmedContent, 0); // New note will be at index 0
|
||||
}
|
||||
|
||||
@@ -543,6 +578,13 @@ ${content}${context}`;
|
||||
const noteIndex = noteCache.findIndex(n => n.id === note.id);
|
||||
tags = await generateTags(trimmedContent, noteIndex);
|
||||
}
|
||||
|
||||
// Generate tags if none are present and auto-generation is enabled
|
||||
if (autoGenerateTags && tags.length === 0) {
|
||||
addDebugInfo('No tags present, generating tags before saving...');
|
||||
const noteIndex = noteCache.findIndex(n => n.id === note.id);
|
||||
tags = await generateTags(trimmedContent, noteIndex);
|
||||
}
|
||||
|
||||
const document = {
|
||||
id: note.id,
|
||||
@@ -1147,6 +1189,10 @@ ${content}${context}`;
|
||||
if (saveTimeoutRef.current) {
|
||||
clearTimeout(saveTimeoutRef.current);
|
||||
}
|
||||
// Clear any pending tag generation timeout on cleanup
|
||||
if (tagGenerationTimeout) {
|
||||
clearTimeout(tagGenerationTimeout);
|
||||
}
|
||||
};
|
||||
}, [currentNote, previousNote, scratchPad, isPreviousNoteModified, isSearchOpen, isGotoOpen, isCleanupOpen]);
|
||||
|
||||
@@ -1778,10 +1824,12 @@ ${content}${context}`;
|
||||
<Textarea
|
||||
value={previousNote.content}
|
||||
onChange={(e) => {
|
||||
const updatedNote = { ...previousNote, content: e.target.value };
|
||||
const newContent = e.target.value;
|
||||
const updatedNote = { ...previousNote, content: newContent };
|
||||
setPreviousNote(updatedNote);
|
||||
setIsPreviousNoteModified(true);
|
||||
if (e.target.value.trim() === '') {
|
||||
debouncedGenerateTags(newContent, currentNoteIndex);
|
||||
if (newContent.trim() === '') {
|
||||
deleteNote(previousNote.id);
|
||||
}
|
||||
}}
|
||||
@@ -1834,7 +1882,9 @@ ${content}${context}`;
|
||||
ref={currentNoteRef}
|
||||
value={currentNote}
|
||||
onChange={(e) => {
|
||||
setCurrentNote(e.target.value);
|
||||
const newContent = e.target.value;
|
||||
setCurrentNote(newContent);
|
||||
debouncedGenerateTags(newContent);
|
||||
}}
|
||||
onBlur={handleCurrentNoteBlur}
|
||||
className={`h-[calc(100%-2rem)] border-0 resize-none focus:ring-0 bg-transparent ${getTextClass('2xl')}`}
|
||||
|
Reference in New Issue
Block a user