Proof of concept for the other one
1import { Plugin } from "obsidian";
2import { CalendarView, VIEW_TYPE_CALENDAR } from "./calendarView";
3
4export default class CalendarViewerPlugin extends Plugin {
5 private lastActiveFilePath: string | null = null;
6
7 async onload(): Promise<void> {
8 this.registerView(
9 VIEW_TYPE_CALENDAR,
10 (leaf) => new CalendarView(leaf, this),
11 );
12
13 // Ribbon icon to open the calendar sidebar
14 this.addRibbonIcon("calendar", "Open Calendar View", () => {
15 this.activateView();
16 });
17
18 // Command to open the calendar sidebar
19 this.addCommand({
20 id: "open-calendar-view",
21 name: "Open Calendar View",
22 callback: () => {
23 this.activateView();
24 },
25 });
26
27 // Re-parse when the active file changes (but skip if same file re-focused)
28 this.registerEvent(
29 this.app.workspace.on("active-leaf-change", () => {
30 const activeFile = this.app.workspace.getActiveFile();
31 const activePath = activeFile?.path ?? null;
32 if (activePath === this.lastActiveFilePath) return;
33 this.lastActiveFilePath = activePath;
34
35 const view = this.getCalendarView();
36 if (view) {
37 view.resetNavigation();
38 view.refresh();
39 }
40 }),
41 );
42
43 // Re-parse when a file is modified (live update)
44 this.registerEvent(
45 this.app.vault.on("modify", (file) => {
46 const activeFile = this.app.workspace.getActiveFile();
47 if (activeFile && file.path === activeFile.path) {
48 const view = this.getCalendarView();
49 if (view) {
50 view.refresh();
51 }
52 }
53 }),
54 );
55 }
56
57 onunload(): void {
58 // Obsidian handles view cleanup via detachLeavesOfType
59 }
60
61 private getCalendarView(): CalendarView | null {
62 const leaves = this.app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR);
63 if (leaves.length > 0) {
64 return leaves[0].view as CalendarView;
65 }
66 return null;
67 }
68
69 private async activateView(): Promise<void> {
70 const existing = this.app.workspace.getLeavesOfType(VIEW_TYPE_CALENDAR);
71
72 if (existing.length === 0) {
73 const leaf = this.app.workspace.getRightLeaf(false);
74 if (leaf) {
75 await leaf.setViewState({
76 type: VIEW_TYPE_CALENDAR,
77 active: true,
78 });
79 this.app.workspace.revealLeaf(leaf);
80 }
81 } else {
82 this.app.workspace.revealLeaf(existing[0]);
83 }
84 }
85}