mirror of
https://github.com/zadam/trilium.git
synced 2025-12-20 14:24:27 +01:00
refactor(breadcrumb): use new component for rendering note links
This commit is contained in:
parent
34343ce356
commit
2693b18ee6
@ -1,10 +1,11 @@
|
|||||||
import treeService from "./tree.js";
|
|
||||||
import linkContextMenuService from "../menus/link_context_menu.js";
|
|
||||||
import appContext, { type NoteCommandData } from "../components/app_context.js";
|
|
||||||
import froca from "./froca.js";
|
|
||||||
import utils from "./utils.js";
|
|
||||||
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
|
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
|
||||||
|
|
||||||
|
import appContext, { type NoteCommandData } from "../components/app_context.js";
|
||||||
import { openInCurrentNoteContext } from "../components/note_context.js";
|
import { openInCurrentNoteContext } from "../components/note_context.js";
|
||||||
|
import linkContextMenuService from "../menus/link_context_menu.js";
|
||||||
|
import froca from "./froca.js";
|
||||||
|
import treeService from "./tree.js";
|
||||||
|
import utils from "./utils.js";
|
||||||
|
|
||||||
function getNotePathFromUrl(url: string) {
|
function getNotePathFromUrl(url: string) {
|
||||||
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
|
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
|
||||||
@ -122,7 +123,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
|||||||
const $container = $("<span>");
|
const $container = $("<span>");
|
||||||
|
|
||||||
if (showNoteIcon) {
|
if (showNoteIcon) {
|
||||||
let icon = await getLinkIcon(noteId, viewMode);
|
const icon = await getLinkIcon(noteId, viewMode);
|
||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
$container.append($("<span>").addClass(`bx ${icon}`)).append(" ");
|
$container.append($("<span>").addClass(`bx ${icon}`)).append(" ");
|
||||||
@ -131,7 +132,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
|||||||
|
|
||||||
const hash = calculateHash({
|
const hash = calculateHash({
|
||||||
notePath,
|
notePath,
|
||||||
viewScope: viewScope
|
viewScope
|
||||||
});
|
});
|
||||||
|
|
||||||
const $noteLink = $("<a>", {
|
const $noteLink = $("<a>", {
|
||||||
@ -171,11 +172,11 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
|||||||
return $container;
|
return $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
export function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
||||||
notePath = notePath || "";
|
notePath = notePath || "";
|
||||||
const params = [
|
const params = [
|
||||||
ntxId ? { ntxId: ntxId } : null,
|
ntxId ? { ntxId } : null,
|
||||||
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId: hoistedNoteId } : null,
|
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId } : null,
|
||||||
viewScope.viewMode && viewScope.viewMode !== "default" ? { viewMode: viewScope.viewMode } : null,
|
viewScope.viewMode && viewScope.viewMode !== "default" ? { viewMode: viewScope.viewMode } : null,
|
||||||
viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null
|
viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null
|
||||||
].filter((p) => !!p);
|
].filter((p) => !!p);
|
||||||
@ -219,7 +220,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const hash = url.substr(hashIdx + 1); // strip also the initial '#'
|
const hash = url.substr(hashIdx + 1); // strip also the initial '#'
|
||||||
let [notePath, paramString] = hash.split("?");
|
const [notePath, paramString] = hash.split("?");
|
||||||
|
|
||||||
const viewScope: ViewScope = {
|
const viewScope: ViewScope = {
|
||||||
viewMode: "default"
|
viewMode: "default"
|
||||||
@ -252,7 +253,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (searchString) {
|
if (searchString) {
|
||||||
return { searchString }
|
return { searchString };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!notePath.match(/^[_a-z0-9]{4,}(\/[_a-z0-9]{4,})*$/i)) {
|
if (!notePath.match(/^[_a-z0-9]{4,}(\/[_a-z0-9]{4,})*$/i)) {
|
||||||
@ -334,7 +335,7 @@ export function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDo
|
|||||||
window.open(hrefLink, "_blank");
|
window.open(hrefLink, "_blank");
|
||||||
} else {
|
} else {
|
||||||
// Enable protocols supported by CKEditor 5 to be clickable.
|
// Enable protocols supported by CKEditor 5 to be clickable.
|
||||||
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(protocol + ":"))) {
|
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(`${protocol }:`))) {
|
||||||
if ( utils.isElectron()) {
|
if ( utils.isElectron()) {
|
||||||
const electron = utils.dynamicRequire("electron");
|
const electron = utils.dynamicRequire("electron");
|
||||||
electron.shell.openExternal(hrefLink);
|
electron.shell.openExternal(hrefLink);
|
||||||
@ -395,7 +396,7 @@ async function loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string | n
|
|||||||
|
|
||||||
href = href || $link.attr("href");
|
href = href || $link.attr("href");
|
||||||
if (!href) {
|
if (!href) {
|
||||||
console.warn("Empty URL for parsing: " + $el[0].outerHTML);
|
console.warn(`Empty URL for parsing: ${$el[0].outerHTML}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,9 +439,9 @@ async function getReferenceLinkTitle(href: string) {
|
|||||||
const attachment = await note.getAttachmentById(viewScope.attachmentId);
|
const attachment = await note.getAttachmentById(viewScope.attachmentId);
|
||||||
|
|
||||||
return attachment ? attachment.title : "[missing attachment]";
|
return attachment ? attachment.title : "[missing attachment]";
|
||||||
} else {
|
|
||||||
return note.title;
|
|
||||||
}
|
}
|
||||||
|
return note.title;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getReferenceLinkTitleSync(href: string) {
|
function getReferenceLinkTitleSync(href: string) {
|
||||||
@ -462,9 +463,9 @@ function getReferenceLinkTitleSync(href: string) {
|
|||||||
const attachment = note.attachments.find((att) => att.attachmentId === viewScope.attachmentId);
|
const attachment = note.attachments.find((att) => att.attachmentId === viewScope.attachmentId);
|
||||||
|
|
||||||
return attachment ? attachment.title : "[missing attachment]";
|
return attachment ? attachment.title : "[missing attachment]";
|
||||||
} else {
|
|
||||||
return note.title;
|
|
||||||
}
|
}
|
||||||
|
return note.title;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glob.device !== "print") {
|
if (glob.device !== "print") {
|
||||||
|
|||||||
@ -25,7 +25,7 @@ import Dropdown from "../react/Dropdown";
|
|||||||
import { FormListItem } from "../react/FormList";
|
import { FormListItem } from "../react/FormList";
|
||||||
import { useActiveNoteContext, useChildNotes, useNote, useNoteIcon, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useStaticTooltip } from "../react/hooks";
|
import { useActiveNoteContext, useChildNotes, useNote, useNoteIcon, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useStaticTooltip } from "../react/hooks";
|
||||||
import Icon from "../react/Icon";
|
import Icon from "../react/Icon";
|
||||||
import NoteLink from "../react/NoteLink";
|
import { NewNoteLink } from "../react/NoteLink";
|
||||||
import { ParentComponent } from "../react/react_utils";
|
import { ParentComponent } from "../react/react_utils";
|
||||||
|
|
||||||
const COLLAPSE_THRESHOLD = 5;
|
const COLLAPSE_THRESHOLD = 5;
|
||||||
@ -114,7 +114,7 @@ function BreadcrumbHoistedNoteRoot({ noteId }: { noteId: string }) {
|
|||||||
"color": getReadableTextColor(workspaceColor)
|
"color": getReadableTextColor(workspaceColor)
|
||||||
} : undefined}
|
} : undefined}
|
||||||
/>
|
/>
|
||||||
<NoteLink
|
<NewNoteLink
|
||||||
notePath={noteId}
|
notePath={noteId}
|
||||||
showNoteIcon
|
showNoteIcon
|
||||||
noPreview
|
noPreview
|
||||||
@ -161,7 +161,7 @@ function BreadcrumbItem({ index, notePath, noteContext, notePathLength, parentCo
|
|||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <NoteLink
|
return <NewNoteLink
|
||||||
notePath={notePath}
|
notePath={notePath}
|
||||||
noContextMenu
|
noContextMenu
|
||||||
onContextMenu={buildContextMenu(notePath, parentComponent)}
|
onContextMenu={buildContextMenu(notePath, parentComponent)}
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
|
import clsx from "clsx";
|
||||||
|
import { HTMLAttributes } from "preact";
|
||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
import link, { ViewScope } from "../../services/link";
|
import link, { calculateHash, ViewScope } from "../../services/link";
|
||||||
import { useImperativeSearchHighlighlighting, useTriliumEvent } from "./hooks";
|
import { useImperativeSearchHighlighlighting, useNote, useNoteIcon, useNoteProperty, useTriliumEvent } from "./hooks";
|
||||||
|
import Icon from "./Icon";
|
||||||
|
|
||||||
interface NoteLinkOpts {
|
interface NoteLinkOpts {
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -83,3 +86,37 @@ export default function NoteLink({ className, containerClassName, notePath, show
|
|||||||
|
|
||||||
return <span className={containerClassName} ref={ref} />;
|
return <span className={containerClassName} ref={ref} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface NewNoteLinkProps extends Pick<HTMLAttributes<HTMLAnchorElement>, "onContextMenu"> {
|
||||||
|
notePath: string;
|
||||||
|
viewScope?: ViewScope;
|
||||||
|
noContextMenu?: boolean;
|
||||||
|
showNoteIcon?: boolean;
|
||||||
|
noPreview?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function NewNoteLink({ notePath, viewScope, noContextMenu, showNoteIcon, noPreview, ...linkProps }: NewNoteLinkProps) {
|
||||||
|
const noteId = notePath.split("/").at(-1);
|
||||||
|
const note = useNote(noteId);
|
||||||
|
const title = useNoteProperty(note, "title");
|
||||||
|
const icon = useNoteIcon(showNoteIcon ? note : null);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<span>
|
||||||
|
{icon && <Icon icon={icon} />}
|
||||||
|
|
||||||
|
<a
|
||||||
|
className={clsx("tn-link", {
|
||||||
|
"no-tooltip-preview": noPreview
|
||||||
|
})}
|
||||||
|
href={calculateHash({ notePath, viewScope })}
|
||||||
|
data-no-context-menu={noContextMenu}
|
||||||
|
{...linkProps}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user