Massive refactor to get rid of the global app.

This commit is contained in:
Simon Cambier
2024-05-25 22:49:50 +02:00
parent bbe7b112ed
commit 6566a2e958
24 changed files with 1532 additions and 1146 deletions

View File

@@ -2,10 +2,11 @@
import { debounce } from 'obsidian'
import { toggleInputComposition } from 'src/globals'
import { createEventDispatcher, tick } from 'svelte'
import { cacheManager } from '../cache-manager'
import type OmnisearchPlugin from '../main'
export let initialValue = ''
export let placeholder = ''
export let plugin: OmnisearchPlugin
let initialSet = false
let value = ''
let elInput: HTMLInputElement
@@ -39,7 +40,7 @@
const debouncedOnInput = debounce(() => {
// If typing a query and not executing it,
// the next time we open the modal, the search field will be empty
cacheManager.addToSearchHistory('')
plugin.cacheManager.addToSearchHistory('')
dispatch('input', value)
}, 300)
</script>
@@ -50,13 +51,13 @@
bind:this="{elInput}"
bind:value="{value}"
class="prompt-input"
use:selectInput
on:compositionend="{_ => toggleInputComposition(false)}"
on:compositionstart="{_ => toggleInputComposition(true)}"
on:input="{debouncedOnInput}"
placeholder="{placeholder}"
spellcheck="false"
type="text" />
type="text"
use:selectInput />
</div>
<slot />
</div>
</div>

View File

@@ -9,7 +9,7 @@
} from 'src/globals'
import { getCtrlKeyLabel, loopIndex } from 'src/tools/utils'
import { onDestroy, onMount, tick } from 'svelte'
import { MarkdownView, App, Platform } from 'obsidian'
import { MarkdownView, Platform } from 'obsidian'
import ModalContainer from './ModalContainer.svelte'
import {
OmnisearchInFileModal,
@@ -18,14 +18,13 @@
import ResultItemInFile from './ResultItemInFile.svelte'
import { Query } from 'src/search/query'
import { openNote } from 'src/tools/notes'
import { stringsToRegex } from 'src/tools/text-processing'
import { Omnisearch } from 'src/search/omnisearch'
import type OmnisearchPlugin from '../main'
export let plugin: OmnisearchPlugin
export let modal: OmnisearchInFileModal
export let parent: OmnisearchVaultModal | null = null
export let singleFilePath = ''
export let previousQuery: string | undefined
export let app: App
let searchQuery: string
let groupedOffsets: number[] = []
@@ -51,10 +50,12 @@
$: (async () => {
if (searchQuery) {
query = new Query(searchQuery)
query = new Query(searchQuery, {
ignoreDiacritics: plugin.settings.ignoreDiacritics,
})
note =
(
await Omnisearch.getInstance().getSuggestions(query, {
await plugin.omnisearch.getSuggestions(query, {
singleFilePath,
})
)[0] ?? null
@@ -131,12 +132,12 @@
if (parent) parent.close()
// Open (or switch focus to) the note
const reg = stringsToRegex(note.foundWords)
const reg = plugin.textProcessor.stringsToRegex(note.foundWords)
reg.exec(note.content)
await openNote(note, reg.lastIndex, newTab)
await openNote(plugin.app, note, reg.lastIndex, newTab)
// Move cursor to the match
const view = app.workspace.getActiveViewOfType(MarkdownView)
const view = plugin.app.workspace.getActiveViewOfType(MarkdownView)
if (!view) {
// Not an editable document, so no cursor to place
return
@@ -155,12 +156,13 @@
}
function switchToVaultModal(): void {
new OmnisearchVaultModal(app, searchQuery ?? previousQuery).open()
new OmnisearchVaultModal(plugin, searchQuery ?? previousQuery).open()
modal.close()
}
</script>
<InputSearch
plugin="{plugin}"
on:input="{e => (searchQuery = e.detail)}"
placeholder="Omnisearch - File"
initialValue="{previousQuery}">
@@ -175,6 +177,7 @@
{#if groupedOffsets.length && note}
{#each groupedOffsets as offset, i}
<ResultItemInFile
{plugin}
offset="{offset}"
note="{note}"
index="{i}"

View File

@@ -1,5 +1,5 @@
<script lang="ts">
import { App, MarkdownView, Notice, Platform, TFile } from 'obsidian'
import { MarkdownView, Notice, Platform, TFile } from 'obsidian'
import { onDestroy, onMount, tick } from 'svelte'
import InputSearch from './InputSearch.svelte'
import ModalContainer from './ModalContainer.svelte'
@@ -24,16 +24,13 @@
} from 'src/components/modals'
import ResultItemVault from './ResultItemVault.svelte'
import { Query } from 'src/search/query'
import * as NotesIndex from '../notes-index'
import { cacheManager } from '../cache-manager'
import { cancelable, CancelablePromise } from 'cancelable-promise'
import { debounce } from 'lodash-es'
import { Omnisearch } from 'src/search/omnisearch'
import { getSettings } from 'src/settings'
import type OmnisearchPlugin from '../main'
export let modal: OmnisearchVaultModal
export let previousQuery: string | undefined
export let app: App
export let plugin: OmnisearchPlugin
let selectedIndex = 0
let historySearchIndex = 0
@@ -51,7 +48,7 @@
$: selectedNote = resultNotes[selectedIndex]
$: searchQuery = searchQuery ?? previousQuery
$: if (getSettings().openInNewPane) {
$: if (plugin.settings.openInNewPane) {
openInNewPaneKey = '↵'
openInCurrentPaneKey = getCtrlKeyLabel() + ' ↵'
createInNewPaneKey = 'shift ↵'
@@ -103,7 +100,7 @@
eventBus.on('vault', Action.PrevSearchHistory, prevSearchHistory)
eventBus.on('vault', Action.NextSearchHistory, nextSearchHistory)
eventBus.on('vault', Action.OpenInNewLeaf, openNoteInNewLeaf)
await NotesIndex.refreshIndex()
await plugin.notesIndexer.refreshIndex()
await updateResultsDebounced()
})
@@ -113,7 +110,9 @@
async function prevSearchHistory() {
// Filter out the empty string, if it's there
const history = (await cacheManager.getSearchHistory()).filter(s => s)
const history = (await plugin.cacheManager.getSearchHistory()).filter(
s => s
)
if (++historySearchIndex >= history.length) {
historySearchIndex = 0
}
@@ -122,7 +121,9 @@
}
async function nextSearchHistory() {
const history = (await cacheManager.getSearchHistory()).filter(s => s)
const history = (await plugin.cacheManager.getSearchHistory()).filter(
s => s
)
if (--historySearchIndex < 0) {
historySearchIndex = history.length ? history.length - 1 : 0
}
@@ -138,10 +139,12 @@
cancelableQuery.cancel()
cancelableQuery = null
}
query = new Query(searchQuery)
query = new Query(searchQuery, {
ignoreDiacritics: plugin.settings.ignoreDiacritics,
})
cancelableQuery = cancelable(
new Promise(resolve => {
resolve(Omnisearch.getInstance().getSuggestions(query))
resolve(plugin.omnisearch.getSuggestions(query))
})
)
resultNotes = await cancelableQuery
@@ -188,7 +191,7 @@
function saveCurrentQuery() {
if (searchQuery) {
cacheManager.addToSearchHistory(searchQuery)
plugin.cacheManager.addToSearchHistory(searchQuery)
}
}
@@ -199,7 +202,7 @@
) {
saveCurrentQuery()
const offset = note.matches?.[0]?.offset ?? 0
openNote(note, offset, newPane, newLeaf)
openNote(plugin.app, note, offset, newPane, newLeaf)
}
async function onClickCreateNote(_e: MouseEvent) {
@@ -211,7 +214,7 @@
}): Promise<void> {
if (searchQuery) {
try {
await createNote(searchQuery, opt?.newLeaf)
await createNote(plugin.app, searchQuery, opt?.newLeaf)
} catch (e) {
new Notice((e as Error).message)
return
@@ -222,11 +225,11 @@
function insertLink(): void {
if (!selectedNote) return
const file = app.vault
const file = plugin.app.vault
.getMarkdownFiles()
.find(f => f.path === selectedNote.path)
const active = app.workspace.getActiveFile()
const view = app.workspace.getActiveViewOfType(MarkdownView)
const active = plugin.app.workspace.getActiveFile()
const view = plugin.app.workspace.getActiveViewOfType(MarkdownView)
if (!view?.editor) {
new Notice('Omnisearch - Error - No active editor', 3000)
return
@@ -235,7 +238,7 @@
// Generate link
let link: string
if (file && active) {
link = app.fileManager.generateMarkdownLink(file, active.path)
link = plugin.app.fileManager.generateMarkdownLink(file, active.path)
} else {
link = `[[${selectedNote.basename}.${getExtension(selectedNote.path)}]]`
}
@@ -249,7 +252,7 @@
modal.close()
}
function switchToInFileModal(): void {
function switchToInFileModal(): void {
// Do nothing if the selectedNote is a PDF,
// or if there is 0 match (e.g indexing in progress)
if (
@@ -264,15 +267,15 @@
if (selectedNote) {
// Open in-file modal for selected search result
const file = app.vault.getAbstractFileByPath(selectedNote.path)
const file = plugin.app.vault.getAbstractFileByPath(selectedNote.path)
if (file && file instanceof TFile) {
new OmnisearchInFileModal(app, file, searchQuery).open()
new OmnisearchInFileModal(plugin, file, searchQuery).open()
}
} else {
// Open in-file modal for active file
const view = app.workspace.getActiveViewOfType(MarkdownView)
const view = plugin.app.workspace.getActiveViewOfType(MarkdownView)
if (view?.file) {
new OmnisearchInFileModal(app, view.file, searchQuery).open()
new OmnisearchInFileModal(plugin, view.file, searchQuery).open()
}
}
}
@@ -295,11 +298,12 @@
<InputSearch
bind:this="{refInput}"
plugin="{plugin}"
initialValue="{searchQuery}"
on:input="{e => (searchQuery = e.detail)}"
placeholder="Omnisearch - Vault">
<div class="omnisearch-input-container__buttons">
{#if getSettings().showCreateButton}
{#if plugin.settings.showCreateButton}
<button on:click="{onClickCreateNote}">Create note</button>
{/if}
{#if Platform.isMobile}
@@ -317,7 +321,7 @@
<ModalContainer>
{#each resultNotes as result, i}
<ResultItemVault
app="{app}"
{plugin}
selected="{i === selectedIndex}"
note="{result}"
on:mousemove="{_ => (selectedIndex = i)}"
@@ -329,7 +333,7 @@
<div style="text-align: center;">
{#if !resultNotes.length && searchQuery && !searching}
We found 0 result for your search here.
{#if getSettings().simpleSearch && searchQuery
{#if plugin.settings.simpleSearch && searchQuery
.split(SPACE_OR_PUNCTUATION)
.some(w => w.length < 3)}
<br />

View File

@@ -1,24 +1,24 @@
<script lang="ts">
import { makeExcerpt, highlightText } from 'src/tools/text-processing'
import type { ResultNote } from '../globals'
import ResultItemContainer from './ResultItemContainer.svelte'
import { cloneDeep } from 'lodash-es'
import type OmnisearchPlugin from '../main'
export let plugin: OmnisearchPlugin
export let offset: number
export let note: ResultNote
export let index = 0
export let selected = false
$: cleanedContent = makeExcerpt(note?.content ?? '', offset)
$: cleanedContent = plugin.textProcessor.makeExcerpt(note?.content ?? '', offset)
</script>
<ResultItemContainer
id="{index.toString()}"
selected="{selected}"
on:mousemove
on:auxclick
on:click
on:auxclick>
on:mousemove
selected="{selected}">
<div class="omnisearch-result__body">
{@html highlightText(cleanedContent, note.matches)}
{@html plugin.textProcessor.highlightText(cleanedContent, note.matches)}
</div>
</ResultItemContainer>

View File

@@ -9,18 +9,12 @@
pathWithoutFilename,
} from '../tools/utils'
import ResultItemContainer from './ResultItemContainer.svelte'
import { TFile, setIcon, App } from 'obsidian'
import { cloneDeep } from 'lodash-es'
import {
stringsToRegex,
getMatches,
makeExcerpt,
highlightText,
} from 'src/tools/text-processing'
import { TFile, setIcon } from 'obsidian'
import type OmnisearchPlugin from '../main'
export let selected = false
export let note: ResultNote
export let app: App
export let plugin: OmnisearchPlugin
let imagePath: string | null = null
let title = ''
@@ -31,16 +25,15 @@
$: {
imagePath = null
if (isFileImage(note.path)) {
const file = app.vault.getAbstractFileByPath(note.path)
const file = plugin.app.vault.getAbstractFileByPath(note.path)
if (file instanceof TFile) {
imagePath = app.vault.getResourcePath(file)
imagePath = plugin.app.vault.getResourcePath(file)
}
}
}
$: reg = stringsToRegex(note.foundWords)
$: matchesTitle = getMatches(title, reg)
$: matchesNotePath = getMatches(notePath, reg)
$: cleanedContent = makeExcerpt(note.content, note.matches[0]?.offset ?? -1)
$: matchesTitle = plugin.textProcessor.getMatches(title, note.foundWords)
$: matchesNotePath = plugin.textProcessor.getMatches(notePath, note.foundWords)
$: cleanedContent = plugin.textProcessor.makeExcerpt(note.content, note.matches[0]?.offset ?? -1)
$: glyph = false //cacheManager.getLiveDocument(note.path)?.doesNotExist
$: {
title = note.basename
@@ -63,15 +56,15 @@
<ResultItemContainer
glyph="{glyph}"
id="{note.path}"
on:click
on:auxclick
on:click
on:mousemove
selected="{selected}">
<div>
<div class="omnisearch-result__title-container">
<span class="omnisearch-result__title">
<span bind:this="{elFilePathIcon}"></span>
<span>{@html highlightText(title, matchesTitle)}</span>
<span>{@html plugin.textProcessor.highlightText(title, matchesTitle)}</span>
<span class="omnisearch-result__extension">
.{getExtension(note.path)}
</span>
@@ -91,14 +84,14 @@
{#if notePath}
<div class="omnisearch-result__folder-path">
<span bind:this="{elFolderPathIcon}"></span>
<span>{@html highlightText(notePath, matchesNotePath)}</span>
<span>{@html plugin.textProcessor.highlightText(notePath, matchesNotePath)}</span>
</div>
{/if}
<div style="display: flex; flex-direction: row;">
{#if $showExcerpt}
<div class="omnisearch-result__body">
{@html highlightText(cleanedContent, note.matches)}
{@html plugin.textProcessor.highlightText(cleanedContent, note.matches)}
</div>
{/if}

View File

@@ -1,15 +1,14 @@
import { App, MarkdownView, Modal, TFile } from 'obsidian'
import { MarkdownView, Modal, TFile } from 'obsidian'
import type { Modifier } from 'obsidian'
import ModalVault from './ModalVault.svelte'
import ModalInFile from './ModalInFile.svelte'
import { Action, eventBus, EventNames, isInputComposition } from '../globals'
import { cacheManager } from 'src/cache-manager'
import { getSettings } from 'src/settings'
import type OmnisearchPlugin from 'src/main'
abstract class OmnisearchModal extends Modal {
protected constructor(app: App) {
super(app)
const settings = getSettings()
protected constructor(plugin: OmnisearchPlugin) {
super(plugin.app)
const settings = plugin.settings
// Remove all the default modal's children
// so that we can more easily customize it
@@ -153,20 +152,20 @@ abstract class OmnisearchModal extends Modal {
export class OmnisearchVaultModal extends OmnisearchModal {
/**
* Instanciate the Omnisearch vault modal
* @param app
* @param plugin
* @param query The query to pre-fill the search field with
*/
constructor(app: App, query?: string) {
super(app)
constructor(plugin: OmnisearchPlugin, query?: string) {
super(plugin)
// Selected text in the editor
const selectedText = app.workspace
const selectedText = plugin.app.workspace
.getActiveViewOfType(MarkdownView)
?.editor.getSelection()
cacheManager.getSearchHistory().then(history => {
plugin.cacheManager.getSearchHistory().then(history => {
// Previously searched query (if enabled in settings)
const previous = getSettings().showPreviousQueryResults
const previous = plugin.settings.showPreviousQueryResults
? history[0]
: null
@@ -174,7 +173,7 @@ export class OmnisearchVaultModal extends OmnisearchModal {
const cmp = new ModalVault({
target: this.modalEl,
props: {
app,
plugin,
modal: this,
previousQuery: query || selectedText || previous || '',
},
@@ -190,17 +189,17 @@ export class OmnisearchVaultModal extends OmnisearchModal {
export class OmnisearchInFileModal extends OmnisearchModal {
constructor(
app: App,
plugin: OmnisearchPlugin,
file: TFile,
searchQuery: string = '',
parent?: OmnisearchModal
) {
super(app)
super(plugin)
const cmp = new ModalInFile({
target: this.modalEl,
props: {
app,
plugin,
modal: this,
singleFilePath: file.path,
parent: parent,