AT protocol bookmarking platforms in obsidian
at responsive-sizing 118 lines 3.3 kB view raw
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 // Name field 30 const nameGroup = form.createEl("div", { cls: "atmark-form-group" }); 31 nameGroup.createEl("label", { text: "Name", attr: { for: "collection-name" } }); 32 const nameInput = nameGroup.createEl("input", { 33 type: "text", 34 cls: "atmark-input", 35 attr: { id: "collection-name", placeholder: "Collection name", required: "true" }, 36 }); 37 38 // Icon field 39 const iconGroup = form.createEl("div", { cls: "atmark-form-group" }); 40 iconGroup.createEl("label", { text: "Icon (optional)", attr: { for: "collection-icon" } }); 41 const iconInput = iconGroup.createEl("input", { 42 type: "text", 43 cls: "atmark-input", 44 attr: { id: "collection-icon" }, 45 }); 46 47 // Description field 48 const descGroup = form.createEl("div", { cls: "atmark-form-group" }); 49 descGroup.createEl("label", { text: "Description", attr: { for: "collection-desc" } }); 50 const descInput = descGroup.createEl("textarea", { 51 cls: "atmark-textarea", 52 attr: { id: "collection-desc", placeholder: "Optional description", rows: "3" }, 53 }); 54 55 // Action buttons 56 const actions = form.createEl("div", { cls: "atmark-modal-actions" }); 57 58 const cancelBtn = actions.createEl("button", { 59 text: "Cancel", 60 cls: "atmark-btn atmark-btn-secondary", 61 type: "button", 62 }); 63 cancelBtn.addEventListener("click", () => this.close()); 64 65 const createBtn = actions.createEl("button", { 66 text: "Create", 67 cls: "atmark-btn atmark-btn-primary", 68 type: "submit", 69 }); 70 71 form.addEventListener("submit", (e) => { 72 e.preventDefault(); 73 void this.handleSubmit(nameInput, iconInput, descInput, createBtn); 74 }); 75 76 // Focus name input 77 nameInput.focus(); 78 } 79 80 private async handleSubmit( 81 nameInput: HTMLInputElement, 82 iconInput: HTMLInputElement, 83 descInput: HTMLTextAreaElement, 84 createBtn: HTMLButtonElement 85 ) { 86 const name = nameInput.value.trim(); 87 if (!name) { 88 new Notice("Please enter a collection name"); 89 return; 90 } 91 92 createBtn.disabled = true; 93 createBtn.textContent = "Creating..."; 94 95 try { 96 await createMarginCollection( 97 this.plugin.client!, 98 this.plugin.settings.identifier, 99 name, 100 descInput.value.trim() || undefined, 101 iconInput.value.trim() || undefined 102 ); 103 104 new Notice(`Created collection "${name}"`); 105 this.close(); 106 this.onSuccess?.(); 107 } catch (err) { 108 const message = err instanceof Error ? err.message : String(err); 109 new Notice(`Failed to create collection: ${message}`); 110 createBtn.disabled = false; 111 createBtn.textContent = "Create"; 112 } 113 } 114 115 onClose() { 116 this.contentEl.empty(); 117 } 118}