Refactor active note inclusion and index event handling to respect setting (#1831)

* Refactor active note inclusion logic

* Refactor IndexEventHandler to manage event listeners based on semantic search settings

- Introduced `shouldHandleEvents` method to determine if indexing-related events should be processed.
- Replaced `initializeEventListeners` with `syncEventListeners` to conditionally register listeners based on settings.
- Added `teardownEventListeners` method to clean up listeners and reset state when not needed.
- Subscribed to settings changes to dynamically manage event listeners.
This commit is contained in:
Logan Yang 2025-09-22 00:02:20 -07:00 committed by GitHub
parent 8076a0e171
commit dd7e9e185f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 62 additions and 28 deletions

View file

@ -550,9 +550,8 @@ const Chat: React.FC<ChatProps> = ({
safeSet.setCurrentAiMessage("");
setContextNotes([]);
clearSelectedTextContexts();
// Only modify includeActiveNote if in a non-COPILOT_PLUS_CHAIN mode
// In COPILOT_PLUS_CHAIN mode, respect the settings.includeActiveNoteAsContext value
if (selectedChain !== ChainType.COPILOT_PLUS_CHAIN) {
// Respect the includeActiveNote setting for all non-project chains
if (selectedChain === ChainType.PROJECT_CHAIN) {
setIncludeActiveNote(false);
} else {
setIncludeActiveNote(settings.includeActiveNoteAsContext);
@ -590,11 +589,10 @@ const Chat: React.FC<ChatProps> = ({
useEffect(() => {
if (settings.includeActiveNoteAsContext !== undefined) {
// Only apply the setting if not in Project mode
if (selectedChain === ChainType.COPILOT_PLUS_CHAIN) {
setIncludeActiveNote(settings.includeActiveNoteAsContext);
} else {
// In other modes, always disable including active note
if (selectedChain === ChainType.PROJECT_CHAIN) {
setIncludeActiveNote(false);
} else {
setIncludeActiveNote(settings.includeActiveNoteAsContext);
}
}
}, [settings.includeActiveNoteAsContext, selectedChain]);

View file

@ -1,6 +1,7 @@
import { getChainType } from "@/aiParams";
import { ChainType } from "@/chainFactory";
import { getSettings } from "@/settings/model";
import { logInfo } from "@/logger";
import { getSettings, subscribeToSettingsChange } from "@/settings/model";
import { App, MarkdownView, Platform, TAbstractFile, TFile } from "obsidian";
import { DBOperations } from "./dbOperations";
import { IndexOperations } from "./indexOperations";
@ -12,24 +13,65 @@ export class IndexEventHandler {
private debounceTimer: number | null = null;
private lastActiveFile: TFile | null = null;
private lastActiveFileMtime: number | null = null;
private listenersActive = false;
constructor(
private app: App,
private indexOps: IndexOperations,
private dbOps: DBOperations
) {
this.initializeEventListeners();
this.syncEventListeners();
subscribeToSettingsChange(() => {
this.syncEventListeners();
});
}
private initializeEventListeners() {
if (getSettings().debug) {
console.log("Copilot Plus: Initializing event listeners");
/**
* Determine whether indexing-related events should be processed based on current settings.
*
* @returns {boolean} True when semantic search indexing should run.
*/
private shouldHandleEvents(): boolean {
return getSettings().enableSemanticSearchV3;
}
/**
* Ensure event listeners are registered only when semantic search indexing is enabled.
*/
private syncEventListeners(): void {
const shouldListen = this.shouldHandleEvents();
if (shouldListen && !this.listenersActive) {
logInfo("Copilot Plus: Initializing semantic index event listeners");
this.app.workspace.on("active-leaf-change", this.handleActiveLeafChange);
this.app.vault.on("delete", this.handleFileDelete);
this.listenersActive = true;
} else if (!shouldListen && this.listenersActive) {
this.teardownEventListeners();
}
this.app.workspace.on("active-leaf-change", this.handleActiveLeafChange);
this.app.vault.on("delete", this.handleFileDelete);
}
/**
* Remove indexing event listeners and reset any pending timers or cached state.
*/
private teardownEventListeners(): void {
if (!this.listenersActive) {
return;
}
this.app.workspace.off("active-leaf-change", this.handleActiveLeafChange);
this.app.vault.off("delete", this.handleFileDelete);
if (this.debounceTimer !== null) {
window.clearTimeout(this.debounceTimer);
this.debounceTimer = null;
}
this.lastActiveFile = null;
this.lastActiveFileMtime = null;
this.listenersActive = false;
}
private handleActiveLeafChange = async (leaf: any) => {
if (!this.shouldHandleEvents()) {
return;
}
if (Platform.isMobile && getSettings().disableIndexOnMobile) {
return;
}
@ -73,6 +115,9 @@ export class IndexEventHandler {
};
private debouncedReindexFile = (file: TFile) => {
if (!this.shouldHandleEvents()) {
return;
}
if (this.debounceTimer !== null) {
window.clearTimeout(this.debounceTimer);
}
@ -87,28 +132,19 @@ export class IndexEventHandler {
};
private handleFileDelete = async (file: TAbstractFile) => {
if (!this.shouldHandleEvents()) {
return;
}
if (file instanceof TFile) {
await this.dbOps.removeDocs(file.path);
}
};
public cleanup() {
if (this.debounceTimer !== null) {
window.clearTimeout(this.debounceTimer);
}
this.app.workspace.off("active-leaf-change", this.handleActiveLeafChange);
this.app.vault.off("delete", this.handleFileDelete);
this.teardownEventListeners();
}
public unload() {
if (this.debounceTimer !== null) {
window.clearTimeout(this.debounceTimer);
}
// Clean up file tracking
this.lastActiveFile = null;
this.lastActiveFileMtime = null;
this.app.workspace.off("active-leaf-change", this.handleActiveLeafChange);
this.app.vault.off("delete", this.handleFileDelete);
this.teardownEventListeners();
}
}