AT protocol bookmarking platforms in obsidian
1import { Modal, Notice } from "obsidian";
2import type ATmarkPlugin from "../main";
3import { createCollection } from "../lib";
4
5export class CreateCollectionModal 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 collection" });
21
22 if (!this.plugin.client) {
23 contentEl.createEl("p", { text: "Not connected." });
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 descGroup = form.createEl("div", { cls: "atmark-form-group" });
38 descGroup.createEl("label", { text: "Description", attr: { for: "collection-desc" } });
39 const descInput = descGroup.createEl("textarea", {
40 cls: "atmark-textarea",
41 attr: { id: "collection-desc", placeholder: "Optional description", rows: "3" },
42 });
43
44 const actions = form.createEl("div", { cls: "atmark-modal-actions" });
45
46 const cancelBtn = actions.createEl("button", {
47 text: "Cancel",
48 cls: "atmark-btn atmark-btn-secondary",
49 type: "button",
50 });
51 cancelBtn.addEventListener("click", () => this.close());
52
53 const createBtn = actions.createEl("button", {
54 text: "Create",
55 cls: "atmark-btn atmark-btn-primary",
56 type: "submit",
57 });
58
59 form.addEventListener("submit", (e) => {
60 e.preventDefault();
61 void this.handleSubmit(nameInput, descInput, createBtn);
62 });
63
64 nameInput.focus();
65 }
66
67 private async handleSubmit(
68 nameInput: HTMLInputElement,
69 descInput: HTMLTextAreaElement,
70 createBtn: HTMLButtonElement
71 ) {
72 const name = nameInput.value.trim();
73 if (!name) {
74 new Notice("Please enter a collection name");
75 return;
76 }
77
78 createBtn.disabled = true;
79 createBtn.textContent = "Creating...";
80
81 try {
82 await createCollection(
83 this.plugin.client,
84 this.plugin.settings.identifier,
85 name,
86 descInput.value.trim()
87 );
88
89 new Notice(`Created collection "${name}"`);
90 this.close();
91 this.onSuccess?.();
92 } catch (err) {
93 const message = err instanceof Error ? err.message : String(err);
94 new Notice(`Failed to create collection: ${message}`);
95 createBtn.disabled = false;
96 createBtn.textContent = "Create";
97 }
98 }
99
100 onClose() {
101 this.contentEl.empty();
102 }
103}