From 28bcf2d8740d55e2b6acb48d34bd94089902ff9b Mon Sep 17 00:00:00 2001 From: huaqo Date: Fri, 24 Apr 2026 10:04:32 +0200 Subject: [PATCH] refactor: more oop style files --- src/AnnotationModal.ts | 58 +++++++ src/CiteModal.ts | 68 +++++++++ src/OpenModal.ts | 45 ++++++ src/Utils.ts | 71 +++++++++ src/{clients.ts => ZoteroClient.ts} | 0 src/main.ts | 4 +- src/modals.ts | 228 ---------------------------- 7 files changed, 245 insertions(+), 229 deletions(-) create mode 100644 src/AnnotationModal.ts create mode 100644 src/CiteModal.ts create mode 100644 src/OpenModal.ts create mode 100644 src/Utils.ts rename src/{clients.ts => ZoteroClient.ts} (100%) delete mode 100644 src/modals.ts diff --git a/src/AnnotationModal.ts b/src/AnnotationModal.ts new file mode 100644 index 0000000..4d686ba --- /dev/null +++ b/src/AnnotationModal.ts @@ -0,0 +1,58 @@ +import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian'; +import { ZoteroClient } from "./ZoteroClient"; +import { ZoteroAnnotation } from "./ZoteroAnnotation"; +import { loadAnnotations, renderZoteroAnnotation } from "./Utils" + +const ZOTERO_BASE_URL = "zotero://select/library/items/"; + +export class AnnotationModal extends FuzzySuggestModal { + private client: ZoteroClient; + private annotations: ZoteroAnnotation[] = []; + private createLink: boolean; + private onChoose: (annotations: string) => void; + + constructor( + app: App, + port: string, + createLink: boolean, + style: string, + onChoose: (annotations: string) => void, + ) { + super(app); + this.client = new ZoteroClient(port, style); + this.setPlaceholder("Loading..."); + this.createLink = createLink + this.onChoose = onChoose; + } + + async onOpen(){ + this.annotations = await loadAnnotations(this.client); + super.onOpen(); + } + + getItems(): ZoteroAnnotation[] { + return this.annotations; + } + + + getItemText(annotation: ZoteroAnnotation): string { + return annotation.toString(); + } + + renderSuggestion(match: FuzzyMatch, el: HTMLElement) { + renderZoteroAnnotation(match, el); + } + + async onChooseItem(annotation: ZoteroAnnotation) { + + let citation = annotation.parentItem.citation; + + if (this.createLink) { + citation = `[${citation}](${ZOTERO_BASE_URL}${annotation.parentItemKey})`; + } + + this.onChoose(`"${annotation.text}" ${citation}`); + } + +} + diff --git a/src/CiteModal.ts b/src/CiteModal.ts new file mode 100644 index 0000000..43d7509 --- /dev/null +++ b/src/CiteModal.ts @@ -0,0 +1,68 @@ +import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian'; +import { ZoteroClient } from "./ZoteroClient"; +import { ZoteroItem } from "./ZoteroItem"; + +const ZOTERO_BASE_URL = "zotero://select/library/items/"; + +export class CiteModal extends FuzzySuggestModal { + + private onChoose: (reference: string) => void; + private client: ZoteroClient; + private items: ZoteroItem[] = []; + private createLink: boolean; + private mode: string; + + constructor( + app: App, + port: string, + createLink: boolean, + style: string, + mode: string, + onChoose: (reference: string) => void, + ) { + super(app); + this.setPlaceholder("Loading..."); + this.client = new ZoteroClient(port, style); + this.createLink = createLink; + this.mode = mode; + this.onChoose = onChoose; + } + + async onOpen(){ + this.items = await loadItems(this, this.client); + super.onOpen(); + } + + getItems(): ZoteroItem[] { + return this.items; + } + + getItemText(item: ZoteroItem): string { + return item.toString(); + } + + renderSuggestion(match: FuzzyMatch, el: HTMLElement) { + renderZoteroItem(match, el); + } + + onChooseItem(item: ZoteroItem) { + + let output = ""; + + if (this.mode === "citation"){ + output = item.citation; + } else if (this.mode === "bibliography"){ + output = item.bibliography; + } else { + throw new Error(`Unknown mode: ${this.mode}`); + } + + if (!this.createLink) { + this.onChoose(output); + } else { + this.onChoose(`[${output}](${ZOTERO_BASE_URL}${item.key})`); + } + + } + +} diff --git a/src/OpenModal.ts b/src/OpenModal.ts new file mode 100644 index 0000000..5713cc2 --- /dev/null +++ b/src/OpenModal.ts @@ -0,0 +1,45 @@ +import { shell } from "electron"; +import { App, FuzzyMatch, FuzzySuggestModal } from 'obsidian'; +import { ZoteroClient } from "./ZoteroClient"; +import { ZoteroItem } from "./ZoteroItem"; + +const ZOTERO_BASE_URL = "zotero://select/library/items/"; + +export class OpenModal extends FuzzySuggestModal { + private client: ZoteroClient; + private items: ZoteroItem[] = []; + + constructor( + app: App, + port: string, + ) { + super(app); + this.client = new ZoteroClient(port); + this.setPlaceholder("Loading..."); + } + + async onOpen(){ + this.items = await loadItems(this, this.client); + super.onOpen(); + } + + getItems(): ZoteroItem[] { + return this.items; + } + + getItemText(item: ZoteroItem): string { + return item.toString(); + } + + renderSuggestion(match: FuzzyMatch, el: HTMLElement) { + renderZoteroItem(match, el); + } + + onChooseItem(item: ZoteroItem) { + if (!item.key) return; + const uri = `${ZOTERO_BASE_URL}${item.key}`; + shell.openExternal(uri); + } + +} + diff --git a/src/Utils.ts b/src/Utils.ts new file mode 100644 index 0000000..8334421 --- /dev/null +++ b/src/Utils.ts @@ -0,0 +1,71 @@ +import { renderResults, Notice } from "obsidian"; + +export function renderZoteroItem( + match: FuzzyMatch, + el: HTMLElement +) { + const { item } = match; + + const titleEl = el.createDiv(); + renderResults(titleEl, item.title, match.match); + + const subtitleEl = el.createEl("small"); + const offset = -(item.title.length + 1); + renderResults( + subtitleEl, + `${item.creators}, ${item.year}`, + match.match, + offset + ); +} + +export function renderZoteroAnnotation( + match: FuzzyMatch, + el: HTMLElement +) { + const { item: annotation } = match; + + const titleEl = el.createDiv(); + renderResults(titleEl, annotation.text, match.match); + + const subtitleEl = el.createEl("small"); + const offset = -(annotation.text.length + 1); + renderResults(subtitleEl, annotation.parentItem.toStringShort(), match.match, offset); +} + +export async function loadItems( + modal: FuzzySuggestModal, + client: ZoteroClient, +): Promise { + try { + const items = await client.getItemsTop(); + modal.setPlaceholder("Search Zotero..."); + modal.inputEl.disabled = false; + modal.inputEl.focus(); + modal.updateSuggestions(); + return items; + } catch (error) { + new Notice( + "Failed to load citations/bibliographies from Zotero." + ); + console.error(error); + modal.close(); + return []; + } +} + +export async function loadAnnotations( + client: ZoteroClient, +): Promise { + + try { + const annotations = await client.getAnnotations(); + return annotations; + } catch (error) { + new Notice( + "Failed to load annotations from Zotero." + ); + console.error(error); + return []; + } +} diff --git a/src/clients.ts b/src/ZoteroClient.ts similarity index 100% rename from src/clients.ts rename to src/ZoteroClient.ts diff --git a/src/main.ts b/src/main.ts index 86e63ff..2171701 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,8 @@ import { App, Editor, MarkdownView, Modal, Plugin, Notice } from 'obsidian'; import { DEFAULT_SETTINGS, Settings, SettingTab } from "./settings"; -import { CiteModal, OpenModal, AnnotationModal } from "./modals" +import { CiteModal } from "./CiteModal"; +import { OpenModal } from "./OpenModal"; +import { AnnotationModal } from "./AnnotationModal"; export default class Cite extends Plugin { settings: Settings; diff --git a/src/modals.ts b/src/modals.ts deleted file mode 100644 index ec67bc5..0000000 --- a/src/modals.ts +++ /dev/null @@ -1,228 +0,0 @@ -import { shell } from "electron"; -import { App, FuzzyMatch, FuzzySuggestModal, renderResults, Notice } from 'obsidian'; -import { ZoteroClient } from "./clients"; -import { ZoteroItem } from "./ZoteroItem"; -import { ZoteroAnnotation } from "./ZoteroAnnotation"; - -const ZOTERO_BASE_URL = "zotero://select/library/items/"; - -function renderZoteroItem( - match: FuzzyMatch, - el: HTMLElement -) { - const { item } = match; - - const titleEl = el.createDiv(); - renderResults(titleEl, item.title, match.match); - - const subtitleEl = el.createEl("small"); - const offset = -(item.title.length + 1); - renderResults( - subtitleEl, - `${item.creators}, ${item.year}`, - match.match, - offset - ); -} - -function renderZoteroAnnotation( - match: FuzzyMatch, - el: HTMLElement -) { - const { item: annotation } = match; - - const titleEl = el.createDiv(); - renderResults(titleEl, annotation.text, match.match); - - const subtitleEl = el.createEl("small"); - const offset = -(annotation.text.length + 1); - renderResults(subtitleEl, annotation.parentItem.toStringShort(), match.match, offset); -} - -async function loadItems( - modal: FuzzySuggestModal, - client: ZoteroClient, -): Promise { - try { - const items = await client.getItemsTop(); - modal.setPlaceholder("Search Zotero..."); - modal.inputEl.disabled = false; - modal.inputEl.focus(); - modal.updateSuggestions(); - return items; - } catch (error) { - new Notice( - "Failed to load citations/bibliographies from Zotero." - ); - console.error(error); - modal.close(); - return []; - } -} - -async function loadAnnotations( - client: ZoteroClient, -): Promise { - - try { - const annotations = await client.getAnnotations(); - return annotations; - } catch (error) { - new Notice( - "Failed to load annotations from Zotero." - ); - console.error(error); - return []; - } -} - -export class AnnotationModal extends FuzzySuggestModal { - private client: ZoteroClient; - private annotations: ZoteroAnnotation[] = []; - private createLink: boolean; - private onChoose: (annotations: string) => void; - - constructor( - app: App, - port: string, - createLink: boolean, - style: string, - onChoose: (annotations: string) => void, - ) { - super(app); - this.client = new ZoteroClient(port, style); - this.setPlaceholder("Loading..."); - this.createLink = createLink - this.onChoose = onChoose; - } - - async onOpen(){ - this.annotations = await loadAnnotations(this.client); - super.onOpen(); - } - - getItems(): ZoteroAnnotation[] { - return this.annotations; - } - - getItemText(annotation: ZoteroAnnotation): string { - return annotation.toString(); - } - - renderSuggestion(match: FuzzyMatch, el: HTMLElement) { - renderZoteroAnnotation(match, el); - } - - async onChooseItem(annotation: ZoteroAnnotation) { - - let citation = annotation.parentItem.citation; - - if (this.createLink) { - citation = `[${citation}](${ZOTERO_BASE_URL}${annotation.parentItemKey})`; - } - - this.onChoose(`"${annotation.text}" ${citation}`); - } - -} - -export class OpenModal extends FuzzySuggestModal { - private client: ZoteroClient; - private items: ZoteroItem[] = []; - - constructor( - app: App, - port: string, - ) { - super(app); - this.client = new ZoteroClient(port); - this.setPlaceholder("Loading..."); - } - - async onOpen(){ - this.items = await loadItems(this, this.client); - super.onOpen(); - } - - getItems(): ZoteroItem[] { - return this.items; - } - - getItemText(item: ZoteroItem): string { - return item.toString(); - } - - renderSuggestion(match: FuzzyMatch, el: HTMLElement) { - renderZoteroItem(match, el); - } - - onChooseItem(item: ZoteroItem) { - if (!item.key) return; - const uri = `${ZOTERO_BASE_URL}${item.key}`; - shell.openExternal(uri); - } - -} - -export class CiteModal extends FuzzySuggestModal { - - private onChoose: (reference: string) => void; - private client: ZoteroClient; - private items: ZoteroItem[] = []; - private createLink: boolean; - private mode: string; - - constructor( - app: App, - port: string, - createLink: boolean, - style: string, - mode: string, - onChoose: (reference: string) => void, - ) { - super(app); - this.setPlaceholder("Loading..."); - this.client = new ZoteroClient(port, style); - this.createLink = createLink; - this.mode = mode; - this.onChoose = onChoose; - } - - async onOpen(){ - this.items = await loadItems(this, this.client); - super.onOpen(); - } - - getItems(): ZoteroItem[] { - return this.items; - } - - getItemText(item: ZoteroItem): string { - return item.toString(); - } - - renderSuggestion(match: FuzzyMatch, el: HTMLElement) { - renderZoteroItem(match, el); - } - - onChooseItem(item: ZoteroItem) { - - let output = ""; - - if (this.mode === "citation"){ - output = item.citation; - } else if (this.mode === "bibliography"){ - output = item.bibliography; - } else { - throw new Error(`Unknown mode: ${this.mode}`); - } - - if (!this.createLink) { - this.onChoose(output); - } else { - this.onChoose(`[${output}](${ZOTERO_BASE_URL}${item.key})`); - } - - } - -}