Files
management/main.ts
2026-05-19 22:02:32 +02:00

105 lines
3.4 KiB
TypeScript

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<void> {
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<void> {}
async activateProjectView(): Promise<void> {
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);
}
}