import { MarkdownView, Platform, Plugin, WorkspaceLeaf } from "obsidian"; import { VIEW_TYPE_PROJECT_VIEW, VIEW_TYPE_PROJECT_DETAILS_VIEW, VIEW_TYPE_COLLECTION_VIEW, RIBBON_ICON, } from "./src/const"; import { ProjectView } from "./src/views/ProjectView"; import { ProjectDetailsView } from "./src/views/ProjectDetailsView"; import { CollectionView } from "./src/views/CollectionView"; import { parseProjectFilePath, projectPathFromChain } from "./src/fs"; import { BreadcrumbSegment, injectMobileBreadcrumb } from "./src/ui"; export default class ProjektkontextPlugin extends Plugin { async onload(): Promise { this.registerView(VIEW_TYPE_PROJECT_VIEW, (leaf) => new ProjectView(leaf)); this.registerView(VIEW_TYPE_PROJECT_DETAILS_VIEW, (leaf) => new ProjectDetailsView(leaf)); this.registerView(VIEW_TYPE_COLLECTION_VIEW, (leaf) => new CollectionView(leaf)); this.addRibbonIcon(RIBBON_ICON, "Projekte", () => { void this.activateProjectView(); }); this.addCommand({ id: "open-projects", name: "Projekte öffnen", callback: () => void this.activateProjectView(), }); if (Platform.isMobile) { const reattach = () => this.reattachMobileBreadcrumbs(); this.registerEvent( this.app.workspace.on("file-open", () => requestAnimationFrame(reattach)), ); this.registerEvent( this.app.workspace.on("active-leaf-change", () => requestAnimationFrame(reattach)), ); this.registerEvent(this.app.workspace.on("layout-change", reattach)); } } async onunload(): Promise {} async activateProjectView(): Promise { const { workspace } = this.app; let leaf: WorkspaceLeaf | null = workspace.getLeavesOfType(VIEW_TYPE_PROJECT_VIEW)[0] ?? null; if (!leaf) { leaf = workspace.getLeaf(false); await leaf.setViewState({ type: VIEW_TYPE_PROJECT_VIEW, active: true }); } workspace.revealLeaf(leaf); } private reattachMobileBreadcrumbs(): void { this.app.workspace.iterateRootLeaves((leaf) => this.applyMobileBreadcrumb(leaf)); } private applyMobileBreadcrumb(leaf: WorkspaceLeaf): void { const view = leaf.view; if (!(view instanceof MarkdownView)) return; const file = view.file; if (!file) { injectMobileBreadcrumb(view, []); return; } const loc = parseProjectFilePath(this.app, file.path); if (!loc) { injectMobileBreadcrumb(view, []); return; } const segments: BreadcrumbSegment[] = [ { label: "Projekte", onClick: () => void leaf.setViewState({ type: VIEW_TYPE_PROJECT_VIEW, active: true }), }, ]; for (let i = 0; i < loc.projectChain.length; i++) { const projectPath = projectPathFromChain(loc.projectChain.slice(0, i + 1)); segments.push({ label: loc.projectChain[i], onClick: () => void leaf.setViewState({ type: VIEW_TYPE_PROJECT_DETAILS_VIEW, active: true, state: { projectPath }, }), }); } if (loc.collection) { const projectPath = projectPathFromChain(loc.projectChain); segments.push({ label: loc.collection, onClick: () => void leaf.setViewState({ type: VIEW_TYPE_COLLECTION_VIEW, active: true, state: { projectPath, collection: loc.collection }, }), }); } segments.push({ label: file.basename }); injectMobileBreadcrumb(view, segments); } }