Skip to content

Commit 8cd1004

Browse files
authored
Merge pull request #3690 from ilandikov/refactor/reuse-query-result
refactor: reuse `QueryResult`
2 parents 7d02ac0 + 1fee494 commit 8cd1004

File tree

4 files changed

+35
-40
lines changed

4 files changed

+35
-40
lines changed

src/Renderer/HtmlQueryResultsRenderer.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,23 +102,23 @@ export class HtmlQueryResultsRenderer extends QueryResultsRendererBase {
102102
explanationsBlock.textContent = explanation;
103103
}
104104

105-
private addToolbar(_queryResult: QueryResult) {
105+
private addToolbar(queryResult: QueryResult) {
106106
if (this.getters.query().queryLayoutOptions.hideToolbar) {
107107
return;
108108
}
109109

110110
const toolbar = createAndAppendElement('div', this.content);
111111
toolbar.classList.add('plugin-tasks-toolbar');
112-
this.addCopyButton(toolbar);
112+
this.addCopyButton(toolbar, queryResult);
113113
}
114114

115-
private addCopyButton(toolbar: HTMLDivElement): void {
115+
private addCopyButton(toolbar: HTMLDivElement, queryResult: QueryResult): void {
116116
const copyButton = createAndAppendElement('button', toolbar);
117117
setIcon(copyButton, 'lucide-copy');
118118
setTooltip(copyButton, 'Copy results');
119119
copyButton.addEventListener('click', async () => {
120120
// TODO reimplement this using QueryResult.asMarkdown() when it supports trees and list items.
121-
await this.markdownRenderer.renderQuery(State.Warm, this.queryRendererParameters.allTasks());
121+
await this.markdownRenderer.renderQuery(State.Warm, queryResult);
122122
await navigator.clipboard.writeText(this.markdownRenderer.markdown);
123123
new Notice('Results copied to clipboard');
124124
});

src/Renderer/QueryResultsRenderer.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { App, Component, TFile } from 'obsidian';
22
import { GlobalQuery } from '../Config/GlobalQuery';
33
import type { IQuery } from '../IQuery';
4+
import { PerformanceTracker } from '../lib/PerformanceTracker';
45
import type { State } from '../Obsidian/Cache';
56
import { getQueryForQueryRenderer } from '../Query/QueryRendererHelper';
67
import type { TasksFile } from '../Scripting/TasksFile';
@@ -138,8 +139,16 @@ export class QueryResultsRenderer {
138139
return this.tasksFile.path;
139140
}
140141

141-
public async render(state: State | State.Warm, tasks: Task[], content: HTMLDivElement) {
142+
public async render(state: State, tasks: Task[], content: HTMLDivElement) {
143+
const measureSearch = new PerformanceTracker(`Search: ${this.query.queryId} - ${this.filePath}`);
144+
measureSearch.start();
145+
const queryResult = this.query.applyQueryToTasks(tasks);
146+
measureSearch.finish();
147+
148+
const measureRender = new PerformanceTracker(`Render: ${this.query.queryId} - ${this.filePath}`);
149+
measureRender.start();
142150
this.htmlRenderer.content = content;
143-
await this.htmlRenderer.renderQuery(state, tasks);
151+
await this.htmlRenderer.renderQuery(state, queryResult);
152+
measureRender.finish();
144153
}
145154
}

src/Renderer/QueryResultsRendererBase.ts

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
1-
import type { TasksFile } from '../Scripting/TasksFile';
1+
import { GlobalFilter } from '../Config/GlobalFilter';
2+
import { GlobalQuery } from '../Config/GlobalQuery';
23
import type { IQuery } from '../IQuery';
34
import { State } from '../Obsidian/Cache';
4-
import { Task } from '../Task/Task';
5-
import type { QueryResult } from '../Query/QueryResult';
6-
import type { TaskGroups } from '../Query/Group/TaskGroups';
7-
import type { ListItem } from '../Task/ListItem';
85
import type { GroupDisplayHeading } from '../Query/Group/GroupDisplayHeading';
9-
import { PerformanceTracker } from '../lib/PerformanceTracker';
6+
import type { TaskGroups } from '../Query/Group/TaskGroups';
107
import { explainResults } from '../Query/QueryRendererHelper';
11-
import { GlobalFilter } from '../Config/GlobalFilter';
12-
import { GlobalQuery } from '../Config/GlobalQuery';
8+
import type { QueryResult } from '../Query/QueryResult';
9+
import type { TasksFile } from '../Scripting/TasksFile';
10+
import type { ListItem } from '../Task/ListItem';
11+
import { Task } from '../Task/Task';
1312

1413
/**
1514
* Because properties in QueryResultsRenderer may be modified during the lifetime of this class,
@@ -34,7 +33,7 @@ export abstract class QueryResultsRendererBase {
3433
return this.getters.tasksFile().path;
3534
}
3635

37-
public async renderQuery(state: State | State.Warm, tasks: Task[]) {
36+
public async renderQuery(state: State, queryResult: QueryResult) {
3837
this.beginRender();
3938

4039
// Don't log anything here, for any state, as it generates huge amounts of
@@ -43,8 +42,7 @@ export abstract class QueryResultsRendererBase {
4342
const query = this.getters.query();
4443
const error = query.error;
4544
if (state === State.Warm && error === undefined) {
46-
query.debug(`[render] Render called: plugin state: ${state}; searching ${tasks.length} tasks`);
47-
await this.renderQuerySearchResults(tasks);
45+
await this.renderQuerySearchResults(queryResult);
4846
} else if (error) {
4947
this.renderErrorMessage(error);
5048
} else {
@@ -59,8 +57,8 @@ export abstract class QueryResultsRendererBase {
5957
*/
6058
protected abstract beginRender(): void;
6159

62-
private async renderQuerySearchResults(tasks: Task[]) {
63-
const queryResult = this.explainAndPerformSearch(tasks);
60+
private async renderQuerySearchResults(queryResult: QueryResult) {
61+
this.explainQuery();
6462

6563
if (queryResult.searchErrorMessage !== undefined) {
6664
// There was an error in the search, for example due to a problem custom function.
@@ -71,10 +69,7 @@ export abstract class QueryResultsRendererBase {
7169
await this.renderSearchResults(queryResult);
7270
}
7371

74-
private explainAndPerformSearch(tasks: Task[]) {
75-
const measureSearch = new PerformanceTracker(`Search: ${this.getters.query().queryId} - ${this.filePath}`);
76-
measureSearch.start();
77-
72+
private explainQuery() {
7873
if (this.getters.query().queryLayoutOptions.explainQuery) {
7974
const explanation = explainResults(
8075
this.getters.source(),
@@ -84,17 +79,9 @@ export abstract class QueryResultsRendererBase {
8479
);
8580
this.renderExplanation(explanation);
8681
}
87-
88-
const queryResult = this.getters.query().applyQueryToTasks(tasks);
89-
90-
measureSearch.finish();
91-
return queryResult;
9282
}
9383

9484
private async renderSearchResults(queryResult: QueryResult) {
95-
const measureRender = new PerformanceTracker(`Render: ${this.getters.query().queryId} - ${this.filePath}`);
96-
measureRender.start();
97-
9885
this.renderSearchResultsHeader(queryResult);
9986

10087
await this.addAllTaskGroups(queryResult.taskGroups);
@@ -103,8 +90,6 @@ export abstract class QueryResultsRendererBase {
10390
this.getters.query().debug(`[render] ${totalTasksCount} tasks displayed`);
10491

10592
this.renderSearchResultsFooter(queryResult);
106-
107-
measureRender.finish();
10893
}
10994

11095
protected abstract renderSearchResultsHeader(queryResult: QueryResult): void;

tests/Renderer/MarkdownQueryResultsRenderer.test.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,17 @@ window.moment = moment;
1515
function createMarkdownRenderer(source: string) {
1616
const tasksFile = new TasksFile('query.md');
1717
const query = new Query(source, tasksFile);
18-
return new MarkdownQueryResultsRenderer({
18+
const renderer = new MarkdownQueryResultsRenderer({
1919
query: () => query,
2020
tasksFile: () => tasksFile,
2121
source: () => source,
2222
});
23+
return { renderer, query };
2324
}
2425

2526
async function renderMarkdown(source: string, tasks: Task[]) {
26-
const renderer = createMarkdownRenderer(source);
27-
await renderer.renderQuery(State.Warm, tasks);
27+
const { renderer, query } = createMarkdownRenderer(source);
28+
await renderer.renderQuery(State.Warm, query.applyQueryToTasks(tasks));
2829
return '\n' + renderer.markdown;
2930
}
3031

@@ -51,14 +52,14 @@ describe('MarkdownQueryResultsRenderer tests', () => {
5152

5253
it('should render single task twice', async () => {
5354
const source = 'hide tree';
54-
const renderer = createMarkdownRenderer(source);
55+
const { renderer, query } = createMarkdownRenderer(source);
5556

56-
const task = new TaskBuilder().description('hello').priority(Priority.Medium).build();
57+
const task = [new TaskBuilder().description('hello').priority(Priority.Medium).build()];
5758

58-
await renderer.renderQuery(State.Warm, [task]);
59+
await renderer.renderQuery(State.Warm, query.applyQueryToTasks(task));
5960
const r1 = renderer.markdown;
6061

61-
await renderer.renderQuery(State.Warm, [task]);
62+
await renderer.renderQuery(State.Warm, query.applyQueryToTasks(task));
6263
const r2 = renderer.markdown;
6364

6465
expect(r1).toEqual(r2);

0 commit comments

Comments
 (0)