mirror of
https://github.com/zadam/trilium.git
synced 2025-12-29 10:44:25 +01:00
feat(note_icon): use grid virtualization for listing high performance
This commit is contained in:
parent
cbb7b4ffea
commit
8f21c0b34a
@ -3,9 +3,10 @@ import "./note_icon.css";
|
||||
import { IconRegistry } from "@triliumnext/commons";
|
||||
import { Dropdown as BootstrapDropdown } from "bootstrap";
|
||||
import clsx from "clsx";
|
||||
import { t, use } from "i18next";
|
||||
import { RefObject } from "preact";
|
||||
import { t } from "i18next";
|
||||
import { CSSProperties, RefObject } from "preact";
|
||||
import { useEffect, useMemo, useRef, useState } from "preact/hooks";
|
||||
import { CellComponentProps, Grid } from "react-window";
|
||||
|
||||
import FNote from "../entities/fnote";
|
||||
import attributes from "../services/attributes";
|
||||
@ -132,13 +133,16 @@ function NoteIconList({ note, dropdownRef }: {
|
||||
}}
|
||||
>
|
||||
{filteredIcons.length ? (
|
||||
(filteredIcons ?? []).map(({ id, terms, iconPack }) => (
|
||||
<span
|
||||
key={id}
|
||||
class={clsx(id, "tn-icon")}
|
||||
title={t("note_icon.icon_tooltip", { name: terms?.[0] ?? id, iconPack })}
|
||||
/>
|
||||
))
|
||||
<Grid
|
||||
columnCount={12}
|
||||
columnWidth={48}
|
||||
rowCount={Math.ceil(filteredIcons.length / 12)}
|
||||
rowHeight={48}
|
||||
cellComponent={IconItemCell}
|
||||
cellProps={{
|
||||
filteredIcons
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div class="no-results">{t("note_icon.no_results")}</div>
|
||||
)}
|
||||
@ -147,6 +151,22 @@ function NoteIconList({ note, dropdownRef }: {
|
||||
);
|
||||
}
|
||||
|
||||
function IconItemCell({ rowIndex, columnIndex, style, filteredIcons }: CellComponentProps<{
|
||||
filteredIcons: IconWithName[];
|
||||
}>): React.JSX.Element {
|
||||
const iconIndex = rowIndex * 12 + columnIndex;
|
||||
const iconData = filteredIcons[iconIndex];
|
||||
const { id, terms, iconPack } = iconData;
|
||||
return (
|
||||
<span
|
||||
key={id}
|
||||
class={clsx(id, "tn-icon")}
|
||||
title={t("note_icon.icon_tooltip", { name: terms?.[0] ?? id, iconPack })}
|
||||
style={style as CSSProperties}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function IconFilterContent({ filterByPrefix, setFilterByPrefix }: {
|
||||
filterByPrefix: string | null;
|
||||
setFilterByPrefix: (value: string | null) => void;
|
||||
@ -212,7 +232,7 @@ function useFilteredIcons(allIcons: IconWithName[] | undefined, search: string |
|
||||
if (processedSearch || filterByPrefix !== null) {
|
||||
icons = icons.filter((icon) => {
|
||||
if (filterByPrefix) {
|
||||
if (!icon.id?.startsWith(`${filterByPrefix}-`)) {
|
||||
if (!icon.id?.startsWith(`${filterByPrefix} `)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@ -292,6 +292,9 @@ importers:
|
||||
react-i18next:
|
||||
specifier: 16.5.0
|
||||
version: 16.5.0(i18next@25.7.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
|
||||
react-window:
|
||||
specifier: 2.2.3
|
||||
version: 2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||
reveal.js:
|
||||
specifier: 5.2.1
|
||||
version: 5.2.1
|
||||
@ -483,11 +486,7 @@ importers:
|
||||
specifier: 11.3.3
|
||||
version: 11.3.3
|
||||
|
||||
apps/icon-pack-builder:
|
||||
devDependencies:
|
||||
'@phosphor-icons/web':
|
||||
specifier: 2.1.2
|
||||
version: 2.1.2
|
||||
apps/icon-pack-builder: {}
|
||||
|
||||
apps/server:
|
||||
dependencies:
|
||||
@ -4035,9 +4034,6 @@ packages:
|
||||
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
'@phosphor-icons/web@2.1.2':
|
||||
resolution: {integrity: sha512-rPAR9o/bEcp4Cw4DEeZHXf+nlGCMNGkNDRizYHM47NLxz9vvEHp/Tt6FMK1NcWadzw/pFDPnRBGi/ofRya958A==}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
@ -12010,6 +12006,12 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
|
||||
react-window@2.2.3:
|
||||
resolution: {integrity: sha512-gTRqQYC8ojbiXyd9duYFiSn2TJw0ROXCgYjenOvNKITWzK0m0eCvkUsEUM08xvydkMh7ncp+LE0uS3DeNGZxnQ==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0
|
||||
react-dom: ^18.0.0 || ^19.0.0
|
||||
|
||||
react@16.14.0:
|
||||
resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@ -18460,8 +18462,6 @@ snapshots:
|
||||
'@parcel/watcher-win32-x64': 2.5.1
|
||||
optional: true
|
||||
|
||||
'@phosphor-icons/web@2.1.2': {}
|
||||
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
@ -28213,6 +28213,11 @@ snapshots:
|
||||
prop-types: 15.8.1
|
||||
react: 19.2.3
|
||||
|
||||
react-window@2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
|
||||
dependencies:
|
||||
react: 19.2.3
|
||||
react-dom: 19.2.3(react@19.2.3)
|
||||
|
||||
react@16.14.0:
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user