mirror of
https://github.com/zadam/trilium.git
synced 2025-10-22 21:39:23 +08:00
chore(react): add back note map link configuration
This commit is contained in:
parent
ad5ff6e41a
commit
2d29d1b41f
5 changed files with 57 additions and 57 deletions
|
@ -169,7 +169,7 @@ const entityMap: Record<string, string> = {
|
|||
"=": "="
|
||||
};
|
||||
|
||||
function escapeHtml(str: string) {
|
||||
export function escapeHtml(str: string) {
|
||||
return str.replace(/[&<>"'`=\/]/g, (s) => entityMap[s]);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,10 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
|
|||
private fixNodes: boolean;
|
||||
private widgetMode: WidgetMode;
|
||||
|
||||
private themeStyle!: string;
|
||||
private $container!: JQuery<HTMLElement>;
|
||||
private $styleResolver!: JQuery<HTMLElement>;
|
||||
private $fixNodesButton!: JQuery<HTMLElement>;
|
||||
graph!: ForceGraph;
|
||||
private noteIdToSizeMap!: Record<string, number>;
|
||||
private zoomLevel!: number;
|
||||
private nodes!: Node[];
|
||||
|
||||
constructor(widgetMode: WidgetMode) {
|
||||
super();
|
||||
|
@ -117,13 +113,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
|
|||
}
|
||||
});
|
||||
|
||||
if (this.mapType === "link") {
|
||||
this.graph
|
||||
.linkLabel((l) => `${esc((l as Link).source.name)} - <strong>${esc((l as Link).name)}</strong> - ${esc((l as Link).target.name)}`)
|
||||
.linkCanvasObject((link, ctx) => this.paintLink(link as Link, ctx))
|
||||
.linkCanvasObjectMode(() => "after");
|
||||
}
|
||||
|
||||
const nodeLinkRatio = data.nodes.length / data.links.length;
|
||||
const magnifiedRatio = Math.pow(nodeLinkRatio, 1.5);
|
||||
const charge = -20 / magnifiedRatio;
|
||||
|
@ -148,45 +137,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
|
|||
this.zoomLevel = level;
|
||||
}
|
||||
|
||||
paintLink(link: Link, ctx: CanvasRenderingContext2D) {
|
||||
if (this.zoomLevel < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.font = `3px ${this.cssData.fontFamily}`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = this.cssData.mutedTextColor;
|
||||
|
||||
const { source, target } = link;
|
||||
if (typeof source !== "object" || typeof target !== "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.x && source.y && target.x && target.y) {
|
||||
const x = (source.x + target.x) / 2;
|
||||
const y = (source.y + target.y) / 2;
|
||||
ctx.save();
|
||||
ctx.translate(x, y);
|
||||
|
||||
const deltaY = source.y - target.y;
|
||||
const deltaX = source.x - target.x;
|
||||
|
||||
let angle = Math.atan2(deltaY, deltaX);
|
||||
let moveY = 2;
|
||||
|
||||
if (angle < -Math.PI / 2 || angle > Math.PI / 2) {
|
||||
angle += Math.PI;
|
||||
moveY = -2;
|
||||
}
|
||||
|
||||
ctx.rotate(angle);
|
||||
ctx.fillText(link.name, 0, moveY);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
renderData(data: Data) {
|
||||
if (this.widgetMode === "ribbon" && this.note?.type !== "search") {
|
||||
setTimeout(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
import "./NoteMap.css";
|
||||
import { getMapRootNoteId, getThemeStyle, NoteMapWidgetMode, rgb2hex } from "./utils";
|
||||
import { getMapRootNoteId, getThemeStyle, MapType, NoteMapWidgetMode, rgb2hex } from "./utils";
|
||||
import { RefObject } from "preact";
|
||||
import FNote from "../../entities/fnote";
|
||||
import { useElementSize, useNoteContext, useNoteLabel } from "../react/hooks";
|
||||
|
@ -16,8 +16,6 @@ interface NoteMapProps {
|
|||
parentRef: RefObject<HTMLElement>;
|
||||
}
|
||||
|
||||
type MapType = "tree" | "link";
|
||||
|
||||
export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const styleResolverRef = useRef<HTMLDivElement>(null);
|
||||
|
@ -50,7 +48,8 @@ export default function NoteMap({ note, widgetMode, parentRef }: NoteMapProps) {
|
|||
noteIdToSizeMap: notesAndRelations.noteIdToSizeMap,
|
||||
notesAndRelations,
|
||||
themeStyle: getThemeStyle(),
|
||||
widgetMode
|
||||
widgetMode,
|
||||
mapType
|
||||
});
|
||||
graph.graphData(notesAndRelations);
|
||||
});
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import type ForceGraph from "force-graph";
|
||||
import { Link, Node, NotesAndRelationsData } from "./data";
|
||||
import { NodeObject } from "force-graph";
|
||||
import { getColorForNode, NoteMapWidgetMode } from "./utils";
|
||||
import { getColorForNode, MapType, NoteMapWidgetMode } from "./utils";
|
||||
import { escapeHtml } from "../../services/utils";
|
||||
|
||||
export interface CssData {
|
||||
fontFamily: string;
|
||||
|
@ -16,9 +17,10 @@ interface RenderData {
|
|||
themeStyle: "light" | "dark";
|
||||
widgetMode: NoteMapWidgetMode;
|
||||
notesAndRelations: NotesAndRelationsData;
|
||||
mapType: MapType;
|
||||
}
|
||||
|
||||
export function setupRendering(graph: ForceGraph, { noteId, themeStyle, widgetMode, noteIdToSizeMap, notesAndRelations, cssData }: RenderData) {
|
||||
export function setupRendering(graph: ForceGraph, { noteId, themeStyle, widgetMode, noteIdToSizeMap, notesAndRelations, cssData, mapType }: RenderData) {
|
||||
// variables for the hover effect. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
|
||||
const neighbours = new Set();
|
||||
const highlightLinks = new Set();
|
||||
|
@ -57,6 +59,46 @@ export function setupRendering(graph: ForceGraph, { noteId, themeStyle, widgetMo
|
|||
ctx.fillText(title, x, y + Math.round(size * 1.5));
|
||||
}
|
||||
|
||||
|
||||
function paintLink(link: Link, ctx: CanvasRenderingContext2D) {
|
||||
if (zoomLevel < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.font = `3px ${cssData.fontFamily}`;
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillStyle = cssData.mutedTextColor;
|
||||
|
||||
const { source, target } = link;
|
||||
if (typeof source !== "object" || typeof target !== "object") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (source.x && source.y && target.x && target.y) {
|
||||
const x = (source.x + target.x) / 2;
|
||||
const y = (source.y + target.y) / 2;
|
||||
ctx.save();
|
||||
ctx.translate(x, y);
|
||||
|
||||
const deltaY = source.y - target.y;
|
||||
const deltaX = source.x - target.x;
|
||||
|
||||
let angle = Math.atan2(deltaY, deltaX);
|
||||
let moveY = 2;
|
||||
|
||||
if (angle < -Math.PI / 2 || angle > Math.PI / 2) {
|
||||
angle += Math.PI;
|
||||
moveY = -2;
|
||||
}
|
||||
|
||||
ctx.rotate(angle);
|
||||
ctx.fillText(link.name, 0, moveY);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// main code for highlighting hovered nodes and neighbours. here we "style" the nodes. the nodes are rendered several hundred times per second.
|
||||
graph
|
||||
.d3AlphaDecay(0.01)
|
||||
|
@ -92,5 +134,13 @@ export function setupRendering(graph: ForceGraph, { noteId, themeStyle, widgetMo
|
|||
highlightLinks.clear();
|
||||
})
|
||||
.onZoom((zoom) => zoomLevel = zoom.k);
|
||||
|
||||
// Link-specific config
|
||||
if (mapType) {
|
||||
graph
|
||||
.linkLabel((l) => `${escapeHtml((l as Link).source.name)} - <strong>${escapeHtml((l as Link).name)}</strong> - ${escapeHtml((l as Link).target.name)}`)
|
||||
.linkCanvasObject((link, ctx) => paintLink(link as Link, ctx))
|
||||
.linkCanvasObjectMode(() => "after");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import hoisted_note from "../../services/hoisted_note";
|
|||
import { Node } from "./data";
|
||||
|
||||
export type NoteMapWidgetMode = "ribbon" | "hoisted";
|
||||
export type MapType = "tree" | "link";
|
||||
|
||||
export function rgb2hex(rgb: string) {
|
||||
return `#${(rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) || [])
|
||||
|
|
Loading…
Add table
Reference in a new issue