mirror of
https://github.com/zadam/trilium.git
synced 2026-02-25 15:50:55 +01:00
Compare commits
52 Commits
feature/ot
...
feat/ui/gr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b223b931ab | ||
|
|
6759fef827 | ||
|
|
896d50b1f8 | ||
|
|
2049c49fdb | ||
|
|
b3c397e847 | ||
|
|
9651ca99f3 | ||
|
|
a6e87f5724 | ||
|
|
cf994dac5a | ||
|
|
95c9c375c9 | ||
|
|
f9804eda8e | ||
|
|
88c2bedbd7 | ||
|
|
49bf49c967 | ||
|
|
506b5c44af | ||
|
|
22ea59a63b | ||
|
|
934aaaf045 | ||
|
|
c6bfcea79f | ||
|
|
6e39fb12e2 | ||
|
|
dbe534d8f8 | ||
|
|
04e5197d00 | ||
|
|
e9dc97daf8 | ||
|
|
3a3cc565ea | ||
|
|
fcf4ffb445 | ||
|
|
b34c27af1f | ||
|
|
64371a6b9c | ||
|
|
182afab12c | ||
|
|
57e888911d | ||
|
|
535054b2d2 | ||
|
|
d40191257c | ||
|
|
87ee1185f2 | ||
|
|
f4b0f810bd | ||
|
|
0934e33af7 | ||
|
|
b3e88f5a44 | ||
|
|
2f23db0c64 | ||
|
|
ca2f39bacd | ||
|
|
e38b89996a | ||
|
|
cfb56cb143 | ||
|
|
477e516473 | ||
|
|
fd601eac5b | ||
|
|
b5300e5b86 | ||
|
|
19d2f02694 | ||
|
|
fec929dfee | ||
|
|
d7339ff14d | ||
|
|
422bc00ade | ||
|
|
8edf5483a6 | ||
|
|
00046d4145 | ||
|
|
25e67f62d5 | ||
|
|
e5eab3952b | ||
|
|
4c36a9cca9 | ||
|
|
fd8ab990bd | ||
|
|
5c007cdebc | ||
|
|
ef6c733f93 | ||
|
|
e7d6658c7a |
57
.vscode/launch.json
vendored
Normal file
57
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Launch client (Chrome)",
|
||||
"request": "launch",
|
||||
"type": "chrome",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}/apps/client"
|
||||
},
|
||||
{
|
||||
"name": "Launch server",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/apps/server/src/main.ts",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"TRILIUM_ENV": "dev",
|
||||
"TRILIUM_DATA_DIR": "${input:trilium_data_dir}",
|
||||
"TRILIUM_RESOURCE_DIR": "${workspaceFolder}/apps/server/src"
|
||||
},
|
||||
"autoAttachChildProcesses": true,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
|
||||
},
|
||||
{
|
||||
"name": "Launch Vitest with current test file",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"autoAttachChildProcesses": true,
|
||||
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
||||
"args": ["run", "${relativeFile}"],
|
||||
"smartStep": true,
|
||||
"console": "integratedTerminal",
|
||||
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Launch client (Chrome) and server",
|
||||
"configurations": ["Launch server","Launch client (Chrome)"],
|
||||
"stopAll": true
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "trilium_data_dir",
|
||||
"type": "promptString",
|
||||
"description": "Select Trilum Notes data directory",
|
||||
"default": "${workspaceFolder}/apps/server/data"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
"keywords": [],
|
||||
"author": "Elian Doran <contact@eliandoran.me>",
|
||||
"license": "AGPL-3.0-only",
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"packageManager": "pnpm@10.30.2",
|
||||
"devDependencies": {
|
||||
"@redocly/cli": "2.19.1",
|
||||
"archiver": "7.0.1",
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
"jquery": "4.0.0",
|
||||
"jquery.fancytree": "2.38.5",
|
||||
"jsplumb": "2.15.6",
|
||||
"katex": "0.16.28",
|
||||
"katex": "0.16.33",
|
||||
"knockout": "3.5.1",
|
||||
"leaflet": "1.9.4",
|
||||
"leaflet-gpx": "2.2.0",
|
||||
@@ -71,7 +71,7 @@
|
||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||
"@prefresh/vite": "2.4.12",
|
||||
"@types/bootstrap": "5.2.10",
|
||||
"@types/jquery": "3.5.33",
|
||||
"@types/jquery": "4.0.0",
|
||||
"@types/leaflet": "1.9.21",
|
||||
"@types/leaflet-gpx": "1.3.8",
|
||||
"@types/mark.js": "8.11.12",
|
||||
|
||||
@@ -1534,7 +1534,8 @@
|
||||
"task-list": "任务列表",
|
||||
"new-feature": "新建",
|
||||
"collections": "集合",
|
||||
"book": "集合"
|
||||
"book": "集合",
|
||||
"ai-chat": "AI聊天"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "保护笔记",
|
||||
@@ -1630,7 +1631,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "没有找到符合搜索条件的笔记。",
|
||||
"search_not_executed": "尚未执行搜索。请点击上方的\"搜索\"按钮查看结果。"
|
||||
"search_not_executed": "尚未执行搜索。",
|
||||
"search_now": "立即搜索"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "配置启动栏"
|
||||
@@ -2005,7 +2007,9 @@
|
||||
"app-restart-required": "(需重启程序以应用更改)"
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} 篇笔记"
|
||||
"total_notes": "{{count}} 篇笔记",
|
||||
"prev_page": "上一页",
|
||||
"next_page": "下一页"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "出现错误无法显示内容。"
|
||||
|
||||
@@ -1679,7 +1679,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Ní bhfuarthas aon nótaí do na paraiméadair chuardaigh tugtha.",
|
||||
"search_not_executed": "Níl an cuardach curtha i gcrích fós. Cliceáil ar an gcnaipe \"Cuardaigh\" thuas chun na torthaí a fheiceáil."
|
||||
"search_not_executed": "Níl an cuardach curtha i gcrích fós.",
|
||||
"search_now": "Cuardaigh anois"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Cumraigh an Barra Seoladh"
|
||||
|
||||
@@ -83,7 +83,10 @@
|
||||
"erase_notes_warning": "Hapus catatan secara permanen (tidak bisa dikembalikan), termasuk semua duplikat. Aksi akan memaksa aplikasi untuk mengulang kembali.",
|
||||
"notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})",
|
||||
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).",
|
||||
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})"
|
||||
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})",
|
||||
"cancel": "Batalkan",
|
||||
"ok": "Setuju",
|
||||
"deleted_relation_text": "Catatan {{- note}} (yang akan dihapus) dirujuk oleh relasi {{- relation}} yang berasal dari {{- source}}."
|
||||
},
|
||||
"clone_to": {
|
||||
"clone_notes_to": "Duplikat catatan ke…",
|
||||
@@ -96,5 +99,12 @@
|
||||
"clone_to_selected_note": "Salin ke catatan yang dipilih",
|
||||
"no_path_to_clone_to": "Tidak ada jalur untuk digandakan.",
|
||||
"note_cloned": "Catatan \"{{clonedTitle}}\" telah digandakan ke dalam \"{{targetTitle}}\""
|
||||
},
|
||||
"search_result": {
|
||||
"search_now": "Cari sekarang"
|
||||
},
|
||||
"export": {
|
||||
"export_note_title": "Mengeluarkan catatan",
|
||||
"close": "Tutup"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
"export_type_subtree": "Questa nota e tutti i suoi discendenti",
|
||||
"format_html": "HTML - raccomandato in quanto mantiene tutti i formati",
|
||||
"format_html_zip": "HTML in archivio ZIP - questo è raccomandato in quanto conserva tutta la formattazione.",
|
||||
"format_markdown": "MArkdown - questo conserva la maggior parte della formattazione.",
|
||||
"format_markdown": "Markdown: preserva la maggior parte della formattazione.",
|
||||
"export_type_single": "Solo questa nota, senza le sottostanti",
|
||||
"format_opml": "OPML - formato per scambio informazioni outline. Formattazione, immagini e files non sono inclusi.",
|
||||
"opml_version_1": "OPML v.1.0 - solo testo semplice",
|
||||
@@ -592,7 +592,7 @@
|
||||
"collapseExpand": "collassa/espande il nodo",
|
||||
"notSet": "non impostato",
|
||||
"goBackForwards": "indietro/avanti nella cronologia",
|
||||
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">finestra di dialogo “Vai a”</a>",
|
||||
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Vai a\"</a>",
|
||||
"title": "Scheda riassuntiva",
|
||||
"noteNavigation": "Nota navigazione",
|
||||
"scrollToActiveNote": "scorri fino alla nota attiva",
|
||||
@@ -1715,7 +1715,8 @@
|
||||
"beta-feature": "Beta",
|
||||
"task-list": "Elenco delle attività",
|
||||
"new-feature": "Nuovo",
|
||||
"collections": "Collezioni"
|
||||
"collections": "Collezioni",
|
||||
"ai-chat": "Chat con IA"
|
||||
},
|
||||
"protect_note": {
|
||||
"toggle-on": "Proteggi la nota",
|
||||
@@ -1793,7 +1794,8 @@
|
||||
},
|
||||
"search_result": {
|
||||
"no_notes_found": "Non sono state trovate note per i parametri di ricerca specificati.",
|
||||
"search_not_executed": "La ricerca non è stata ancora eseguita. Clicca sul pulsante \"Cerca\" qui sopra per visualizzare i risultati."
|
||||
"search_not_executed": "La ricerca non è stata ancora eseguita.",
|
||||
"search_now": "Cerca ora"
|
||||
},
|
||||
"spacer": {
|
||||
"configure_launchbar": "Configura Launchbar"
|
||||
@@ -2020,7 +2022,9 @@
|
||||
"percentage": "%"
|
||||
},
|
||||
"pagination": {
|
||||
"total_notes": "{{count}} note"
|
||||
"total_notes": "{{count}} note",
|
||||
"prev_page": "Pagina precedente",
|
||||
"next_page": "Pagina successiva"
|
||||
},
|
||||
"collections": {
|
||||
"rendering_error": "Impossibile mostrare il contenuto a causa di un errore."
|
||||
|
||||
@@ -599,7 +599,8 @@
|
||||
"beta-feature": "Beta",
|
||||
"task-list": "タスクリスト",
|
||||
"new-feature": "New",
|
||||
"collections": "コレクション"
|
||||
"collections": "コレクション",
|
||||
"ai-chat": "AI チャット"
|
||||
},
|
||||
"edited_notes": {
|
||||
"no_edited_notes_found": "この日の編集されたノートはまだありません...",
|
||||
|
||||
@@ -9,7 +9,8 @@ import Button from "../react/Button";
|
||||
import "./Pagination.css";
|
||||
import clsx from "clsx";
|
||||
|
||||
interface PaginationContext {
|
||||
export interface PaginationContext {
|
||||
className?: string;
|
||||
page: number;
|
||||
setPage: Dispatch<StateUpdater<number>>;
|
||||
pageNotes?: FNote[];
|
||||
@@ -18,11 +19,11 @@ interface PaginationContext {
|
||||
totalNotes: number;
|
||||
}
|
||||
|
||||
export function Pager({ page, pageSize, setPage, pageCount, totalNotes }: Omit<PaginationContext, "pageNotes">) {
|
||||
export function Pager({ className, page, pageSize, setPage, pageCount, totalNotes }: Omit<PaginationContext, "pageNotes">) {
|
||||
if (pageCount < 2) return;
|
||||
|
||||
return (
|
||||
<div className="note-list-pager-container">
|
||||
<div className={clsx("note-list-pager-container", className)}>
|
||||
<div className="note-list-pager">
|
||||
<ActionButton
|
||||
icon="bx bx-chevron-left"
|
||||
|
||||
@@ -13,6 +13,14 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.note-list-bottom-pager {
|
||||
margin-block: 8px;
|
||||
}
|
||||
|
||||
&:not(:has(.note-list-bottom-pager)) {
|
||||
margin-bottom: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
/* #region List view / Grid view common styles */
|
||||
@@ -107,7 +115,7 @@
|
||||
.nested-note-list .note-book-content,
|
||||
.note-list-container .note-book-content {
|
||||
display: none;
|
||||
animation: note-preview-show .25s ease-out;
|
||||
animation: note-preview-show .35s ease-out;
|
||||
will-change: opacity;
|
||||
|
||||
&.note-book-content-ready {
|
||||
@@ -347,7 +355,15 @@
|
||||
|
||||
.note-book-card .note-book-content {
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
font-size: 0.8rem;
|
||||
|
||||
&.note-book-content-overflowing {
|
||||
mask-image: linear-gradient(to bottom, black calc(100% - 75px), transparent 100%);
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: 100% 100%;
|
||||
}
|
||||
|
||||
.ck-content p {
|
||||
margin-bottom: 0.5em;
|
||||
@@ -358,6 +374,26 @@
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.ck-content .table {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
overflow-x: scroll;
|
||||
--scrollbar-thickness: 0;
|
||||
scrollbar-width: none;
|
||||
|
||||
table {
|
||||
width: max-content;
|
||||
table-layout: auto;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
display: block;
|
||||
position: sticky;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rendered-content,
|
||||
.rendered-content.text-with-ellipsis {
|
||||
padding: .5rem 1rem 1rem 1rem;
|
||||
@@ -368,6 +404,10 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.type-video video {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-size: 1rem;
|
||||
color: var(--active-item-text-color);
|
||||
|
||||
@@ -13,13 +13,15 @@ import { useImperativeSearchHighlighlighting, useNoteLabel, useNoteLabelBoolean,
|
||||
import Icon from "../../react/Icon";
|
||||
import NoteLink from "../../react/NoteLink";
|
||||
import { ViewModeProps } from "../interface";
|
||||
import { Pager, usePagination } from "../Pagination";
|
||||
import { Pager, usePagination, PaginationContext } from "../Pagination";
|
||||
import { filterChildNotes, useFilteredNoteIds } from "./utils";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
import { clsx } from "clsx";
|
||||
import ActionButton from "../../react/ActionButton";
|
||||
import linkContextMenuService from "../../../menus/link_context_menu";
|
||||
import { TargetedMouseEvent } from "preact";
|
||||
import { ComponentChildren, TargetedMouseEvent } from "preact";
|
||||
|
||||
const contentSizeObserver = new ResizeObserver(onContentResized);
|
||||
|
||||
export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||
const expandDepth = useExpansionDepth(note);
|
||||
@@ -27,32 +29,18 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
||||
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
||||
|
||||
return (
|
||||
<div className="note-list list-view">
|
||||
<CollectionProperties
|
||||
note={note}
|
||||
centerChildren={<Pager {...pagination} />}
|
||||
/>
|
||||
|
||||
{ noteIds.length > 0 && <div className="note-list-wrapper">
|
||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
||||
|
||||
<Card className={clsx("nested-note-list", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<ListNoteCard
|
||||
key={childNote.noteId}
|
||||
note={childNote} parentNote={note}
|
||||
expandDepth={expandDepth} highlightedTokens={highlightedTokens}
|
||||
currentLevel={1} includeArchived={includeArchived} />
|
||||
))}
|
||||
</Card>
|
||||
|
||||
<Pager {...pagination} />
|
||||
</div>}
|
||||
</div>
|
||||
);
|
||||
return <NoteList note={note} viewMode="list-view" noteIds={noteIds} pagination={pagination}>
|
||||
<Card className={clsx("nested-note-list", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<ListNoteCard
|
||||
key={childNote.noteId}
|
||||
note={childNote} parentNote={note}
|
||||
expandDepth={expandDepth} highlightedTokens={highlightedTokens}
|
||||
currentLevel={1} includeArchived={includeArchived} />
|
||||
))}
|
||||
</Card>
|
||||
</NoteList>;
|
||||
}
|
||||
|
||||
export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||
@@ -60,32 +48,47 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
||||
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
||||
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
||||
|
||||
return (
|
||||
<div className="note-list grid-view">
|
||||
<CollectionProperties
|
||||
note={note}
|
||||
centerChildren={<Pager {...pagination} />}
|
||||
/>
|
||||
|
||||
<div className="note-list-wrapper">
|
||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
||||
|
||||
<div className={clsx("note-list-container use-tn-links", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<GridNoteCard key={childNote.noteId}
|
||||
note={childNote}
|
||||
parentNote={note}
|
||||
highlightedTokens={highlightedTokens}
|
||||
includeArchived={includeArchived} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Pager {...pagination} />
|
||||
</div>
|
||||
return <NoteList note={note} viewMode="grid-view" noteIds={noteIds} pagination={pagination}>
|
||||
<div className={clsx("note-list-container use-tn-links", {"search-results": (noteType === "search")})}>
|
||||
{pageNotes?.map(childNote => (
|
||||
<GridNoteCard key={childNote.noteId}
|
||||
note={childNote}
|
||||
parentNote={note}
|
||||
highlightedTokens={highlightedTokens}
|
||||
includeArchived={includeArchived} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
</NoteList>
|
||||
}
|
||||
|
||||
interface NoteListProps {
|
||||
note: FNote,
|
||||
viewMode: "list-view" | "grid-view",
|
||||
noteIds: string[],
|
||||
pagination: PaginationContext,
|
||||
children: ComponentChildren
|
||||
}
|
||||
|
||||
function NoteList(props: NoteListProps) {
|
||||
const noteType = useNoteProperty(props.note, "type");
|
||||
const hasCollectionProperties = ["book", "search"].includes(noteType ?? "");
|
||||
|
||||
return <div className={clsx("note-list", props.viewMode)}>
|
||||
<CollectionProperties
|
||||
note={props.note}
|
||||
centerChildren={<Pager className="note-list-top-pager" {...props.pagination} />}
|
||||
/>
|
||||
|
||||
{props.noteIds.length > 0 && <div className="note-list-wrapper">
|
||||
{!hasCollectionProperties && <Pager {...props.pagination} />}
|
||||
|
||||
{props.children}
|
||||
|
||||
<Pager className="note-list-bottom-pager" {...props.pagination} />
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: {
|
||||
@@ -175,7 +178,8 @@ function GridNoteCard(props: GridNoteCardProps) {
|
||||
showNotePath={props.parentNote.type === "search"}
|
||||
highlightedTokens={props.highlightedTokens}
|
||||
/>
|
||||
<NoteMenuButton notePath={notePath} />
|
||||
{!props.note.isOptions() && <NoteMenuButton notePath={notePath} />}
|
||||
|
||||
</h5>
|
||||
<NoteContent note={props.note}
|
||||
trim
|
||||
@@ -210,6 +214,17 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc
|
||||
const [ready, setReady] = useState(false);
|
||||
const [noteType, setNoteType] = useState<string>("none");
|
||||
|
||||
useEffect(() => {
|
||||
const contentElement = contentRef.current;
|
||||
if (!contentElement) return;
|
||||
|
||||
contentSizeObserver.observe(contentElement);
|
||||
|
||||
return () => {
|
||||
contentSizeObserver.unobserve(contentElement);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
content_renderer.getRenderedContent(note, {
|
||||
trim,
|
||||
@@ -296,4 +311,11 @@ function useExpansionDepth(note: FNote) {
|
||||
}
|
||||
return parseInt(expandDepth, 10);
|
||||
|
||||
}
|
||||
|
||||
function onContentResized(entries: ResizeObserverEntry[], observer: ResizeObserver): void {
|
||||
for (const contentElement of entries) {
|
||||
const isOverflowing = ((contentElement.target.scrollHeight > contentElement.target.clientHeight))
|
||||
contentElement.target.classList.toggle("note-book-content-overflowing", isOverflowing);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
.collection-properties {
|
||||
padding: 0.55em 12px;
|
||||
padding: 0.55em var(--content-margin-inline);
|
||||
display: flex;
|
||||
gap: 0.25em;
|
||||
align-items: center;
|
||||
|
||||
@@ -26,7 +26,6 @@ export default function NoteTitleWidget(props: {className?: string}) {
|
||||
|| note === undefined
|
||||
|| (note.isProtected && !protected_session_holder.isProtectedSessionAvailable())
|
||||
|| isLaunchBarConfig(note.noteId)
|
||||
|| note.noteId.startsWith("_help_")
|
||||
|| viewScope?.viewMode !== "default";
|
||||
setReadOnly(isReadOnly);
|
||||
}, [ note, note?.noteId, note?.isProtected, viewScope?.viewMode ]);
|
||||
|
||||
@@ -94,6 +94,11 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||
"application/pdf"
|
||||
]
|
||||
|
||||
const COLLECTIONS_WITH_BACKGROUND_EFFECTS = [
|
||||
"grid",
|
||||
"list"
|
||||
]
|
||||
|
||||
if (note.isOptions()) {
|
||||
return true;
|
||||
}
|
||||
@@ -102,6 +107,10 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (note.type === "book" && COLLECTIONS_WITH_BACKGROUND_EFFECTS.includes(note.getLabelValue("viewType") ?? "none")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
}
|
||||
|
||||
.tn-card-frame,
|
||||
.tn-card-section {
|
||||
.tn-card-body .tn-card-section {
|
||||
padding: var(--card-padding-block) var(--card-padding-inline);
|
||||
border: 1px solid var(--card-border-color, var(--main-border-color));
|
||||
background: var(--card-background-color);
|
||||
|
||||
@@ -1383,28 +1383,3 @@ export function useGetContextDataFrom<K extends keyof NoteContextDataMap>(
|
||||
return data;
|
||||
}
|
||||
|
||||
export function useColorScheme() {
|
||||
const themeStyle = getThemeStyle();
|
||||
const defaultValue = themeStyle === "auto" ? (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) : themeStyle === "dark";
|
||||
const [ prefersDark, setPrefersDark ] = useState(defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
if (themeStyle !== "auto") return;
|
||||
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const listener = () => setPrefersDark((window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches));
|
||||
|
||||
mediaQueryList.addEventListener("change", listener);
|
||||
return () => mediaQueryList.removeEventListener("change", listener);
|
||||
}, []);
|
||||
|
||||
return prefersDark ? "dark" : "light";
|
||||
}
|
||||
|
||||
function getThemeStyle() {
|
||||
const style = window.getComputedStyle(document.body);
|
||||
const themeStyle = style.getPropertyValue("--theme-style");
|
||||
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
|
||||
return themeStyle as "light" | "dark";
|
||||
}
|
||||
return "auto";
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export default function ScrollPadding() {
|
||||
const [height, setHeight] = useState<number>(10);
|
||||
const isEnabled = ["text", "code"].includes(note?.type ?? "")
|
||||
&& viewScope?.viewMode === "default"
|
||||
&& note?.isContentAvailable()
|
||||
&& !note?.isTriliumSqlite();
|
||||
|
||||
const refreshHeight = () => {
|
||||
|
||||
@@ -6,12 +6,12 @@ import "./MindMap.css";
|
||||
import nodeMenu from "@mind-elixir/node-menu";
|
||||
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
||||
import { snapdom } from "@zumer/snapdom";
|
||||
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME, DARK_THEME } from "mind-elixir";
|
||||
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options } from "mind-elixir";
|
||||
import { HTMLAttributes, RefObject } from "preact";
|
||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||
|
||||
import utils from "../../services/utils";
|
||||
import { useColorScheme, useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
||||
import { useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
||||
import { refToJQuerySelector } from "../react/react_utils";
|
||||
import { TypeWidgetProps } from "./type_widget";
|
||||
|
||||
@@ -85,11 +85,9 @@ export default function MindMap({ note, ntxId, noteContext }: TypeWidgetProps) {
|
||||
},
|
||||
onContentChange: (content) => {
|
||||
let newContent: MindElixirData;
|
||||
|
||||
if (content) {
|
||||
try {
|
||||
newContent = JSON.parse(content) as MindElixirData;
|
||||
delete newContent.theme; // The theme is managed internally by the widget, so we remove it from the loaded content to avoid inconsistencies.
|
||||
} catch (e) {
|
||||
console.warn(e);
|
||||
console.debug("Wrong JSON content: ", content);
|
||||
@@ -153,7 +151,6 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
|
||||
const apiRef = useRef<MindElixirInstance>(null);
|
||||
const [ locale ] = useTriliumOption("locale");
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
function reinitialize() {
|
||||
if (!containerRef.current) return;
|
||||
@@ -161,8 +158,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
const mind = new VanillaMindElixir({
|
||||
el: containerRef.current,
|
||||
locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined,
|
||||
editable,
|
||||
theme: LIGHT_THEME
|
||||
editable
|
||||
});
|
||||
|
||||
if (editable) {
|
||||
@@ -183,14 +179,6 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
||||
};
|
||||
}, []);
|
||||
|
||||
// React to theme changes.
|
||||
useEffect(() => {
|
||||
if (!apiRef.current) return;
|
||||
const newTheme = colorScheme === "dark" ? DARK_THEME : LIGHT_THEME;
|
||||
if (apiRef.current.theme === newTheme) return; // Avoid unnecessary theme changes, which can be expensive to render.
|
||||
apiRef.current.changeTheme(newTheme);
|
||||
}, [ colorScheme ]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = apiRef.current?.getData();
|
||||
reinitialize();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||
import { TypeWidgetProps } from "../type_widget";
|
||||
import "@excalidraw/excalidraw/index.css";
|
||||
import { useColorScheme, useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
||||
import { useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
||||
import { useCallback, useMemo, useRef } from "preact/hooks";
|
||||
import { type ExcalidrawImperativeAPI, type AppState } from "@excalidraw/excalidraw/types";
|
||||
import options from "../../../services/options";
|
||||
@@ -19,9 +19,12 @@ window.EXCALIDRAW_ASSET_PATH = `${window.location.pathname}/node_modules/@excali
|
||||
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||
const colorScheme = useColorScheme();
|
||||
const themeStyle = useMemo(() => {
|
||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
||||
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
||||
}, []);
|
||||
const [ locale ] = useTriliumOption("locale");
|
||||
const persistence = useCanvasPersistence(note, noteContext, apiRef, colorScheme, isReadOnly);
|
||||
const persistence = useCanvasPersistence(note, noteContext, apiRef, themeStyle, isReadOnly);
|
||||
|
||||
/** Use excalidraw's native zoom instead of the global zoom. */
|
||||
const onWheel = useCallback((e: MouseEvent) => {
|
||||
@@ -51,7 +54,7 @@ export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||
<div className="excalidraw-wrapper">
|
||||
<Excalidraw
|
||||
excalidrawAPI={api => apiRef.current = api}
|
||||
theme={colorScheme}
|
||||
theme={themeStyle}
|
||||
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
||||
zenModeEnabled={false}
|
||||
isCollaborating={false}
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
"postinstall": "wxt prepare"
|
||||
},
|
||||
"keywords": [],
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"packageManager": "pnpm@10.30.2",
|
||||
"devDependencies": {
|
||||
"@wxt-dev/auto-icons": "1.1.0",
|
||||
"wxt": "0.20.17"
|
||||
"wxt": "0.20.18"
|
||||
},
|
||||
"dependencies": {
|
||||
"cash-dom": "8.1.5"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@preact/preset-vite": "2.10.3",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-preact": "2.0.0",
|
||||
"typescript": "5.9.3",
|
||||
"user-agent-data-types": "0.4.2",
|
||||
|
||||
@@ -58,10 +58,10 @@
|
||||
"cross-env": "10.1.0",
|
||||
"dpdm": "4.0.1",
|
||||
"esbuild": "0.27.3",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-preact": "2.0.0",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-playwright": "2.7.0",
|
||||
"eslint-plugin-playwright": "2.7.1",
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"happy-dom": "20.7.0",
|
||||
"http-server": "14.1.1",
|
||||
@@ -73,7 +73,7 @@
|
||||
"tslib": "2.8.1",
|
||||
"tsx": "4.21.0",
|
||||
"typescript": "5.9.3",
|
||||
"typescript-eslint": "8.56.0",
|
||||
"typescript-eslint": "8.56.1",
|
||||
"upath": "2.0.1",
|
||||
"vite": "7.3.1",
|
||||
"vite-plugin-dts": "4.5.4",
|
||||
@@ -93,7 +93,7 @@
|
||||
"url": "https://github.com/TriliumNext/Trilium/issues"
|
||||
},
|
||||
"homepage": "https://triliumnotes.org",
|
||||
"packageManager": "pnpm@10.30.1",
|
||||
"packageManager": "pnpm@10.30.2",
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/browser": "4.0.18",
|
||||
"@vitest/coverage-istanbul": "4.0.18",
|
||||
"ckeditor5": "47.4.0",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"lint-staged": "16.2.7",
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/browser": "4.0.18",
|
||||
"@vitest/coverage-istanbul": "4.0.18",
|
||||
"ckeditor5": "47.4.0",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"lint-staged": "16.2.7",
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/browser": "4.0.18",
|
||||
"@vitest/coverage-istanbul": "4.0.18",
|
||||
"ckeditor5": "47.4.0",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"lint-staged": "16.2.7",
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/browser": "4.0.18",
|
||||
"@vitest/coverage-istanbul": "4.0.18",
|
||||
"ckeditor5": "47.4.0",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"lint-staged": "16.2.7",
|
||||
|
||||
@@ -27,12 +27,12 @@
|
||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"@vitest/browser": "4.0.18",
|
||||
"@vitest/coverage-istanbul": "4.0.18",
|
||||
"ckeditor5": "47.4.0",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"eslint-config-ckeditor5": ">=9.1.0",
|
||||
"http-server": "14.1.1",
|
||||
"lint-staged": "16.2.7",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"ckeditor5-premium-features": "47.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@smithy/middleware-retry": "4.4.33",
|
||||
"@types/jquery": "3.5.33"
|
||||
"@smithy/middleware-retry": "4.4.36",
|
||||
"@types/jquery": "4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,6 @@
|
||||
"codemirror-lang-elixir": "4.0.0",
|
||||
"codemirror-lang-hcl": "0.1.0",
|
||||
"codemirror-lang-mermaid": "0.5.0",
|
||||
"eslint-linter-browserify": "10.0.1"
|
||||
"eslint-linter-browserify": "10.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,17 +25,17 @@
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"fuse.js": "7.1.0",
|
||||
"katex": "0.16.28",
|
||||
"katex": "0.16.33",
|
||||
"mermaid": "11.12.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@digitak/esrun": "3.2.26",
|
||||
"@triliumnext/ckeditor5": "workspace:*",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
||||
"@typescript-eslint/parser": "8.56.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||
"@typescript-eslint/parser": "8.56.1",
|
||||
"dotenv": "17.3.1",
|
||||
"esbuild": "0.27.3",
|
||||
"eslint": "10.0.1",
|
||||
"eslint": "10.0.2",
|
||||
"highlight.js": "11.11.1",
|
||||
"typescript": "5.9.3"
|
||||
}
|
||||
|
||||
1018
pnpm-lock.yaml
generated
1018
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user