Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion apps/obsidian/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Plugin, Editor, Menu, TFile, Events } from "obsidian";
import { Plugin, Editor, Menu, TFile } from "obsidian";
import { SettingsTab } from "~/components/Settings";
import { Settings } from "~/types";
import { registerCommands } from "~/utils/registerCommands";
Expand All @@ -10,10 +10,12 @@ import {
} from "~/utils/createNode";
import { DEFAULT_SETTINGS } from "~/constants";
import { CreateNodeModal } from "~/components/CreateNodeModal";
import { TagNodeHandler } from "~/utils/tagNodeHandler";

export default class DiscourseGraphPlugin extends Plugin {
settings: Settings = { ...DEFAULT_SETTINGS };
private styleElement: HTMLStyleElement | null = null;
private tagNodeHandler: TagNodeHandler | null = null;

async onload() {
await this.loadSettings();
Expand All @@ -32,6 +34,15 @@ export default class DiscourseGraphPlugin extends Plugin {
// Initialize frontmatter CSS
this.updateFrontmatterStyles();

// Initialize tag node handler
try {
this.tagNodeHandler = new TagNodeHandler(this);
this.tagNodeHandler.initialize();
} catch (error) {
console.error("Failed to initialize TagNodeHandler:", error);
this.tagNodeHandler = null;
}

this.registerEvent(
// @ts-ignore - file-menu event exists but is not in the type definitions
this.app.workspace.on("file-menu", (menu: Menu, file: TFile) => {
Expand Down Expand Up @@ -200,6 +211,11 @@ export default class DiscourseGraphPlugin extends Plugin {
this.styleElement.remove();
}

if (this.tagNodeHandler) {
this.tagNodeHandler.cleanup();
this.tagNodeHandler = null;
}

this.app.workspace.detachLeavesOfType(VIEW_TYPE_DISCOURSE_CONTEXT);
}
}
69 changes: 69 additions & 0 deletions apps/obsidian/src/utils/colorUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { DiscourseNode } from "~/types";

// Color palette similar to Roam's implementation
const COLOR_PALETTE: Record<string, string> = {
black: "#1d1d1d",
blue: "#4263eb",
green: "#099268",
grey: "#adb5bd",
lightBlue: "#4dabf7",
lightGreen: "#40c057",
lightRed: "#ff8787",
lightViolet: "#e599f7",
orange: "#f76707",
red: "#e03131",
violet: "#ae3ec9",
white: "#ffffff",
yellow: "#ffc078",
};

const COLOR_ARRAY = Object.keys(COLOR_PALETTE);

// TODO switch to colord - https://linear.app/discourse-graphs/issue/ENG-836/button-like-css-styling-for-node-tag
export const getContrastColor = (bgColor: string): string => {
const hex = bgColor.replace("#", "");

if (hex.length !== 6) return "#000000";

const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);

if (isNaN(r) || isNaN(g) || isNaN(b)) return "#000000";

const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;

return luminance > 0.5 ? "#000000" : "#ffffff";
};

export const getNodeTagColors = (
nodeType: DiscourseNode,
nodeIndex: number,
): { backgroundColor: string; textColor: string } => {
const customColor = nodeType.color || "";

const safeIndex =
nodeIndex >= 0 && nodeIndex < COLOR_ARRAY.length ? nodeIndex : 0;
const paletteColorKey = COLOR_ARRAY[safeIndex];
const paletteColor = paletteColorKey
? COLOR_PALETTE[paletteColorKey]
: COLOR_PALETTE.blue;

const backgroundColor = customColor || paletteColor || "#4263eb";
const textColor = getContrastColor(backgroundColor);

return { backgroundColor, textColor };
};


export const getAllDiscourseNodeColors = (
nodeTypes: DiscourseNode[],
): Array<{
nodeType: DiscourseNode;
colors: { backgroundColor: string; textColor: string };
}> => {
return nodeTypes.map((nodeType, index) => ({
nodeType,
colors: getNodeTagColors(nodeType, index),
}));
};
Loading