Skip to content

Commit

Permalink
add search
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicoptima committed Jul 15, 2023
1 parent c23b166 commit f3ba15a
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 6 deletions.
5 changes: 5 additions & 0 deletions common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,27 @@ export interface LoomSettings {
n: number;

showSettings: boolean;
showSearchBar: boolean;
showNodeBorders: boolean;
showExport: boolean;
}

export type SearchResultState = "result" | "ancestor" | "none" | null;

export interface Node {
text: string;
parentId: string | null;
collapsed: boolean;
unread: boolean;
bookmarked: boolean;
lastVisited?: number;
searchResultState: SearchResultState;
}

export interface NoteState {
current: string;
hoisted: string[];
searchTerm: string;
nodes: Record<string, Node>;
generating: string | null;
}
52 changes: 51 additions & 1 deletion main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ import {
loomEditorPluginSpec,
MakePromptFromPassagesModal,
} from './views';
import { PROVIDERS, Provider, LoomSettings, Node, NoteState } from './common';
import {
PROVIDERS,
Provider,
LoomSettings,
SearchResultState,
Node,
NoteState
} from './common';

import {
App,
Expand Down Expand Up @@ -69,6 +76,7 @@ const DEFAULT_SETTINGS: LoomSettings = {
n: 5,

showSettings: false,
showSearchBar: false,
showNodeBorders: false,
showExport: false,
};
Expand Down Expand Up @@ -153,6 +161,7 @@ export default class LoomPlugin extends Plugin {
collapsed: false,
unread,
bookmarked: false,
searchResultState: null,
};
return [id, node];
}
Expand All @@ -162,6 +171,7 @@ export default class LoomPlugin extends Plugin {
this.state[file.path] = {
current: rootId,
hoisted: [] as string[],
searchTerm: "",
nodes: { [rootId]: root },
generating: null,
};
Expand Down Expand Up @@ -582,6 +592,7 @@ export default class LoomPlugin extends Plugin {
this.state[view.file.path] = {
current,
hoisted: [] as string[],
searchTerm: "",
nodes: { [current]: node },
generating: null,
};
Expand Down Expand Up @@ -920,6 +931,45 @@ export default class LoomPlugin extends Plugin {
)
);

this.registerEvent(
// @ts-expect-error
this.app.workspace.on("loom:search", (term: string) => this.withFile((file) => {
const state = this.state[file.path];

this.state[file.path].searchTerm = term;
if (!term) {
Object.keys(state.nodes).forEach((id) => {
this.state[file.path].nodes[id].searchResultState = null;
});
this.save(); // don't re-render
return;
}

const matches = Object.entries(state.nodes)
.filter(([, node]) => node.text.toLowerCase().includes(term.toLowerCase()))
.map(([id]) => id);

let ancestors: string[] = [];
for (const id of matches) {
let parentId = state.nodes[id].parentId;
while (parentId !== null) {
ancestors.push(parentId);
parentId = state.nodes[parentId].parentId;
}
}

Object.keys(state.nodes).forEach((id) => {
let searchResultState: SearchResultState;
if (matches.includes(id)) searchResultState = "result";
else if (ancestors.includes(id)) searchResultState = "ancestor";
else searchResultState = "none";
this.state[file.path].nodes[id].searchResultState = searchResultState;
});

this.save();
}))
);

this.registerEvent(
// @ts-expect-error
this.app.workspace.on("loom:import", (path: string) =>
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "loom",
"name": "Loom",
"version": "1.14.2",
"version": "1.15.0",
"minAppVersion": "0.15.0",
"description": "Loom in Obsidian",
"author": "celeste",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-loom",
"version": "1.14.2",
"version": "1.15.0",
"description": "Loom in Obsidian",
"main": "main.js",
"scripts": {
Expand Down
22 changes: 21 additions & 1 deletion styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,14 @@ body {
flex-grow: 1;
}
.loom__alt-export-field button {
margin-left: 0.5em;
margin-left: 0.6em;
}

/* search bar */

.loom__search-bar {
width: 100%;
margin-bottom: 0.8em;
}

/* settings */
Expand Down Expand Up @@ -131,6 +138,19 @@ body {
margin-right: -0.3em;
}

.loom__node-search-result {
background-color: rgba(255, 255, 0, 0.1);
}
.loom__node-search-result.is-active {
background-color: rgba(255, 255, 0, 0.2);
}
.loom__node-search-result:hover {
background-color: rgba(255, 255, 0, 0.2) !important;
}
.loom__node-search-result:not(:hover) {
padding-right: 0.3em;
}

.loom__node-unread {
font-weight: bold !important;
}
Expand Down
37 changes: 35 additions & 2 deletions views.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export class LoomView extends ItemView {
getNoteState: () => NoteState | null;
getSettings: () => LoomSettings;

tree: HTMLElement;

constructor(
leaf: WorkspaceLeaf,
getNoteState: () => NoteState | null,
Expand Down Expand Up @@ -42,14 +44,16 @@ export class LoomView extends ItemView {
this.renderNavButtons(settings);
const container = this.containerEl.createDiv({ cls: "outline" });
if (settings.showExport) this.renderAltExportInterface(container);
if (settings.showSearchBar) this.renderSearchBar(container, state);
if (settings.showSettings) this.renderSettings(container, settings);

if (!state) {
container.createDiv({ cls: "pane-empty", text: "No note selected." });
return;
}
this.renderBookmarks(container, state);
this.renderTree(container, state);
this.tree = container.createDiv();
this.renderTree(this.tree, state);

this.containerEl.scrollTop = scroll;
}
Expand Down Expand Up @@ -81,6 +85,12 @@ export class LoomView extends ItemView {
"settings",
"Show settings"
);
settingNavButton(
"showSearchBar",
settings.showSearchBar,
"search",
"Show search bar"
);
settingNavButton(
"showNodeBorders",
settings.showNodeBorders,
Expand Down Expand Up @@ -142,6 +152,19 @@ export class LoomView extends ItemView {
});
}

renderSearchBar(container: HTMLElement, state: NoteState | null) {
const searchBar = container.createEl("input", {
cls: "loom__search-bar",
value: state?.searchTerm || "",
attr: { type: "text", placeholder: "Search..." },
});
searchBar.addEventListener("input", () => {
const state = this.getNoteState();
this.app.workspace.trigger("loom:search", searchBar.value);
if (state) this.renderTree(this.tree, state);
});
}

renderSettings(container: HTMLElement, settings: LoomSettings) {
const settingsContainer = container.createDiv({ cls: "loom__settings" });

Expand Down Expand Up @@ -230,12 +253,18 @@ export class LoomView extends ItemView {
}

renderTree(container: HTMLElement, state: NoteState) {
container.empty();

const treeHeader = container.createDiv({
cls: "tree-item-self loom__tree-header"
});
let headerText;
if (state.searchTerm) headerText = "Search results";
else if (state.hoisted.length > 0) headerText = "Hoisted node";
else headerText = "All nodes";
treeHeader.createSpan({
cls: "tree-item-inner loom__tree-header-text",
text: state.hoisted.length > 0 ? "Hoisted node" : "All nodes"
text: headerText,
});

if (state.hoisted.length > 0)
Expand All @@ -257,13 +286,17 @@ export class LoomView extends ItemView {
) {
const node = state.nodes[id];

if (inTree && node.searchResultState === "none") return;

const branchContainer = container.createDiv({});

const nodeContainer = branchContainer.createDiv({
cls: "is-clickable outgoing-link-item tree-item-self loom__node",
attr: { id: inTree ? `loom__node-${id}` : null },
});
if (id === state.current) nodeContainer.addClass("is-active");
if (node.searchResultState === "result")
nodeContainer.addClass("loom__node-search-result");
if (node.unread) nodeContainer.addClass("loom__node-unread");

const children = Object.entries(state.nodes)
Expand Down

0 comments on commit f3ba15a

Please sign in to comment.