mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
This commit is contained in:
parent
e0daf807a6
commit
11c1c0638d
@ -2,11 +2,10 @@ import * as React from 'react';
|
||||
import { AppState } from '../app.reducer';
|
||||
import CommandService, { SearchResult as CommandSearchResult } from '@joplin/lib/services/CommandService';
|
||||
import KeymapService from '@joplin/lib/services/KeymapService';
|
||||
import shim from '@joplin/lib/shim';
|
||||
const { connect } = require('react-redux');
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
import SearchEngine from '@joplin/lib/services/search/SearchEngine';
|
||||
import SearchEngine, { ComplexTerm } from '@joplin/lib/services/search/SearchEngine';
|
||||
import gotoAnythingStyleQuery from '@joplin/lib/services/search/gotoAnythingStyleQuery';
|
||||
import BaseModel, { ModelType } from '@joplin/lib/BaseModel';
|
||||
import Tag from '@joplin/lib/models/Tag';
|
||||
@ -14,7 +13,7 @@ import Folder from '@joplin/lib/models/Folder';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
import ItemList from '../gui/ItemList';
|
||||
import HelpButton from '../gui/HelpButton';
|
||||
const { surroundKeywords, nextWhitespaceIndex, removeDiacritics } = require('@joplin/lib/string-utils.js');
|
||||
import { surroundKeywords, nextWhitespaceIndex, removeDiacritics } from '@joplin/lib/string-utils';
|
||||
import { mergeOverlappingIntervals } from '@joplin/lib/ArrayUtils';
|
||||
import markupLanguageUtils from '../utils/markupLanguageUtils';
|
||||
import focusEditorIfEditorCommand from '@joplin/lib/services/commands/focusEditorIfEditorCommand';
|
||||
@ -23,6 +22,7 @@ import { MarkupLanguage, MarkupToHtml } from '@joplin/renderer';
|
||||
import Resource from '@joplin/lib/models/Resource';
|
||||
import { NoteEntity, ResourceEntity } from '@joplin/lib/services/database/types';
|
||||
import Dialog from '../gui/Dialog';
|
||||
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
|
||||
|
||||
const logger = Logger.create('GotoAnything');
|
||||
|
||||
@ -129,8 +129,7 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
private inputRef: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
private itemListRef: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
private listUpdateIID_: any;
|
||||
private listUpdateQueue_: AsyncActionQueue;
|
||||
private markupToHtml_: MarkupToHtml;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
private userCallback_: any = null;
|
||||
@ -141,6 +140,7 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
const startString = props?.userData?.startString ? props?.userData?.startString : '';
|
||||
|
||||
this.userCallback_ = props?.userData?.callback;
|
||||
this.listUpdateQueue_ = new AsyncActionQueue(100);
|
||||
|
||||
this.state = {
|
||||
query: startString,
|
||||
@ -235,7 +235,7 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.listUpdateIID_) shim.clearTimeout(this.listUpdateIID_);
|
||||
void this.listUpdateQueue_.reset();
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'VISIBLE_DIALOGS_REMOVE',
|
||||
@ -263,12 +263,7 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
public scheduleListUpdate() {
|
||||
if (this.listUpdateIID_) shim.clearTimeout(this.listUpdateIID_);
|
||||
|
||||
this.listUpdateIID_ = shim.setTimeout(async () => {
|
||||
await this.updateList();
|
||||
this.listUpdateIID_ = null;
|
||||
}, 100);
|
||||
this.listUpdateQueue_.push(() => this.updateList());
|
||||
}
|
||||
|
||||
public async keywords(searchQuery: string) {
|
||||
@ -360,7 +355,6 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
}
|
||||
} else {
|
||||
const limit = 20;
|
||||
const searchKeywords = await this.keywords(searchQuery);
|
||||
|
||||
// Note: any filtering must be done **before** fetching the notes, because we're
|
||||
// going to apply a limit to the number of fetched notes.
|
||||
@ -381,6 +375,10 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
results = results.filter(r => !!notesById[r.id])
|
||||
.map(r => ({ ...r, title: notesById[r.id].title }));
|
||||
|
||||
const normalizedKeywords = (await this.keywords(searchQuery)).map(
|
||||
({ valueRegex }: ComplexTerm) => new RegExp(removeDiacritics(valueRegex), 'ig'),
|
||||
);
|
||||
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const row = results[i];
|
||||
const path = Folder.folderPathString(this.props.folders, row.parent_id);
|
||||
@ -388,21 +386,14 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
if (row.fields.includes('body')) {
|
||||
let fragments = '...';
|
||||
|
||||
if (i < limit) { // Display note fragments of search keyword matches
|
||||
const { markupLanguage, content } = getContentMarkupLanguageAndBody(
|
||||
row,
|
||||
notesById,
|
||||
resources,
|
||||
);
|
||||
|
||||
const loadFragments = (markupLanguage: MarkupLanguage, content: string) => {
|
||||
const indices = [];
|
||||
const body = this.markupToHtml().stripMarkup(markupLanguage, content, { collapseWhiteSpaces: true });
|
||||
const normalizedBody = removeDiacritics(body);
|
||||
|
||||
// Iterate over all matches in the body for each search keyword
|
||||
for (let { valueRegex } of searchKeywords) {
|
||||
valueRegex = removeDiacritics(valueRegex);
|
||||
|
||||
for (const match of removeDiacritics(body).matchAll(new RegExp(valueRegex, 'ig'))) {
|
||||
for (const keywordRegex of normalizedKeywords) {
|
||||
for (const match of normalizedBody.matchAll(keywordRegex)) {
|
||||
// Populate 'indices' with [begin index, end index] of each note fragment
|
||||
// Begins at the regex matching index, ends at the next whitespace after seeking 15 characters to the right
|
||||
indices.push([match.index, nextWhitespaceIndex(body, match.index + match[0].length + 15)]);
|
||||
@ -418,6 +409,19 @@ class DialogComponent extends React.PureComponent<Props, State> {
|
||||
fragments = mergedIndices.map((f: any) => body.slice(f[0], f[1])).join(' ... ');
|
||||
// Add trailing ellipsis if the final fragment doesn't end where the note is ending
|
||||
if (mergedIndices.length && mergedIndices[mergedIndices.length - 1][1] !== body.length) fragments += ' ...';
|
||||
};
|
||||
|
||||
if (i < limit) { // Display note fragments of search keyword matches
|
||||
const { markupLanguage, content } = getContentMarkupLanguageAndBody(
|
||||
row,
|
||||
notesById,
|
||||
resources,
|
||||
);
|
||||
|
||||
// Don't load fragments for long notes -- doing so can lead to UI freezes.
|
||||
if (content.length < 100_000) {
|
||||
loadFragments(markupLanguage, content);
|
||||
}
|
||||
}
|
||||
|
||||
results[i] = { ...row, path, fragments };
|
||||
|
@ -16,7 +16,7 @@ import { isCallbackUrl, parseCallbackUrl } from '../../callbackUrlUtils';
|
||||
import replaceUnsupportedCharacters from '../../utils/replaceUnsupportedCharacters';
|
||||
import { htmlentitiesDecode } from '@joplin/utils/html';
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const { pregQuote, scriptType, removeDiacritics } = require('../../string-utils.js');
|
||||
import { pregQuote, scriptType, removeDiacritics } from '../../string-utils';
|
||||
|
||||
enum SearchType {
|
||||
Auto = 'auto',
|
||||
@ -59,7 +59,7 @@ export interface ComplexTerm {
|
||||
value: string;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
scriptType: any;
|
||||
valueRegex?: RegExp;
|
||||
valueRegex?: string;
|
||||
}
|
||||
|
||||
export interface Terms {
|
||||
|
@ -2,7 +2,7 @@ const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = new Entities().encode;
|
||||
const stringUtilsCommon = require('./string-utils-common.js');
|
||||
|
||||
export const pregQuote = stringUtilsCommon.pregQuote;
|
||||
export const pregQuote = stringUtilsCommon.pregQuote as (str: string, delimiter?: string)=> string;
|
||||
export const replaceRegexDiacritics = stringUtilsCommon.replaceRegexDiacritics;
|
||||
|
||||
const defaultDiacriticsRemovalMap = [
|
||||
|
Loading…
Reference in New Issue
Block a user