feat(breadcrumb_badges): add tooltips for the badges

This commit is contained in:
Elian Doran 2025-12-10 09:27:44 +02:00
parent efe7fc0ee7
commit 61592716f9
No known key found for this signature in database
3 changed files with 35 additions and 8 deletions

View File

@ -2132,9 +2132,14 @@
}, },
"breadcrumb_badges": { "breadcrumb_badges": {
"read_only_explicit": "Read-only", "read_only_explicit": "Read-only",
"read_only_explicit_description": "This note has been manually set to read-only.\nClick to edit it temporarily.",
"read_only_auto": "Auto read-only", "read_only_auto": "Auto read-only",
"read_only_auto_description": "This note was set automatically to read-only mode for performance reasons. This automatic limit is adjustable from settings.\n\nClick to edit it temporarily.",
"read_only_temporarily_disabled": "Temporarily editable", "read_only_temporarily_disabled": "Temporarily editable",
"read_only_temporarily_disabled_description": "This note is currently editable, but it is normally read-only. The note will go back to being read-only as soon as you navigate to another note.\n\nClick to re-enable read-only mode.",
"shared_publicly": "Shared publicly", "shared_publicly": "Shared publicly",
"shared_locally": "Shared locally" "shared_publicly_description": "This note has been published online at {{- link}}, and is publicly accessible.\n\nClick to navigate to the shared note.",
"shared_locally": "Shared locally",
"shared_locally_description": "This note is shared on the local network only at {{- link}}.\n\nClick to navigate to the shared note."
} }
} }

View File

@ -1,11 +1,13 @@
import "./BreadcrumbBadges.css"; import "./BreadcrumbBadges.css";
import { ComponentChildren } from "preact"; import { ComponentChildren, MouseEventHandler } from "preact";
import { useIsNoteReadOnly, useNoteContext } from "./react/hooks"; import { useIsNoteReadOnly, useNoteContext, useStaticTooltip } from "./react/hooks";
import Icon from "./react/Icon"; import Icon from "./react/Icon";
import { useShareInfo } from "./shared_info"; import { useShareInfo } from "./shared_info";
import clsx from "clsx"; import clsx from "clsx";
import { t } from "../services/i18n"; import { t } from "../services/i18n";
import { useRef } from "preact/hooks";
import { goToLinkExt } from "../services/link";
export default function BreadcrumbBadges() { export default function BreadcrumbBadges() {
return ( return (
@ -25,6 +27,7 @@ function ReadOnlyBadge() {
if (isTemporarilyEditable) { if (isTemporarilyEditable) {
return <Badge return <Badge
icon="bx bx-lock-open-alt" icon="bx bx-lock-open-alt"
tooltip={t("breadcrumb_badges.read_only_temporarily_disabled_description")}
onClick={() => enableEditing(false)} onClick={() => enableEditing(false)}
> >
{t("breadcrumb_badges.read_only_temporarily_disabled")} {t("breadcrumb_badges.read_only_temporarily_disabled")}
@ -32,7 +35,9 @@ function ReadOnlyBadge() {
} else if (isReadOnly) { } else if (isReadOnly) {
return <Badge return <Badge
icon="bx bx-lock-alt" icon="bx bx-lock-alt"
onClick={() => enableEditing()}> tooltip={isExplicitReadOnly ? t("breadcrumb_badges.read_only_explicit_description") : t("breadcrumb_badges.read_only_auto_description")}
onClick={() => enableEditing()}
>
{isExplicitReadOnly ? t("breadcrumb_badges.read_only_explicit") : t("breadcrumb_badges.read_only_auto")} {isExplicitReadOnly ? t("breadcrumb_badges.read_only_explicit") : t("breadcrumb_badges.read_only_auto")}
</Badge>; </Badge>;
} }
@ -40,20 +45,35 @@ function ReadOnlyBadge() {
function ShareBadge() { function ShareBadge() {
const { note } = useNoteContext(); const { note } = useNoteContext();
const { isSharedExternally, link } = useShareInfo(note); const { isSharedExternally, link, linkHref } = useShareInfo(note);
return (link && return (link &&
<Badge <Badge
icon={isSharedExternally ? "bx bx-world" : "bx bx-link"} icon={isSharedExternally ? "bx bx-world" : "bx bx-link"}
tooltip={isSharedExternally ?
t("breadcrumb_badges.shared_publicly_description", { link }) :
t("breadcrumb_badges.shared_locally_description", { link })
}
onClick={(e) => linkHref && goToLinkExt(e, linkHref)}
> >
{isSharedExternally ? t("breadcrumb_badges.shared_publicly") : t("breadcrumb_badges.shared_locally")} {isSharedExternally ? t("breadcrumb_badges.shared_publicly") : t("breadcrumb_badges.shared_locally")}
</Badge> </Badge>
); );
} }
function Badge({ icon, children, onClick }: { icon: string, children: ComponentChildren, onClick?: () => void }) { function Badge({ icon, children, tooltip, onClick }: { icon: string, tooltip: string, children: ComponentChildren, onClick?: MouseEventHandler<HTMLDivElement> }) {
const containerRef = useRef<HTMLDivElement>(null);
useStaticTooltip(containerRef, {
placement: "bottom",
fallbackPlacements: [ "bottom" ],
animation: false,
html: true,
title: tooltip
});
return ( return (
<div <div
ref={containerRef}
className={clsx("breadcrumb-badge", { "clickable": !!onClick })} className={clsx("breadcrumb-badge", { "clickable": !!onClick })}
onClick={onClick} onClick={onClick}
> >

View File

@ -26,6 +26,7 @@ export default function SharedInfo() {
export function useShareInfo(note: FNote | null | undefined) { export function useShareInfo(note: FNote | null | undefined) {
const [ link, setLink ] = useState<string>(); const [ link, setLink ] = useState<string>();
const [ linkHref, setLinkHref ] = useState<string>();
const [ syncServerHost ] = useTriliumOption("syncServerHost"); const [ syncServerHost ] = useTriliumOption("syncServerHost");
function refresh() { function refresh() {
@ -52,9 +53,10 @@ export function useShareInfo(note: FNote | null | undefined) {
} }
setLink(`<a href="${link}" class="external tn-link">${link}</a>`); setLink(`<a href="${link}" class="external tn-link">${link}</a>`);
setLinkHref(link);
} }
useEffect(refresh, [ note ]); useEffect(refresh, [ note, syncServerHost ]);
useTriliumEvent("entitiesReloaded", ({ loadResults }) => { useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (loadResults.getAttributeRows().find((attr) => attr.name?.startsWith("_share") && attributes.isAffecting(attr, note))) { if (loadResults.getAttributeRows().find((attr) => attr.name?.startsWith("_share") && attributes.isAffecting(attr, note))) {
refresh(); refresh();
@ -63,7 +65,7 @@ export function useShareInfo(note: FNote | null | undefined) {
} }
}); });
return { link, isSharedExternally: !!syncServerHost }; return { link, linkHref, isSharedExternally: !!syncServerHost };
} }
function getShareId(note: FNote) { function getShareId(note: FNote) {