AT protocol bookmarking platforms in obsidian

rename

+41 -49
+5 -6
manifest.json
··· 1 1 { 2 - "id": "sample-plugin", 3 - "name": "Sample Plugin", 2 + "id": "atmark", 3 + "name": "ATmark", 4 4 "version": "1.0.0", 5 5 "minAppVersion": "0.15.0", 6 - "description": "Demonstrates some of the capabilities of the Obsidian API.", 7 - "author": "Obsidian", 8 - "authorUrl": "https://obsidian.md", 9 - "fundingUrl": "https://obsidian.md/pricing", 6 + "description": "Obsidian plugin for AT Protocol bookmark platforms", 7 + "author": "treethought", 8 + "authorUrl": "https://github.com/treethought", 10 9 "isDesktopOnly": false 11 10 }
+2 -2
package.json
··· 1 1 { 2 - "name": "obsidian-sample-plugin", 2 + "name": "obsidian-atmark", 3 3 "version": "1.0.0", 4 - "description": "This is a sample plugin for Obsidian (https://obsidian.md)", 4 + "description": "Obsidian plugin for AT Protocol bookmark platforms", 5 5 "main": "main.js", 6 6 "type": "module", 7 7 "scripts": {
+19 -29
src/main.ts
··· 1 - import { Notice, Plugin, WorkspaceLeaf } from "obsidian"; 1 + import { Editor, MarkdownView, Notice, Plugin, WorkspaceLeaf } from "obsidian"; 2 2 import type { Client } from "@atcute/client"; 3 3 import { DEFAULT_SETTINGS, AtProtoSettings, SettingTab } from "./settings"; 4 4 import { createAuthenticatedClient, createPublicClient } from "./auth"; 5 5 import { getCollections } from "./lib"; 6 6 import { SembleCollectionsView, VIEW_TYPE_SEMBLE_COLLECTIONS } from "views/collections"; 7 7 import { SembleCardsView, VIEW_TYPE_SEMBLE_CARDS } from "views/cards"; 8 + import { CreateCardModal } from "components/cardForm"; 8 9 9 - export default class MyPlugin extends Plugin { 10 + export default class ATmarkPlugin extends Plugin { 10 11 settings: AtProtoSettings = DEFAULT_SETTINGS; 11 12 client: Client | null = null; 12 13 ··· 21 22 this.registerView(VIEW_TYPE_SEMBLE_CARDS, (leaf) => { 22 23 return new SembleCardsView(leaf, this); 23 24 }); 25 + this.addCommand({ 26 + id: 'semble-add-card', 27 + name: 'Create Semble Card', 28 + editorCheckCallback: (checking: boolean, editor: Editor, _view: MarkdownView) => { 29 + const sel = editor.getSelection() 24 30 31 + if (!this.settings.identifier || !this.settings.appPassword) { 32 + new Notice("Please set your Bluesky credentials in the plugin settings to create new records."); 33 + return false; 34 + } 35 + if (!checking) { 36 + new CreateCardModal(this, sel).open(); 37 + } 38 + return true; 25 39 26 - this.addCommand({ 27 - id: "list-collections", 28 - name: "List Collections", 29 - callback: () => this.listCollections(), 30 - }); 40 + }, 41 + }) 42 + 31 43 32 44 this.addCommand({ 33 45 id: "view-semble-collections", ··· 64 76 await this.initClient(); 65 77 } 66 78 67 - private async listCollections() { 68 - if (!this.client) return; 69 - 70 - const repo = this.settings.identifier 71 - 72 - try { 73 - const resp = await getCollections(this.client, repo); 74 - if (!resp.ok) { 75 - new Notice(`Failed: ${resp.data?.error}`); 76 - return; 77 - } 78 - if (resp.data.records.length === 0) { 79 - new Notice("No collections found"); 80 - return; 81 - } 82 - console.log("Collections:", resp.data.records); 83 - new Notice(`Found ${resp.data.records.length} collections`); 84 - } catch (e) { 85 - new Notice(`Failed: ${e}`); 86 - } 87 - } 88 79 89 80 async activateView(v: string) { 90 81 const { workspace } = this.app; ··· 93 84 const leaves = workspace.getLeavesOfType(v); 94 85 95 86 if (leaves.length > 0) { 96 - console.log("Found existing leaves:", leaves); 97 87 // A leaf with our view already exists, use that 98 88 leaf = leaves[0] as WorkspaceLeaf; 99 89 workspace.revealLeaf(leaf);
+3 -3
src/settings.ts
··· 1 1 import { App, PluginSettingTab, Setting } from "obsidian"; 2 - import type MyPlugin from "./main"; 2 + import type ATmarkPlugin from "./main"; 3 3 4 4 export interface AtProtoSettings { 5 5 identifier: string; ··· 12 12 }; 13 13 14 14 export class SettingTab extends PluginSettingTab { 15 - plugin: MyPlugin; 15 + plugin: ATmarkPlugin; 16 16 17 - constructor(app: App, plugin: MyPlugin) { 17 + constructor(app: App, plugin: ATmarkPlugin) { 18 18 super(app, plugin); 19 19 this.plugin = plugin; 20 20 }
+5 -5
src/views/cards.ts
··· 1 1 import { ItemView, WorkspaceLeaf, setIcon } from "obsidian"; 2 - import type MyPlugin from "../main"; 2 + import type ATmarkPlugin from "../main"; 3 3 import { getCollections, getCollectionLinks, getCards } from "../lib"; 4 4 import type { Main as Card, NoteContent, UrlContent } from "../lexicons/types/network/cosmik/card"; 5 5 import type { Main as CollectionLink } from "../lexicons/types/network/cosmik/collectionLink"; ··· 25 25 } 26 26 27 27 export class SembleCardsView extends ItemView { 28 - plugin: MyPlugin; 28 + plugin: ATmarkPlugin; 29 29 collectionUri: string | null = null; 30 30 collectionName: string = "All Cards"; 31 31 32 - constructor(leaf: WorkspaceLeaf, plugin: MyPlugin) { 32 + constructor(leaf: WorkspaceLeaf, plugin: ATmarkPlugin) { 33 33 super(leaf); 34 34 this.plugin = plugin; 35 35 } ··· 160 160 this.plugin.activateView(VIEW_TYPE_SEMBLE_COLLECTIONS); 161 161 }); 162 162 163 - const brand = nav.createEl("span", { text: "Semble", cls: "semble-brand" }); 163 + nav.createEl("span", { text: "Semble", cls: "semble-brand" }); 164 164 165 165 header.createEl("h2", { text: this.collectionName, cls: "semble-page-title" }); 166 166 ··· 194 194 const header = el.createEl("div", { cls: "semble-card-header" }); 195 195 header.createEl("span", { 196 196 text: card.type, 197 - cls: `semble-badge semble-badge-${card.type.toLowerCase()}`, 197 + cls: `semble-badge semble-badge-${card.type?.toLowerCase() || "unknown"}`, 198 198 }); 199 199 200 200 if (card.type === "NOTE") {
+7 -4
src/views/collections.ts
··· 1 1 import { ItemView, WorkspaceLeaf, setIcon } from "obsidian"; 2 - import type MyPlugin from "../main"; 2 + import type ATmarkPlugin from "../main"; 3 3 import { getCollections } from "../lib"; 4 4 import type { Main as Collection } from "../lexicons/types/network/cosmik/collection"; 5 5 import { SembleCardsView, VIEW_TYPE_SEMBLE_CARDS } from "./cards"; ··· 12 12 } 13 13 14 14 export class SembleCollectionsView extends ItemView { 15 - plugin: MyPlugin; 15 + plugin: ATmarkPlugin; 16 16 17 - constructor(leaf: WorkspaceLeaf, plugin: MyPlugin) { 17 + constructor(leaf: WorkspaceLeaf, plugin: ATmarkPlugin) { 18 18 super(leaf); 19 19 this.plugin = plugin; 20 20 } ··· 51 51 container.empty(); 52 52 container.addClass("semble-collections-view"); 53 53 54 - container.createEl("h4", { text: "Collections" }); 54 + const header = container.createEl("div", { cls: "semble-page-header" }); 55 + const nav = header.createEl("div", { cls: "semble-nav-row" }); 56 + nav.createEl("span", { text: "Semble", cls: "semble-brand" }); 57 + header.createEl("h2", { text: "Collections", cls: "semble-page-title" }); 55 58 56 59 if (!this.plugin.client) { 57 60 container.createEl("p", { text: "Not connected. Configure credentials in settings." });