177 lines
5.1 KiB
Svelte
177 lines
5.1 KiB
Svelte
<script lang="ts">
|
|
import { setIcon, TFile } from 'obsidian'
|
|
import { showExcerpt } from 'src/settings/utils'
|
|
import { onMount } from 'svelte'
|
|
import type { ResultNote } from '../globals'
|
|
import type LocatorPlugin from '../main'
|
|
import { getDefaultIconSVG } from '../tools/icon-utils'
|
|
import {
|
|
getExtension,
|
|
isFileCanvas,
|
|
isFileExcalidraw,
|
|
isFileImage,
|
|
isFilePDF,
|
|
pathWithoutFilename,
|
|
} from '../tools/utils'
|
|
import ResultItemContainer from './ResultItemContainer.svelte'
|
|
|
|
export let selected = false
|
|
export let note: ResultNote
|
|
export let plugin: LocatorPlugin
|
|
|
|
let imagePath: string | null = null
|
|
let title = ''
|
|
let notePath = ''
|
|
const folderIconSVG = getDefaultIconSVG('folder')
|
|
const fileIconSVG = getDefaultIconSVG(note.path)
|
|
let iconDataLoaded = false // Flag to indicate iconData is loaded
|
|
|
|
// Initialize icon data and icon packs once when the component mounts
|
|
onMount(async () => {
|
|
iconDataLoaded = true // Set the flag after iconData is loaded
|
|
})
|
|
|
|
// Reactive statement to call loadIcons() whenever the note changes and iconData is loaded
|
|
$: if (note && note.path && iconDataLoaded) {
|
|
;(async () => {
|
|
// Update title and notePath before loading icons
|
|
title = note.displayTitle || note.basename
|
|
notePath = pathWithoutFilename(note.path)
|
|
})()
|
|
}
|
|
|
|
// Svelte action to render SVG content with dynamic updates
|
|
function renderSVG(node: HTMLElement, svgContent: string) {
|
|
node.innerHTML = svgContent
|
|
return {
|
|
update(newSvgContent: string) {
|
|
node.innerHTML = newSvgContent
|
|
},
|
|
destroy() {
|
|
node.innerHTML = ''
|
|
},
|
|
}
|
|
}
|
|
let elFolderPathIcon: HTMLElement | null = null
|
|
let elFilePathIcon: HTMLElement | null = null
|
|
let elEmbedIcon: HTMLElement | null = null
|
|
|
|
$: {
|
|
imagePath = null
|
|
if (isFileImage(note.path)) {
|
|
const file = plugin.app.vault.getAbstractFileByPath(note.path)
|
|
if (file instanceof TFile) {
|
|
imagePath = plugin.app.vault.getResourcePath(file)
|
|
}
|
|
}
|
|
}
|
|
|
|
$: 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.displayTitle || note.basename
|
|
notePath = pathWithoutFilename(note.path)
|
|
|
|
// Icons
|
|
if (elFolderPathIcon) {
|
|
setIcon(elFolderPathIcon, 'folder-open')
|
|
}
|
|
if (elFilePathIcon) {
|
|
if (isFileImage(note.path)) {
|
|
setIcon(elFilePathIcon, 'image')
|
|
} else if (isFilePDF(note.path)) {
|
|
setIcon(elFilePathIcon, 'file-text')
|
|
} else if (isFileCanvas(note.path) || isFileExcalidraw(note.path)) {
|
|
setIcon(elFilePathIcon, 'layout-dashboard')
|
|
} else {
|
|
setIcon(elFilePathIcon, 'file')
|
|
}
|
|
}
|
|
if (elEmbedIcon) {
|
|
setIcon(elEmbedIcon, 'corner-down-right')
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<ResultItemContainer
|
|
{glyph}
|
|
id={note.path}
|
|
cssClass=" {note.isEmbed ? 'omnisearch-result__embed' : ''}"
|
|
on:auxclick
|
|
on:click
|
|
on:mousemove
|
|
{selected}>
|
|
<div>
|
|
<div class="omnisearch-result__title-container">
|
|
<span class="omnisearch-result__title">
|
|
{#if note.isEmbed}
|
|
<span
|
|
bind:this={elEmbedIcon}
|
|
title="The document above is embedded in this note" />
|
|
{:else}
|
|
<!-- File Icon -->
|
|
<span class="omnisearch-result__icon" use:renderSVG={fileIconSVG} />
|
|
{/if}
|
|
<span>
|
|
{@html plugin.textProcessor.highlightText(title, matchesTitle)}
|
|
</span>
|
|
{#if !note.displayTitle}
|
|
<span class="omnisearch-result__extension">
|
|
.{getExtension(note.path)}
|
|
</span>
|
|
{/if}
|
|
|
|
<!-- Counter -->
|
|
{#if note.matches.length > 0}
|
|
<span class="omnisearch-result__counter">
|
|
{note.matches.length} {note.matches.length > 1
|
|
? 'matches'
|
|
: 'match'}
|
|
</span>
|
|
{/if}
|
|
</span>
|
|
</div>
|
|
|
|
<!-- Folder path -->
|
|
{#if notePath}
|
|
<div class="omnisearch-result__folder-path">
|
|
<!-- Folder Icon -->
|
|
<span class="omnisearch-result__icon" use:renderSVG={folderIconSVG} />
|
|
|
|
<span>
|
|
{@html plugin.textProcessor.highlightText(notePath, matchesNotePath)}
|
|
</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Do not display the excerpt for embedding references -->
|
|
{#if !note.isEmbed}
|
|
<div style="display: flex; flex-direction: row;">
|
|
{#if $showExcerpt}
|
|
<div class="omnisearch-result__body">
|
|
{@html plugin.textProcessor.highlightText(
|
|
cleanedContent,
|
|
note.matches
|
|
)}
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Image -->
|
|
{#if imagePath}
|
|
<div class="omnisearch-result__image-container">
|
|
<img style="width: 100px" src={imagePath} alt="" />
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
</ResultItemContainer>
|