From 6eff62f73f0f2d2626c609e5fe67254fa70fd156 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Fri, 12 Dec 2025 20:55:54 +0200 Subject: [PATCH] feat(status_bar): add new attachment count --- .../src/translations/en/translation.json | 5 +- apps/client/src/widgets/layout/StatusBar.css | 18 +++--- apps/client/src/widgets/layout/StatusBar.tsx | 58 ++++++++++++++++++- .../src/widgets/type_widgets/Attachment.tsx | 35 ++++++----- 4 files changed, 89 insertions(+), 27 deletions(-) diff --git a/apps/client/src/translations/en/translation.json b/apps/client/src/translations/en/translation.json index 283711567..b168d3019 100644 --- a/apps/client/src/translations/en/translation.json +++ b/apps/client/src/translations/en/translation.json @@ -2156,8 +2156,9 @@ "status_bar": { "language_title": "Change the language of the entire content", "note_info_title": "View information about this note such as the creation/modification date or the note size.", - "backlinks": "{{count}}", "backlinks_title_one": "This note is linked from {{count}} other note.\n\nClick to view the list of backlinks.", - "backlinks_title_other": "This note is linked from {{count}} other notes.\n\nClick to view the list of backlinks." + "backlinks_title_other": "This note is linked from {{count}} other notes.\n\nClick to view the list of backlinks.", + "attachments_title_one": "This note has {{count}} attachment. Click to open the list of attachments in a new tab.", + "attachments_title_other": "This note has {{count}} attachments. Click to open the list of attachments in a new tab." } } diff --git a/apps/client/src/widgets/layout/StatusBar.css b/apps/client/src/widgets/layout/StatusBar.css index 688d8904d..094e2d3b8 100644 --- a/apps/client/src/widgets/layout/StatusBar.css +++ b/apps/client/src/widgets/layout/StatusBar.css @@ -15,27 +15,29 @@ padding: 0.1em; display: flex; gap: 0.1em; + font-size: 0.85em; - .status-bar-dropdown-button { - background: transparent; + .btn { padding: 0 0.5em !important; + background: transparent; display: flex; align-items: center; - - &:after { - content: unset; - } + border: 0; &:focus, &:hover { background: var(--input-background-color); } } + + .status-bar-dropdown-button { + &:after { + content: unset; + } + } } .dropdown { - font-size: 0.85em; - .dropdown-toggle { padding: 0.1em 0.25em; } diff --git a/apps/client/src/widgets/layout/StatusBar.tsx b/apps/client/src/widgets/layout/StatusBar.tsx index 6279629a4..9be622371 100644 --- a/apps/client/src/widgets/layout/StatusBar.tsx +++ b/apps/client/src/widgets/layout/StatusBar.tsx @@ -4,7 +4,7 @@ import { Locale } from "@triliumnext/commons"; import clsx from "clsx"; import { type ComponentChildren } from "preact"; import { createPortal } from "preact/compat"; -import { useState } from "preact/hooks"; +import { useContext, useRef, useState } from "preact/hooks"; import NoteContext from "../../components/note_context"; import FNote from "../../entities/fnote"; @@ -15,12 +15,17 @@ import { formatDateTime } from "../../utils/formatters"; import { BacklinksList, useBacklinkCount } from "../FloatingButtonsDefinitions"; import Dropdown, { DropdownProps } from "../react/Dropdown"; import { FormDropdownDivider, FormListItem } from "../react/FormList"; -import { useActiveNoteContext } from "../react/hooks"; +import { useActiveNoteContext, useStaticTooltip, useTooltip } from "../react/hooks"; import Icon from "../react/Icon"; import { ContentLanguagesModal, useLanguageSwitcher } from "../ribbon/BasicPropertiesTab"; import { NoteSizeWidget, useNoteMetadata } from "../ribbon/NoteInfoTab"; import { useProcessedLocales } from "../type_widgets/options/components/LocaleSelector"; import Breadcrumb from "./Breadcrumb"; +import { useAttachments } from "../type_widgets/Attachment"; +import ActionButton from "../react/ActionButton"; +import Button from "../react/Button"; +import { CommandNames } from "../../components/app_context"; +import { ParentComponent } from "../react/react_utils"; interface StatusBarContext { note: FNote; @@ -40,6 +45,7 @@ export default function StatusBar() {
+ @@ -75,6 +81,35 @@ function StatusBarDropdown({ children, icon, text, buttonClassName, titleOptions ); } +function StatusBarButton({ className, icon, text, title, triggerCommand }: { + className?: string; + icon: string; + title: string; + text?: string | number; + disabled?: boolean; + triggerCommand: CommandNames; +}) { + const parentComponent = useContext(ParentComponent); + const buttonRef = useRef(null); + useStaticTooltip(buttonRef, { + placement: "top", + fallbackPlacements: [ "top" ], + popperConfig: { strategy: "fixed" }, + title + }); + + return ( + + ); +} + //#region Language Switcher function LanguageSwitcher({ note }: StatusBarContext) { const [ modalShown, setModalShown ] = useState(false); @@ -166,7 +201,7 @@ function BacklinksBadge({ note, viewScope }: StatusBarContext) { @@ -175,3 +210,20 @@ function BacklinksBadge({ note, viewScope }: StatusBarContext) { ); } //#endregion + +//#region Attachment count +function AttachmentCount({ note }: StatusBarContext) { + const attachments = useAttachments(note); + const count = attachments.length; + + return (note && count > 0 && + + ); +} +//#endregion diff --git a/apps/client/src/widgets/type_widgets/Attachment.tsx b/apps/client/src/widgets/type_widgets/Attachment.tsx index 3fdc60e93..bef480c6f 100644 --- a/apps/client/src/widgets/type_widgets/Attachment.tsx +++ b/apps/client/src/widgets/type_widgets/Attachment.tsx @@ -26,24 +26,13 @@ import ws from "../../services/ws"; import appContext from "../../components/app_context"; import { ConvertAttachmentToNoteResponse } from "@triliumnext/commons"; import options from "../../services/options"; +import FNote from "../../entities/fnote"; /** * Displays the full list of attachments of a note and allows the user to interact with them. */ export function AttachmentList({ note }: TypeWidgetProps) { - const [ attachments, setAttachments ] = useState([]); - - function refresh() { - note.getAttachments().then(attachments => setAttachments(Array.from(attachments))); - } - - useEffect(refresh, [ note ]); - - useTriliumEvent("entitiesReloaded", ({ loadResults }) => { - if (loadResults.getAttachmentRows().some((att) => att.attachmentId && att.ownerId === note.noteId)) { - refresh(); - } - }); + const attachments = useAttachments(note); return ( <> @@ -59,7 +48,25 @@ export function AttachmentList({ note }: TypeWidgetProps) { )}
- ) + ); +} + +export function useAttachments(note: FNote) { + const [ attachments, setAttachments ] = useState([]); + + function refresh() { + note.getAttachments().then(attachments => setAttachments(Array.from(attachments))); + } + + useEffect(refresh, [ note ]); + + useTriliumEvent("entitiesReloaded", ({ loadResults }) => { + if (loadResults.getAttachmentRows().some((att) => att.attachmentId && att.ownerId === note.noteId)) { + refresh(); + } + }); + + return attachments; } function AttachmentListHeader({ noteId }: { noteId: string }) {