diff --git a/package.json b/package.json index 56e4c92..fe0c530 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "vite": "^3.2.5" }, "dependencies": { + "cancelable-promise": "^4.3.1", "dexie": "^3.2.2", "lodash-es": "4.17.21", "minisearch": "6.0.0-beta.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 960560d..76fc572 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,7 @@ specifiers: '@types/pako': ^2.0.0 babel-jest: ^27.5.1 builtin-modules: ^3.3.0 + cancelable-promise: ^4.3.1 dexie: ^3.2.2 esbuild: 0.14.0 esbuild-plugin-copy: 1.3.0 @@ -34,6 +35,7 @@ specifiers: vite: ^3.2.5 dependencies: + cancelable-promise: 4.3.1 dexie: 3.2.2 lodash-es: 4.17.21 minisearch: 6.0.0-beta.1 @@ -2112,6 +2114,10 @@ packages: engines: {node: '>=10'} dev: true + /cancelable-promise/4.3.1: + resolution: {integrity: sha512-A/8PwLk/T7IJDfUdQ68NR24QHa8rIlnN/stiJEBo6dmVUkD4K14LswG0w3VwdeK/o7qOwRUR1k2MhK5Rpy2m7A==} + dev: false + /caniuse-lite/1.0.30001436: resolution: {integrity: sha512-ZmWkKsnC2ifEPoWUvSAIGyOYwT+keAaaWPHiQ9DfMqS1t6tfuyFYoWR78TeZtznkEQ64+vGXH9cZrElwR2Mrxg==} dev: true diff --git a/src/components/InputSearch.svelte b/src/components/InputSearch.svelte index f303c5d..e649c54 100644 --- a/src/components/InputSearch.svelte +++ b/src/components/InputSearch.svelte @@ -39,7 +39,7 @@ // the next time we open the modal, the search field will be empty cacheManager.addToSearchHistory('') dispatch('input', value) - }, 500) + }, 250)
diff --git a/src/components/ModalVault.svelte b/src/components/ModalVault.svelte index 84065c2..f02841d 100644 --- a/src/components/ModalVault.svelte +++ b/src/components/ModalVault.svelte @@ -3,16 +3,32 @@ import { onDestroy, onMount, tick } from 'svelte' import InputSearch from './InputSearch.svelte' import ModalContainer from './ModalContainer.svelte' - import { eventBus, indexingStep, IndexingStepType, type ResultNote, } from 'src/globals' + import { + eventBus, + indexingStep, + IndexingStepType, + type ResultNote, + SPACE_OR_PUNCTUATION, + } from 'src/globals' import { createNote, openNote } from 'src/tools/notes' - import { getCtrlKeyLabel, getExtension, isFilePDF, loopIndex, } from 'src/tools/utils' - import { OmnisearchInFileModal, type OmnisearchVaultModal, } from 'src/components/modals' + import { + getCtrlKeyLabel, + getExtension, + isFilePDF, + loopIndex, + } from 'src/tools/utils' + import { + OmnisearchInFileModal, + type OmnisearchVaultModal, + } from 'src/components/modals' import ResultItemVault from './ResultItemVault.svelte' import { Query } from 'src/search/query' import { settings } from '../settings' import * as NotesIndex from '../notes-index' import { cacheManager } from '../cache-manager' import { searchEngine } from 'src/search/omnisearch' + import CancelablePromise, { cancelable } from 'cancelable-promise' + import { update } from 'lodash-es' export let modal: OmnisearchVaultModal export let previousQuery: string | undefined @@ -23,18 +39,30 @@ let query: Query let indexingStepDesc = '' let searching = true - let refInput: InputSearch|undefined + let refInput: InputSearch | undefined + + let pWaitingResults: CancelablePromise | null = null $: selectedNote = resultNotes[selectedIndex] $: searchQuery = searchQuery ?? previousQuery $: if (searchQuery) { - resultNotes = [] + if (pWaitingResults) { + pWaitingResults.cancel() + pWaitingResults = null + } searching = true - updateResults().then(() => { - searching = false - }).catch((e) => { - console.error(e) - }) + pWaitingResults = cancelable( + new Promise((resolve, reject) => { + updateResults() + .then(() => { + searching = false + resolve(null) + }) + .catch(e => { + reject(e) + }) + }) + ) } else { searching = false resultNotes = [] @@ -193,7 +221,10 @@ function switchToInFileModal(): void { // Do nothing if the selectedNote is a PDF, // or if there is 0 match (e.g indexing in progress) - if (selectedNote && (isFilePDF(selectedNote?.path) || !selectedNote?.matches.length)) { + if ( + selectedNote && + (isFilePDF(selectedNote?.path) || !selectedNote?.matches.length) + ) { return } @@ -232,8 +263,8 @@ {#if settings.showCreateButton} @@ -258,6 +289,15 @@
{#if !resultNotes.length && searchQuery && !searching} We found 0 result for your search here. + {#if settings.simpleSearch && searchQuery + .split(SPACE_OR_PUNCTUATION) + .some(w => w.length < 3)} +
+ + You have enabled "Simpler Search" in the settings, try to type more + characters. + + {/if} {:else if searching} Searching... {/if} diff --git a/src/search/omnisearch.ts b/src/search/omnisearch.ts index df88b74..4eb06a1 100644 --- a/src/search/omnisearch.ts +++ b/src/search/omnisearch.ts @@ -55,6 +55,7 @@ export class Omnisearch { private minisearch: MiniSearch private indexedDocuments: Map = new Map() private previousResults: SearchResult[] = [] + private previousQuery: Query | null = null constructor() { this.minisearch = new MiniSearch(Omnisearch.options) @@ -154,6 +155,7 @@ export class Omnisearch { ): Promise { if (query.isEmpty()) { this.previousResults = [] + this.previousQuery = null return [] } @@ -172,7 +174,12 @@ export class Omnisearch { headings3: settings.weightH3, }, }) - if (!results.length) return this.previousResults + + // If the query does not return any result, + // retry but with a shorter prefix limit + if (!results.length) { + return [] + } if (options.singleFilePath) { return results.filter(r => r.id === options.singleFilePath) @@ -249,6 +256,7 @@ export class Omnisearch { (result, index, arr) => arr.findIndex(t => t.id === result.id) === index ) + this.previousQuery = query this.previousResults = results return results diff --git a/src/settings.ts b/src/settings.ts index 2e6357a..2092003 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -210,7 +210,8 @@ export class SettingsTab extends PluginSettingTab { new Setting(containerEl) .setName('Simpler search') .setDesc( - `Enable this if Obsidian often freezes while making searches. This may return fewer results.` + `Enable this if Obsidian often freezes while making searches. + Words shorter than 3 characters won't be used as prefixes; this can reduce search delay but will return fewer results.` ) .addToggle(toggle => toggle.setValue(settings.simpleSearch).onChange(async v => {