Various AT Protocol integrations with obsidian
20
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove session from plugin class

+36 -38
+4
src/components/loginMessage.ts
··· 1 + export function renderLoginMessage(container: HTMLElement) { 2 + const message = container.createEl("div", { cls: "atmosphere-auth-required" }); 3 + message.createEl("p", { text: "Please log in by opening Atmosphere settings" }); 4 + }
+9 -33
src/main.ts
··· 1 - import { Plugin, WorkspaceLeaf } from "obsidian"; 1 + import { Notice, Plugin, WorkspaceLeaf } from "obsidian"; 2 2 import { DEFAULT_SETTINGS, AtProtoSettings, SettingTab } from "./settings"; 3 3 import { AtmosphereView, VIEW_TYPE_ATMOSPHERE_BOOKMARKS } from "./views/bookmarks"; 4 4 import { publishFileAsDocument } from "./commands/publishDocument"; 5 5 import { StandardFeedView, VIEW_ATMOSPHERE_STANDARD_FEED } from "views/standardfeed"; 6 6 import { ATClient } from "lib/client"; 7 7 import { Clipper } from "lib/clipper"; 8 - import { OAuthModal } from "./components/oAuthModal"; 9 - import type { OAuthSession } from "@atcute/oauth-node-client"; 10 8 11 9 export default class AtmospherePlugin extends Plugin { 12 10 settings: AtProtoSettings = DEFAULT_SETTINGS; 13 11 client: ATClient; 14 12 clipper: Clipper; 15 - session: OAuthSession | null = null; 16 13 17 14 async onload() { 18 15 await this.loadSettings(); ··· 68 65 this.addSettingTab(new SettingTab(this.app, this)); 69 66 } 70 67 71 - async doOAuth(): Promise<void> { 72 - return new Promise<void>((resolve, reject) => { 73 - const modal = new OAuthModal(this, async (session) => { 74 - this.session = session; 75 - this.client = new ATClient(session); 76 68 77 - this.settings.identifier = session.did; 78 - await this.saveSettings(); 79 - // TODO: Store session for persistence across restarts 80 - resolve(); 81 - }); 69 + checkLoggedIn() { 70 + if (this.client?.loggedIn) { 71 + return true; 72 + } 82 73 83 - // Override close to reject if not authenticated 84 - const originalClose = modal.close.bind(modal); 85 - modal.close = () => { 86 - originalClose(); 87 - if (!this.session) { 88 - reject(new Error("OAuth flow cancelled")); 89 - } 90 - }; 91 - 92 - modal.open(); 93 - }); 74 + new Notice("Please log in by opening Atmosphere settings"); 75 + return false; 94 76 } 95 77 96 78 async activateView(v: string) { 97 - // Check if we need to authenticate 98 - if (!this.client || !this.client.loggedIn) { 99 - try { 100 - await this.doOAuth(); 101 - } catch (error) { 102 - console.error("OAuth failed:", error); 103 - return; 104 - } 79 + if (!this.checkLoggedIn()) { 80 + return; 105 81 } 106 82 107 83 const { workspace } = this.app;
+9 -5
src/settings.ts
··· 3 3 import { isActorIdentifier } from "@atcute/lexicons/syntax"; 4 4 import { OauthServer } from "./lib/oauth"; 5 5 import { ATClient } from "./lib/client"; 6 + import { VIEW_TYPE_ATMOSPHERE_BOOKMARKS } from "./views/bookmarks"; 7 + import { VIEW_ATMOSPHERE_STANDARD_FEED } from "./views/standardfeed"; 6 8 7 9 export interface AtProtoSettings { 8 10 identifier: string; ··· 46 48 .setButtonText("Log out") 47 49 .setCta() 48 50 .onClick(async () => { 49 - this.plugin.session = null; 50 51 this.plugin.client = null as any; 51 52 52 53 this.plugin.settings.identifier = ""; 53 54 await this.plugin.saveSettings(); 54 55 55 - // refresh settings 56 + // close all plugin views 57 + this.app.workspace.detachLeavesOfType(VIEW_TYPE_ATMOSPHERE_BOOKMARKS); 58 + this.app.workspace.detachLeavesOfType(VIEW_ATMOSPHERE_STANDARD_FEED); 59 + 56 60 this.display(); 57 61 new Notice("Logged out successfully"); 58 62 }) ··· 94 98 const oauth = new OauthServer(); 95 99 const session = await oauth.authorize(handle); 96 100 97 - this.plugin.session = session; 98 101 this.plugin.client = new ATClient(session); 99 102 this.plugin.settings.identifier = session.did; 103 + const actor = await this.plugin.client.getActor(session.did); 104 + 100 105 await this.plugin.saveSettings(); 101 106 102 - new Notice(`Successfully authenticated as ${session.handle}`); 107 + new Notice(`Successfully logged in as ${actor.handle}`); 103 108 104 - // refresh settings to show authenticated state 105 109 this.display(); 106 110 } catch (error) { 107 111 console.error("Login failed:", error);
+6
src/views/bookmarks.ts
··· 5 5 import { SembleSource } from "../sources/semble"; 6 6 import { BookmarkSource } from "../sources/bookmark"; 7 7 import { MarginSource } from "../sources/margin"; 8 + import { renderLoginMessage } from "components/loginMessage"; 8 9 9 10 export const VIEW_TYPE_ATMOSPHERE_BOOKMARKS = "atmosphere-bookmarks"; 10 11 ··· 70 71 const container = this.contentEl; 71 72 container.empty(); 72 73 container.addClass("atmosphere-view"); 74 + 75 + if (!this.plugin.checkLoggedIn()) { 76 + renderLoginMessage(container) 77 + return 78 + } 73 79 74 80 this.renderHeader(container); 75 81
+8
src/views/standardfeed.ts
··· 5 5 import { Main as Publication } from "@atcute/standard-site/types/publication"; 6 6 import { ATRecord } from "lib"; 7 7 import { parseResourceUri } from "@atcute/lexicons"; 8 + import { renderLoginMessage } from "components/loginMessage"; 8 9 9 10 export const VIEW_ATMOSPHERE_STANDARD_FEED = "atmosphere-standard-site-feed"; 10 11 ··· 36 37 const container = this.contentEl; 37 38 container.empty(); 38 39 container.addClass("standard-site-view"); 40 + 41 + // Check authentication 42 + if (!this.plugin.checkLoggedIn()) { 43 + renderLoginMessage(container) 44 + return 45 + } 46 + 39 47 this.renderHeader(container); 40 48 41 49 const loading = container.createEl("p", { text: "Loading subscriptions..." });