mirror of
https://github.com/zadam/trilium.git
synced 2026-01-06 06:34:25 +01:00
feat(icon_packs): integrate boxicons JSON
This commit is contained in:
parent
0c77563672
commit
78bec0c782
File diff suppressed because it is too large
Load Diff
@ -1,19 +1,17 @@
|
|||||||
import "./note_icon.css";
|
import "./note_icon.css";
|
||||||
|
|
||||||
|
import { IconRegistry } from "@triliumnext/commons";
|
||||||
import { t } from "i18next";
|
import { t } from "i18next";
|
||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
import FNote from "../entities/fnote";
|
import FNote from "../entities/fnote";
|
||||||
import attributes from "../services/attributes";
|
import attributes from "../services/attributes";
|
||||||
import server from "../services/server";
|
import server from "../services/server";
|
||||||
import type { Icon } from "./icon_list";
|
|
||||||
import ActionButton from "./react/ActionButton";
|
|
||||||
import Button from "./react/Button";
|
import Button from "./react/Button";
|
||||||
import Dropdown from "./react/Dropdown";
|
import Dropdown from "./react/Dropdown";
|
||||||
import { FormDropdownDivider, FormListItem } from "./react/FormList";
|
import { FormDropdownDivider, FormListItem } from "./react/FormList";
|
||||||
import FormTextBox from "./react/FormTextBox";
|
import FormTextBox from "./react/FormTextBox";
|
||||||
import { useNoteContext, useNoteLabel } from "./react/hooks";
|
import { useNoteContext, useNoteLabel } from "./react/hooks";
|
||||||
import Icon from "./react/Icon";
|
|
||||||
|
|
||||||
interface IconToCountCache {
|
interface IconToCountCache {
|
||||||
iconClassToCountMap: Record<string, number>;
|
iconClassToCountMap: Record<string, number>;
|
||||||
@ -21,12 +19,9 @@ interface IconToCountCache {
|
|||||||
|
|
||||||
interface IconData {
|
interface IconData {
|
||||||
iconToCount: Record<string, number>;
|
iconToCount: Record<string, number>;
|
||||||
icons: Icon[];
|
icons: IconRegistry["sources"][number]["icons"];
|
||||||
}
|
}
|
||||||
|
|
||||||
let fullIconData: {
|
|
||||||
icons: Icon[];
|
|
||||||
};
|
|
||||||
let iconToCountCache!: Promise<IconToCountCache> | null;
|
let iconToCountCache!: Promise<IconToCountCache> | null;
|
||||||
|
|
||||||
export default function NoteIcon() {
|
export default function NoteIcon() {
|
||||||
@ -62,31 +57,21 @@ function NoteIconList({ note }: { note: FNote }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function loadIcons() {
|
async function loadIcons() {
|
||||||
if (!fullIconData) {
|
|
||||||
fullIconData = (await import("./icon_list.js")).default;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter by text and/or category.
|
// Filter by text and/or category.
|
||||||
let icons: Pick<Icon, "name" | "term" | "className">[] = [
|
let icons: IconRegistry["sources"][number]["icons"] = [
|
||||||
...fullIconData.icons,
|
...glob.iconRegistry.sources.map(s => s.icons).flat()
|
||||||
...glob.iconRegistry.sources.map(s => s.icons.map(icon => ({
|
|
||||||
name: icon.terms.at(0) ?? "",
|
|
||||||
term: icon.terms.slice(1),
|
|
||||||
className: icon.id
|
|
||||||
}))).flat()
|
|
||||||
];
|
];
|
||||||
const processedSearch = search?.trim()?.toLowerCase();
|
const processedSearch = search?.trim()?.toLowerCase();
|
||||||
if (processedSearch || filterByPrefix !== null) {
|
if (processedSearch || filterByPrefix !== null) {
|
||||||
icons = icons.filter((icon) => {
|
icons = icons.filter((icon) => {
|
||||||
if (filterByPrefix) {
|
if (filterByPrefix) {
|
||||||
if (!icon.className?.startsWith(`${filterByPrefix} `)) {
|
if (!icon.id?.startsWith(`${filterByPrefix} `)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processedSearch) {
|
if (processedSearch) {
|
||||||
if (!icon.name.includes(processedSearch) &&
|
if (!icon.terms?.some((t) => t.includes(processedSearch))) {
|
||||||
!icon.term?.find((t) => t.includes(processedSearch))) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,8 +84,8 @@ function NoteIconList({ note }: { note: FNote }) {
|
|||||||
const iconToCount = await getIconToCountMap();
|
const iconToCount = await getIconToCountMap();
|
||||||
if (iconToCount) {
|
if (iconToCount) {
|
||||||
icons.sort((a, b) => {
|
icons.sort((a, b) => {
|
||||||
const countA = iconToCount[a.className ?? ""] || 0;
|
const countA = iconToCount[a.id ?? ""] || 0;
|
||||||
const countB = iconToCount[b.className ?? ""] || 0;
|
const countB = iconToCount[b.id ?? ""] || 0;
|
||||||
|
|
||||||
return countB - countA;
|
return countB - countA;
|
||||||
});
|
});
|
||||||
@ -168,8 +153,8 @@ function NoteIconList({ note }: { note: FNote }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(iconData?.icons ?? []).map(({className, name}) => (
|
{(iconData?.icons ?? []).map(({ id, terms }) => (
|
||||||
<span class={className} title={name} />
|
<span key={id} class={id} title={terms[0]} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
@ -193,7 +178,7 @@ function IconFilterContent({ filterByPrefix, setFilterByPrefix }: {
|
|||||||
<FormDropdownDivider />
|
<FormDropdownDivider />
|
||||||
|
|
||||||
{glob.iconRegistry.sources.map(({ prefix, name, icon }) => (
|
{glob.iconRegistry.sources.map(({ prefix, name, icon }) => (
|
||||||
<FormListItem
|
prefix !== "bx" && <FormListItem
|
||||||
key={prefix}
|
key={prefix}
|
||||||
onClick={() => setFilterByPrefix(prefix)}
|
onClick={() => setFilterByPrefix(prefix)}
|
||||||
icon={icon}
|
icon={icon}
|
||||||
|
|||||||
10455
apps/server/src/services/icon_pack_boxicons-v2.json
Normal file
10455
apps/server/src/services/icon_pack_boxicons-v2.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,7 @@ import { IconRegistry } from "@triliumnext/commons";
|
|||||||
|
|
||||||
import type BAttachment from "../becca/entities/battachment";
|
import type BAttachment from "../becca/entities/battachment";
|
||||||
import type BNote from "../becca/entities/bnote";
|
import type BNote from "../becca/entities/bnote";
|
||||||
|
import boxiconsManifest from "./icon_pack_boxicons-v2.json";
|
||||||
import log from "./log";
|
import log from "./log";
|
||||||
import search from "./search/services/search";
|
import search from "./search/services/search";
|
||||||
import { safeExtractMessageAndStackFromError } from "./utils";
|
import { safeExtractMessageAndStackFromError } from "./utils";
|
||||||
@ -30,19 +31,32 @@ interface ProcessResult {
|
|||||||
manifest: IconPackManifest;
|
manifest: IconPackManifest;
|
||||||
fontMime: string;
|
fontMime: string;
|
||||||
fontAttachmentId: string;
|
fontAttachmentId: string;
|
||||||
manifestNote: BNote;
|
title: string;
|
||||||
|
icon: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getIconPacks() {
|
export function getIconPacks() {
|
||||||
return search.searchNotes("#iconPack")
|
const defaultIconPack: ProcessResult = {
|
||||||
|
manifest: boxiconsManifest,
|
||||||
|
fontMime: "font/woff2",
|
||||||
|
fontAttachmentId: "builtin-boxicons-v2",
|
||||||
|
title: "Boxicons",
|
||||||
|
icon: "bx bx-package"
|
||||||
|
};
|
||||||
|
const customIconPacks = search.searchNotes("#iconPack")
|
||||||
.map(iconPackNote => processIconPack(iconPackNote))
|
.map(iconPackNote => processIconPack(iconPackNote))
|
||||||
.filter(Boolean) as ProcessResult[];
|
.filter(Boolean) as ProcessResult[];
|
||||||
|
|
||||||
|
return [
|
||||||
|
defaultIconPack,
|
||||||
|
...customIconPacks
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateIconRegistry(iconPacks: ProcessResult[]): IconRegistry {
|
export function generateIconRegistry(iconPacks: ProcessResult[]): IconRegistry {
|
||||||
const sources: IconRegistry["sources"] = [];
|
const sources: IconRegistry["sources"] = [];
|
||||||
|
|
||||||
for (const { manifest, manifestNote } of iconPacks) {
|
for (const { manifest, title, icon } of iconPacks) {
|
||||||
const icons: IconRegistry["sources"][number]["icons"] = Object.entries(manifest.icons)
|
const icons: IconRegistry["sources"][number]["icons"] = Object.entries(manifest.icons)
|
||||||
.map(( [id, { terms }] ) => {
|
.map(( [id, { terms }] ) => {
|
||||||
if (!id || !terms) return null;
|
if (!id || !terms) return null;
|
||||||
@ -53,8 +67,8 @@ export function generateIconRegistry(iconPacks: ProcessResult[]): IconRegistry {
|
|||||||
|
|
||||||
sources.push({
|
sources.push({
|
||||||
prefix: manifest.prefix,
|
prefix: manifest.prefix,
|
||||||
name: manifestNote.title,
|
name: title,
|
||||||
icon: manifestNote.getIcon(),
|
icon,
|
||||||
icons
|
icons
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -79,7 +93,8 @@ export function processIconPack(iconPackNote: BNote): ProcessResult | undefined
|
|||||||
manifest,
|
manifest,
|
||||||
fontMime: attachment.mime,
|
fontMime: attachment.mime,
|
||||||
fontAttachmentId: attachment.attachmentId,
|
fontAttachmentId: attachment.attachmentId,
|
||||||
manifestNote: iconPackNote
|
title: iconPackNote.title,
|
||||||
|
icon: iconPackNote.getIcon()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user