AT protocol bookmarking platforms in obsidian
1import { Modal, Notice } from "obsidian";
2import type ATmarkPlugin from "../main";
3import { createMarginCollection } from "../lib";
4
5export class CreateMarginCollectionModal extends Modal {
6 plugin: ATmarkPlugin;
7 onSuccess?: () => void;
8
9 constructor(plugin: ATmarkPlugin, onSuccess?: () => void) {
10 super(plugin.app);
11 this.plugin = plugin;
12 this.onSuccess = onSuccess;
13 }
14
15 onOpen() {
16 const { contentEl } = this;
17 contentEl.empty();
18 contentEl.addClass("atmark-modal");
19
20 contentEl.createEl("h2", { text: "New margin collection" });
21
22 if (!this.plugin.client) {
23 // contentEl.createEl("p", { text: "Not Logged In. Please Login Using Settings." });
24 return;
25 }
26
27 const form = contentEl.createEl("form", { cls: "atmark-form" });
28
29 const nameGroup = form.createEl("div", { cls: "atmark-form-group" });
30 nameGroup.createEl("label", { text: "Name", attr: { for: "collection-name" } });
31 const nameInput = nameGroup.createEl("input", {
32 type: "text",
33 cls: "atmark-input",
34 attr: { id: "collection-name", placeholder: "Collection name", required: "true" },
35 });
36
37 const iconGroup = form.createEl("div", { cls: "atmark-form-group" });
38 iconGroup.createEl("label", { text: "Icon (optional)", attr: { for: "collection-icon" } });
39 const iconInput = iconGroup.createEl("input", {
40 type: "text",
41 cls: "atmark-input",
42 attr: { id: "collection-icon" },
43 });
44
45 const descGroup = form.createEl("div", { cls: "atmark-form-group" });
46 descGroup.createEl("label", { text: "Description", attr: { for: "collection-desc" } });
47 const descInput = descGroup.createEl("textarea", {
48 cls: "atmark-textarea",
49 attr: { id: "collection-desc", placeholder: "Optional description", rows: "3" },
50 });
51
52 const actions = form.createEl("div", { cls: "atmark-modal-actions" });
53
54 const cancelBtn = actions.createEl("button", {
55 text: "Cancel",
56 cls: "atmark-btn atmark-btn-secondary",
57 type: "button",
58 });
59 cancelBtn.addEventListener("click", () => this.close());
60
61 const createBtn = actions.createEl("button", {
62 text: "Create",
63 cls: "atmark-btn atmark-btn-primary",
64 type: "submit",
65 });
66
67 form.addEventListener("submit", (e) => {
68 e.preventDefault();
69 void this.handleSubmit(nameInput, iconInput, descInput, createBtn);
70 });
71
72 nameInput.focus();
73 }
74
75 private async handleSubmit(
76 nameInput: HTMLInputElement,
77 iconInput: HTMLInputElement,
78 descInput: HTMLTextAreaElement,
79 createBtn: HTMLButtonElement
80 ) {
81 const name = nameInput.value.trim();
82 if (!name) {
83 new Notice("Please enter a collection name");
84 return;
85 }
86
87 createBtn.disabled = true;
88 createBtn.textContent = "Creating...";
89
90 try {
91 await createMarginCollection(
92 this.plugin.client,
93 this.plugin.settings.identifier,
94 name,
95 descInput.value.trim() || undefined,
96 iconInput.value.trim() || undefined
97 );
98
99 new Notice(`Created collection "${name}"`);
100 this.close();
101 this.onSuccess?.();
102 } catch (err) {
103 const message = err instanceof Error ? err.message : String(err);
104 new Notice(`Failed to create collection: ${message}`);
105 createBtn.disabled = false;
106 createBtn.textContent = "Create";
107 }
108 }
109
110 onClose() {
111 this.contentEl.empty();
112 }
113}