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 appContext, { type NoteCommandData } from "../components/app_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) {
|
||||
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
|
||||
@ -122,7 +123,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
const $container = $("<span>");
|
||||
|
||||
if (showNoteIcon) {
|
||||
let icon = await getLinkIcon(noteId, viewMode);
|
||||
const icon = await getLinkIcon(noteId, viewMode);
|
||||
|
||||
if (icon) {
|
||||
$container.append($("<span>").addClass(`bx ${icon}`)).append(" ");
|
||||
@ -131,7 +132,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
|
||||
const hash = calculateHash({
|
||||
notePath,
|
||||
viewScope: viewScope
|
||||
viewScope
|
||||
});
|
||||
|
||||
const $noteLink = $("<a>", {
|
||||
@ -171,11 +172,11 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
|
||||
return $container;
|
||||
}
|
||||
|
||||
function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
||||
export function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
|
||||
notePath = notePath || "";
|
||||
const params = [
|
||||
ntxId ? { ntxId: ntxId } : null,
|
||||
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId: hoistedNoteId } : null,
|
||||
ntxId ? { ntxId } : null,
|
||||
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId } : null,
|
||||
viewScope.viewMode && viewScope.viewMode !== "default" ? { viewMode: viewScope.viewMode } : null,
|
||||
viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null
|
||||
].filter((p) => !!p);
|
||||
@ -219,7 +220,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
}
|
||||
|
||||
const hash = url.substr(hashIdx + 1); // strip also the initial '#'
|
||||
let [notePath, paramString] = hash.split("?");
|
||||
const [notePath, paramString] = hash.split("?");
|
||||
|
||||
const viewScope: ViewScope = {
|
||||
viewMode: "default"
|
||||
@ -252,7 +253,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
|
||||
}
|
||||
|
||||
if (searchString) {
|
||||
return { searchString }
|
||||
return { searchString };
|
||||
}
|
||||
|
||||
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");
|
||||
} else {
|
||||
// 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()) {
|
||||
const electron = utils.dynamicRequire("electron");
|
||||
electron.shell.openExternal(hrefLink);
|
||||
@ -395,7 +396,7 @@ async function loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string | n
|
||||
|
||||
href = href || $link.attr("href");
|
||||
if (!href) {
|
||||
console.warn("Empty URL for parsing: " + $el[0].outerHTML);
|
||||
console.warn(`Empty URL for parsing: ${$el[0].outerHTML}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -438,9 +439,9 @@ async function getReferenceLinkTitle(href: string) {
|
||||
const attachment = await note.getAttachmentById(viewScope.attachmentId);
|
||||
|
||||
return attachment ? attachment.title : "[missing attachment]";
|
||||
} else {
|
||||
return note.title;
|
||||
}
|
||||
return note.title;
|
||||
|
||||
}
|
||||
|
||||
function getReferenceLinkTitleSync(href: string) {
|
||||
@ -462,9 +463,9 @@ function getReferenceLinkTitleSync(href: string) {
|
||||
const attachment = note.attachments.find((att) => att.attachmentId === viewScope.attachmentId);
|
||||
|
||||
return attachment ? attachment.title : "[missing attachment]";
|
||||
} else {
|
||||
return note.title;
|
||||
}
|
||||
return note.title;
|
||||
|
||||
}
|
||||
|
||||
if (glob.device !== "print") {
|
||||
|
||||
@ -25,7 +25,7 @@ import Dropdown from "../react/Dropdown";
|
||||
import { FormListItem } from "../react/FormList";
|
||||
import { useActiveNoteContext, useChildNotes, useNote, useNoteIcon, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useStaticTooltip } from "../react/hooks";
|
||||
import Icon from "../react/Icon";
|
||||
import NoteLink from "../react/NoteLink";
|
||||
import { NewNoteLink } from "../react/NoteLink";
|
||||
import { ParentComponent } from "../react/react_utils";
|
||||
|
||||
const COLLAPSE_THRESHOLD = 5;
|
||||
@ -114,7 +114,7 @@ function BreadcrumbHoistedNoteRoot({ noteId }: { noteId: string }) {
|
||||
"color": getReadableTextColor(workspaceColor)
|
||||
} : undefined}
|
||||
/>
|
||||
<NoteLink
|
||||
<NewNoteLink
|
||||
notePath={noteId}
|
||||
showNoteIcon
|
||||
noPreview
|
||||
@ -161,7 +161,7 @@ function BreadcrumbItem({ index, notePath, noteContext, notePathLength, parentCo
|
||||
</>;
|
||||
}
|
||||
|
||||
return <NoteLink
|
||||
return <NewNoteLink
|
||||
notePath={notePath}
|
||||
noContextMenu
|
||||
onContextMenu={buildContextMenu(notePath, parentComponent)}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import clsx from "clsx";
|
||||
import { HTMLAttributes } from "preact";
|
||||
import { useEffect, useRef, useState } from "preact/hooks";
|
||||
|
||||
import link, { ViewScope } from "../../services/link";
|
||||
import { useImperativeSearchHighlighlighting, useTriliumEvent } from "./hooks";
|
||||
import link, { calculateHash, ViewScope } from "../../services/link";
|
||||
import { useImperativeSearchHighlighlighting, useNote, useNoteIcon, useNoteProperty, useTriliumEvent } from "./hooks";
|
||||
import Icon from "./Icon";
|
||||
|
||||
interface NoteLinkOpts {
|
||||
className?: string;
|
||||
@ -83,3 +86,37 @@ export default function NoteLink({ className, containerClassName, notePath, show
|
||||
|
||||
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