Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | 32x 32x 32x 32x 32x 32x 32x 32x 32x 32x 32x 26x 26x 26x 26x 26x 26x 5x 5x 26x 26x 26x 26x 26x 33x 7x 26x 26x 5x 5x 32x 31x 31x 31x 40x 38x 6x 6x 4x 4x 4x 4x 3x 3x 2x 2x 1x | import { App, Modal, Notice } from "obsidian";
import type LilbeePlugin from "../main";
import { ConfirmModal } from "./confirm-modal";
import { DocumentList } from "../components/document-list";
import { MESSAGES } from "../locales/en";
import { bindEscapeToClose, debounce, DEBOUNCE_MS } from "../utils";
export class DocumentsModal extends Modal {
private plugin: LilbeePlugin;
private list: DocumentList | null = null;
private unbindScroll: (() => void) | null = null;
private resultsEl: HTMLElement | null = null;
private removeBtn: HTMLElement | null = null;
private searchQuery = "";
private debouncedSearch: () => void;
private cancelDebouncedSearch: () => void;
constructor(app: App, plugin: LilbeePlugin) {
super(app);
this.plugin = plugin;
const searchDebounced = debounce(() => this.resetAndFetch(), DEBOUNCE_MS);
this.debouncedSearch = searchDebounced.run;
this.cancelDebouncedSearch = searchDebounced.cancel;
bindEscapeToClose(this);
}
onOpen(): void {
const { contentEl } = this;
contentEl.empty();
contentEl.addClass("lilbee-documents-modal");
contentEl.createEl("h2", { text: MESSAGES.TITLE_DOCUMENTS });
const searchInput = contentEl.createEl("input", {
cls: "lilbee-documents-search",
placeholder: MESSAGES.PLACEHOLDER_SEARCH_DOCUMENTS,
attr: { type: "text" },
});
searchInput.addEventListener("input", () => {
this.searchQuery = searchInput.value;
this.debouncedSearch();
});
this.removeBtn = contentEl.createEl("button", {
text: MESSAGES.BUTTON_DELETE_SELECTED,
cls: "lilbee-documents-remove",
});
(this.removeBtn as HTMLButtonElement).disabled = true;
this.removeBtn.addEventListener("click", () => void this.removeSelected());
this.resultsEl = contentEl.createDiv({ cls: "lilbee-documents-results" });
this.list = new DocumentList(
this.resultsEl,
(limit, offset) => this.plugin.api.listDocuments(this.searchQuery || undefined, limit, offset),
{ selectable: true, onSelectionChange: () => this.updateRemoveBtn() },
);
this.unbindScroll = this.list.bindScroll(this.resultsEl);
this.resetAndFetch();
}
onClose(): void {
this.cancelDebouncedSearch();
this.unbindScroll?.();
}
private resetAndFetch(): void {
if (!this.list) return;
this.list.reset();
this.updateRemoveBtn();
void this.list.loadMore();
}
private updateRemoveBtn(): void {
if (!this.removeBtn || !this.list) return;
(this.removeBtn as HTMLButtonElement).disabled = this.list.selected.length === 0;
}
private async removeSelected(): Promise<void> {
const names = this.list?.selected ?? [];
if (names.length === 0) return;
const confirm = new ConfirmModal(this.app, MESSAGES.NOTICE_CONFIRM_DELETE_DOCS(names.length));
confirm.open();
const confirmed = await confirm.result;
if (!confirmed) return;
try {
const result = await this.plugin.api.removeDocuments(names);
new Notice(MESSAGES.NOTICE_DELETED(result.removed));
this.resetAndFetch();
} catch {
new Notice(MESSAGES.ERROR_DELETE_DOCUMENTS);
}
}
}
|