Compare commits

...

2520 Commits

Author SHA1 Message Date
perfectra1n
6c656c73a3 feat(dev): merge main into feature branch 2025-12-27 22:39:07 -08:00
Elian Doran
5174deac07 fix(status_bar): attribute count displays system links 2025-12-27 23:02:35 +02:00
Elian Doran
a6c515aea0 Translations update from Hosted Weblate (#8189) 2025-12-26 23:02:47 +02:00
green
850710926e Translated using Weblate (Japanese)
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-26 21:50:48 +01:00
noobhjy
904da14895 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-26 21:50:47 +01:00
Kuzma Simonov
4c5bc3a3d3 Translated using Weblate (Russian)
Currently translated at 100.0% (1730 of 1730 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-26 21:50:47 +01:00
Elian Doran
af4fc11a4e docs(release): fix link to new layout 2025-12-26 14:13:52 +02:00
Elian Doran
a63b8b2031 chore(release): prepare for v0.101.1 2025-12-26 14:01:04 +02:00
Elian Doran
7b02d87558 docs(release): prepare for v0.101.1 2025-12-26 13:59:49 +02:00
Elian Doran
16737b93dd fix(client): not working in HTTPs (closes #8165) 2025-12-26 13:51:01 +02:00
Elian Doran
c23fe7cf13 fix(table_of_contents): not showing on first render of read-only notes 2025-12-26 13:28:29 +02:00
Adorian Doran
6d80323a76 style/text selection: refactor, apply custom color tint over the note title selection 2025-12-26 11:45:42 +02:00
Adorian Doran
8b630c6e2e UI fixes (#8180) 2025-12-26 11:25:29 +02:00
Adorian Doran
047a8d9644 Fix #8177 2025-12-26 10:56:48 +02:00
Adorian Doran
f14ae01fab style/links: fix background color 2025-12-26 10:42:53 +02:00
Adorian Doran
785470b0ae style/global menu: fix icon alignment 2025-12-26 10:31:06 +02:00
Adorian Doran
73918c042b Fix #8170 2025-12-26 10:28:25 +02:00
Elian Doran
8d6eb6fa53 fix(right_pane): toggle shortcut not working on new layout 2025-12-25 23:42:45 +02:00
Elian Doran
f97fbf8325 Translations update from Hosted Weblate (#8161) 2025-12-25 23:24:14 +02:00
Mohammed Saati
e7d6e646be Translated using Weblate (Arabic)
Currently translated at 60.9% (1054 of 1730 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-12-25 21:22:36 +00:00
Mohammed Saati
839444af47 Translated using Weblate (Arabic)
Currently translated at 57.8% (88 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-12-25 21:22:35 +00:00
Hosted Weblate
24a58da4b6 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-25 21:22:34 +00:00
Elian Doran
aa37196169 fix(layout): missing right pane toggle on macos vertical layout (closes #8157) 2025-12-25 23:22:17 +02:00
Elian Doran
f821d7fcd6 fix(desktop): right margin on icon 2025-12-25 23:16:07 +02:00
Elian Doran
b417831507 Merge branch 'main' of github.com:TriliumNext/Trilium 2025-12-25 22:52:04 +02:00
Elian Doran
a4dbefd7ef fix(launch_bar): note launcher no longer hoisting in same tab (closes #8160) 2025-12-25 22:52:01 +02:00
Elian Doran
2d486c9934 chore(release): prepare for v0.101.0 2025-12-25 19:14:38 +02:00
Elian Doran
47cfbd0740 docs(release): prepare for v0.101.0 2025-12-25 19:08:55 +02:00
Elian Doran
f09d918695 fix(promoted_attributes): editing with multiplicity modifies all displayed values (closes #7992) 2025-12-25 18:32:52 +02:00
Elian Doran
33098a1120 feat(login): implement better time comparison management across several features (#8129) 2025-12-25 17:58:36 +02:00
Elian Doran
73f7c42437 Fixes for main (#8151) 2025-12-25 15:40:37 +02:00
Elian Doran
4ff0e2a1d9 Merge branch 'main' into feature/fixes_for_main 2025-12-25 15:40:34 +02:00
Elian Doran
afeaf51831 style(attachment): fix margin for code blocks 2025-12-25 11:54:00 +02:00
Adorian Doran
98db2fcd7b fix note title color for legacy themes (#7997) 2025-12-25 11:40:00 +02:00
Elian Doran
6b4d069211 fix(attachment): deletion time displayed incorrectly (closes #7987) 2025-12-25 11:34:49 +02:00
Adorian Doran
cecf7e6afb style/selected tree item color: use the color adjusted for readability 2025-12-25 11:34:41 +02:00
Adorian Doran
920e53957c Merge branch 'main' of https://github.com/TriliumNext/Trilium into bugfix/title-color-in-note-tree 2025-12-25 11:32:08 +02:00
Elian Doran
27c3d4da3c style(attachment): improve paddings & margins, remove scroll for image 2025-12-25 11:28:51 +02:00
Elian Doran
00a1a63d7e chore(attachment): use admonition instead of alert 2025-12-25 11:25:48 +02:00
Elian Doran
b0e7b6ce67 chore: address requested changes 2025-12-25 11:22:18 +02:00
Elian Doran
e06c004e0d Merge remote-tracking branch 'origin/main' into feature/fixes_for_main
; Conflicts:
;	apps/client/src/stylesheets/theme-next/base.css
2025-12-25 11:01:49 +02:00
Adorian Doran
a47ea0d653 style/quick editor: fix title margin 2025-12-25 10:47:05 +02:00
Adorian Doran
86c04cae96 style/menus: fix broken margin 2025-12-25 10:31:00 +02:00
Elian Doran
9eedbb8cd5 chore(deps): update dependency webdriverio to v9.22.0 (#8155) 2025-12-25 09:50:07 +02:00
Elian Doran
85404b02fc fix(deps): update dependency @codemirror/view to v6.39.7 (#8154) 2025-12-25 09:49:37 +02:00
Elian Doran
ae08c47929 chore(deps): update dependency @redocly/cli to v2.14.1 (#8153) 2025-12-25 09:49:12 +02:00
Adorian Doran
c97a6d82c3 style/menus: rollback a change 2025-12-25 05:13:17 +02:00
Adorian Doran
656b261946 style/note attachments: fix the context menu getting clipped 2025-12-25 05:10:20 +02:00
Adorian Doran
13fb57b46d Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-25 05:05:13 +02:00
Adorian Doran
fe38689a26 style/note attachments: make the list scrollable again 2025-12-25 05:05:03 +02:00
Adorian Doran
62263e3eea style/menus: fix menu backdrop effects 2025-12-25 04:44:51 +02:00
Adorian Doran
22d258b6bc style/menus: fix transparent submenus 2025-12-25 04:21:36 +02:00
Adorian Doran
51242f9bcb style/menus: ignore the disabled destructive menu items from being highlighted with red 2025-12-25 04:10:16 +02:00
Adorian Doran
ab0a0d3807 style/menus: bring back the red trash bin icon 2025-12-25 04:03:27 +02:00
Adorian Doran
cc37da9f11 style/menus: improve the icon-caption alignment 2025-12-25 03:46:32 +02:00
renovate[bot]
404618ed79 chore(deps): update dependency webdriverio to v9.22.0 2025-12-25 00:44:26 +00:00
renovate[bot]
3deda84b38 fix(deps): update dependency @codemirror/view to v6.39.7 2025-12-25 00:43:46 +00:00
renovate[bot]
ccf8e07316 chore(deps): update dependency @redocly/cli to v2.14.1 2025-12-25 00:43:09 +00:00
Adorian Doran
9c73b71feb style: add some animations when opening the sidebar and the bottom panel 2025-12-25 02:40:42 +02:00
Adorian Doran
bbec2f6082 style/bottom panel: improve appearance 2025-12-25 02:26:17 +02:00
Adorian Doran
924bd4512b style/options: tweak the padding of the page 2025-12-25 02:00:18 +02:00
Adorian Doran
ecb8bc0158 style/note header: fix a background issue on code notes 2025-12-25 01:50:28 +02:00
Adorian Doran
67b01ec1d8 style/bottom bar: tweak light color scheme colors 2025-12-25 01:31:47 +02:00
Adorian Doran
7ca7dd8867 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-25 01:22:43 +02:00
Adorian Doran
ac086bc2a4 style/UI switcher illustration: improve 2025-12-25 01:22:35 +02:00
Elian Doran
a583369658 fix(zen): formatting toolbar disappearing due to specificity 2025-12-24 23:56:31 +02:00
Elian Doran
4bc2e9743c Translations update from Hosted Weblate (#8149) 2025-12-24 23:40:48 +02:00
Elian Doran
ba2ba4fd80 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-24 23:40:24 +02:00
Elian Doran
52aaa72935 fix(launch_bar): bookmarks not refreshing 2025-12-24 23:16:09 +02:00
Kuzma Simonov
4123c24a9f Translated using Weblate (Russian)
Currently translated at 100.0% (1726 of 1726 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-24 21:15:43 +00:00
noobhjy
4bba910501 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1726 of 1726 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-24 21:15:42 +00:00
green
3b31916b26 Translated using Weblate (Japanese)
Currently translated at 100.0% (1726 of 1726 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-24 21:15:41 +00:00
Francis C.
4234ee97fb Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1724 of 1724 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-24 21:15:41 +00:00
Marcelo Nolasco
a5c8287446 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1724 of 1724 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-12-24 21:15:40 +00:00
Luk On
77a90e524a Translated using Weblate (Polish)
Currently translated at 100.0% (1724 of 1724 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-24 21:15:39 +00:00
Francis C.
814f81adfc Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1724 of 1724 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-24 21:15:39 +00:00
Adorian Doran
45c8b24b9c UI Tweaks (#8152) 2025-12-24 23:15:17 +02:00
Adorian Doran
2a7023ea16 style/tab bar: fix tab button rounded corners on horizontal layout 2025-12-24 23:06:06 +02:00
Elian Doran
4a2ff25052 chore(client): provide workaround for bypassing widget-missing-parent 2025-12-24 22:55:54 +02:00
Elian Doran
93582c1489 test(client): fix broken test after change to reference links 2025-12-24 22:41:29 +02:00
Adorian Doran
37d647261a style/watched file change alert bar: tweak 2025-12-24 22:39:10 +02:00
Adorian Doran
8af549aba4 style/bottom panel: do not use Mica on horizontal layout 2025-12-24 22:21:42 +02:00
Elian Doran
662423221e docs(user): mention new printing limitations 2025-12-24 22:21:14 +02:00
Adorian Doran
d6cd252f23 style/note title widget: fix the input selected text color when the current note is tinted 2025-12-24 22:13:52 +02:00
Adorian Doran
5af87788c6 style/quick edit/promoted attributes: fix card ghost margin causing unnecessary scroll 2025-12-24 21:59:55 +02:00
Adorian Doran
c329ab7eee style/zen mode/formatting toolbar: fix the background 2025-12-24 21:45:51 +02:00
Adorian Doran
2340c307cf style/label & relation definition dialog: fix the deformed close button 2025-12-24 20:06:50 +02:00
Adorian Doran
219454c7d3 style/links: fix the color for links referencing colored notes 2025-12-24 19:41:05 +02:00
Adorian Doran
3c14750e90 style/links: improve the selection outline 2025-12-24 19:36:26 +02:00
Elian Doran
b49ca3efe3 fix(print): disable for protected notes 2025-12-24 19:27:29 +02:00
Elian Doran
d21127e3a7 chore(client): fix typecheck 2025-12-24 19:25:13 +02:00
Elian Doran
9adf24da01 chore(client): address requested changes 2025-12-24 19:23:17 +02:00
Elian Doran
571cdfdeea feat(print): report for electron as well 2025-12-24 19:16:31 +02:00
Elian Doran
c2214493dc feat(print): add links to print report 2025-12-24 18:59:50 +02:00
Elian Doran
293ef60350 feat(print): display list of ignored notes 2025-12-24 18:50:50 +02:00
Elian Doran
60866c959f feat(print): report ignored notes 2025-12-24 18:42:13 +02:00
Elian Doran
84c40eb233 fix(print): skip files from being printed 2025-12-24 17:56:15 +02:00
Elian Doran
2afc8d181d fix(print): don't skip child notes if parent note has to be skipped 2025-12-24 17:55:30 +02:00
Elian Doran
66cdee82a4 fix(print): skip printing protected notes if session not available 2025-12-24 17:54:27 +02:00
Elian Doran
502c896616 fix(breadcrumbs): bottom gap caused by scrollbar in context menu 2025-12-24 17:45:45 +02:00
Elian Doran
b5af513371 fix(breadcrumbs): not reacting to protected session being started 2025-12-24 17:41:44 +02:00
Elian Doran
30cc221eca fix(breadcrumbs): branch prefix not shown 2025-12-24 17:37:31 +02:00
Elian Doran
db3aedf39d fix(note_detail): spaced update sometimes overwrites when note type is changed 2025-12-24 16:36:34 +02:00
Elian Doran
fd760951cc fix(text): recreating editor rapidly causes error 2025-12-24 16:23:17 +02:00
Elian Doran
b84cdd648f fix(layout): broken layout if new-layout is enabled as experimental feature 2025-12-24 16:05:20 +02:00
Elian Doran
b94b30e864 fix(options): new layout shown in experimental options 2025-12-24 15:51:26 +02:00
Elian Doran
0027bca415 fix(collections/grid): not displaying some images properly (closes #7969) 2025-12-24 15:02:17 +02:00
Elian Doran
4ac3634b04 fix(collections/list): archived notes always shown in sub-children (closes #8127) 2025-12-24 13:28:26 +02:00
Elian Doran
3207f37ac3 chore(client): format ListOrGridView 2025-12-24 13:20:00 +02:00
Elian Doran
28d3e61199 fix(text): search crashes editor (closes #8114) 2025-12-24 13:16:35 +02:00
Elian Doran
e476a2d306 fix(status_bar): code popup not displaying tooltips 2025-12-24 12:59:13 +02:00
Elian Doran
1d6766d9f3 fix(call_to_action): new layout message displayed for new installations as well 2025-12-24 12:49:45 +02:00
Elian Doran
b429861e8f fix(note_list): reference links displayed incorrectly 2025-12-24 12:45:11 +02:00
Elian Doran
81c55aab72 fix(launch_bar): escaped HTML in tooltip 2025-12-24 12:28:31 +02:00
Elian Doran
f67e06c8b2 fix(geomap): vector maps not rendering labels
Obtained from https://www.npmjs.com/package/@versatiles/style
2025-12-24 12:25:21 +02:00
Elian Doran
b3d92f932f fix(breadcrumbs): menu dismisses on click 2025-12-24 12:19:00 +02:00
Elian Doran
478c0e93f0 fix(breadcrumbs): last arrow not displayed on overflow menu 2025-12-24 12:14:54 +02:00
Elian Doran
bd24cf68b6 fix(note_type_switcher): don't read blob 2025-12-24 11:40:01 +02:00
Elian Doran
faea35b363 Revert "chore(right_pane): revert note data store"
This reverts commit 02294206ec.
2025-12-24 11:35:23 +02:00
Elian Doran
6b66d2089f fix(inline_title): reading metadata on every keystroke 2025-12-24 11:33:44 +02:00
Elian Doran
df05101e93 fix(inline_title): prevent flicker when updating tooltip 2025-12-24 10:52:36 +02:00
Elian Doran
7a1ea8833f fix(inline_title): tooltip getting stuck if refresh 2025-12-24 10:49:36 +02:00
Elian Doran
3600192933 fix(status_bar): note info requesting update on each keystroke 2025-12-24 10:38:57 +02:00
Elian Doran
d6d75a0e48 Minor tweaks (#8145) 2025-12-24 09:42:29 +02:00
Elian Doran
102e10efe3 fix(deps): update dependency @codemirror/view to v6.39.6 (#8147) 2025-12-24 09:41:28 +02:00
Elian Doran
a516185a2e fix(deps): update dependency preact to v10.28.1 (#8148) 2025-12-24 09:37:35 +02:00
Elian Doran
ae81b20334 chore(deps): update pnpm to v10.26.2 (#8146) 2025-12-24 09:29:18 +02:00
renovate[bot]
8fffbdc748 fix(deps): update dependency preact to v10.28.1 2025-12-24 00:25:29 +00:00
renovate[bot]
14d7d1da03 fix(deps): update dependency @codemirror/view to v6.39.6 2025-12-24 00:24:44 +00:00
renovate[bot]
9cb565e821 chore(deps): update pnpm to v10.26.2 2025-12-24 00:24:06 +00:00
Elian Doran
e3595a43c2 docs(user): missing language tags for JSX code blocks 2025-12-24 00:42:20 +02:00
Elian Doran
963fcd615a docs(user): missing language tags for code blocks 2025-12-24 00:30:16 +02:00
Elian Doran
fc8605a14f docs(user): broken code blocks due to table 2025-12-24 00:26:29 +02:00
Elian Doran
04fffb7ee0 Merge remote-tracking branch 'origin/main' into feature/minor_tweaks 2025-12-24 00:20:48 +02:00
Elian Doran
86307b482f docs(user): change URL for demo notes 2025-12-24 00:01:13 +02:00
Elian Doran
3e50262665 fix(status_bar): attribute pane not shown when adding new attribute def 2025-12-23 23:40:16 +02:00
Elian Doran
4e5c97d548 fix(toast): unreadable buttons on light theme 2025-12-23 23:06:29 +02:00
Elian Doran
1185d4b10b chore(layout): reduce padding for promoted attributes 2025-12-23 23:02:26 +02:00
Elian Doran
19cd7a0cad feat(script): improve script error message 2025-12-23 23:02:15 +02:00
Elian Doran
8fda283977 fix(title_actions): dark background in code affecting readability 2025-12-23 22:14:07 +02:00
Elian Doran
6e3a020d0f chore(badges): increase threshold for hiding text 2025-12-23 22:02:06 +02:00
Elian Doran
2fef25e57b chore(badges): allow overflow with clipping 2025-12-23 22:01:49 +02:00
Elian Doran
89ef38ba97 docs(user): mention history navigation buttons in the tab bar 2025-12-23 21:16:24 +02:00
Elian Doran
e96ee87472 chore: prevent error in .envrc for non nix systems (#8144) 2025-12-23 21:10:56 +02:00
Elian Doran
ae83126903 chore(tab_navigation): enable on server as well 2025-12-23 21:09:03 +02:00
Elian Doran
a6c7610fcc fix(dropdown): clicking in the outer area of a menu dismisses it 2025-12-23 21:06:47 +02:00
contributor
d8ce0e5f16 chore: use direnv built-in has command
https://direnv.net/man/direnv-stdlib.1.html#stdlib
2025-12-23 20:52:07 +02:00
Elian Doran
1eebc8ff77 fix(note_badges): avoid "shared locally" on server build 2025-12-23 20:44:12 +02:00
Elian Doran
00592025c0 fix(breadcrumb): overflow hides more items than threshold 2025-12-23 20:40:56 +02:00
Elian Doran
1ac7db41d3 fix(note_title_actions): edited notes link looking strange 2025-12-23 20:33:46 +02:00
contributor
ce84e7a861 chore: prevent error in .envrc for non nix systems 2025-12-23 20:25:15 +02:00
Elian Doran
cf039916d3 chore(note_title_actions): rephrase edited notes 2025-12-23 20:08:21 +02:00
Elian Doran
bfb3ed3ddf chore(layout): relocate note type switcher right above content 2025-12-23 20:03:27 +02:00
Elian Doran
a4f34ce6c5 refactor(client): remove items array 2025-12-23 19:55:50 +02:00
Elian Doran
2ac3d3aaed style(layout): adjust paddings slightly 2025-12-23 19:49:21 +02:00
Elian Doran
494b99d073 chore(layout): integrate edited notes into note title actions 2025-12-23 19:34:19 +02:00
Elian Doran
8434549a9b feat(breadcrumbs): display separator even if no child notes 2025-12-23 19:15:48 +02:00
Elian Doran
c1e01467a5 fix(breadcrumbs): not showing on first render 2025-12-23 19:12:18 +02:00
Elian Doran
4bd8eeb52a Translations update from Hosted Weblate (#8143) 2025-12-23 15:41:11 +02:00
Marcelo Nolasco
f4a6edbc9f Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pt_BR/
2025-12-23 13:38:17 +00:00
noobhjy
0d0a1866e4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1720 of 1720 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-23 13:38:16 +00:00
green
cd47e79a1b Translated using Weblate (Japanese)
Currently translated at 100.0% (1720 of 1720 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-23 13:38:16 +00:00
Kuzma Simonov
d0a83f7c05 Translated using Weblate (Russian)
Currently translated at 100.0% (1720 of 1720 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-23 13:38:15 +00:00
Marcelo Nolasco
26160b44ea Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (1720 of 1720 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-12-23 13:38:14 +00:00
Giovi
9df7b04d7d Translated using Weblate (Italian)
Currently translated at 100.0% (1720 of 1720 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-23 13:38:13 +00:00
Elian Doran
b8d933d308 Icons for code notes by mime type (#8142) 2025-12-23 15:37:51 +02:00
Elian Doran
9021b119b2 fix(client): some tooltips don't render correctly due to extra whitespace 2025-12-23 15:34:53 +02:00
Elian Doran
35034fe9df chore: address requested changes 2025-12-23 15:30:57 +02:00
Elian Doran
2eef655ec2 feat(client): display mapped icon as default for notes 2025-12-23 15:15:22 +02:00
Elian Doran
57ff2f4023 feat(status_bar): display icon for code note switcher 2025-12-23 15:00:31 +02:00
Elian Doran
df6331e3a0 chore(commons): add icon mappings to some common mime types 2025-12-23 15:00:19 +02:00
Elian Doran
b84da65a81 fix(code): not reacting to mime type changes 2025-12-23 14:38:17 +02:00
Elian Doran
58e04a6f72 Support for scripting with Preact and JSX (#8126) 2025-12-23 13:50:35 +02:00
Elian Doran
450bdeb39e fix(deps): update dependency @codemirror/view to v6.39.5 (#8137) 2025-12-23 13:39:58 +02:00
Elian Doran
79494e8cfe chore(deps): update dependency @ckeditor/ckeditor5-dev-build-tools to v54.2.3 (#8135) 2025-12-23 13:39:40 +02:00
Elian Doran
2afba34055 chore(deps): update typescript-eslint monorepo to v8.50.1 (#8136) 2025-12-23 13:39:26 +02:00
Elian Doran
c391234eeb fix(deps): update fullcalendar monorepo to v6.1.20 (#8138) 2025-12-23 13:39:13 +02:00
Elian Doran
a3fca323c7 test(server): fix test depending on note content 2025-12-23 13:38:38 +02:00
Elian Doran
9332b9ca8f docs(demo): add JSX widget showcase 2025-12-23 13:34:26 +02:00
Elian Doran
8740bf84cf chore(mime_types): set JSX as enabled by default 2025-12-23 13:12:29 +02:00
Elian Doran
1554085d7a chore(scripts/preact): address review 2025-12-23 13:06:33 +02:00
renovate[bot]
7dd4c09057 fix(deps): update fullcalendar monorepo to v6.1.20 2025-12-23 11:05:39 +00:00
renovate[bot]
eafd5140ea fix(deps): update dependency @codemirror/view to v6.39.5 2025-12-23 11:04:52 +00:00
renovate[bot]
cddde353cd chore(deps): update typescript-eslint monorepo to v8.50.1 2025-12-23 11:04:01 +00:00
renovate[bot]
e4ef8f2352 chore(deps): update dependency @ckeditor/ckeditor5-dev-build-tools to v54.2.3 2025-12-23 11:02:27 +00:00
Elian Doran
2561c7ca0d Merge remote-tracking branch 'origin/main' into feature/preact_scripts 2025-12-23 13:00:55 +02:00
Elian Doran
b4e4950d20 chore(client): fix typecheck 2025-12-23 12:59:22 +02:00
Adorian Doran
a4be86dbd8 style/text: prevent reference links inherit color from the current note 2025-12-23 05:26:54 +02:00
Adorian Doran
b6ca6476de demo notes: change the icon and color for the "Trilium Demo" branch 2025-12-23 05:00:23 +02:00
Adorian Doran
db1f632859 style/zen mode: make the read-only note badge visible 2025-12-23 04:24:39 +02:00
Adorian Doran
7af8acec0f style/zen mode: fix the title widget layout, make the icon and title editable 2025-12-23 04:20:17 +02:00
Adorian Doran
3f1b0fa71e style/breadcrumb: tweak 2025-12-23 04:02:53 +02:00
Adorian Doran
519323292c style/breadcrumb: tweak 2025-12-23 03:48:09 +02:00
Adorian Doran
2d6f17aeaa style/breadcrumb: tweak dropdown lists 2025-12-23 03:07:30 +02:00
Adorian Doran
7507d6b385 style/bottom panel: tweak colors 2025-12-23 02:52:03 +02:00
Adorian Doran
d4fa21e7c1 style/bottom panel: tweak colors 2025-12-22 23:57:40 +02:00
Adorian Doran
608f156b82 client: rename "status bar pane" to "bottom panel" 2025-12-22 23:40:11 +02:00
Adorian Doran
0c965bfdf4 client/status bar panes: extract colors as CSS variables 2025-12-22 23:36:35 +02:00
Adorian Doran
d407c72fae Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-22 23:27:55 +02:00
Adorian Doran
bdc0b062d5 client/status bar panes: improve 2025-12-22 23:27:45 +02:00
Elian Doran
0b912b9c7d Translations update from Hosted Weblate (#8134) 2025-12-22 22:35:26 +02:00
Anton Antonov
99ac6b4df1 Translated using Weblate (Bulgarian)
Currently translated at 16.4% (25 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/bg/
2025-12-22 20:23:36 +00:00
Hosted Weblate
b0a97208a2 Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/
2025-12-22 20:23:36 +00:00
Anton Antonov
6e044b19c8 Translated using Weblate (Bulgarian)
Currently translated at 12.5% (19 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/bg/
2025-12-22 20:23:35 +00:00
Anton Antonov
198dd15fb4 Added translation using Weblate (Bulgarian) 2025-12-22 20:23:34 +00:00
Anton Antonov
18f3b83827 Added translation using Weblate (Bulgarian) 2025-12-22 20:23:33 +00:00
Anton Antonov
8142b7489a Added translation using Weblate (Bulgarian) 2025-12-22 20:23:33 +00:00
Anton Antonov
7bf0a4134e Added translation using Weblate (Bulgarian) 2025-12-22 20:23:32 +00:00
Kuzma Simonov
29ed08d062 Translated using Weblate (Russian)
Currently translated at 100.0% (1718 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-22 20:23:31 +00:00
Francis C.
68dc7eedec Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.5% (1711 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-22 20:23:31 +00:00
Yunho Park
3fc195998c Translated using Weblate (Korean)
Currently translated at 67.7% (103 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-12-22 20:23:30 +00:00
Kuzma Simonov
b6d550f682 Translated using Weblate (Russian)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-12-22 20:23:29 +00:00
Adorian Doran
1f55ff536e client/status bar panes: tweak 2025-12-22 22:23:16 +02:00
Adorian Doran
67fb8d0354 client/status bar panes: tweak 2025-12-22 21:25:39 +02:00
Adorian Doran
1408b159d7 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-22 19:40:01 +02:00
Adorian Doran
74b00e60e3 client/status bar panes: refactor into own component, add title bar and close button 2025-12-22 19:39:52 +02:00
Elian Doran
1b18a964b9 chore(deps): update dependency @types/tabulator-tables to v6.3.1 (#8131) 2025-12-22 19:35:09 +02:00
renovate[bot]
931f0a694e chore(deps): update dependency @types/tabulator-tables to v6.3.1 2025-12-22 01:50:47 +00:00
Adorian Doran
0d32e1f0d8 style/classic toolbar: fix broken border radius 2025-12-22 02:43:39 +02:00
Adorian Doran
d0f91e7709 style/status bar: hide the focus outline for dropdown buttons 2025-12-22 02:37:00 +02:00
Adorian Doran
353d626d45 style/breadcrumb: tweak arrows 2025-12-22 02:29:05 +02:00
Adorian Doran
af67a3ba11 style/breadcrumb: use scrollable dropdowns for note listings 2025-12-22 02:24:34 +02:00
Adorian Doran
a867c646e4 style: refactor 2025-12-22 02:23:43 +02:00
Adorian Doran
150e2504b1 style: add (limited) support for scrollable menus 2025-12-22 02:20:56 +02:00
Adorian Doran
aa7ae150dc style/text editor/links: tweak 2025-12-22 02:04:35 +02:00
Adorian Doran
d99e08bfdd style/text editor: fix links 2025-12-22 01:39:33 +02:00
Elian Doran
29d038c76b Translations update from Hosted Weblate (#8130) 2025-12-22 00:25:39 +02:00
Barszczun
f1615bb4f6 Translated using Weblate (Polish)
Currently translated at 99.6% (1712 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-21 23:11:12 +01:00
Elian Doran
0688ea7de3 chore(client): address requested changes 2025-12-21 22:59:21 +02:00
Elian Doran
af37c175a3 chore(client): fix typecheck 2025-12-21 22:55:20 +02:00
Elian Doran
7567903da3 docs(user): improve documentation on custom widgets & Preact 2025-12-21 22:51:23 +02:00
Elian Doran
531698cafb fix(server/script): ignoring sub-component JSX 2025-12-21 20:01:59 +02:00
perfectra1n
f45920e506 fix(comparison): check all tokens, and do not short-circuit 2025-12-21 09:26:20 -08:00
perfectra1n
6fdd418edd fix(comparison): also fix string comparison hashes in recovery codes 2025-12-21 09:22:53 -08:00
perfectra1n
409ecb84a8 feat(login): implement better time comparison management across several features 2025-12-21 08:58:38 -08:00
Elian Doran
f68f99806b Merge remote-tracking branch 'origin/main' into feature/preact_scripts 2025-12-21 18:25:24 +02:00
Elian Doran
ea1efb785b Translations update from Hosted Weblate (#8128) 2025-12-21 17:13:12 +02:00
noobhjy
308943f754 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1718 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-21 15:00:25 +00:00
green
d43409f6e4 Translated using Weblate (Japanese)
Currently translated at 100.0% (1718 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-21 15:00:23 +00:00
noobhjy
4f51aa7a43 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 96.2% (1654 of 1718 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-21 15:00:22 +00:00
Elian Doran
c4f55395a9 feat(client/jsx): disable debug info 2025-12-21 13:31:44 +02:00
Elian Doran
444c0c6107 chore(client/jsx): fix errors in API 2025-12-21 13:19:42 +02:00
Elian Doran
4da5cb43fc fet(client/jsx): expose basic React widgets 2025-12-21 13:16:05 +02:00
Elian Doran
e6b79e83c4 fet(client/jsx): basic support for JSX render notes 2025-12-21 11:18:42 +02:00
Elian Doran
6e67da7b1f chore(deps): revert sucrase from client 2025-12-21 10:32:54 +02:00
Elian Doran
9071e54bfe chore(client/jsx): use different method for launcher widget defs 2025-12-21 10:26:20 +02:00
Elian Doran
783b5ac8e3 feat(client/jsx): support launcher widgets 2025-12-21 10:23:34 +02:00
Elian Doran
f3f491d141 feat(client/bundle): respect position for TSX widgets 2025-12-21 10:02:13 +02:00
Adorian Doran
a9f58262fc style/links: tweak 2025-12-21 00:29:25 +02:00
Adorian Doran
3ef39784ed Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-21 00:21:26 +02:00
Adorian Doran
24d0d562a9 style/links: tweak 2025-12-21 00:21:17 +02:00
Elian Doran
86c5a4d10c chore(etapi): Add missing share format (#8125) 2025-12-20 23:58:24 +02:00
Elian Doran
f8bf301d12 feat(client/bundle): use new toast for script errors with known note ID 2025-12-20 23:34:36 +02:00
Adorian Doran
32f0d81c07 style/links: tweak colors 2025-12-20 23:33:27 +02:00
Elian Doran
2c25786fa2 feat(client/bundle): expose Trilium hooks 2025-12-20 23:26:10 +02:00
Elian Doran
1093acfe45 feat(client/bundle): make Preact custom widgets content-sized by default 2025-12-20 23:17:30 +02:00
Elian Doran
76f054bbd5 feat(client/bundle): support rendering in other places 2025-12-20 23:16:19 +02:00
Adorian Doran
1ed4192c93 style/note badges: tweak 2025-12-20 23:12:39 +02:00
Elian Doran
c558255450 feat(client/bundle): add button to open script note 2025-12-20 22:51:04 +02:00
Elian Doran
1e94125133 feat(client/bundle): display toast when parent is missing 2025-12-20 22:45:58 +02:00
Elian Doran
64a770175f refactor(client/bundle): use type for parent name 2025-12-20 22:40:03 +02:00
Elian Doran
e0416097e1 feat(script/jsx): support import syntax for api 2025-12-20 22:23:25 +02:00
Elian Doran
6c1b327f5f feat(script/jsx): support import syntax for preact 2025-12-20 22:14:45 +02:00
Wael Nasreddine
17a9550803 chore(etapi): Add missing share format 2025-12-20 12:01:12 -08:00
Elian Doran
284b66acd2 feat(script/jsx): support export default syntax 2025-12-20 21:59:03 +02:00
Elian Doran
dcd73ff9f9 test(script/jsx): JSX fragment 2025-12-20 21:37:41 +02:00
Elian Doran
645557b505 test(script/jsx): basic JSX processing 2025-12-20 21:35:52 +02:00
Elian Doran
22a83d9f82 refactor(script/jsx): "react-widget" -> "preact-widget" 2025-12-20 21:26:01 +02:00
Elian Doran
f64de3acca chore(script/jsx): move defineWidget into Preact API 2025-12-20 21:25:36 +02:00
Elian Doran
34d5793888 chore(script/jsx): expose RightPanelWidget 2025-12-20 21:19:53 +02:00
Adorian Doran
0de9b219a5 style/note badges: extract colors as CSS variables 2025-12-20 20:41:23 +02:00
Elian Doran
44ca9f457c feat(script/jsx): add support for React hooks 2025-12-20 20:29:03 +02:00
Adorian Doran
93eead04a9 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-20 20:27:12 +02:00
Adorian Doran
8ff1f7ec84 style/classic toolbar: tweak background color 2025-12-20 20:27:04 +02:00
Elian Doran
4d7e5bc8f6 chore(script/jsx): move Preact API in dedicated object 2025-12-20 20:10:19 +02:00
Elian Doran
644ff07a50 feat(script/jsx): get right panel widgets to actually render 2025-12-20 19:49:24 +02:00
Elian Doran
41220a9d1d fix(script/jsx): cannot find preact hydration function 2025-12-20 19:45:44 +02:00
Elian Doran
88945788d6 fix(script/jsx): critical crash if widget fails to render 2025-12-20 19:41:48 +02:00
Elian Doran
fe8f033409 chore(script/jsx): get widgets to be interpreted 2025-12-20 19:36:02 +02:00
Elian Doran
eee7c49f6e fix(script/jsx): module not defined 2025-12-20 19:28:26 +02:00
Elian Doran
d036bf0870 fix(client): full crash if server fails to obtain list of widgets 2025-12-20 19:18:50 +02:00
Elian Doran
fa8ff4bfbf chore(script/jsx): basic client-side logic to render bundles 2025-12-20 19:01:29 +02:00
Elian Doran
3619c0c3e4 feat(script/jsx): compile JSX on server side 2025-12-20 18:46:15 +02:00
Elian Doran
883e32f5c9 chore(script): install sucrase 2025-12-20 18:03:45 +02:00
Elian Doran
8722ed405e docs(user): add missing share aliases 2025-12-20 17:56:18 +02:00
Adorian Doran
201c3a6eba style: tint the text selection according to the note's custom color 2025-12-20 16:13:38 +02:00
Adorian Doran
5a46f6ad04 style/classic toolbar: tweak 2025-12-20 15:51:55 +02:00
Adorian Doran
4f20ffe933 Tweak the classic formatting toolbar (#8123) 2025-12-20 15:33:17 +02:00
Adorian Doran
061b0966bb rollback: style/tab bar: visually merge the tab bar with the center panel 2025-12-20 15:28:46 +02:00
Elian Doran
bd799823b8 docs(user): add troubleshooting on content-sized 2025-12-20 13:54:50 +02:00
Elian Doran
c581ee7252 docs(user): improve examples for right pane widgets 2025-12-20 13:29:38 +02:00
Elian Doran
666c434c74 docs(user): mention changes to sidebar 2025-12-20 13:17:01 +02:00
Elian Doran
78ac59581e New layout: Right panel (sidebar) (#8095) 2025-12-20 13:09:59 +02:00
Elian Doran
d7b370253d chore(right_pane): fix regression in highlights_list 2025-12-20 13:00:13 +02:00
Elian Doran
1e885625f6 chore(right_pane): address requested changes 2025-12-20 12:58:06 +02:00
Adorian Doran
8cf6a6b9ae style: make the center panel border radius apply over the classic formatting toolbar if required 2025-12-20 12:51:43 +02:00
Elian Doran
f1ca8881a1 chore(right_pane): fix typecheck 2025-12-20 12:32:20 +02:00
Elian Doran
ea76fd797c chore(right_pane): address requested changes 2025-12-20 12:29:43 +02:00
Elian Doran
b248805905 feat(right_pane): add count to highlights list 2025-12-20 12:25:43 +02:00
Adorian Doran
7af5c77bcb style/tab bar: tweak margin 2025-12-20 12:18:11 +02:00
Elian Doran
35afd60d00 feat(right_pane): respect position 2025-12-20 12:17:14 +02:00
Elian Doran
2b827991ef feat(right_pane): only grow table of contents & highlights 2025-12-20 11:52:40 +02:00
Elian Doran
bc8c852a4d chore(right_pane): align collapse icon with menu item 2025-12-20 11:48:47 +02:00
Elian Doran
cd49c36529 chore(right_pane): decrease context menu size slightly 2025-12-20 11:45:08 +02:00
Elian Doran
a0577dc202 chore(right_pane): use menu instead of button for highlights list 2025-12-20 11:42:21 +02:00
Elian Doran
dced799976 feat(right_pane): add context menu with go to source for custom widgets 2025-12-20 11:39:46 +02:00
Elian Doran
eeea96b98c chore(right_pane): missing key for custom widgets 2025-12-20 11:17:29 +02:00
Elian Doran
e82e92c22c fix(right_pane): custom widgets not aware of note context 2025-12-20 11:16:41 +02:00
Elian Doran
e1df65adce fix(right_pane): custom widgets not rendering after being expanded 2025-12-20 11:09:59 +02:00
Adorian Doran
b7b7610f4d style/classic toolbar: allow customizing the background color via a CSS variable 2025-12-20 11:05:14 +02:00
Adorian Doran
37ea1584c9 style/tab bar: visually merge the tab bar with the center panel 2025-12-20 10:42:13 +02:00
Elian Doran
aac4316fb8 feat(right_pane): render title bar 2025-12-20 10:33:28 +02:00
Elian Doran
fb96b3f80a Translations update from Hosted Weblate (#8120) 2025-12-20 09:04:25 +02:00
Maxime
243d8158cf Translated using Weblate (French)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-12-20 07:03:32 +00:00
Eugene
6861a61cac Translated using Weblate (Russian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2025-12-20 07:03:31 +00:00
Kuzma Simonov
d3299d8aa4 Translated using Weblate (Russian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2025-12-20 07:03:30 +00:00
Maxime
0be5581fe5 Translated using Weblate (French)
Currently translated at 99.7% (388 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/fr/
2025-12-20 07:03:30 +00:00
Kuzma Simonov
60572a28ff Translated using Weblate (Russian)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-12-20 07:03:29 +00:00
Maxime
422c391c82 Translated using Weblate (French)
Currently translated at 95.9% (1640 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-12-20 07:03:28 +00:00
Kuzma Simonov
457d30cd80 Translated using Weblate (Russian)
Currently translated at 100.0% (1709 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-20 07:03:27 +00:00
Hosted Weblate
9caa058b18 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-20 07:03:26 +00:00
Elian Doran
33bde688c1 chore(deps): update dependency @redocly/cli to v2.14.0 (#8118) 2025-12-20 09:03:18 +02:00
Elian Doran
e79da6b0f3 chore(deps): update pnpm to v10.26.1 (#8117) 2025-12-20 09:02:39 +02:00
Elian Doran
3e527b9f5c chore(deps): update dependency openai to v6.15.0 (#8119) 2025-12-20 09:01:46 +02:00
renovate[bot]
ba242a6169 chore(deps): update dependency openai to v6.15.0 2025-12-20 01:00:35 +00:00
renovate[bot]
489113f582 chore(deps): update dependency @redocly/cli to v2.14.0 2025-12-20 00:59:47 +00:00
renovate[bot]
0fa6335d0f chore(deps): update pnpm to v10.26.1 2025-12-20 00:58:53 +00:00
Elian Doran
8f1614f603 chore(right_pane_widget): basic support for custom widgets 2025-12-20 00:01:21 +02:00
Elian Doran
a5f322617d chore(script): remove node-detail-pane 2025-12-19 23:44:19 +02:00
Elian Doran
6da42fac20 feat(right_pane_widget): handle zero headings 2025-12-19 23:32:58 +02:00
Elian Doran
fad6414e1d feat(right_pane_widget): handle zero highlights 2025-12-19 23:29:52 +02:00
Elian Doran
c0cd9e36d9 feat(right_pane_widget): hide highlights if disabled in settings 2025-12-19 23:25:58 +02:00
Elian Doran
e94704ce64 chore(right_pane_widget): respect highlight settings 2025-12-19 23:18:28 +02:00
Elian Doran
7a5d24f968 feat(right_pane_widget): options modal for highlight list 2025-12-19 23:02:32 +02:00
Elian Doran
9d351ae479 chore(options/text_notes): adapt to new layout sidebar 2025-12-19 22:33:26 +02:00
Elian Doran
01d4fa8afd chore(right_pane_widget): add padding to no items 2025-12-19 22:26:17 +02:00
Elian Doran
7d386c249a fix(right_pane_widget): toggle button clipped on desktop 2025-12-19 22:23:46 +02:00
Elian Doran
45dd47d039 feat(layout): button to toggle right pane on vertical layout 2025-12-19 21:20:36 +02:00
Elian Doran
06ad0bfa90 feat(hooks): react faster to setting options 2025-12-19 21:12:49 +02:00
Elian Doran
3d9efb23ec chore(right_pane): make right pane collapsible 2025-12-19 21:11:46 +02:00
Elian Doran
9acef4d502 feat(layout): button to toggle right pane on horizontal layout 2025-12-19 21:05:21 +02:00
Elian Doran
d22583457f style(right_pane): left-align title 2025-12-19 20:51:27 +02:00
Elian Doran
290469d1df Translations update from Hosted Weblate (#8115) 2025-12-19 14:28:57 +02:00
Kuzma Simonov
de5b766d0c Translated using Weblate (Russian)
Currently translated at 17.7% (27 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2025-12-19 12:26:27 +01:00
Kuzma Simonov
cbeb5dfb58 Translated using Weblate (Russian)
Currently translated at 98.0% (1676 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-19 12:26:27 +01:00
Kuzma Simonov
be5448eba2 Translated using Weblate (Russian)
Currently translated at 65.5% (76 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ru/
2025-12-19 12:26:24 +01:00
Kuzma Simonov
200e5d04a4 Translated using Weblate (Russian)
Currently translated at 97.6% (380 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ru/
2025-12-19 12:26:24 +01:00
Elian Doran
c7bbf709a1 Translations update from Hosted Weblate (#8108) 2025-12-19 08:39:18 +02:00
Elian Doran
23c2a59eba chore(deps): update dependency fs-extra to v11.3.3 (#8103) 2025-12-19 08:38:40 +02:00
Hosted Weblate
bf74c40f73 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-19 07:38:21 +01:00
Elian Doran
2af1ceda0b fix(deps): update dependency preact-iso to v2.11.1 (#8105) 2025-12-19 08:38:15 +02:00
renovate[bot]
44ae60005c chore(deps): update dependency fs-extra to v11.3.3 2025-12-19 06:38:07 +00:00
Elian Doran
3d591922bb chore(deps): update dependency @redocly/cli to v2.13.0 (#8106) 2025-12-19 08:37:41 +02:00
Elian Doran
31b2aba44c fix(deps): update dependency @codemirror/commands to v6.10.1 (#8104) 2025-12-19 08:37:01 +02:00
Elian Doran
df1c6196bf chore(deps): update dependency esbuild to v0.27.2 (#8102) 2025-12-19 08:36:18 +02:00
Elian Doran
96f4567ba1 chore(deps): update dependency @smithy/middleware-retry to v4.4.17 (#8101) 2025-12-19 08:32:52 +02:00
Adorian Doran
3e783817b6 style/quick edit dialog: tweak title 2025-12-19 02:51:04 +02:00
Adorian Doran
f7f3f707f1 client/note title row: use distinct style when used as a note split title 2025-12-19 02:46:50 +02:00
Adorian Doran
5ce81f1a32 client/note title widget: add support for custom CSS class name 2025-12-19 02:30:46 +02:00
renovate[bot]
53df319aeb chore(deps): update dependency @redocly/cli to v2.13.0 2025-12-19 00:17:52 +00:00
renovate[bot]
c56a253e49 fix(deps): update dependency preact-iso to v2.11.1 2025-12-19 00:17:17 +00:00
renovate[bot]
551b2aa33a fix(deps): update dependency @codemirror/commands to v6.10.1 2025-12-19 00:16:42 +00:00
Adorian Doran
8e245ccad8 Note header: apply note custom colors over the note icons (#8100) 2025-12-19 02:15:30 +02:00
renovate[bot]
03cea8b702 chore(deps): update dependency esbuild to v0.27.2 2025-12-19 00:15:28 +00:00
renovate[bot]
c94b5bc6c9 chore(deps): update dependency @smithy/middleware-retry to v4.4.17 2025-12-19 00:14:36 +00:00
Adorian Doran
69dc1ba68f Merge branch 'main' into feat/note-header/custom-colors 2025-12-19 02:12:25 +02:00
Adorian Doran
32f7ae1edd client: refactor 2025-12-19 02:12:00 +02:00
Adorian Doran
0de05ed16e style/note icon: apply note custom colors over the icons of the quick edit dialog as well 2025-12-19 02:01:03 +02:00
Adorian Doran
58e24c98ed style/note icon: fix the parent note color being applied over note links and board items 2025-12-19 01:55:52 +02:00
Adorian Doran
46da118749 style/note icon: cleanup 2025-12-19 01:43:11 +02:00
Adorian Doran
3f7514c9c7 style/note icon: tweak dark mode colors 2025-12-19 01:39:36 +02:00
Adorian Doran
5123f7b678 style/note icon: fix broken hover color for monochrome icons 2025-12-19 01:38:34 +02:00
Adorian Doran
b8af961690 style/note icon: refactor variable names 2025-12-19 01:23:56 +02:00
Adorian Doran
5bcec9fcfd style/note icon: add hover effect for custom colors 2025-12-19 01:21:52 +02:00
Elian Doran
0a2d4131d7 feat(docs): improve link docs organization (#8057) 2025-12-19 00:26:09 +02:00
Elian Doran
9ef4ab9983 fix(search): add null check for canvas elements in fulltext search (#8090) 2025-12-19 00:22:43 +02:00
Elian Doran
2a237e9a49 Translations update from Hosted Weblate (#8081) 2025-12-19 00:20:30 +02:00
Elian Doran
29115f5e61 Translated using Weblate (Dutch)
Currently translated at 25.8% (30 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/nl/
2025-12-18 23:19:45 +01:00
noobhjy
3411ed79d8 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1709 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-18 23:14:32 +01:00
green
b9c6cae5b4 Translated using Weblate (Japanese)
Currently translated at 100.0% (1709 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-18 23:14:31 +01:00
Luk On
cc84d09230 Translated using Weblate (Polish)
Currently translated at 100.0% (1709 of 1709 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-18 23:14:30 +01:00
Luk On
a82b12a599 Translated using Weblate (Polish)
Currently translated at 100.0% (1703 of 1703 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-18 23:14:29 +01:00
noobhjy
65ebbc71f5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1703 of 1703 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-18 23:14:29 +01:00
green
77c1a00831 Translated using Weblate (Japanese)
Currently translated at 100.0% (1703 of 1703 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-18 23:14:28 +01:00
Hosted Weblate
8eb6bf402d Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-18 23:14:27 +01:00
Elian Doran
e45beb541e Fix translation text for database cleaning button (#8080) 2025-12-19 00:14:19 +02:00
Elian Doran
334c31e79d fix(right_pane): table of contents no longer visible 2025-12-18 17:00:11 +02:00
Elian Doran
a986c84ce7 chore(right_pane): remove redundant check for note type 2025-12-18 16:59:40 +02:00
Elian Doran
9b21e042ec feat(floating_buttons): handle case when empty 2025-12-18 16:58:15 +02:00
Elian Doran
c44bb6c203 chore(floating_buttons): revert changes due to new layout 2025-12-18 16:33:12 +02:00
Elian Doran
ddb6b3ea8a feat(right_pane): store expansion state 2025-12-18 16:29:35 +02:00
Elian Doran
a4024d17ba fix(highlights_list): empty results 2025-12-18 16:18:31 +02:00
Elian Doran
57081a1bfb feat(right_pane): make whole title clickable 2025-12-18 16:16:52 +02:00
Elian Doran
7af063e7cd feat(right_pane): simplify collapsing mechanism 2025-12-18 16:15:21 +02:00
Elian Doran
7b04ca8cc7 style(right_pane): improve header space slightly 2025-12-18 15:57:48 +02:00
Elian Doran
02294206ec chore(right_pane): revert note data store 2025-12-18 15:42:44 +02:00
Elian Doran
7f7ec5d858 chore(right_pane): make the gutter slightly bigger 2025-12-18 15:40:09 +02:00
Elian Doran
ea3222cf12 chore(right_pane): more advanced expand/collapse 2025-12-18 14:57:42 +02:00
Elian Doran
5dacfd3ac6 chore(right_pane): basic expand support 2025-12-18 14:52:22 +02:00
Elian Doran
682c61305c chore(right_pane): basic collapse support 2025-12-18 14:43:54 +02:00
Elian Doran
b5bfb02d96 chore(right_pane): experiment with resizable sections 2025-12-18 14:12:28 +02:00
Elian Doran
fc3692333a chore(right_pane): improve style slightly 2025-12-18 14:10:16 +02:00
Elian Doran
28d9d98964 fix(highlights_list): unable to scroll to text fragments 2025-12-18 13:45:45 +02:00
Elian Doran
751a874c51 chore(highlights_list): improve performance by matching fewer elements 2025-12-18 13:38:52 +02:00
Elian Doran
d18ac0c613 fix(highlights_list): displaying non-highlighted attributes 2025-12-18 13:33:08 +02:00
Elian Doran
cd9654cd5f chore(highlights_list): reintroduce support for read-only notes 2025-12-18 13:29:36 +02:00
Elian Doran
925049357a fix(highlights_list): missing key 2025-12-18 13:20:04 +02:00
Elian Doran
d920da9e6f chore(highlights_list): render highlights 2025-12-18 13:17:41 +02:00
Elian Doran
b42a4dcb36 chore(highlights_list): react to changes 2025-12-18 13:13:05 +02:00
Elian Doran
7085e62cfc chore(highlights_list): reintroduce navigation 2025-12-18 13:09:53 +02:00
Elian Doran
73f2f56932 chore(highlights_list): read highlights from CK 2025-12-18 12:52:22 +02:00
Elian Doran
dbf29ed23f chore(highlights_list): start from scratch 2025-12-18 12:38:45 +02:00
Elian Doran
b0e1751dc7 chore(toc): reintroduce navigation in readonly text notes 2025-12-18 12:09:05 +02:00
Elian Doran
bf5c56a61a chore(toc): reintroduce navigation in editable text notes 2025-12-18 12:04:42 +02:00
Elian Doran
96ccb1e67e fix(toc): sometimes not reacting to read-only note switching 2025-12-18 11:46:21 +02:00
Elian Doran
704dcd011e feat(toc): basic support for docs 2025-12-18 11:46:13 +02:00
Elian Doran
b93c80fe7b feat(toc): basic support for read-only text 2025-12-18 11:12:36 +02:00
Elian Doran
41751c205c refactor(toc): reorder according to purpose 2025-12-18 10:58:25 +02:00
Elian Doran
852398426e chore(toc): add unique keys to headings 2025-12-18 10:56:44 +02:00
Elian Doran
73f1b91d34 chore(toc): reintroduce basic collapse support 2025-12-18 10:49:33 +02:00
Xen0r
28da93fc65 Merge branch 'main' into main 2025-12-18 09:36:55 +01:00
Elian Doran
87a98201b4 chore(toc): reintroduce hierarchy 2025-12-18 10:30:39 +02:00
Elian Doran
60342c0f6f fix(toc): not working on note switch 2025-12-18 10:08:10 +02:00
Elian Doran
97a3e439d2 refactor(toc): decouple CKEditor TOC 2025-12-18 09:58:10 +02:00
Jason Wasem
ee6f988c35 refactor(search): simplify null check and use join for text concatenation
根据代码审查建议优化代码:
- 移除多余的 `elements &&` 检查,因为 Array.isArray() 本身可处理 null/undefined
- 使用 `join(" ")` 替代 `toString()` 以确保文本元素用空格分隔,更适合全文搜索
- 移除显式类型声明,让 TypeScript 自动推断

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 10:01:13 +08:00
Adorian Doran
7cfc67cf9f style/note icon: tweak colors 2025-12-18 03:14:21 +02:00
Adorian Doran
ea2dd0293f style/note icon: tweak colors 2025-12-18 02:05:49 +02:00
Adorian Doran
76c16f3a62 style/note icon: apply the note custom color on the icon 2025-12-18 00:53:09 +02:00
Elian Doran
094f77b1af chore(toc): react to changes 2025-12-18 00:38:40 +02:00
Elian Doran
b2bcbdde3f style(attachment): top padding not matching side padding 2025-12-18 00:25:16 +02:00
Elian Doran
eceb7179b8 style(attachment): code block cuts off card 2025-12-18 00:20:48 +02:00
Elian Doran
3a46a9fbc3 chore(toc): attempt to read using CKEditor API 2025-12-18 00:16:03 +02:00
Elian Doran
2e484a11e6 feat(layout/right_pane): basic store to read content without blob 2025-12-17 23:40:25 +02:00
Elian Doran
98ed442d27 chore(layout/right_pane): empty table of contents 2025-12-17 23:19:42 +02:00
Elian Doran
dac923e45d chore(layout/right_pane): bring back resizer 2025-12-17 23:17:25 +02:00
Elian Doran
f46de50f17 refactor(layout/right_pane): CSS for container 2025-12-17 23:03:57 +02:00
Elian Doran
616af1502f feat(layout/right_pane): create empty container 2025-12-17 23:01:44 +02:00
Adorian Doran
c9fae88a86 style/note: add custom note color CSS variables on the split containers 2025-12-17 22:48:47 +02:00
Elian Doran
9872a3d522 feat(call_to_action): add more info button for new layout 2025-12-17 22:46:25 +02:00
Elian Doran
851169e061 fix(edited_notes): no message if there are no edited notes on a day 2025-12-17 22:39:24 +02:00
Elian Doran
f3b274650e docs(user): mark new layout in feature highlights 2025-12-17 22:34:01 +02:00
Elian Doran
3293ed2ce0 docs(user): document the new layout 2025-12-17 22:34:01 +02:00
Elian Doran
231ec39025 New layout refinement (#8088) 2025-12-17 18:51:38 +02:00
Jason Wasem
ecb972c71c fix(search): add null check for canvas elements in fulltext search
添加对 Canvas 笔记 elements 字段的空值检查,防止当 elements 为 null 或非数组时搜索功能报错。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 00:42:12 +08:00
Elian Doran
c7f1e46b26 e2e(server): disable new layout and call-to-action for now 2025-12-17 18:05:39 +02:00
Elian Doran
b9c39d757b style(next): match attachment code border radius with context menu 2025-12-17 17:42:03 +02:00
Elian Doran
ea4a3b7f07 chore(client): address requested changes 2025-12-17 17:24:15 +02:00
Elian Doran
cbecc24999 feat(call_to_action): inform about the layout change 2025-12-17 16:05:55 +02:00
Elian Doran
261c1f77cf fix(layout): 2px margin in code notes 2025-12-17 15:47:11 +02:00
Elian Doran
87d99aaffa fix(layout): experimental styles not applied 2025-12-17 15:46:00 +02:00
Elian Doran
d0b0a13b6d chore(options/appearance): use translations 2025-12-17 15:44:01 +02:00
Elian Doran
1ed83b3598 Merge remote-tracking branch 'origin/main' into layout/refinement 2025-12-17 15:43:51 +02:00
Elian Doran
2759beb5d0 feat(options/appearance): improve new layout 2025-12-17 15:34:44 +02:00
Elian Doran
d623b2ffa0 feat(options/appearance): switch between layouts 2025-12-17 15:17:54 +02:00
Elian Doran
3ed613cf1d style(options/appearance): improve layout slightly 2025-12-17 12:40:36 +02:00
Elian Doran
948a6f84d6 feat(options/appearance): add basic illustration for old layout 2025-12-17 12:37:12 +02:00
Xen0r
334024b2d1 Merge branch 'main' into main 2025-12-17 10:28:53 +01:00
Elian Doran
6aa14d17d7 chore(deps): update dependency openai to v6.14.0 (#8086) 2025-12-17 11:26:29 +02:00
Elian Doran
e1da74d4d1 fix(deps): update dependency mind-elixir to v5.3.8 (#8085) 2025-12-17 11:26:15 +02:00
Elian Doran
a6012283da fix(deps): update dependency lodash-es to v4.17.22 (#8084) 2025-12-17 11:25:23 +02:00
Elian Doran
e450e0299f chore(deps): update vitest monorepo to v4.0.16 (#8083) 2025-12-17 11:25:03 +02:00
Xen0r
816f851709 Update translation.json 2025-12-17 10:22:13 +01:00
Xen0r
514ded5b8d Merge branch 'main' into main 2025-12-17 10:20:10 +01:00
Nate River
35a109616c Update apps/client/src/stylesheets/theme-light.css
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-17 11:25:41 +08:00
Nate River
641176011f Update apps/client/src/stylesheets/theme-dark.css
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-17 11:25:35 +08:00
renovate[bot]
304fd37ce2 chore(deps): update dependency openai to v6.14.0 2025-12-17 00:03:10 +00:00
renovate[bot]
51ef473964 fix(deps): update dependency mind-elixir to v5.3.8 2025-12-17 00:02:27 +00:00
Adorian Doran
96f148a870 Tweak note title and icon (#8082) 2025-12-17 02:01:58 +02:00
renovate[bot]
150bc07d28 fix(deps): update dependency lodash-es to v4.17.22 2025-12-17 00:01:46 +00:00
renovate[bot]
dcec780846 chore(deps): update vitest monorepo to v4.0.16 2025-12-17 00:01:03 +00:00
Adorian Doran
03602addc5 Merge branch 'main' into feat/tweak/note-title-and-icon-widgets 2025-12-17 01:59:07 +02:00
Adorian Doran
fc9f47a801 style/note title & icon: fix an issue pointed by gemini-code-assist 2025-12-17 01:58:20 +02:00
Adorian Doran
3b6a823556 style/note title & icon: tweak icon size 2025-12-17 01:48:35 +02:00
Adorian Doran
b8ceb10e68 style/note title & icon: update the colors for the dark color scheme 2025-12-17 01:39:14 +02:00
Adorian Doran
ddca68eafa style/note title & icon: add support for both dark and light color schemes 2025-12-17 01:33:23 +02:00
Adorian Doran
468d4a4369 style/inline title: fix (again) icon hover color 2025-12-17 01:15:35 +02:00
Adorian Doran
c31f35dbd7 style/inline title: handle empty icons when the icon selection is disabled 2025-12-17 01:11:23 +02:00
Elian Doran
b5129402be chore(deps): update dependency vite to v7.3.0 (#8071) 2025-12-17 01:05:15 +02:00
Elian Doran
f38dfb035a chore(deps): update typescript-eslint monorepo to v8.50.0 (#8073) 2025-12-17 01:04:19 +02:00
Elian Doran
c2bee1a968 chore(deps): update dependency @ckeditor/ckeditor5-dev-build-tools to v54 (#8074) 2025-12-17 01:03:46 +02:00
Adorian Doran
84f7ae9f05 style/inline title: fix icon hover color 2025-12-17 01:03:01 +02:00
Elian Doran
c4df640ea4 chore(deps): update pnpm to v10.26.0 (#8072) 2025-12-17 01:01:04 +02:00
Elian Doran
fe5e1eb066 chore(deps): update dependency openai to v6.13.0 (#8070) 2025-12-17 01:00:32 +02:00
Elian Doran
6abc5a777f fix(deps): update dependency i18next to v25.7.3 (#8069) 2025-12-17 01:00:14 +02:00
Adorian Doran
08730dd821 style/inline title: add an intro animation for the note type selector 2025-12-17 01:00:07 +02:00
Elian Doran
b08ea33eb0 chore(deps): update dependency @smithy/middleware-retry to v4.4.16 (#8068) 2025-12-17 00:59:52 +02:00
Elian Doran
f389fc3414 chore(deps): update dependency @redocly/cli to v2.12.7 (#8067) 2025-12-17 00:59:27 +02:00
Elian Doran
cb024d0455 Translations update from Hosted Weblate (#8066) 2025-12-17 00:59:02 +02:00
Adorian Doran
286d2e8e5b style/inline title: tweak the layout of the note type selector 2025-12-17 00:52:47 +02:00
Adorian Doran
5446d8a932 style/inline title: improve the note icon focus indicator 2025-12-17 00:33:33 +02:00
Adorian Doran
07dcdf3078 style/inline title: replace the hover effect of the note icon 2025-12-17 00:16:45 +02:00
Adorian Doran
143b1827e6 style/inline title: tweak appearance 2025-12-17 00:09:15 +02:00
Adorian Doran
6f494e3e38 style/inline title: use a better layout 2025-12-16 23:33:57 +02:00
Xen0r
e88623e9fa Fix translation text for database cleaning button 2025-12-16 22:00:21 +01:00
Adorian Doran
cad86d4b21 style/note title & icon: tweak appearance 2025-12-16 22:54:55 +02:00
Adorian Doran
5ffae303c4 style/forms/buttons: add a generic class for focusable buttons 2025-12-16 22:54:12 +02:00
Adorian Doran
35218aca71 style/note title & icon: add a circular background for the note icon 2025-12-16 22:34:42 +02:00
Adorian Doran
9542c9776a style/note title & icon: use CSS variables to adjust size, improve the layout on different sizes 2025-12-16 20:30:58 +02:00
Elian Doran
af02685f2f chore(options): fix misalignment in options row 2025-12-16 20:14:21 +02:00
Elian Doran
737e5b85b4 fix(badges): "temporarily editable" remaining after changing editability 2025-12-16 19:40:24 +02:00
Elian Doran
90a7217b32 feat(layout): preserve newlines in tooltips 2025-12-16 19:29:59 +02:00
Elian Doran
77b92385cb feat(layout): keyboard shortcut for promoted attributes 2025-12-16 19:21:50 +02:00
Elian Doran
22e0776049 fix(layout): toggleRibbonTabNoteMap not working in old layout 2025-12-16 19:12:42 +02:00
Elian Doran
db51198449 feat(layout): keyboard shortcut for similar notes 2025-12-16 19:01:03 +02:00
Elian Doran
998a16ab87 feat(layout): keyboard shortcut for note paths 2025-12-16 18:59:36 +02:00
Elian Doran
4f1c19f1e2 feat(layout): keyboard shortcut for note info 2025-12-16 18:57:25 +02:00
Elian Doran
1835676d09 feat(layout): keyboard shortcut for owned & inherited attributes 2025-12-16 18:54:15 +02:00
Elian Doran
2eaa4ef206 fix(note_info): fixed note types do not have icon 2025-12-16 18:43:04 +02:00
Elian Doran
a5fcee500e feat(layout): keyboard shortcut for image properties 2025-12-16 18:40:37 +02:00
Elian Doran
613764d423 feat(layout): keyboard shortcut for file properties 2025-12-16 18:39:31 +02:00
Elian Doran
0518e64576 feat(layout): keyboard shortcut for collection properties 2025-12-16 18:32:33 +02:00
Elian Doran
713900b2b3 feat(layout): focus exactly on basic properties 2025-12-16 18:29:46 +02:00
Elian Doran
c0eb34927f feat(layout): keyboard shortcut for basic properties 2025-12-16 18:23:14 +02:00
Elian Doran
ec3c9a9ae5 feat(layout): keyboard shortcut for formatting toolbar 2025-12-16 18:16:05 +02:00
noobhjy
70374b622e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1700 of 1700 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-16 17:02:40 +01:00
green
7fcc0ae290 Translated using Weblate (Japanese)
Currently translated at 99.8% (1697 of 1700 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-16 17:02:40 +01:00
Luk On
1de4db1a08 Translated using Weblate (Polish)
Currently translated at 100.0% (1700 of 1700 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-16 17:02:40 +01:00
Hosted Weblate
74ac58d3a6 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-16 17:02:40 +01:00
Luk On
993f56976e Translated using Weblate (Polish)
Currently translated at 99.9% (1698 of 1699 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-16 17:02:40 +01:00
Giovi
94859f2303 Translated using Weblate (Italian)
Currently translated at 100.0% (1699 of 1699 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-16 17:02:40 +01:00
Elian Doran
db116981b8 fix(note_info): MIME type entry shown even when empty 2025-12-16 17:53:05 +02:00
Elian Doran
2e563b0a1f feat(note_info): display user-friendly note type name & icon 2025-12-16 17:53:05 +02:00
Elian Doran
7222b233f0 feat(note_info): separate note type from mime type 2025-12-16 17:53:05 +02:00
Adorian Doran
bea15c46e5 style/new layout: fix the title actions container wasting vertical space when empty 2025-12-16 17:49:17 +02:00
Elian Doran
d96157de47 New layout: Power breadcrumbs (#8077) 2025-12-16 17:43:19 +02:00
Elian Doran
120b5c678d chore(client): fix typecheck 2025-12-16 17:27:29 +02:00
Elian Doran
8c008e2e3a chore(breadcrumb): address requested changes 2025-12-16 17:17:58 +02:00
Elian Doran
7e07280eb3 feat(breadcrumb): relocate copy note path to empty area 2025-12-16 16:14:08 +02:00
Elian Doran
d28c3f0851 feat(breadcrumb): hide archived notes if needed 2025-12-16 16:08:41 +02:00
Elian Doran
0390fd3174 fix(breadcrumb): hiding archived notes doesn't update tree 2025-12-16 16:03:09 +02:00
Elian Doran
193c9d8fa6 feat(breadcrumb): option to hide archived notes 2025-12-16 16:00:23 +02:00
Elian Doran
3a4cff6529 feat(breadcrumb): allow creating notes from separator menu 2025-12-16 15:35:14 +02:00
Elian Doran
5449d033bf feat(breadcrumb): indicate archived in separator menu 2025-12-16 15:05:33 +02:00
Elian Doran
66ed88c409 fix(breadcrumb): archived not respected by last item 2025-12-16 15:03:47 +02:00
Elian Doran
94df5c9126 feat(breadcrumb): respect note color class in context menu 2025-12-16 15:02:16 +02:00
Elian Doran
181ea31c1c chore(client): improve error handling message in events 2025-12-16 14:06:12 +02:00
Elian Doran
f235839d03 feat(breadcrumb): indicate archived notes 2025-12-16 13:50:53 +02:00
Elian Doran
d97b68fcd7 feat(breadcrumb): maintain note color on hover 2025-12-16 13:44:35 +02:00
Elian Doran
79d1a509e5 feat(breadcrumb): respect note color in last item 2025-12-16 13:42:41 +02:00
Elian Doran
0af5fa9f0c feat(breadcrumb): respect note color 2025-12-16 13:40:22 +02:00
Elian Doran
2693b18ee6 refactor(breadcrumb): use new component for rendering note links 2025-12-16 13:36:50 +02:00
Elian Doran
34343ce356 fix(server): autocomplete shows empty name for hoisted note 2025-12-16 12:53:51 +02:00
Elian Doran
c9025f2304 fix(breadcrumb): not reacting to changes in note path 2025-12-16 12:43:26 +02:00
Elian Doran
ec22fd9e99 refactor(breadcrumb): use existing function to parse note path 2025-12-16 10:56:00 +02:00
Elian Doran
15f9b2cadf feat(breadcrumb): add context menu on last item 2025-12-16 10:52:03 +02:00
Elian Doran
7c85fe1c37 feat(breadcrumb): add search in subtree 2025-12-16 10:46:56 +02:00
Elian Doran
d1820a6bc3 feat(breadcrumb): color selector 2025-12-16 10:43:56 +02:00
Elian Doran
d1575a28ad feat(breadcrumb): add duplicate/archive/delete options 2025-12-16 10:34:43 +02:00
Elian Doran
d13e19cf59 feat(breadcrumb): copy note path to clipboard & recent changes in subtree options 2025-12-16 10:26:46 +02:00
Elian Doran
0b7ffdf109 chore(breadcrumb): remove keyboard shortcuts 2025-12-16 10:20:15 +02:00
Elian Doran
e91cb1a198 feat(breadcrumb): add clone to/move to options 2025-12-16 10:16:09 +02:00
Elian Doran
51fcda646d feat(breadcrumb): add hoist option 2025-12-16 10:09:10 +02:00
Elian Doran
cb8e35c4dc feat(breadcrumb): get link menu items 2025-12-16 10:03:28 +02:00
Elian Doran
9d581347f1 Revert "feat(breadcrumb): get tree menu to show"
This reverts commit 96a6ea4c7a.
2025-12-16 09:56:21 +02:00
Elian Doran
96a6ea4c7a feat(breadcrumb): get tree menu to show 2025-12-16 09:35:19 +02:00
Elian Doran
587ea42700 chore(breadcrumb): get a menu to render on note link 2025-12-16 09:27:40 +02:00
renovate[bot]
8a5c7b3551 chore(deps): update dependency @ckeditor/ckeditor5-dev-build-tools to v54 2025-12-16 01:20:12 +00:00
renovate[bot]
f1fa44feb6 chore(deps): update typescript-eslint monorepo to v8.50.0 2025-12-16 01:19:39 +00:00
renovate[bot]
569cb6bf53 chore(deps): update pnpm to v10.26.0 2025-12-16 01:19:08 +00:00
renovate[bot]
3445b594e8 chore(deps): update dependency vite to v7.3.0 2025-12-16 01:18:58 +00:00
renovate[bot]
676595dd6b chore(deps): update dependency openai to v6.13.0 2025-12-16 01:18:25 +00:00
renovate[bot]
f8c84602f4 fix(deps): update dependency i18next to v25.7.3 2025-12-16 01:17:51 +00:00
renovate[bot]
d41842bc2a chore(deps): update dependency @smithy/middleware-retry to v4.4.16 2025-12-16 01:17:16 +00:00
renovate[bot]
ced47e64db chore(deps): update dependency @redocly/cli to v2.12.7 2025-12-16 01:16:41 +00:00
Elian Doran
16a6344687 fix(layout/badges): not reacting to changes in share 2025-12-16 00:10:42 +02:00
Elian Doran
7bac0b25ce feat(layout/badges): interactive share badge 2025-12-16 00:07:19 +02:00
Elian Doran
6094f738f2 New layout refinements (#8064) 2025-12-15 17:47:03 +02:00
Elian Doran
c3a6d1bba8 feat(badge): bigger dropdown arrow 2025-12-15 17:17:01 +02:00
Elian Doran
1feeb350ce chore(client): address requested changes 2025-12-15 17:14:00 +02:00
Elian Doran
f21ba207fe feat(inline_title): improve fit on small splits 2025-12-15 16:50:26 +02:00
Elian Doran
07c8ff4571 chore(note_type_switcher): shorten last modified date 2025-12-15 16:49:09 +02:00
Elian Doran
71d8588091 feat(note_type_switcher): use arrows next to dropdowns 2025-12-15 16:47:53 +02:00
Elian Doran
3c41b7e5a9 feat(note_type_switcher): use singular form 2025-12-15 16:45:56 +02:00
Elian Doran
41b7a295b9 feat(breadcrumb): add tooltip about jumping to top 2025-12-15 16:40:36 +02:00
Elian Doran
ca8e889e1e feat(breadcrumb): respect workspace color 2025-12-15 16:37:33 +02:00
Elian Doran
6d4e52c928 feat(breadcrumb): prefer workspace icon class 2025-12-15 16:31:43 +02:00
Elian Doran
e2fac8ab05 feat(breadcrumb): distinguish between workspace and hoisted notes 2025-12-15 16:26:25 +02:00
Elian Doran
af3883fdac feat(breadcrumb): react to hosted note ID change 2025-12-15 16:20:17 +02:00
Elian Doran
83777d7ea0 feat(breadcrumb): unhoist badge 2025-12-15 16:02:31 +02:00
Elian Doran
c6854c84b9 feat(breadcrumb): use different approach for displaying workspace icon 2025-12-15 15:52:55 +02:00
Elian Doran
eb99352fff Revert "feat(breadcrumb): display workspace text"
This reverts commit 441958028d.
2025-12-15 15:29:53 +02:00
Elian Doran
7dac5d424b Translations update from Hosted Weblate (#8061) 2025-12-15 15:24:27 +02:00
Elian Doran
441958028d feat(breadcrumb): display workspace text 2025-12-15 15:10:37 +02:00
Elian Doran
80b61a35a9 feat(breadcrumb): display correct icon for first note when hoisted 2025-12-15 15:10:37 +02:00
Elian Doran
61df0f3d31 feat(breadcrumb): trim path when hoisted 2025-12-15 15:10:37 +02:00
green
23ece9fc86 Translated using Weblate (Japanese)
Currently translated at 100.0% (1695 of 1695 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-15 13:15:48 +01:00
Kuzma Simonov
220e3d7195 Translated using Weblate (Russian)
Currently translated at 95.0% (1602 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-15 13:15:47 +01:00
Kuzma Simonov
392c0311e5 Translated using Weblate (Russian)
Currently translated at 17.1% (26 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ru/
2025-12-15 13:15:46 +01:00
Adorian Doran
3abdcfa7a5 style/status bar/breadcrumb: tweak the last segment 2025-12-15 14:15:36 +02:00
Elian Doran
4896042fc4 fix(layout): classic toolbar not appearing after making a note temporarily editable 2025-12-15 12:45:27 +02:00
Elian Doran
7edfd5d7b4 fix(layout): classic toolbar in zen mode 2025-12-15 12:41:34 +02:00
Elian Doran
ad8e52f744 feat(layout): disable transition when promoted attributes are shown by default 2025-12-15 12:14:44 +02:00
Elian Doran
455dc5dc11 feat(layout): automatically collapse promoted attributes in full-height notes 2025-12-15 12:10:12 +02:00
Elian Doran
158f5ac310 feat(layout): use collapsible for promoted attributes 2025-12-15 12:10:12 +02:00
Elian Doran
fb70029091 fix(icon-list): border-left icon regular missing 2025-12-15 12:10:12 +02:00
Elian Doran
b370512893 fix(status_bar): unable to dismiss panes 2025-12-15 12:10:12 +02:00
Elian Doran
764607314c feat(tree): change icon for note paths 2025-12-15 12:10:12 +02:00
Adorian Doran
dbcf9b01c5 style/status bar/note paths flyout: document 2025-12-15 12:06:32 +02:00
Adorian Doran
93ce77438f style/status bar/note paths flyout: tweak the current path arrow 2025-12-15 12:04:39 +02:00
Adorian Doran
14c30661e6 Restyle the backlinks flyout (#8063) 2025-12-15 12:01:48 +02:00
Adorian Doran
37efc44f43 Merge branch 'main' into feat/restyle/backlinks-panel 2025-12-15 11:54:03 +02:00
Adorian Doran
6aaade846a style/status bar/backlinks flyout: restyle 2025-12-15 11:52:04 +02:00
Elian Doran
bd2402396b New layout: Remove floating buttons (#8059) 2025-12-15 11:11:18 +02:00
Elian Doran
a9b3479216 fix(mermaid): preview not 100% height on vertical layout 2025-12-15 10:54:39 +02:00
Adorian Doran
05e98877b0 style/status bar/backlinks flyout: rename HTML tag 2025-12-15 10:52:14 +02:00
Elian Doran
862ddf3a71 fix(mermaid): 1px border visible in read-only mode 2025-12-15 10:51:54 +02:00
Elian Doran
c1df2c45de fix(context_menu): regression on mobile sub-menu 2025-12-15 10:47:28 +02:00
Elian Doran
065e97c940 chore(layout/note_actions): address requested changes 2025-12-15 10:41:58 +02:00
Elian Doran
adae7fa03b feat(layout/note_actions): integrate in-app help button 2025-12-15 10:24:24 +02:00
Elian Doran
b725dbea7e feat(layout/note_actions): export as image 2025-12-15 10:06:01 +02:00
Elian Doran
4b80eec000 feat(layout/note_actions): integrate geo map add button 2025-12-15 09:14:19 +02:00
Elian Doran
d7722a1e05 feat(layout/note_actions): integrate add child for relation map 2025-12-15 09:07:45 +02:00
Elian Doran
35cfcc59f6 feat(layout/note_actions): integrate zoom buttons into relation map 2025-12-15 09:04:31 +02:00
Elian Doran
192190d685 fix(layout/note_actions): save to note not disappearing after save 2025-12-15 08:46:27 +02:00
Elian Doran
d6cc4bfa9c fix(layout/note_actions): buttons not reacting to mime type changes 2025-12-15 08:34:40 +02:00
Elian Doran
ed284fbc5f feat(layout/note_actions): integrate open API docs 2025-12-15 08:33:15 +02:00
Elian Doran
cb0efe25f5 feat(layout/note_actions): integrate save to note button 2025-12-15 08:24:59 +02:00
Elian Doran
906fe4f8da feat(layout/note_actions): integrate execute script button 2025-12-15 08:19:40 +02:00
Elian Doran
04a641199b feat(layout/note_actions): prevent layout shift by disabling button 2025-12-15 08:17:01 +02:00
Elian Doran
50cbad22d0 feat(layout/note_actions): integrate toggle read-only button 2025-12-15 08:15:00 +02:00
Elian Doran
4cfe59271f feat(layout/note_actions): integrate switch split orientation 2025-12-15 08:12:39 +02:00
Elian Doran
ba7969dad4 style(backend-log): remove extra padding & decrease font size 2025-12-15 08:08:45 +02:00
Elian Doran
43b6440bf9 style: borderless and paddingless code editor 2025-12-15 08:05:18 +02:00
Elian Doran
3e19a163c2 feat(layout/note_actions): integrate refresh backend log 2025-12-15 08:00:03 +02:00
Elian Doran
ca39282269 fix(global_menu): alignment of advanced button 2025-12-15 07:53:34 +02:00
Elian Doran
016389df68 fix(context_menu): clicking on a submenu dismisses it 2025-12-15 07:51:53 +02:00
Elian Doran
17db2a6b38 Revert "fix(context_menu): clicking submenu dismisses the menu"
This reverts commit 34bc444b18.
2025-12-15 07:46:36 +02:00
Elian Doran
bc8f17ee5c New layout refinement (#8053) 2025-12-15 07:36:58 +02:00
Elian Doran
0c8944ab8e chore(layout): address requested changes 2025-12-15 07:27:55 +02:00
Elian Doran
0960b585bd fix(layout): note actions button duplicated in old layout 2025-12-15 07:25:49 +02:00
Chris Cavalluzzi
55649c3750 fix(docs): mismatching phrasing in reference link notes 2025-12-14 21:17:59 -07:00
Chris Cavalluzzi
51bbf71577 feat(docs): improve link docs organization 2025-12-14 19:30:21 -07:00
Adorian Doran
728fab1dda Tweak note info (#8056) 2025-12-15 02:24:41 +02:00
Adorian Doran
d5ec80d85d client/status bar/note info: fix an issue pointed by gemini-code-assist 2025-12-15 02:23:57 +02:00
Adorian Doran
15ef93d7e6 style/status bar/note info: tweak appearance 2025-12-15 02:07:14 +02:00
Adorian Doran
9711b22ea9 style/status bar/note info: replace the "calculate" button with a link 2025-12-15 01:55:43 +02:00
Adorian Doran
b9c7d2b01d Tweak note paths (#8055) 2025-12-15 01:48:03 +02:00
Adorian Doran
9834846a23 client/status bar/note paths: fix the issues pointed by gemini-code-assist 2025-12-15 01:43:36 +02:00
Adorian Doran
65f425df2c style/status bar/note paths: fix an issue pointed by gemini-code-assist 2025-12-15 01:37:36 +02:00
Adorian Doran
a551dfe4d6 style/status bar/note paths: fix the final path segment color when icons are displayed 2025-12-15 01:18:35 +02:00
Adorian Doran
e9bfacdb7c style/status bar/note paths: highlight the current path 2025-12-15 01:12:51 +02:00
Adorian Doran
3ba7b7d439 style/status bar/note paths: refactor 2025-12-15 00:49:25 +02:00
Adorian Doran
381943818d client/status bar/note paths: improve appearance 2025-12-15 00:37:23 +02:00
Adorian Doran
d1ae2db587 client/status bar/note paths: replace the "Clone note to new location" button with a link 2025-12-15 00:31:36 +02:00
Elian Doran
8fa6e38382 refactor(ribbon): decouple completely from new layout 2025-12-14 23:50:40 +02:00
Elian Doran
749074ea94 chore(layout/status_bar): enforce single pane opened at a time 2025-12-14 23:35:16 +02:00
Elian Doran
f1bb786a49 chore(layout): support for similar notes in the status bar 2025-12-14 23:29:01 +02:00
Elian Doran
42bde3873b fix(layout): extra spacing between badges when no custom actions are available 2025-12-14 23:02:24 +02:00
Elian Doran
4877238015 refactor(layout): integrate copy image reference to button to all supported note types 2025-12-14 22:56:39 +02:00
Elian Doran
16374aaf1d refactor(layout): use note.isContentAvailable() 2025-12-14 22:51:50 +02:00
Elian Doran
19709f749a feat(layout): integrate copy reference to clipboard button 2025-12-14 22:50:26 +02:00
Elian Doran
09c7affc16 feat(layout): integrate file-similar options to image 2025-12-14 22:45:23 +02:00
Elian Doran
01e197fd46 feat(layout): integrate original file name into status bar 2025-12-14 22:34:13 +02:00
Elian Doran
0fe129ac16 feat(layout): add a margin for custom note action buttons 2025-12-14 22:22:41 +02:00
Elian Doran
3c52ceb4e6 refactor(layout): extract file actions to separate file 2025-12-14 22:16:54 +02:00
Elian Doran
8ba2357d91 feat(layout/file): upload new revision button 2025-12-14 22:14:05 +02:00
Elian Doran
20f4990d48 feat(layout/file): open externally & download buttons 2025-12-14 22:07:25 +02:00
Elian Doran
8c793bf0fe fix(layout): title area gets wrong note context 2025-12-14 21:58:10 +02:00
Elian Doran
12a0eebafe refactor(layout): handle note actions differently 2025-12-14 21:57:16 +02:00
Elian Doran
092c7dff6b fix(layout): extra padding when no note title actions 2025-12-14 21:38:02 +02:00
Elian Doran
7a1ff42d67 feat(layout/search_properties): expand search properties 2025-12-14 21:29:10 +02:00
Elian Doran
5a09a80902 feat(layout): basic ARIA & some padding 2025-12-14 21:20:55 +02:00
Elian Doran
a7ca839afb feat(layout/search_definition): integrate view options directly in search parameters 2025-12-14 20:48:50 +02:00
Elian Doran
6b9b9a96c3 feat(layout): integrate search parameters ribbon tab 2025-12-14 20:34:55 +02:00
Elian Doran
272888acab refactor(ribbon): format SearchDefinitionTab 2025-12-14 20:27:34 +02:00
Elian Doran
283e3c9de1 style(layout/edited_notes): increase vertical padding slighly 2025-12-14 20:23:08 +02:00
Elian Doran
859087b850 feat(layout/edited_notes): respect choice to auto-open 2025-12-14 20:21:30 +02:00
Elian Doran
f7b911dc0b feat(layout): make edited notes collapsible 2025-12-14 20:15:17 +02:00
Elian Doran
9d7e2855d3 feat(layout): edited notes underneath title details 2025-12-14 19:39:55 +02:00
Elian Doran
8e6ea87754 fix(context_menu): regressions on mobile 2025-12-14 12:02:40 +02:00
Elian Doran
34bc444b18 fix(context_menu): clicking submenu dismisses the menu 2025-12-14 12:02:32 +02:00
Elian Doran
860a903336 feat(breadcrumb): hide note paths if only one 2025-12-14 11:49:16 +02:00
Elian Doran
be923ad2b7 chore(breadcrumb): add text span for hiding them at some point 2025-12-14 11:47:18 +02:00
Elian Doran
d2da1ed1e7 feat(breadcrumb): make tooltips shorter 2025-12-14 11:26:09 +02:00
Elian Doran
1c05f5e5c3 feat(breadcrumb): disable tooltip animation for faster input 2025-12-14 11:21:27 +02:00
Elian Doran
e043f30cc6 feat(breadcrumb): add text for all items 2025-12-14 11:20:24 +02:00
Elian Doran
e1611d83a3 fix(breadcrumb): tree displayed in root navigation 2025-12-14 11:12:14 +02:00
Elian Doran
58e2111a8f chore(nix): update flake lock 2025-12-14 11:01:25 +02:00
Elian Doran
c5e4c484dc chore(deps): update react monorepo to v19.2.3 (#8033) 2025-12-14 10:58:02 +02:00
Elian Doran
75a6dece7a Translations update from Hosted Weblate (#8052) 2025-12-14 10:57:37 +02:00
Hosted Weblate
5c0e7736d6 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-14 09:52:47 +01:00
Elian Doran
2562ecd055 feat(renovate): enable nix 2025-12-14 10:52:29 +02:00
Elian Doran
aaaa47b575 Translations update from Hosted Weblate (#8049) 2025-12-14 10:33:29 +02:00
green
21d82ec1d7 Translated using Weblate (Japanese)
Currently translated at 100.0% (1686 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-14 09:21:46 +01:00
Luk On
5af8444cac Translated using Weblate (Polish)
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/pl/
2025-12-14 09:21:46 +01:00
Wojciech O
cd82c34b93 Translated using Weblate (Polish)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-12-14 09:21:45 +01:00
noobhjy
d182659d62 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1686 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-14 09:21:44 +01:00
Mik Piet
171f428b9d Translated using Weblate (Polish)
Currently translated at 100.0% (1686 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-14 09:21:43 +01:00
kamykO
da4ca9c804 Translated using Weblate (Polish)
Currently translated at 100.0% (1686 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-14 09:21:43 +01:00
Luk On
c019341503 Translated using Weblate (Polish)
Currently translated at 100.0% (1686 of 1686 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-14 09:21:42 +01:00
Hosted Weblate
7234f04b56 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-14 09:21:42 +01:00
Elian Doran
1998cbc005 chore(deps): update dependency @types/node to v24.10.4 (#8050) 2025-12-14 10:21:26 +02:00
renovate[bot]
5914073c3f chore(deps): update dependency @types/node to v24.10.4 2025-12-14 02:09:59 +00:00
Elian Doran
d5aadf2604 chore: add dev shell and direnv support (#8011) 2025-12-13 22:49:35 +02:00
renovate[bot]
1fe22f940b chore(deps): update react monorepo to v19.2.3 2025-12-13 20:46:52 +00:00
Elian Doran
0cdaf70efe chore(deps): update dependency electron to v39.2.7 (#8030) 2025-12-13 22:46:30 +02:00
Elian Doran
8174c65243 chore(deps): update dependency eslint to v9.39.2 (#8031) 2025-12-13 22:45:31 +02:00
Elian Doran
2645801277 chore(deps): update dependency vite to v7.2.7 (#8032) 2025-12-13 22:44:45 +02:00
Elian Doran
fb8c31cb9c fix(deps): update dependency i18next to v25.7.2 (#8035) 2025-12-13 22:44:05 +02:00
Elian Doran
7287dbd64f fix(deps): update dependency preact-render-to-string to v6.6.4 (#8036) 2025-12-13 22:43:19 +02:00
renovate[bot]
6569d64931 fix(deps): update dependency preact-render-to-string to v6.6.4 2025-12-13 19:24:56 +00:00
renovate[bot]
e9f3216926 fix(deps): update dependency i18next to v25.7.2 2025-12-13 19:24:28 +00:00
renovate[bot]
ca0af9646d chore(deps): update dependency vite to v7.2.7 2025-12-13 19:23:33 +00:00
renovate[bot]
92dfafd1ff chore(deps): update dependency eslint to v9.39.2 2025-12-13 19:23:05 +00:00
renovate[bot]
d04dde3b97 chore(deps): update dependency electron to v39.2.7 2025-12-13 19:22:36 +00:00
Elian Doran
4c520c6df3 e2e(server): broken test after submenu 2025-12-13 21:10:59 +02:00
Adorian Doran
65d6ed1cdc Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-13 20:42:24 +02:00
Adorian Doran
3352a92445 style/new layout/inline title: tweak 2025-12-13 20:42:16 +02:00
Elian Doran
bc8c55b8fb Translations update from Hosted Weblate (#8047) 2025-12-13 20:37:28 +02:00
Elian Doran
7660914eb8 Merge branch 'main' into weblate-trilium-client 2025-12-13 20:34:04 +02:00
Elian Doran
869aec778c New layout: Shared formatting toolbar (#8046) 2025-12-13 20:15:43 +02:00
noobhjy
255726dcc4 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1685 of 1685 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-13 18:09:10 +00:00
Adorian Doran
9969000807 style/new layout/note title: tweak 2025-12-13 20:08:57 +02:00
Elian Doran
3b909fd739 chore(layout/formatting_toolbar): address requested changes 2025-12-13 19:59:45 +02:00
Elian Doran
ad08fb8132 chore(formatting_toolbar): address self-review 2025-12-13 19:32:44 +02:00
Elian Doran
8d536a6040 fix(formatting_toolbar): view mode check not working in multi-split 2025-12-13 19:29:13 +02:00
Elian Doran
2b1bc8e2b9 feat(inline_title): in split, avoid layout shift by maintaining the toolbar 2025-12-13 16:54:04 +02:00
Adorian Doran
563194ff6c client/note menu: localize string 2025-12-13 16:45:09 +02:00
Elian Doran
0c9ff4dae4 chore(inline_title): fix type error 2025-12-13 16:43:27 +02:00
Elian Doran
b10e7f1811 fix(inline_title): some badges not visible in split 2025-12-13 16:42:06 +02:00
Elian Doran
f93ad499e2 feat(layout/formatting_toolbar): move above sidebar 2025-12-13 16:35:48 +02:00
Adorian Doran
87a51251ca client/layout/status bar: replace some icons 2025-12-13 16:33:33 +02:00
Elian Doran
b56e5b2483 fix(inline_title): note type switcher visible for options 2025-12-13 16:33:33 +02:00
Elian Doran
476c162016 fix(layout/formatting_toolbar): memory leak for closed tabs 2025-12-13 16:31:19 +02:00
Elian Doran
4182f6043a feat(layout/formatting_toolbar): render cached components 2025-12-13 16:26:01 +02:00
Elian Doran
aa528c65b7 chore(layout/formatting_toolbar): render without adapter 2025-12-13 16:05:11 +02:00
Elian Doran
4998560e31 chore(layout/inline_title): show note type switcher for code notes as well 2025-12-13 15:55:56 +02:00
Elian Doran
86f36922c4 Translations update from Hosted Weblate (#8025) 2025-12-13 15:42:54 +02:00
Hosted Weblate
4f617b86d3 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-13 13:34:47 +00:00
noobhjy
b28527e10d Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1683 of 1683 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-13 13:34:46 +00:00
green
fbb8924ebf Translated using Weblate (Japanese)
Currently translated at 100.0% (1683 of 1683 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-13 13:34:45 +00:00
Hosted Weblate
f68c9b751f Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-13 13:34:45 +00:00
Luk On
8091f02b16 Translated using Weblate (Polish)
Currently translated at 100.0% (1677 of 1677 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-13 13:34:44 +00:00
noobhjy
f4c68d115b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1677 of 1677 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-13 13:34:43 +00:00
Luk On
6c70d6b9ae Translated using Weblate (Polish)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pl/
2025-12-13 13:34:43 +00:00
Luk On
1ea12567a3 Translated using Weblate (Polish)
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/pl/
2025-12-13 13:34:42 +00:00
Luk On
2d16ab7a70 Translated using Weblate (Polish)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-12-13 13:34:41 +00:00
Luk On
a228ba5273 Translated using Weblate (Polish)
Currently translated at 100.0% (1677 of 1677 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-13 13:34:41 +00:00
Luk On
d0477e9ebf Translated using Weblate (Polish)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pl/
2025-12-13 13:34:40 +00:00
Luk On
c99907972d Translated using Weblate (Polish)
Currently translated at 11.2% (13 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/pl/
2025-12-13 13:34:39 +00:00
Luk On
b9ebc7d7ea Translated using Weblate (Polish)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/pl/
2025-12-13 13:34:39 +00:00
green
4f9e2c5eca Translated using Weblate (Japanese)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-12-13 13:34:38 +00:00
green
ab1f8ee5ae Translated using Weblate (Japanese)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-12-13 13:34:37 +00:00
green
89276ad51a Translated using Weblate (Japanese)
Currently translated at 100.0% (1677 of 1677 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-13 13:34:36 +00:00
green
eca533a517 Translated using Weblate (Japanese)
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ja/
2025-12-13 13:34:36 +00:00
Elian Doran
0be578c517 chore(deps): update dependency @electron/rebuild to v4.0.2 (#8028) 2025-12-13 15:34:09 +02:00
Elian Doran
198b315602 chore(deps): update dependency @redocly/cli to v2.12.6 (#8029) 2025-12-13 15:33:28 +02:00
Elian Doran
6474abc983 fix(deps): update dependency eslint-linter-browserify to v9.39.2 (#8034) 2025-12-13 15:32:33 +02:00
Elian Doran
2137dbe849 chore(deps): update node.js to v24.12.0 (#8037) 2025-12-13 15:32:07 +02:00
Elian Doran
b7b46703d9 chore(deps): update pnpm to v10.25.0 (#8038) 2025-12-13 15:31:13 +02:00
Elian Doran
d2d96a1421 chore(deps): update typescript-eslint monorepo to v8.49.0 (#8039) 2025-12-13 15:30:26 +02:00
Elian Doran
cfcc309e5a fix(deps): update dependency @codemirror/view to v6.39.4 (#8040) 2025-12-13 15:28:35 +02:00
Elian Doran
7d87ec942e fix(deps): update dependency react-i18next to v16.5.0 (#8041) 2025-12-13 15:26:40 +02:00
Elian Doran
4def13272f chore(deps): update github artifact actions (major) (#8042) 2025-12-13 15:25:59 +02:00
Elian Doran
c4f914bb7b New layout: Title bar & inline title (#8044) 2025-12-13 15:09:30 +02:00
Elian Doran
6bf213a0b0 fix(layout/status_bar): some popups not dismissing 2025-12-13 15:02:16 +02:00
Elian Doran
694cd2bc7c chore(layout/title_bar): address LLM review 2025-12-13 14:58:11 +02:00
Elian Doran
3851a94400 fix(layout/title_bar): badges not collapsing 2025-12-13 14:51:58 +02:00
Elian Doran
e296416a54 fix(layout/inline-title): title not shown when switching to other types of notes 2025-12-13 14:38:58 +02:00
Elian Doran
0bd89a659c chore(layout/inline-title): disable pointer events while hidden 2025-12-13 14:00:27 +02:00
Elian Doran
0ada6523a8 feat(layout/inline-title): add transition 2025-12-13 13:58:20 +02:00
Elian Doran
56570d7ba1 fix(layout/inline-title): text displayed even when note is not empty 2025-12-13 13:46:28 +02:00
Elian Doran
0ffdedcfa6 feat(layout/inline-title): dropdown for collections 2025-12-13 13:45:34 +02:00
Elian Doran
f391bb8eec feat(layout/inline-title): support built-in templates 2025-12-13 13:35:32 +02:00
Elian Doran
7000076961 feat(layout/inline-title): react to template add/remove 2025-12-13 13:26:48 +02:00
Elian Doran
e0f6ba808c feat(layout/inline-title): template switcher 2025-12-13 13:24:32 +02:00
Elian Doran
4c2fe8a846 feat(layout/inline-title): group some note types 2025-12-13 13:12:03 +02:00
Elian Doran
2ea23368bc feat(vscode): eslint on save 2025-12-13 12:59:32 +02:00
Elian Doran
87666005a6 feat(layout/inline-title): add an intro text 2025-12-13 12:57:33 +02:00
Elian Doran
7666f44b7a fix(layout/inline-title): hide note type switcher on other note types 2025-12-13 12:49:51 +02:00
Elian Doran
470f6e5334 feat(layout/inline-title): hide note type switcher when empty 2025-12-13 12:48:20 +02:00
Elian Doran
a2b007874b feat(layout/inline-title): not reacting to note type changes 2025-12-13 12:43:15 +02:00
Elian Doran
9946d8c6b9 fix(layout/statusbar): code note switcher displayed for other note types 2025-12-13 12:29:59 +02:00
Elian Doran
02fab16475 feat(layout/inline-title): add icons 2025-12-13 12:28:22 +02:00
Elian Doran
5145ce2d23 feat(layout/inline-title): horizontal scroll via wheel 2025-12-13 12:27:45 +02:00
Elian Doran
e06abe6e5b fix(layout/inline-title): current note type displayed in switcher 2025-12-13 12:26:02 +02:00
Elian Doran
50a847777e feat(layout/inline-title): basic note type switcher 2025-12-13 12:25:01 +02:00
Elian Doran
4473f80d73 refactor(layout): remove floating title bar experiment 2025-12-13 12:02:17 +02:00
Elian Doran
70c918c9c6 feat(layout/inline-title): support in options as well 2025-12-13 12:01:06 +02:00
Elian Doran
0939975631 style(layout/inline-title): use muted text color 2025-12-13 11:58:35 +02:00
Elian Doran
0ef90c6165 fix(layout/inline-title): hide in attachments and other view scopes 2025-12-13 11:57:53 +02:00
Elian Doran
cef14a3b19 feat(layout/inline-title): support code 2025-12-13 11:51:57 +02:00
Elian Doran
61d3141bce refactor(layout/inline-title): extract specific styles 2025-12-13 11:49:05 +02:00
Elian Doran
f040a0b6d1 refactor(layout/inline-title): separate old title details into title actions 2025-12-13 11:46:42 +02:00
Elian Doran
e9dfec88c9 feat(layout/inline-title): bring back creation and modification date 2025-12-13 11:43:27 +02:00
Elian Doran
6fa97c845a fix(layout/inline-title): still visible in other note types 2025-12-13 11:37:56 +02:00
Elian Doran
f686d9ecd0 feat(layout/inline-title): keep header bar visible 2025-12-13 11:34:29 +02:00
Elian Doran
621ebe4396 feat(layout/inline-title): title and icon 2025-12-13 11:33:02 +02:00
Adorian Doran
ac2a566685 client/note menu: reorganize menu items 2025-12-13 11:29:39 +02:00
Elian Doran
ac3d57d5da chore(layout): remove ribbon border 2025-12-13 11:28:52 +02:00
Elian Doran
9ab5eef984 feat(layout/inline-title): intersection observer 2025-12-13 11:26:42 +02:00
Elian Doran
912f90accf feat(layout/inline-title): collapse title for text notes 2025-12-13 11:17:39 +02:00
Elian Doran
6463b0dcaa chore(layout/inline-title): placeholder for the title 2025-12-13 11:08:34 +02:00
Elian Doran
0b45fb6764 feat(layout/title): hide note badges while editing title 2025-12-13 10:57:34 +02:00
Elian Doran
330d71847b refactor(layout/title): rename to note badges 2025-12-13 10:54:19 +02:00
Elian Doran
60c8f0c78b refactor(layout/title): relocate badges to layouts dir 2025-12-13 10:47:46 +02:00
Elian Doran
fcbd1ab0b1 chore(layout/title): remove spacer 2025-12-13 10:44:33 +02:00
Elian Doran
3549bfb328 feat(layout/title): collapse badges and note title while constrained in size 2025-12-13 10:43:32 +02:00
Elian Doran
c97038fffd chore(layout): revert breadcrumb row 2025-12-13 10:26:25 +02:00
Elian Doran
15b5885982 New layout: status bar (#8021) 2025-12-13 10:23:12 +02:00
renovate[bot]
6aa8d9fbf9 chore(deps): update github artifact actions 2025-12-13 01:19:13 +00:00
renovate[bot]
eccf4620ac fix(deps): update dependency react-i18next to v16.5.0 2025-12-13 01:19:08 +00:00
renovate[bot]
f08fbe9bb2 fix(deps): update dependency @codemirror/view to v6.39.4 2025-12-13 01:18:39 +00:00
renovate[bot]
bfa87af489 chore(deps): update typescript-eslint monorepo to v8.49.0 2025-12-13 01:18:08 +00:00
renovate[bot]
a7899b7505 chore(deps): update pnpm to v10.25.0 2025-12-13 01:17:37 +00:00
renovate[bot]
e80b5cddcd chore(deps): update node.js to v24.12.0 2025-12-13 01:17:27 +00:00
renovate[bot]
db12f9b8dc fix(deps): update dependency eslint-linter-browserify to v9.39.2 2025-12-13 01:15:42 +00:00
renovate[bot]
f4c95195c9 chore(deps): update dependency @redocly/cli to v2.12.6 2025-12-13 01:12:39 +00:00
renovate[bot]
e2cbff7b3a chore(deps): update dependency @electron/rebuild to v4.0.2 2025-12-13 01:11:53 +00:00
Elian Doran
98a3c8150c feat(breadcrumb): replace title editing with jump to top 2025-12-13 01:45:02 +02:00
Elian Doran
447e09fec1 feat(note_actions): hide code notes from new layout 2025-12-13 01:24:37 +02:00
Elian Doran
7d2a1bb2e5 feat(status_bar): modal for configuring list of code languages 2025-12-13 01:19:20 +02:00
Elian Doran
40fcf79778 fix(status_bar): code mime not updating between notes 2025-12-13 01:14:50 +02:00
Elian Doran
88a779bbdb feat(status_bar): indicate selected code mime in menu 2025-12-13 01:10:38 +02:00
Elian Doran
db04514769 fix(status_bar): code mime switcher is clipped 2025-12-13 01:07:30 +02:00
Elian Doran
23062470f5 feat(status_bar): code mime switcher 2025-12-13 01:03:57 +02:00
Elian Doran
5bad043ed5 chore(status_bar): address requested changes 2025-12-13 00:43:00 +02:00
Elian Doran
4ab8af0995 feat(status_bar): keep button active when dropdown is shown 2025-12-13 00:37:29 +02:00
Elian Doran
1a65c5e13e feat(status_bar): hide note paths in hidden notes 2025-12-13 00:30:22 +02:00
Elian Doran
fc08946038 chore(status_bar): avoid shifting due to language switcher 2025-12-13 00:27:51 +02:00
Elian Doran
4d6dba06ad refactor(ribbon): remove left-over logic for calculating ribbon height 2025-12-13 00:24:05 +02:00
Elian Doran
d7887fe25f chore(layout): hide ribbon in new layout 2025-12-13 00:22:34 +02:00
Elian Doran
81dd50e752 fix(status_bar): wrong font size for language selector text 2025-12-13 00:13:06 +02:00
Elian Doran
fe13065ef8 lint: status bar 2025-12-13 00:11:28 +02:00
Elian Doran
eb02330fdf feat(status_bar): integrate note paths widget 2025-12-13 00:05:33 +02:00
Elian Doran
738fa6fd0e lint: note paths 2025-12-12 23:51:03 +02:00
Elian Doran
0c1c7e4f8e feat(status_bar): note paths (no interaction yet) 2025-12-12 23:47:31 +02:00
Elian Doran
9eb9b66398 fix(status_bar): keyboard shortcuts to add attributes not working 2025-12-12 23:34:26 +02:00
Elian Doran
9db046b401 fix(status_bar): attributes not editable from modal 2025-12-12 23:29:59 +02:00
Elian Doran
914272eee0 style(status_bar): improve layout and spacing slightly 2025-12-12 23:13:31 +02:00
Elian Doran
2b7e203bcc refactor(status_bar): remove wrapper container for breadcrumb 2025-12-12 23:07:57 +02:00
Elian Doran
a61ddedc0b refactor(status_bar): remove old breadcrumb styles 2025-12-12 23:06:47 +02:00
Elian Doran
60fc34ffac feat(status_bar): functional attribute toggle button 2025-12-12 21:57:42 +02:00
Elian Doran
685109556c chore(ribbon): hide inherited & owned attributes on new layout 2025-12-12 21:49:42 +02:00
Elian Doran
45927053f3 fix(ribbon): links in inherited attributes not visible 2025-12-12 21:48:11 +02:00
Elian Doran
5d438a877b feat(status_bar): improve alignment of attribute editor 2025-12-12 21:44:27 +02:00
Elian Doran
870499bc3a feat(status_bar): basic integration of inherited attributes 2025-12-12 21:41:05 +02:00
Elian Doran
c6d97e3d4b feat(status_bar): basic integration of attribute editor 2025-12-12 21:30:32 +02:00
Elian Doran
efff38b116 feat(status_bar): attribute button (not yet interactive) 2025-12-12 21:19:23 +02:00
Elian Doran
1b725175c6 refactor(status_bar): solve warnings 2025-12-12 20:59:57 +02:00
Elian Doran
6eff62f73f feat(status_bar): add new attachment count 2025-12-12 20:55:54 +02:00
Elian Doran
95d2160c76 feat(status_bar): integrate backlinks 2025-12-12 20:31:19 +02:00
Elian Doran
2b195155ed fix(note_details): appearing in options 2025-12-12 20:21:55 +02:00
Elian Doran
28e9abc8bb chore(status_bar): re-order icons to avoid layout shifting 2025-12-12 20:19:37 +02:00
Elian Doran
0162b9d441 fix(status_bar): language selector appearing for non-text notes 2025-12-12 20:18:50 +02:00
Elian Doran
0545b929e1 fix(status_bar): react to active note context 2025-12-12 20:17:53 +02:00
Elian Doran
d2b32ff5af feat(status_bar): relocate to outside split area 2025-12-12 19:47:47 +02:00
Elian Doran
2d3776cd5f feat(status_bar): integrate note info badge 2025-12-12 19:31:00 +02:00
Elian Doran
2638963171 feat(status_bar/language): add tooltip 2025-12-12 18:58:54 +02:00
Elian Doran
24ed97f65d feat(status_bar/language): improve display of more languages 2025-12-12 18:53:54 +02:00
Elian Doran
c099634e39 feat(status_bar/language): improve display of Asian languages 2025-12-12 18:50:48 +02:00
Elian Doran
12be14e6cf feat(status_bar/language): display icon 2025-12-12 18:47:34 +02:00
Elian Doran
4dc773c1a3 refactor(status_bar/language): stop reusing UI for greater customisibility 2025-12-12 18:29:40 +02:00
Elian Doran
31c5323fd9 feat(status_bar/language): compact locale name 2025-12-12 18:05:10 +02:00
Elian Doran
74b6e7bf63 fix(breadcrumb): some dropdowns not visible 2025-12-12 17:55:22 +02:00
Elian Doran
34025fa646 fix(global_menu): dev menu wrongly positioned on horizontal layout 2025-12-12 14:41:10 +02:00
Elian Doran
df9554194a feat(layout/status_bar): integrate language selector basically 2025-12-12 00:34:47 +02:00
Elian Doran
4e1188484d refactor(layout/status_bar): move breadcrumbs into layout dir 2025-12-12 00:24:30 +02:00
Elian Doran
2f44b9dc59 feat(layout/status_bar): integrate breadcrumbs 2025-12-12 00:21:40 +02:00
Elian Doran
9ee3c48485 chore(layout): relocate ribbon on the top temporarily 2025-12-12 00:15:58 +02:00
Elian Doran
78b9c94829 chore(layout/status_bar): create empty component 2025-12-12 00:13:38 +02:00
Elian Doran
4c8225ed73 Translations update from Hosted Weblate (#8020) 2025-12-11 23:58:41 +02:00
noobhjy
88aad6d351 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1668 of 1668 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-11 20:38:41 +00:00
Elian Doran
d99d701095 feat(global_menu): add support for all experimental options 2025-12-11 22:38:22 +02:00
Elian Doran
61fe27abbe feat(layout): extract floating titlebar into its own experimental feature 2025-12-11 22:29:22 +02:00
Elian Doran
24cd5006d5 chore(note_map): open in reusable split 2025-12-11 22:14:08 +02:00
Elian Doran
726d6aad65 feat(layout): integrate note map 2025-12-11 22:01:22 +02:00
Elian Doran
bd9fe14a6c chore(layout): remove title extra spacing for now 2025-12-11 21:08:36 +02:00
Elian Doran
792a10ace5 New layout: Integrate small ribbon categories + collection properties (#8018) 2025-12-11 20:59:31 +02:00
Elian Doran
e9ac69b8e5 chore(note_bars/collection): address change request 2025-12-11 20:33:52 +02:00
Elian Doran
c76ff2d371 feat(note_bars/collection): add a help button 2025-12-11 20:19:06 +02:00
Elian Doran
8ab9e30404 chore(note_bars/collection): disable ribbon tab 2025-12-11 20:13:04 +02:00
Elian Doran
53b7d93efb feat(note_bars/collection): support comboboxes 2025-12-11 20:09:25 +02:00
Elian Doran
00df3c3d1f feat(note_bars/collection): support number fields 2025-12-11 19:51:40 +02:00
Elian Doran
e766b82418 feat(note_bars/collection): add icon to checkboxes 2025-12-11 19:44:22 +02:00
Elian Doran
9f4757af5b chore(note_bars/collection): put archived notes at the end 2025-12-11 19:39:07 +02:00
Elian Doran
1a9fb34a6e feat(note_bars/collection): support dropdown menu click action 2025-12-11 19:37:04 +02:00
Elian Doran
a1513a3567 feat(note_bars/collection): support split button properties 2025-12-11 19:34:22 +02:00
Elian Doran
0de67b6a69 feat(note_bars/collection): support button properties 2025-12-11 19:29:27 +02:00
Elian Doran
fec5ee9335 feat(note_bars/collection): integrate show archived notes 2025-12-11 19:21:51 +02:00
Elian Doran
b540111fa4 feat(note_bars): add icons to view type switcher 2025-12-11 18:59:28 +02:00
Elian Doran
0eed72b888 feat(note_bars): view type switcher 2025-12-11 18:53:48 +02:00
Elian Doran
0856d3dbdf fix(layout): note title padding on full-height note 2025-12-11 18:02:52 +02:00
Elian Doran
a9b453c27a feat(breadcrumb_badges): integrate query/script tab 2025-12-11 17:43:00 +02:00
Elian Doran
fa8287269f feat(breadcrumb_badges): integrate note properties tab 2025-12-11 17:34:04 +02:00
Elian Doran
1eee471018 fix(breadcrumb_badges): temporarily editable showing up always in popup editor 2025-12-11 17:20:28 +02:00
Elian Doran
c3829f82ab New layout: Note info (#8015) 2025-12-11 17:18:19 +02:00
Elian Doran
a51820f5df chore(note_info): address requested changes 2025-12-11 16:57:04 +02:00
Elian Doran
68591fb511 feat(note_info): hide ribbon on new layout 2025-12-11 16:48:49 +02:00
Elian Doran
3795ce2143 feat(note_info): integrate near the note title 2025-12-11 16:47:44 +02:00
Elian Doran
3561a4f14d feat(note_info): add back tooltip for note size 2025-12-11 16:38:31 +02:00
Elian Doran
84cda001aa feat(note_info): improve layout slightly 2025-12-11 16:33:18 +02:00
Elian Doran
481127a560 docs(user): mention version for board custom attributes 2025-12-11 10:57:30 +02:00
Elian Doran
c708e7cd61 Translations update from Hosted Weblate (#8016) 2025-12-11 10:49:33 +02:00
Elian Doran
fee0268792 Translated using Weblate (Romanian)
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ro/
2025-12-11 09:47:52 +01:00
green
953593c9d4 Translated using Weblate (Japanese)
Currently translated at 100.0% (1668 of 1668 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-11 09:47:52 +01:00
Elian Doran
5ff60e53cb Translated using Weblate (Romanian)
Currently translated at 100.0% (1668 of 1668 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-12-11 09:47:51 +01:00
Giovi
b38ee36fae Translated using Weblate (Italian)
Currently translated at 100.0% (1668 of 1668 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-11 09:47:49 +01:00
Hosted Weblate
38a415faf0 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-11 09:32:25 +01:00
Elian Doran
1e26864842 Translations update from Hosted Weblate (#8006) 2025-12-11 10:32:09 +02:00
Elian Doran
4b74ad5577 feat(breadcrumb/note_info): note size 2025-12-11 00:34:25 +02:00
Elian Doran
e5696713de feat(breadcrumb/note_info): modification/creation date 2025-12-11 00:23:32 +02:00
Elian Doran
2e44397c88 feat(breadcrumb/note_info): get basic dropdown 2025-12-11 00:18:56 +02:00
Francis C.
5d19881981 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1658 of 1658 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-10 22:38:11 +01:00
Tomas Adamek
1711384eaa Translated using Weblate (Czech)
Currently translated at 35.3% (41 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/cs/
2025-12-10 22:38:11 +01:00
Tomas Adamek
9897efe4af Translated using Weblate (Czech)
Currently translated at 5.3% (88 of 1658 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-12-10 22:38:10 +01:00
Francis C.
884578ea95 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hans/
2025-12-10 22:38:09 +01:00
Francis C.
e404e76299 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (116 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hant/
2025-12-10 22:38:09 +01:00
green
1db54cba3e Translated using Weblate (Japanese)
Currently translated at 100.0% (1658 of 1658 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-10 22:38:08 +01:00
Francis C.
77e3cc4021 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1658 of 1658 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-10 22:38:07 +01:00
pythaac
242c63dfb4 Translated using Weblate (Korean)
Currently translated at 65.1% (99 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-12-10 22:38:06 +01:00
Abdulmajeed Alaskar
f5440576b5 Translated using Weblate (Arabic)
Currently translated at 53.9% (82 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ar/
2025-12-10 22:38:06 +01:00
Abdulmajeed Alaskar
b020365af4 Translated using Weblate (Arabic)
Currently translated at 29.3% (34 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ar/
2025-12-10 22:38:05 +01:00
green
25e5bf0b86 Translated using Weblate (Japanese)
Currently translated at 100.0% (1648 of 1648 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-10 22:38:05 +01:00
Elian Doran
19b32dd3a6 New layout: Integrate Basic properties (#8014) 2025-12-10 23:37:54 +02:00
Elian Doran
1ab89d0db0 fix(status_bar): language selector not updating properly 2025-12-10 23:36:47 +02:00
Elian Doran
6e8e10323f chore(client): address requested changes 2025-12-10 23:19:17 +02:00
Elian Doran
58bc5dc66a chore(ribbon): hide basic properties from the ribbon on new layout 2025-12-10 23:07:35 +02:00
Elian Doran
db42bb603b feat(status_bar): add help item 2025-12-10 23:04:32 +02:00
Elian Doran
cb382c9537 fix(global_menu): layout switcher sometimes fails 2025-12-10 22:57:52 +02:00
Elian Doran
a4b79a2dc9 fix(ribbon): content code modal hidden behind backdrop 2025-12-10 22:56:29 +02:00
Elian Doran
0f867e02c4 fix(ribbon): content languages modal hidden behind backdrop 2025-12-10 22:52:13 +02:00
Elian Doran
ab1b4b37f4 feat(global_menu): add an option to switch layouts 2025-12-10 22:51:47 +02:00
Elian Doran
5a1d138f29 feat(status_bar): language selector 2025-12-10 22:39:07 +02:00
Elian Doran
06a5298efa feat(note_actions): hide options in attachments 2025-12-10 22:27:56 +02:00
Elian Doran
db720acc18 feat(note_actions): hide options in help pages 2025-12-10 22:25:09 +02:00
Elian Doran
8d8ff25bae feat(note_actions): reintroduce help pages 2025-12-10 22:21:15 +02:00
Elian Doran
6f85b7cc09 feat(note_actions): integrate note type 2025-12-10 21:54:17 +02:00
Elian Doran
77f5770bff feat(note_actions): protect note switch 2025-12-10 20:57:15 +02:00
Elian Doran
14cda5b921 fix(note_actions): editability context menu is too narrow 2025-12-10 20:46:58 +02:00
Elian Doran
36b1182565 feat(widgets/toggle): disable if going too fast 2025-12-10 20:33:30 +02:00
Elian Doran
483327c808 fix(widgets/toggle): double event triggering when in menu 2025-12-10 20:30:55 +02:00
Elian Doran
efb2f9a048 chore(note_actions): reintroduce disabled logic for toggles 2025-12-10 20:20:21 +02:00
Elian Doran
01978dabf0 fix(breadcrumb_badges): doesn't refresh when switching editability 2025-12-10 19:05:33 +02:00
Elian Doran
cfbd2bf53a feat(note_actions): integrate editability menu into new layout 2025-12-10 18:58:46 +02:00
Elian Doran
9262f94190 feat(note_actions): integrate template switch into new layout 2025-12-10 18:43:34 +02:00
Elian Doran
b36a0bd10b feat(note_actions): integrate shared switch into new layout 2025-12-10 18:40:56 +02:00
Elian Doran
2dc8948f33 chore(breadcrumb_badges): chagne icon for shared locally 2025-12-10 18:35:29 +02:00
Elian Doran
9f2ed2f9d4 feat(widgets/toggle): disable transitions on first render 2025-12-10 18:33:29 +02:00
Elian Doran
e0f7d65f77 feat(widgets): toggle from label 2025-12-10 18:24:31 +02:00
Elian Doran
f18ac3a923 feat(note_actions): integrate bookmark into new layout 2025-12-10 18:20:36 +02:00
Elian Doran
b39a6bcc97 feat(widgets): prevent clicks in toggle from dismissing menu 2025-12-10 18:17:39 +02:00
Elian Doran
8fa9c25f2a feat(widgets): menu item with toggle 2025-12-10 18:07:38 +02:00
Elian Doran
84bde62e05 New layout improvements (#8012) 2025-12-10 17:50:31 +02:00
Elian Doran
5bb4621097 chore(layout): address requested changes 2025-12-10 17:42:08 +02:00
Elian Doran
f1edf84f4d fix(layout): title background for code notes 2025-12-10 17:13:52 +02:00
Elian Doran
f7955a9040 fix(client/dropdown): tooltip flickering due to child elements 2025-12-10 17:02:11 +02:00
Elian Doran
7c5df21685 feat(note_actions): group development options 2025-12-10 16:51:07 +02:00
Elian Doran
2060bb8cdd feat(breadcrumb): show note preview 2025-12-10 16:14:40 +02:00
Elian Doran
a9b4e7b1e2 style(layout): apply heavy padding to title only in normal view 2025-12-10 16:11:17 +02:00
Elian Doran
82528c4478 style(layout): slightly smaller note title in full-height note type 2025-12-10 15:23:42 +02:00
Zexin Yuan
4dcfc3e0bc chore: add dev shell and direnv support 2025-12-10 21:17:11 +08:00
Elian Doran
999315d3c6 feat(breadcrumb): basic rename note support 2025-12-10 15:16:45 +02:00
Elian Doran
aef0b03c34 feat(breadcrumb_row): collapse badges sooner 2025-12-10 13:38:15 +02:00
Elian Doran
49f008c46f feat(breadcrumb_row): improve button fit on constrained width 2025-12-10 13:37:07 +02:00
Elian Doran
bd81db4117 feat(breadcrumb_row): improve badge fit on constrained width 2025-12-10 13:33:33 +02:00
Elian Doran
9f274883e3 feat(breadcrumb_badges): basic shrink support 2025-12-10 13:06:25 +02:00
Elian Doran
07b76b80f4 feat(layout): hide note details in attachment view 2025-12-10 12:52:03 +02:00
Elian Doran
0014f0a88d feat(layout): minor improvements to title/icon alignment 2025-12-10 12:50:05 +02:00
Elian Doran
63f7a78d31 chore(note_actions): use dedicated translation for note revisions 2025-12-10 12:46:23 +02:00
Elian Doran
e556c090ff fix(ribbon): attribute details not shown in new layout 2025-12-10 12:40:06 +02:00
Elian Doran
c4f483c250 feat(options/advanced): automatically refresh 2025-12-10 12:29:12 +02:00
Elian Doran
4031332b98 feat(note_title_details): tooltips for values 2025-12-10 12:25:38 +02:00
Elian Doran
10cb7c8d6a feat(note_title_details): hide creation dates on hidden notes 2025-12-10 12:10:32 +02:00
Elian Doran
be190bfe33 feat(layout): improve layout for full-height notes 2025-12-10 12:06:05 +02:00
Elian Doran
4d7d642952 fix(layout): floating toolbar displayed in attachments 2025-12-10 11:58:17 +02:00
Elian Doran
737711e5eb fix(layout): weird title in full-width & attachments 2025-12-10 11:56:34 +02:00
Elian Doran
42fc128f97 chore(breadcrumb_badges/backlinks): display actual count of backlinks 2025-12-10 11:51:09 +02:00
Elian Doran
b03e6c3b19 chore(breadcrumb_badges/backlinks): display list of backlinks on click 2025-12-10 11:41:14 +02:00
Elian Doran
66008489c4 chore(breadcrumb_badges): fake backlink widget 2025-12-10 11:21:06 +02:00
Elian Doran
3262e3490a feat(breadcrumb_badges): integrate into quick edit 2025-12-10 11:10:26 +02:00
Elian Doran
16a73b0848 fix(popup_editor): wrong margin for title 2025-12-10 11:03:12 +02:00
Elian Doran
52bb4d7a0e feat(breadcrumb_badges): make badge not wrap-around 2025-12-10 09:52:46 +02:00
Elian Doran
40b5e4d549 feat(breadcrumb_badges): proper link handling support 2025-12-10 09:47:05 +02:00
Elian Doran
b014ea8950 feat(breadcrumb_badges): add colors to the badges 2025-12-10 09:38:55 +02:00
Elian Doran
61592716f9 feat(breadcrumb_badges): add tooltips for the badges 2025-12-10 09:27:44 +02:00
Elian Doran
efe7fc0ee7 chore(layout): hide breadcrumb badges if not on new layout 2025-12-10 09:12:57 +02:00
Elian Doran
a810db3641 feat(breadcrumb_badges): display badge when editing is unlocked 2025-12-10 09:11:28 +02:00
Elian Doran
f8b292dfa3 Experimental layout (#8005) 2025-12-09 23:35:15 +02:00
Elian Doran
fc2ab91280 feat(options/advanced): add description for experimental 2025-12-09 23:16:30 +02:00
Elian Doran
668ee219c6 chore(layout): use translation for badges 2025-12-09 23:02:21 +02:00
Elian Doran
ee6512a1a6 refactor(layout): align name for breadcrumb badges 2025-12-09 23:00:41 +02:00
Elian Doran
fe1f590286 chore(layout): use translations for note title details 2025-12-09 23:00:02 +02:00
Elian Doran
876e8f843a chore(layout): use i18n for options 2025-12-09 22:58:16 +02:00
Elian Doran
a45c1a1dc8 chore(layout): fix regressions after merge 2025-12-09 22:57:36 +02:00
Elian Doran
f8377169e6 Merge remote-tracking branch 'origin/main' into feature/new_layout 2025-12-09 22:46:18 +02:00
Elian Doran
a197a33d35 chore(experimental_features): address review 2025-12-09 22:43:39 +02:00
Elian Doran
3060207d04 feat(layout): created & modification date 2025-12-09 22:22:28 +02:00
Elian Doran
28c1d0b3f5 feat(layout): indicate clickable badges 2025-12-09 21:50:38 +02:00
Elian Doran
644d051477 feat(layout): add shared badge 2025-12-09 21:44:39 +02:00
Elian Doran
f42031c8de feat(layout): add icon to the badge 2025-12-09 21:11:30 +02:00
Elian Doran
6b50d9b087 feat(layout): implement read-only badge 2025-12-09 21:06:28 +02:00
Elian Doran
a0f0da64b4 feat(layout): new icon for note actions & fix padding 2025-12-09 20:59:28 +02:00
Elian Doran
1e72ebd104 feat(layout): move revisions button to note actions 2025-12-09 20:48:54 +02:00
Elian Doran
1184a95697 style(layout): missed bottom border in ribbon buttons 2025-12-09 20:44:58 +02:00
Elian Doran
cd0e4a5678 feat(layout): move fixed formatting toolbar above 2025-12-09 20:36:48 +02:00
Elian Doran
394f6c3110 feat(layout): respect content width for title 2025-12-09 20:22:31 +02:00
Elian Doran
e2b6d0c256 feat(layout): move the note title into the scrollable region 2025-12-09 20:09:06 +02:00
Elian Doran
fe7ca210dd feat(layout): move the note actions into the breadcrumb area 2025-12-09 20:05:42 +02:00
Elian Doran
e58d6bf2a3 feat(layout): reverse the layout of the ribbon 2025-12-09 19:51:53 +02:00
Elian Doran
460d20d6b2 feat(layout): move ribbon to the bottom as experimental layout 2025-12-09 19:42:37 +02:00
Elian Doran
ae154212fe feat(client/server): basic support for experimental features 2025-12-09 19:34:03 +02:00
Elian Doran
28bb4edbac chore(layout): revert work on floating panel 2025-12-09 19:18:48 +02:00
Elian Doran
1ceed1b47b chore(layout): revert work on floating panel 2025-12-09 19:11:27 +02:00
Elian Doran
9445e64c2e Translations update from Hosted Weblate (#8004) 2025-12-09 17:49:32 +02:00
Matheus Fongaro (MatioZG)
e6fba03ba7 Translated using Weblate (Portuguese (Brazil))
Currently translated at 3.2% (5 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pt_BR/
2025-12-09 16:16:40 +01:00
green
b027ca5c09 Translated using Weblate (Japanese)
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-09 16:16:39 +01:00
Elian Doran
e98df30500 fix(popup-editor): broken title bar layout 2025-12-09 17:16:29 +02:00
Elian Doran
111c44dadf fix(content_header): z-index issues 2025-12-09 17:11:28 +02:00
Elian Doran
cb31c25e6c fix(content_header): note icon dropdown broken when scrolling 2025-12-09 17:08:03 +02:00
Elian Doran
5d59c953c2 fix(layout): title row background in settings 2025-12-09 16:39:31 +02:00
Elian Doran
a2cff42981 fix(layout): scrollbar design in code note 2025-12-09 16:31:47 +02:00
Elian Doran
cae892a971 fix(layout): title not visible on dark code theme 2025-12-09 16:27:19 +02:00
Elian Doran
f8447d923e feat(ribbon): hide when in options 2025-12-09 16:22:03 +02:00
Elian Doran
3b8dabc9d2 Back/forward navigation in tab bar (#8003) 2025-12-09 16:11:17 +02:00
Elian Doran
cda39e967c chore(tab_navigation): address requested changes 2025-12-09 16:02:24 +02:00
Elian Doran
7da9367dc9 fix(tab_navigation): affecting server and mobile views 2025-12-09 15:59:15 +02:00
Elian Doran
82d97ef26f feat(tab_navigation): hide buttons if launcher ones are used 2025-12-09 15:30:46 +02:00
Elian Doran
9e094f1d96 feat(tab_navigation): add it to horizontal layout as well 2025-12-09 15:14:13 +02:00
Elian Doran
da7e15c268 refactor(tab_navigation): sort imports 2025-12-09 15:06:54 +02:00
Elian Doran
24806a810c feat(tab_navigation): display note icon in history navigation 2025-12-09 15:02:52 +02:00
Elian Doran
a2ace4510a Translations update from Hosted Weblate (#8000) 2025-12-09 15:00:26 +02:00
Elian Doran
5c8132088f feat(client): use chevrons to display note path 2025-12-09 14:49:19 +02:00
Elian Doran
7ee060b228 feat(tab_navigation): improve indicator for current item in context menu 2025-12-09 14:41:17 +02:00
Elian Doran
4b2a4b8f7b feat(tab_navigation): reflect state of history by disabling the buttons 2025-12-09 14:29:45 +02:00
Elian Doran
5a668ede01 chore(tab_navigation): reintroduce history cleaning 2025-12-09 14:24:39 +02:00
Elian Doran
9e099444b6 feat(tab_navigation): functional context menu 2025-12-09 14:23:06 +02:00
Elian Doran
e3f5b3535a feat(tab_navigation): functional back/forward buttons 2025-12-09 14:10:11 +02:00
Elian Doran
346ad1e8a3 feat(tab_navigation): add the buttons on vertical layout 2025-12-09 14:06:57 +02:00
Elian Doran
2a9558e9c5 style(ribbon): make icons slightly bigger 2025-12-09 13:18:25 +02:00
Hosted Weblate
c324f66aef Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-09 12:15:20 +01:00
Elian Doran
e688f2cdb6 Add breadcrumbs to navigation (#7995) 2025-12-09 13:15:03 +02:00
Elian Doran
2ff8762a22 chore(client): fix typecheck 2025-12-09 13:07:41 +02:00
Elian Doran
4d75221938 chore(breadcrumbs): address requested changes 2025-12-09 12:41:54 +02:00
Elian Doran
658b699b71 fix(collections/geomap): fake floating buttons mispositioned 2025-12-09 12:24:28 +02:00
Elian Doran
72b0d03546 chore(layout): remove some title margins 2025-12-09 12:23:05 +02:00
Elian Doran
19980807f2 style(ribbon): fix some alignment issues & decrease button size 2025-12-09 12:20:27 +02:00
Elian Doran
3514e3d057 fix(floating_buttons): wrong position when at the top of the note 2025-12-09 11:46:16 +02:00
Elian Doran
fb6c82740c chore(ribbon): remove top transition completely 2025-12-09 11:38:04 +02:00
Elian Doran
8df5a010c9 fix(ribbon): note buttons cut off 2025-12-09 11:36:00 +02:00
Elian Doran
895e9b8bf0 chore(client/layout): reduce transitions 2025-12-09 11:30:18 +02:00
Elian Doran
bfcf85e0d2 fix(client/layout): content header height not properly resized when switching notes 2025-12-09 11:27:05 +02:00
Elian Doran
5770222304 fix(client/floating_buttons): clipped by floating content header 2025-12-09 11:08:28 +02:00
Elian Doran
d5d2815bdf fix(client/floating_buttons): clipped by ribbon 2025-12-09 09:20:31 +02:00
Elian Doran
7fc3d413e5 fix(client): 1px scroll in full-height note 2025-12-09 09:13:18 +02:00
Elian Doran
474228b630 style(client): remove bottom border & box-shadow for content header 2025-12-09 08:22:51 +02:00
Elian Doran
0805e077a1 feat(ribbon): basic implementation for scroll pinning 2025-12-09 08:18:27 +02:00
Elian Doran
6b059a9a75 feat(ribbon): context menu for root item 2025-12-09 08:01:52 +02:00
Elian Doran
7377e4e34d chore(ribbon): improve paddings slightly 2025-12-09 07:58:59 +02:00
Elian Doran
6fac947d9c chore(ribbon): address requested changes 2025-12-09 07:50:21 +02:00
Elian Doran
5973e5ca26 chore(ribbon): remove label for the root entirely 2025-12-09 07:46:46 +02:00
Nriver
5907b7090e fix note title color for legacy themes 2025-12-09 10:49:28 +08:00
Elian Doran
6570a55e7e Translations update from Hosted Weblate (#7993) 2025-12-08 23:56:13 +02:00
Elian Doran
608ab53933 chore(ribbon): reduce note title padding 2025-12-08 23:41:17 +02:00
Elian Doran
05679f7a8d feat(ribbon): prototype sticky ribbon 2025-12-08 23:33:55 +02:00
noobhjy
f4838bb3b5 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.1% (115 of 116 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/zh_Hans/
2025-12-08 21:21:24 +00:00
pythaac
edb2a65196 Translated using Weblate (Korean)
Currently translated at 61.8% (94 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-12-08 21:21:23 +00:00
Hosted Weblate
fd721cac51 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-08 21:21:23 +00:00
pythaac
a1ff3cc8f7 Translated using Weblate (Korean)
Currently translated at 57.2% (87 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-12-08 21:21:21 +00:00
Adorian Doran
3fa6b264e5 style/note colors: include the original custom color 2025-12-08 23:18:14 +02:00
Elian Doran
fcf51ec6da chore(eslint): apply to .tsx as well 2025-12-08 23:14:09 +02:00
Elian Doran
d15b5f8cbc style(next): basic styling of ribbon as a floating toolbar 2025-12-08 23:13:58 +02:00
Elian Doran
ef3cbcac6d refactor(breadcrumb): fix eslint issues 2025-12-08 23:09:00 +02:00
Elian Doran
b16893c4d2 feat(breadcrumb): collapse items if the list is too big 2025-12-08 23:03:31 +02:00
Elian Doran
a365814aaa feat(breadcrumb): improve overflow slightly 2025-12-08 22:54:31 +02:00
Elian Doran
eca2116adc feat(breadcrumb): make the root note clickable 2025-12-08 22:46:04 +02:00
Elian Doran
4cfa403657 feat(breadcrumb): apply ellipsis to dropdown 2025-12-08 22:40:37 +02:00
Elian Doran
70ded4c2cd chore(breadcrumb): use bold for highlighting active entry 2025-12-08 22:38:06 +02:00
Elian Doran
3fe45db6ef feat(breadcrumb): improve overflow support 2025-12-08 22:17:49 +02:00
Elian Doran
11467775b6 feat(breadcrumb): basic overflow support 2025-12-08 22:09:46 +02:00
Elian Doran
1e5fcf635e feat(breadcrumb): show root title if it's the one active 2025-12-08 22:05:09 +02:00
Elian Doran
223ba4643f fix(breadcrumb): breadcrumb shown if there are no children 2025-12-08 21:57:51 +02:00
Elian Doran
200fd76929 feat(breadcrumb): display a checkbox for the current note 2025-12-08 21:52:36 +02:00
Elian Doran
c5c4ecd6e6 feat(breadcrumb): show current item 2025-12-08 17:04:08 +02:00
Elian Doran
bedca9f82c feat(breadcrumb): hide root icon 2025-12-08 16:45:26 +02:00
Elian Doran
adc356eff3 fix(breadcrumb): navigation on first level not working 2025-12-08 16:41:06 +02:00
Elian Doran
c4285772b3 feat(breadcrumb): basic navigation in separator 2025-12-08 16:34:40 +02:00
Elian Doran
a02235f2bd feat(breadcrumb): set up dropdown 2025-12-08 16:03:12 +02:00
Elian Doran
5f215b14c2 feat(breadcrumb): start implementing interactive breadcrumbs 2025-12-08 16:01:34 +02:00
Elian Doran
6e29fe8d58 feat(breadcrumb): hide preview 2025-12-08 15:56:03 +02:00
Elian Doran
43ceb1982d feat(breadcrumb): hide last note 2025-12-08 15:53:17 +02:00
Elian Doran
d02ec47d77 feat(breadcrumb): get breadcrumb to render 2025-12-08 15:16:06 +02:00
Elian Doran
9942950710 feat(layout): relocate title into scrollable region 2025-12-08 14:54:57 +02:00
Elian Doran
a6682be251 fix(webview): layout issues when when no webviewSrc 2025-12-08 14:21:59 +02:00
Elian Doran
baee2cd6b2 chore(scripts): add proper typechecking 2025-12-08 14:13:18 +02:00
Elian Doran
3ee8eac635 chore(readme): order languages alphabetically 2025-12-08 14:13:17 +02:00
Elian Doran
ce5a775160 Translations update from Hosted Weblate (#7991) 2025-12-08 13:22:19 +02:00
Elian Doran
2cf66d1c53 Delete CNAME 2025-12-08 12:59:39 +02:00
Hosted Weblate
eaee67d742 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-08 11:59:30 +01:00
Elian Doran
c681496b1b chore(readme): fix links to old docs 2025-12-08 12:58:48 +02:00
Elian Doran
829d3e046d chore(readme): fix links to docs 2025-12-08 12:51:07 +02:00
Elian Doran
5c8df540db chore(readme): fix language switcher links (closes #7246) 2025-12-08 12:43:00 +02:00
Elian Doran
8920e6e448 chore(readme): disable translation for language switcher 2025-12-08 12:00:30 +02:00
Elian Doran
3cb860232e Translations update from Hosted Weblate (#7990) 2025-12-08 11:57:43 +02:00
Hosted Weblate
d588518ba1 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-08 10:55:07 +01:00
Elian Doran
d6f727d17a Translations update from Hosted Weblate (#7989) 2025-12-08 11:54:51 +02:00
Wen QI
82c40302bd Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-08 10:53:50 +01:00
Andreas H.
c40c62a247 Translated using Weblate (German)
Currently translated at 99.2% (1634 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-12-08 10:53:50 +01:00
Wen QI
8048b5ebca Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.4% (1637 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-08 10:53:49 +01:00
green
03ba43df5d Translated using Weblate (Japanese)
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-08 10:53:49 +01:00
Elian Doran
a4b95b45ec chore(readme): rewrite links 2025-12-08 11:52:28 +02:00
Elian Doran
59513962fe chore(readme): add script to copy README into docs 2025-12-08 11:49:12 +02:00
Elian Doran
a201b43cde fix(launch_bar): sync status not correctly rendered 2025-12-08 11:30:33 +02:00
Elian Doran
f98c77bd16 Translations update from Hosted Weblate (#7988) 2025-12-08 09:44:13 +02:00
green
2596359b25 Translated using Weblate (Japanese)
Currently translated at 100.0% (1646 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-08 08:30:46 +01:00
minkipark
e0a0263607 Translated using Weblate (Korean)
Currently translated at 3.0% (50 of 1646 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-12-08 08:30:45 +01:00
green
2d3feedb07 Translated using Weblate (Japanese)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-12-08 08:30:45 +01:00
Hosted Weblate
af392fad3d Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-08 08:30:44 +01:00
Elian Doran
ef74490c44 chore(deps): update dependency jsonc-eslint-parser to v2.4.2 (#7982) 2025-12-08 09:30:31 +02:00
Elian Doran
b6856e18a8 fix(deps): update dependency katex to v0.16.27 (#7983) 2025-12-08 09:30:08 +02:00
renovate[bot]
de1d4424d9 fix(deps): update dependency katex to v0.16.27 2025-12-08 01:03:42 +00:00
renovate[bot]
5ec45bb575 chore(deps): update dependency jsonc-eslint-parser to v2.4.2 2025-12-08 01:02:52 +00:00
Elian Doran
cb3aced2ed docs(script): clarify originEntity and activeContext 2025-12-07 23:58:02 +02:00
Elian Doran
2f13a1ad21 fix(mind-map): show text in links between nodes on export (#7938) 2025-12-07 23:20:18 +02:00
Elian Doran
045127adee chore(vscode): add errorlens to recommendations 2025-12-07 23:11:07 +02:00
Elian Doran
db1a0c0362 i18n(client): update renamed key 2025-12-07 23:07:30 +02:00
Elian Doran
dcaf91a878 CKEditor stability improvements (#7979) 2025-12-07 22:40:52 +02:00
Elian Doran
a9209f5103 chore(ckeditor/watchdog): accidental comment 2025-12-07 22:32:06 +02:00
Elian Doran
ea613986c2 chore(server): add OpenAPI spec for to-markdown 2025-12-07 22:26:21 +02:00
Elian Doran
1ed46bd47c refactor(server): add validation for HTML/Markdown rendering 2025-12-07 22:24:14 +02:00
Elian Doran
f1ee79e75a refactor(client): inconsistent prefix for messages 2025-12-07 22:23:19 +02:00
Elian Doran
cd27160905 chore(ckeditor/watchdog): fix typecheck issues 2025-12-07 22:09:30 +02:00
Elian Doran
9ddf4a1308 feat(ckeditor/watchdog): ignore model out of bounds (closes #7739) 2025-12-07 22:00:10 +02:00
Elian Doran
a1c5ed9eb5 feat(ckeditor/watchdog): ignore parent check (closes #5776) 2025-12-07 21:59:52 +02:00
Elian Doran
7a4f19eada chore(ckeditor): revert breaking change 2025-12-07 21:34:10 +02:00
Elian Doran
397fb785d6 feat(ckeditor/watchdog): functional copy to clipboard button 2025-12-07 21:21:55 +02:00
Elian Doran
75a1fcc933 chore(dialog): fix mandatory parameter 2025-12-07 21:06:56 +02:00
Elian Doran
292cbf1383 feat(ckeditor/watchdog): add a title to the details screen 2025-12-07 21:03:39 +02:00
Elian Doran
37a14fefb3 feat(ckeditor/watchdog): improve layout of info dialog 2025-12-07 21:01:56 +02:00
Elian Doran
f424633d8c feat(ckeditor/watchdog): improve dialog size 2025-12-07 20:59:53 +02:00
Elian Doran
048258d2d1 feat(toast): improve button layout 2025-12-07 20:59:41 +02:00
Elian Doran
f779108b6c feat(ckeditor/watchdog): add a more details button 2025-12-07 20:40:29 +02:00
Elian Doran
522f3ae0a1 feat(toast): support buttons 2025-12-07 20:39:27 +02:00
Elian Doran
3fc7067c59 feat(dialog): support React nodes in info dialog 2025-12-07 20:39:11 +02:00
Elian Doran
c600e8ef89 feat(ckeditor/watchdog): add a toast to indicate the error 2025-12-07 20:16:34 +02:00
Elian Doran
5ad267fe1b chore(ckeditor): try to disable watchdog timer 2025-12-07 20:09:56 +02:00
Elian Doran
d8b3e438f8 chore(ckeditor): solve a few eslint warnings 2025-12-07 19:46:06 +02:00
Elian Doran
2834af66e9 feat(ckeditor/watchdog): restore focus after crash 2025-12-07 19:36:46 +02:00
Elian Doran
1bbf86fbeb feat(ckeditor/watchdog): use data stored in the spaced update 2025-12-07 19:30:35 +02:00
Elian Doran
f662b95dc9 chore(vscode): remove now unnecessary extension recommendations 2025-12-07 19:03:05 +02:00
Elian Doran
9ad4b725ac chore(eslint): report missing semicolons 2025-12-07 00:42:25 +02:00
Elian Doran
0182c61aec chore(vscode): mark all eslint rules as warnings 2025-12-07 00:42:00 +02:00
Elian Doran
78362535c7 chore(eslint): downgrade import sorting to warning 2025-12-07 00:36:39 +02:00
Elian Doran
ae7b31f343 chore(dx): trim trailing whitespace in CSS 2025-12-07 00:35:28 +02:00
Elian Doran
f16441bba4 Port toast to React (#7975) 2025-12-07 00:34:25 +02:00
Elian Doran
d3f9bb6def chore(toast): address requested changes 2025-12-07 00:33:37 +02:00
Elian Doran
e02440aa59 fix(toast): persistent toasts no longer working 2025-12-07 00:20:56 +02:00
Elian Doran
f1d87c29d3 chore(toast): fix typecheck issues 2025-12-07 00:15:00 +02:00
Elian Doran
21335b1b00 refactor(toast): get rid of autohide 2025-12-07 00:07:43 +02:00
Elian Doran
7463570e76 refactor(toast): rename delay to timeout 2025-12-07 00:06:42 +02:00
Elian Doran
da17a63ef5 refactor(toast): get rid of closeAfter in favor of delay 2025-12-07 00:04:12 +02:00
Elian Doran
eb8f2021cb fix(toast): add fallback if icon doesn't start with bx- 2025-12-06 23:49:56 +02:00
Elian Doran
888ff33be1 fix(toast): missing message icon 2025-12-06 23:46:21 +02:00
Elian Doran
b46850e86e refactor(toast): relocate styles into own file 2025-12-06 23:38:40 +02:00
Elian Doran
f053587f09 chore(toast): port toast to react 2025-12-06 23:37:56 +02:00
Elian Doran
7a3092a23b fix(read-only-bar): button shrinks when window is small 2025-12-06 23:00:57 +02:00
Elian Doran
d95450ae07 feat(client): detect communication errors with Traefik 2025-12-06 22:57:13 +02:00
Elian Doran
230def10fe feat(client): improve error message for HTTP errors 2025-12-06 22:12:06 +02:00
Elian Doran
036f8e49a4 docs(server/proxy): breaking change in Traefik 3.6.4 2025-12-06 21:51:56 +02:00
Elian Doran
4eca8a5640 feat(dx): add a way to run traefik reverse proxy 2025-12-06 21:37:24 +02:00
Elian Doran
08f96a91f3 docs(readme): fix a space 2025-12-06 19:37:25 +02:00
Elian Doran
2e915eccd6 Clean up _regroup (#7970) 2025-12-06 19:27:15 +02:00
Elian Doran
c05c58c82b Merge remote-tracking branch 'origin/main' into chore/cleanup_regroup 2025-12-06 19:18:23 +02:00
Elian Doran
572feed918 chore(regroup): address requested changes 2025-12-06 19:17:56 +02:00
Elian Doran
d30d207ab5 test(server): solve some local timeouts 2025-12-06 19:08:19 +02:00
Elian Doran
2a6b91dd04 chore(regroup): reintroduce code coverage 2025-12-06 19:08:03 +02:00
Elian Doran
3dee1725b3 chore(regroup): reintroduce old e2e tests 2025-12-06 18:54:38 +02:00
Elian Doran
f7ac465e67 chore(eslint): integrate preact config 2025-12-06 15:31:38 +02:00
Elian Doran
912f14549c chore(eslint): integrate playwright e2e 2025-12-06 15:20:05 +02:00
Elian Doran
21079335e7 chore(eslint): remove unnecessary files 2025-12-06 14:58:38 +02:00
Elian Doran
85741240f1 chore(eslint): reintegrate simple import sort 2025-12-06 14:50:41 +02:00
Elian Doran
3df9a87b29 chore(eslint): clean up unnecessary dependency in client 2025-12-06 14:48:00 +02:00
Elian Doran
acd60007ac chore(eslint): integrate formatter config 2025-12-06 14:43:08 +02:00
Elian Doran
f66c9630e3 chore(deps): update dependency vite to v7.2.6 (#7951) 2025-12-06 12:25:52 +02:00
Elian Doran
50a5892a31 chore(deps): update typescript-eslint monorepo to v8.48.1 (#7953) 2025-12-06 12:25:14 +02:00
renovate[bot]
c5f58437b1 chore(deps): update typescript-eslint monorepo to v8.48.1 2025-12-06 10:10:32 +00:00
Elian Doran
a915424d9a chore(deps): update softprops/action-gh-release action to v2.5.0 (#7958) 2025-12-06 12:10:09 +02:00
renovate[bot]
be7699c600 chore(deps): update dependency vite to v7.2.6 2025-12-06 10:09:14 +00:00
Elian Doran
a7c946ddae fix(deps): update codemirror themes (#7955) 2025-12-06 12:08:43 +02:00
Elian Doran
4b741a9434 chore(deps): update dependency openai to v6.10.0 (#7957) 2025-12-06 12:07:52 +02:00
Elian Doran
cd963272d4 chore(deps): update vitest monorepo to v4.0.15 (#7954) 2025-12-06 12:07:11 +02:00
Elian Doran
9de17ead91 Translations update from Hosted Weblate (#7966) 2025-12-06 12:05:21 +02:00
pythaac
d98b133d63 Translated using Weblate (Korean)
Currently translated at 52.6% (80 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-12-06 11:04:27 +01:00
Elian Doran
361e8e0066 chore(deps): update dependency electron to v39 (#7536) 2025-12-06 12:04:20 +02:00
Elian Doran
523c44b796 fix(deps): update dependency mermaid to v11.12.2 (#7956) 2025-12-06 11:53:14 +02:00
Elian Doran
4bd60ed6a1 chore(deps): update react monorepo to v19.2.1 (#7952) 2025-12-06 11:52:11 +02:00
Elian Doran
7d57f08baf chore(deps): update dependency express to v5.2.1 (#7950) 2025-12-06 11:35:10 +02:00
Elian Doran
5e7f54dbc3 chore(deps): update dependency esbuild to v0.27.1 (#7949) 2025-12-06 11:34:36 +02:00
Elian Doran
dfb9ce990d chore(eslint): basic config 2025-12-06 11:05:34 +02:00
Elian Doran
e87a368e87 chore(regroup): remove some redundant files 2025-12-06 10:52:41 +02:00
Elian Doran
44506057fd chore(regroup): clean bin dir 2025-12-06 10:50:42 +02:00
Elian Doran
ff08eadb23 fix(server/scripts): generate-document failing (closes #5422) 2025-12-06 10:49:14 +02:00
Elian Doran
ebb1a3feb2 chore(regroup): integrate generate_document 2025-12-06 10:35:57 +02:00
Elian Doran
81bc85b8e4 chore(regroup): adapt export-schema script 2025-12-06 10:29:08 +02:00
Elian Doran
4a749f52e9 chore(regroup): remove old release scripts 2025-12-06 10:11:28 +02:00
Elian Doran
25e37ddd78 chore(regroup): relocate icon scripts 2025-12-06 10:07:23 +02:00
renovate[bot]
46a9cfcc67 chore(deps): update react monorepo to v19.2.1 2025-12-06 08:00:01 +00:00
Elian Doran
66ff944660 chore(deps): update dependency @types/reveal.js to v5.2.2 (#7948) 2025-12-06 09:58:15 +02:00
Elian Doran
988db59197 chore(deps): update dependency @smithy/middleware-retry to v4.4.14 (#7947) 2025-12-06 09:57:54 +02:00
Elian Doran
34e321407a chore(deps): update dependency @redocly/cli to v2.12.3 (#7946) 2025-12-06 09:57:31 +02:00
Elian Doran
44c0028a51 chore(regroup): clean up translation scripts 2025-12-06 09:43:54 +02:00
Elian Doran
264b75cd68 chore(regroup): clean up migration scripts 2025-12-06 09:43:02 +02:00
renovate[bot]
cf9ccdcab6 chore(deps): update dependency electron to v39 2025-12-06 07:36:35 +00:00
renovate[bot]
48e18e533c chore(deps): update dependency openai to v6.10.0 2025-12-06 07:35:53 +00:00
renovate[bot]
12ef778bf4 fix(deps): update dependency mermaid to v11.12.2 2025-12-06 07:35:15 +00:00
Elian Doran
6c31a1788a Port launch bar to React (#7934) 2025-12-06 09:35:06 +02:00
renovate[bot]
aa7c6da8ef fix(deps): update codemirror themes 2025-12-06 07:34:30 +00:00
renovate[bot]
1ff40cace0 chore(deps): update vitest monorepo to v4.0.15 2025-12-06 07:33:52 +00:00
renovate[bot]
0a1dadbea1 chore(deps): update dependency express to v5.2.1 2025-12-06 07:30:48 +00:00
renovate[bot]
24edbdba5e chore(deps): update dependency esbuild to v0.27.1 2025-12-06 07:30:09 +00:00
renovate[bot]
db504eff88 chore(deps): update dependency @types/reveal.js to v5.2.2 2025-12-06 07:29:26 +00:00
renovate[bot]
5e09925659 chore(deps): update dependency @smithy/middleware-retry to v4.4.14 2025-12-06 07:28:42 +00:00
renovate[bot]
d1b2b351c8 chore(deps): update dependency @redocly/cli to v2.12.3 2025-12-06 07:28:02 +00:00
Elian Doran
50b0dc178e chore(regroup): clean up old ETAPI tests
They are already integrated in apps/server/spec/etapi.
2025-12-06 09:27:56 +02:00
Elian Doran
b34118e395 fix(deps): update ckeditor monorepo to v47.3.0 (#7959) 2025-12-06 09:26:03 +02:00
Elian Doran
e6436f9021 fix(text): code block background not correct 2025-12-06 09:16:20 +02:00
Elian Doran
831d1b4f3a chore(text): remove workaround for superscript icon 2025-12-06 09:15:40 +02:00
renovate[bot]
0456d1ca29 fix(deps): update ckeditor monorepo to v47.3.0 2025-12-06 07:04:27 +00:00
Elian Doran
fcd151022e fix(deps): update dependency i18next to v25.7.1 (#7960) 2025-12-06 08:59:19 +02:00
Elian Doran
0c1998002e fix(deps): update dependency preact to v10.28.0 (#7961) 2025-12-06 08:58:33 +02:00
Elian Doran
b8c33ce7fa e2e(server): locator failing due to removal of "visible" 2025-12-06 08:54:35 +02:00
Elian Doran
454cd633e8 fix(read_only_text): missing padding in <pre> without <code> 2025-12-06 08:46:44 +02:00
renovate[bot]
53cb9a6e10 fix(deps): update dependency preact to v10.28.0 2025-12-06 06:43:06 +00:00
renovate[bot]
8d6ff763d6 fix(deps): update dependency i18next to v25.7.1 2025-12-06 06:42:29 +00:00
Elian Doran
ecf15af3a0 fix(deps): update dependency react-i18next to v16.4.0 (#7962) 2025-12-06 08:38:20 +02:00
Elian Doran
716823789d chore(deps): update apple-actions/import-codesign-certs action to v6 (#7963) 2025-12-06 08:37:58 +02:00
Elian Doran
3c192badce chore(deps): update dependency @anthropic-ai/sdk to v0.71.2 (#7945) 2025-12-06 08:37:04 +02:00
renovate[bot]
d94b611d10 chore(deps): update apple-actions/import-codesign-certs action to v6 2025-12-06 02:54:20 +00:00
renovate[bot]
e2ce329b6c fix(deps): update dependency react-i18next to v16.4.0 2025-12-06 02:54:16 +00:00
renovate[bot]
ef902fc706 chore(deps): update softprops/action-gh-release action to v2.5.0 2025-12-06 02:51:28 +00:00
renovate[bot]
a7fc94c303 chore(deps): update dependency @anthropic-ai/sdk to v0.71.2 2025-12-06 02:42:34 +00:00
Elian Doran
c8c6d1bb1e docs(user): document launch bar widgets 2025-12-05 23:24:18 +02:00
Elian Doran
a205108681 chore(react/launch_bar): address requested changes 2025-12-05 22:57:07 +02:00
Elian Doran
31561879b3 chore(launch_bar): address requested changes 2025-12-05 19:40:36 +02:00
Elian Doran
fdb6677153 chore(launch_bar): reintroduce keyboard shortcuts 2025-12-05 19:23:40 +02:00
Elian Doran
17241be4bc fix(launch_bar): note context not properly set for legacy widgets 2025-12-05 18:01:46 +02:00
Elian Doran
3bf6de9c76 fix(launch_bar): calendar month selector dropdown wrongly positioned 2025-12-05 17:36:04 +02:00
Elian Doran
a53322e7cb refactor(launch_bar): deduplicate launcher note props 2025-12-05 17:16:55 +02:00
Elian Doran
a107c126e4 fix(launch_bar): dynamic dropdown not repositioning 2025-12-05 17:11:53 +02:00
Elian Doran
3a8dcae53a fix(launch_bar): wrong position of dropdown 2025-12-05 16:45:38 +02:00
Elian Doran
b99d4532df fix(react): duplicate tooltips on focus vs hover 2025-12-05 16:39:55 +02:00
Elian Doran
6e8f8ea357 fix(launch_bar): horizontal launch bar scrolling with dropdown open 2025-12-05 15:53:17 +02:00
Elian Doran
83838bbe76 fix(launch_bar): calendar month selector not actually working 2025-12-05 15:50:25 +02:00
Elian Doran
66620aabe2 fix(launch_bar): calendar dropdown hiding on month selection 2025-12-05 15:43:44 +02:00
Elian Doran
74fcf8270d chore(launch_bar): improve positioning of the month dropdown 2025-12-05 15:31:14 +02:00
Elian Doran
91b4e32a38 fix(launch_bar): calendar month selector clipped 2025-12-05 15:29:25 +02:00
Elian Doran
3f0c114f24 fix(launch_bar): handle week number wrap-around for next year in calendar 2025-12-05 15:17:51 +02:00
Elian Doran
30fe6b93c4 chore(launch_bar): remove now redundant file 2025-12-05 15:10:48 +02:00
Elian Doran
ec99242314 fix(launch_bar): dropdown tooltip visible when hovering popup 2025-12-05 15:06:55 +02:00
Elian Doran
9149fb7a85 fix(launch_bar): tooltip error for dropdowns 2025-12-05 15:02:13 +02:00
Elian Doran
3c919d9a8a fix(launch_bar): global menu size 2025-12-05 14:52:57 +02:00
Elian Doran
22f9ce1e2e Merge remote-tracking branch 'origin/main' into react/launch_bar 2025-12-05 12:22:36 +02:00
Elian Doran
72b01cec70 Merge branch 'stable' 2025-12-05 12:22:14 +02:00
Elian Doran
982fb212e4 docs(release): update change log for #7939 2025-12-05 12:19:12 +02:00
Elian Doran
9fcee9cc53 Fix (NoteMap): map overflows when switching type in ribbon (#7939) 2025-12-05 12:17:08 +02:00
Elian Doran
57b8bc2645 feat(launch_bar): faster tooltips 2025-12-05 12:12:02 +02:00
Elian Doran
3ad4ca3943 fix(launch_bar): bootstrap tooltip for dropdown 2025-12-05 12:06:53 +02:00
Elian Doran
237ffeff52 fix(launch_bar): title position of action buttons 2025-12-05 12:04:26 +02:00
Elian Doran
fb491d9790 Fix (NoteMap): map overflows when switching type in ribbon (#7939) 2025-12-05 11:59:08 +02:00
Elian Doran
facd03b6ad feat(launch_bar): horizontal scroll using mouse wheel 2025-12-05 11:54:31 +02:00
Elian Doran
f5f38ca670 refactor(widgets): relocate AI chat button 2025-12-05 11:53:38 +02:00
Elian Doran
83e599f0e9 refactor(widgets): relocate note launcher & command button 2025-12-05 11:52:52 +02:00
Elian Doran
48cd06f37e feat(bundle): improve error handling message 2025-12-05 11:49:09 +02:00
Elian Doran
aac9d2d1c4 fix(toast): icon missing for error messages 2025-12-05 11:45:02 +02:00
Elian Doran
7e2e1c12b9 chore(widgets): fix error icon in toast & improve message reporting 2025-12-05 11:42:56 +02:00
Elian Doran
3410dd4eba chore(react/launch_bar): bring back reporting widget that failed 2025-12-05 11:40:50 +02:00
Elian Doran
d511085db3 chore(react/launch_bar): port launcher container & launcher 2025-12-05 11:31:52 +02:00
Elian Doran
caaa3583a7 chore(react/launch_bar): port sync status 2025-12-05 10:22:34 +02:00
Elian Doran
185e5691a4 chore(react/launch_bar): bring back week highlighting 2025-12-05 09:52:46 +02:00
Elian Doran
20f44cc64f chore(react/launch_bar): reimplement week notes 2025-12-05 09:36:21 +02:00
SiriusXT
07ef94afd9 Merge branch 'main' into fix/note_map 2025-12-05 15:21:30 +08:00
SiriusXT
2d33b8a958 fix(note_map): initialize map state when switching map type in ribbon 2025-12-05 15:21:06 +08:00
Elian Doran
d283f5dbb4 chore(react/launch_bar): hide dropdown when selecting date 2025-12-05 09:15:01 +02:00
Elian Doran
1af76c4d06 chore(react/launch_bar): clicking on calendar days 2025-12-05 09:11:50 +02:00
Elian Doran
07498c6bef chore(react/launch_bar): add link to existing days 2025-12-05 09:02:51 +02:00
Elian Doran
18f9ebbc4f chore(react/launch_bar): reintroduce day highlighting 2025-12-05 08:56:35 +02:00
SiriusXT
85b4f652f4 chore(note_map): improve the icon for expanding/collapsing the map 2025-12-05 11:21:44 +08:00
SiriusXT
eec6f7336c fix (note_map): map overflows when switching map type in ribbon 2025-12-05 11:21:33 +08:00
Lucas
f976dd8d30 Apply suggestions from code review
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-04 13:08:28 -08:00
Lucas
2d3aa3a96e Merge branch 'main' into main 2025-12-04 13:04:24 -08:00
Elian Doran
1195cbd772 Translations update from Hosted Weblate (#7937) 2025-12-04 22:59:00 +02:00
Hosted Weblate
cebfa674ef Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-04 21:56:39 +01:00
Elian Doran
3ed596496d Merge branch 'main' of github.com:TriliumNext/Trilium 2025-12-04 22:56:20 +02:00
Elian Doran
d99ef78348 fix(client): find and replace in floating toolbar 2025-12-04 22:56:15 +02:00
lzinga
2666c1e196 feat(snapdom): update screenshot generation options for SVG and PNG exports 2025-12-04 12:52:01 -08:00
Lucas
4b8c8888ee Merge branch 'TriliumNext:main' into main 2025-12-04 12:49:37 -08:00
lzinga
ce1fd64aa9 feat(export): enhance SVG and PNG export functionality with snapdom integration 2025-12-04 12:49:10 -08:00
Elian Doran
bd1479b14a Translations update from Hosted Weblate (#7935) 2025-12-04 22:32:47 +02:00
Elian Doran
baee9520d1 Apply suggestion from @gemini-code-assist[bot]
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-04 22:32:08 +02:00
green
adb30a526e Translated using Weblate (Japanese)
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-04 21:27:44 +01:00
noobhjy
60c40457fc Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-04 21:27:43 +01:00
noobhjy
a6df457c9c Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-04 21:27:42 +01:00
Francis C.
3fd8fb0308 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-04 21:27:41 +01:00
Elian Doran
7d4a7d4ab6 feat(dev): option to crash CKEditor 2025-12-04 22:15:13 +02:00
Elian Doran
4571b95683 chore(react/launch_bar): fix style for month selector 2025-12-04 21:37:02 +02:00
Elian Doran
a65d2a1bba chore(react/launch_bar): reintroduce year selector 2025-12-04 21:24:35 +02:00
lzinga
5c9503732d fix(mind-map): show text in links between nodes on export 2025-12-04 11:08:44 -08:00
Elian Doran
2dbbf7f350 chore(react/launch_bar): reintroduce month dropdown 2025-12-04 20:13:46 +02:00
Elian Doran
e1cce220b3 chore(react/launch_bar): add back icons for previous/next month 2025-12-04 19:56:44 +02:00
Elian Doran
e0aed26f63 refactor(react/launch_bar): extract calendar impl into single file 2025-12-04 19:46:25 +02:00
Elian Doran
62fd07258e chore(react/launch_bar): get days of the week to render 2025-12-04 19:43:47 +02:00
Elian Doran
0d8127140f chore(react/launch_bar): get week numbers to render 2025-12-04 19:38:56 +02:00
Elian Doran
bab5326d7c refactor(react/launch_bar): use different mechanism for gathering calendar info 2025-12-04 19:22:28 +02:00
Elian Doran
5c8445f3fe chore(react/launch_bar): get calendar to render days 2025-12-04 19:03:28 +02:00
Elian Doran
604488b166 chore(react/launch_bar): port custom widget 2025-12-04 17:55:38 +02:00
Elian Doran
b7d7fc8b67 chore(react/launch_bar): remove an old file 2025-12-04 17:17:41 +02:00
Elian Doran
1f4872f72b chore(react/launch_bar): port script launcher 2025-12-04 17:16:47 +02:00
Elian Doran
f89c40cde6 fix(react/launch_bar): type error in bookmarks 2025-12-04 17:07:13 +02:00
Elian Doran
670edbc22a chore(react/launch_bar): port quick search launcher 2025-12-04 17:01:35 +02:00
Elian Doran
54f70c8158 chore(react/launch_bar): port today launcher 2025-12-04 16:53:05 +02:00
Elian Doran
0d6bcba023 chore(react/launch_bar): port note launcher 2025-12-04 16:33:58 +02:00
Elian Doran
06a9f95979 chore(react/launch_bar): remove old file 2025-12-04 16:23:14 +02:00
Elian Doran
03cdfc259e refactor(react/launch_bar): deduplicate launcher icon and title 2025-12-04 16:22:46 +02:00
Elian Doran
1963b5732a refactor(react/launch_bar): extract note launcher from bookmark button 2025-12-04 16:13:16 +02:00
Elian Doran
1e05dc937c refactor(react/launch_bar): port command buttons 2025-12-04 16:04:14 +02:00
Elian Doran
c3b22ff737 refactor(react/launch_bar): port protected session status widget 2025-12-04 15:54:27 +02:00
Elian Doran
991f07e148 refactor(react/launch_bar): port ai chat button 2025-12-04 15:47:42 +02:00
Elian Doran
8efb849391 refactor(react/launch_bar): port history navigation 2025-12-04 15:44:10 +02:00
Elian Doran
5b310f3e46 refactor(react/launch_bar): port spacer 2025-12-04 15:02:46 +02:00
Elian Doran
5f54e42a43 refactor(react/launch_bar): extract icon class 2025-12-04 14:47:30 +02:00
Elian Doran
a83f20e454 refactor(react/launch_bar): extract dropdown & button style 2025-12-04 14:46:23 +02:00
Elian Doran
cdab86bd83 chore(react/launch_bar): port bookmark_folder 2025-12-04 14:41:07 +02:00
Elian Doran
48cbb80e79 chore(react/launch_bar): port open_note_button_widget 2025-12-04 14:18:04 +02:00
Elian Doran
1af6200655 chore(react/launch_bar): get launch bar to render React widgets 2025-12-04 13:24:47 +02:00
Elian Doran
b8585594cd fix(text): duplicate search dialogs (closes #5735) 2025-12-04 13:03:08 +02:00
Elian Doran
d173cc982c chore(release): prepare for v0.100.0 2025-12-04 12:21:40 +02:00
Elian Doran
471c57b3ed docs(release): changelog for v0.100.0 2025-12-04 10:43:34 +02:00
Elian Doran
093d7d783b fix(promoted_attributes): value sometimes empty when reopening note 2025-12-04 10:38:07 +02:00
Elian Doran
7cc20600e7 Disable spell-check on code-snippets (#7929) 2025-12-04 07:47:02 +00:00
Elian Doran
559c654fbb fix(promoted_attributes): not reacting to inheritable changes 2025-12-04 09:44:54 +02:00
Elian Doran
01a03e3e97 docs(user): mark #calendar:color as completely removed 2025-12-04 09:27:17 +02:00
Elian Doran
dd3233a556 docs(user): document calendar interaction on mobile 2025-12-04 09:22:25 +02:00
Elian Doran
c4a426566f feat(collections/calendar): change click behaviour on mobile 2025-12-04 09:09:23 +02:00
Elian Doran
c081a596df Unify Dayjs between client and server (#7930) 2025-12-04 07:08:11 +00:00
Elian Doran
6b07908cf7 chore(server): fix some more dependencies to JSON 2025-12-04 08:45:28 +02:00
Elian Doran
2985bd0a1c chore(dayjs): fix typecheck 2025-12-03 23:29:38 +02:00
Lucas
975e8487fc Merge branch 'TriliumNext:main' into main 2025-12-03 12:59:47 -08:00
Elian Doran
54408d3ec8 chore(dayjs): address requested changes 2025-12-03 22:24:30 +02:00
Elian Doran
8b3afc1f49 fix(share): reference links outside share appear as [missing note] 2025-12-03 22:22:10 +02:00
Elian Doran
e15bc5a232 Merge branch 'main' into main 2025-12-03 20:05:00 +00:00
Elian Doran
8fdda59440 Merge branch 'main' into feature/unify_dayjs 2025-12-03 20:04:48 +00:00
Elian Doran
d5cbf362f8 test(client): fix typecheck issue 2025-12-03 22:04:39 +02:00
Elian Doran
6f85d3370c docs(technical): dayjs intro & supported plugins 2025-12-03 22:01:06 +02:00
Elian Doran
8c324cd185 test(client): running script bundle with dayjs 2025-12-03 21:44:34 +02:00
Elian Doran
f7f7fda040 feat(dayjs): enable duration plugin (closes #4456) 2025-12-03 21:26:10 +02:00
Elian Doran
74c11f4d4e chore(test): warning of unsupported requests 2025-12-03 21:15:16 +02:00
Elian Doran
0525cfab79 feat(client): set dayjs locale 2025-12-03 21:10:54 +02:00
Elian Doran
2d73627908 test(dayjs): add a test for all plugins 2025-12-03 20:58:52 +02:00
Elian Doran
94d015789d test(dayjs): relocate dayjs tests into commons 2025-12-03 20:54:35 +02:00
Elian Doran
af2f6246e8 chore(commons): tests not run 2025-12-03 20:49:57 +02:00
Elian Doran
ebbdf0294a refactor(dayjs): relocate locale loading in commons 2025-12-03 20:49:15 +02:00
Elian Doran
5df539f0a4 refactor(dayjs): relocate all plugins and imports to commons 2025-12-03 20:44:48 +02:00
lzinga
4f6dfeb773 fixed whitespace and redundant lines. 2025-12-03 10:12:05 -08:00
lzinga
52bb83e878 feat(plugins): add InlineCodeNoSpellcheck plugin to disable spellcheck for inline code 2025-12-03 10:02:35 -08:00
Elian Doran
286a8626d1 Translations update from Hosted Weblate (#7928) 2025-12-03 17:54:26 +00:00
Elian Doran
aa62dc3f32 Translated using Weblate (Romanian)
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-12-03 17:52:47 +00:00
Elian Doran
045e7977d5 fix(map): markers disappearing due to infinite map 2025-12-03 19:51:01 +02:00
Elian Doran
e0dc25ad23 fix(print): fails if included note could not be found 2025-12-03 19:16:58 +02:00
Elian Doran
9d0499a306 fix(note_actions): print disabled not reacting to note type changes 2025-12-03 19:06:20 +02:00
Elian Doran
b971e002ce chore(tree_context_menu): clarify "Convert to attachment" message 2025-12-03 18:56:49 +02:00
Elian Doran
5fd488e210 feat(tree_context_menu): disable "Convert to attachment" if no eligible notes 2025-12-03 18:55:10 +02:00
Elian Doran
eb84da4c51 fix(code): too much padding 2025-12-03 18:47:14 +02:00
Elian Doran
49243148a2 fix(note_list): note list shown when switching types (e.g. for mindmap) 2025-12-03 18:40:24 +02:00
Elian Doran
276241cdff style(attachment): basic attachment card design 2025-12-03 18:29:49 +02:00
Elian Doran
6772453b3a fix(attachment): duplicate padding in code blocks 2025-12-03 18:23:31 +02:00
Elian Doran
18e2f1f90c fix(attachment): attachment content overlapping 2025-12-03 18:22:52 +02:00
Elian Doran
67d2175ce9 Translations update from Hosted Weblate (#7924) 2025-12-03 08:46:09 +00:00
Elian Doran
8a3283f1ea Update apps/client/src/translations/it/translation.json
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-03 08:45:42 +00:00
green
2fb47fc186 Translated using Weblate (Japanese)
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-03 09:18:16 +01:00
Giovi
4530c9a40c Translated using Weblate (Italian)
Currently translated at 100.0% (1636 of 1636 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-03 09:18:15 +01:00
Elian Doran
a867a25d5f fix(markdown): show 'import successful' when canceling markdown import (#7899) 2025-12-02 12:11:25 +00:00
Elian Doran
10910ac2ed fix(backlinks): list not refreshing & not reacting to all changes 2025-12-02 13:30:37 +02:00
Elian Doran
514f5a0c81 chore(markdown_import): don't display anything on empty input 2025-12-02 12:26:47 +02:00
Elian Doran
6b18ed6477 refactor(markdown_import): deduplicate submit 2025-12-02 12:24:22 +02:00
Elian Doran
e07b6cc409 Merge remote-tracking branch 'origin/main' into fix/markdown
; Conflicts:
;	apps/client/src/stylesheets/style.css
2025-12-02 12:20:01 +02:00
Elian Doran
5ae67fda7f fix(ckeditor/math): math can be inserted in code blocks (closes #7913) 2025-12-02 12:13:40 +02:00
Elian Doran
1a03c0ca9f fix(collections/calendar): events not updating sometimes 2025-12-02 10:56:58 +02:00
Elian Doran
dc211b4d00 fix(ckeditor): markdown icon broken due to a workaround 2025-12-02 10:27:13 +02:00
Elian Doran
2e767ffde1 fix(ribbon): formatting toolbar not showing up if focus on edited notes is active 2025-12-02 10:13:54 +02:00
Elian Doran
9f74a54c0d fix(react/type_widgets): revision causes jump at start of editor (closes #7912) 2025-12-02 10:06:08 +02:00
Elian Doran
a7870495ac docs(user): mention split focus 2025-12-02 09:44:20 +02:00
Elian Doran
a8ec323ea8 docs(user): document split functionality on mobile 2025-12-02 09:42:38 +02:00
Elian Doran
4b7d243406 Prototype/mobile split (#7906) 2025-12-02 07:35:34 +00:00
Elian Doran
1855588270 chore(client): fix missing argument in context menu 2025-12-02 09:02:11 +02:00
Elian Doran
e545e0c3a5 Translations update from Hosted Weblate (#7919) 2025-12-02 06:50:19 +00:00
Hosted Weblate
b24a0f1595 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-02 06:48:51 +00:00
Elian Doran
3f2bfc3050 docs: add comprehensive AI coding agent instructions for copilot-instructions (#7917) 2025-12-02 06:48:40 +00:00
Elian Doran
66f100d534 chore(i18n/client): remove two unused messages 2025-12-02 08:46:53 +02:00
Elian Doran
e641d5ba0f Translations update from Hosted Weblate (#7911) 2025-12-02 06:46:23 +00:00
Marble127
6f8cebf954 Translated using Weblate (Dutch)
Currently translated at 26.2% (31 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/nl/
2025-12-02 07:26:27 +01:00
Marble127
2d2f2457cb Translated using Weblate (Dutch)
Currently translated at 3.2% (53 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/nl/
2025-12-02 07:26:26 +01:00
Marble127
68fa243af4 Translated using Weblate (Dutch)
Currently translated at 12.8% (50 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/nl/
2025-12-02 07:26:25 +01:00
Marble127
9cb133c8a6 Translated using Weblate (Dutch)
Currently translated at 20.3% (31 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/nl/
2025-12-02 07:26:25 +01:00
green
33f6c75917 Translated using Weblate (Japanese)
Currently translated at 100.0% (1639 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-02 07:26:24 +01:00
Lluís Forns
49acd5e8c2 Translated using Weblate (Catalan)
Currently translated at 6.8% (112 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ca/
2025-12-02 07:26:23 +01:00
Elian Doran
85266adf20 Translated using Weblate (Spanish)
Currently translated at 99.6% (1633 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-12-02 07:26:22 +01:00
Elian Doran
27edea8380 Translated using Weblate (French)
Currently translated at 98.3% (1612 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-12-02 07:26:22 +01:00
Elian Doran
dccddb8d43 Translated using Weblate (Portuguese)
Currently translated at 94.6% (1551 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt/
2025-12-02 07:26:21 +01:00
Elian Doran
5f9d7a223a Translated using Weblate (Arabic)
Currently translated at 64.0% (1049 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ar/
2025-12-02 07:26:20 +01:00
Elian Doran
29b71262d6 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 99.8% (1636 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-02 07:26:20 +01:00
Lluís Forns
0cfcbcf5df Translated using Weblate (Catalan)
Currently translated at 1.6% (2 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ca/
2025-12-02 07:26:19 +01:00
Elian Doran
e1258384d8 Translated using Weblate (Polish)
Currently translated at 31.1% (511 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pl/
2025-12-02 07:26:18 +01:00
Lluís Forns
8837eddd40 Translated using Weblate (Catalan)
Currently translated at 18.2% (71 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ca/
2025-12-02 07:26:17 +01:00
Lluís Forns
f919d46e9a Translated using Weblate (Catalan)
Currently translated at 2.6% (4 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ca/
2025-12-02 07:26:16 +01:00
Elian Doran
98094fac63 Translated using Weblate (Italian)
Currently translated at 99.7% (1635 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-02 07:26:15 +01:00
Elian Doran
f94ccee252 Translated using Weblate (German)
Currently translated at 99.8% (1637 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-12-02 07:26:14 +01:00
Elian Doran
7c4b338539 Translated using Weblate (Russian)
Currently translated at 97.3% (1595 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ru/
2025-12-02 07:26:14 +01:00
Elian Doran
d88431f9e3 Translated using Weblate (Ukrainian)
Currently translated at 97.1% (1593 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/uk/
2025-12-02 07:26:13 +01:00
Elian Doran
5f86068489 Translated using Weblate (Portuguese (Brazil))
Currently translated at 96.8% (1587 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/pt_BR/
2025-12-02 07:26:12 +01:00
Elian Doran
36bc226674 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 99.7% (1635 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-02 07:26:12 +01:00
Hosted Weblate
7947745218 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-02 07:26:11 +01:00
Hosted Weblate
19697aabfb Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-02 07:26:10 +01:00
Elian Doran
87af23598d Translated using Weblate (Romanian)
Currently translated at 99.5% (1631 of 1639 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-12-02 07:26:09 +01:00
Hosted Weblate
4ed7966a5a Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-12-02 07:26:08 +01:00
Giovi
8d86b5c7e6 Translated using Weblate (Italian)
Currently translated at 100.0% (1638 of 1638 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-12-02 07:26:07 +01:00
Elian Doran
cdf9458962 chore(deps): update dependency express to v5.2.0 [security] (#7915) 2025-12-02 06:25:40 +00:00
Lucas
83df37c2d1 Update .github/copilot-instructions.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-01 16:25:09 -08:00
Lucas
bc7b3165c8 Update .github/copilot-instructions.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-01 16:25:02 -08:00
Lucas
c332e9764a Update .github/copilot-instructions.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-12-01 16:24:50 -08:00
lzinga
004d48d36c docs: add comprehensive AI coding agent instructions for copilot-instructions 2025-12-01 16:15:43 -08:00
Elian Doran
28b263a445 chore(mobile/split): address requested changes 2025-12-01 23:51:12 +02:00
Elian Doran
e0e9310907 feat(mobile/split): rephase open in note split if a split is already open 2025-12-01 23:46:29 +02:00
renovate[bot]
68b9159b2b chore(deps): update dependency express to v5.2.0 [security] 2025-12-01 21:38:46 +00:00
Elian Doran
f5940cbf70 feat(mobile/split): hide split button if split is already open 2025-12-01 23:36:15 +02:00
Elian Doran
bfb143bb51 Merge remote-tracking branch 'origin/main' into prototype/mobile_split 2025-12-01 23:27:58 +02:00
Adorian Doran
64662d5215 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-01 16:33:41 +02:00
Adorian Doran
31cedad976 documentation: mark "calendar:color" as deprecated 2025-12-01 16:33:31 +02:00
Elian Doran
9682df6240 feat(mobile/split): collapse inactive split when keyboard is opened 2025-12-01 15:48:18 +02:00
Elian Doran
a718908385 fix(mobile/split): link context menu opening in the wrong split 2025-12-01 15:23:57 +02:00
Elian Doran
12ac5147d3 Merge branch 'main' of github.com:TriliumNext/Trilium 2025-12-01 14:40:25 +02:00
Elian Doran
17291ff61d chore(deps): remove unnecessary package 2025-12-01 14:34:55 +02:00
Adorian Doran
f3e334470e style: refactor 2025-12-01 14:27:49 +02:00
Adorian Doran
9407051f1e style: refactor 2025-12-01 14:24:13 +02:00
Adorian Doran
08a6d36153 style/calendar collection/list view: use separate style for the archived events 2025-12-01 14:13:23 +02:00
Adorian Doran
f906fb9b4c Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-01 14:08:32 +02:00
Adorian Doran
b4a6356724 style/calendar collection/list view: fix dot colors 2025-12-01 14:08:24 +02:00
Elian Doran
8eca14069a fix(e2e): i18n test failing to due to English selection 2025-12-01 14:02:32 +02:00
Elian Doran
1af0477ac0 chore(ci): fix duplicate artifact name error 2025-12-01 13:53:07 +02:00
Elian Doran
43920f12ae feat(backlinks): use proper plural 2025-12-01 13:50:59 +02:00
Elian Doran
5a0beec6cb fix(backlinks): not refreshed after inserting a new link 2025-12-01 13:37:15 +02:00
Elian Doran
98241fb54b fix(promoted_attributes): value carrying over onto new notes 2025-12-01 13:37:15 +02:00
Adorian Doran
3051664228 style: fix typo 2025-12-01 13:34:36 +02:00
Adorian Doran
1ed774365c client/Kanban board collection: reorder context menu items 2025-12-01 13:33:20 +02:00
Adorian Doran
f2e33dfd58 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-01 13:29:39 +02:00
Adorian Doran
90b5282b39 client/calendar collection: add "Archive note" command to the context menu 2025-12-01 13:29:28 +02:00
Elian Doran
d520fc46b9 fix(text): code blocks cannot wrap automatically (#7910) 2025-12-01 11:18:31 +00:00
Adorian Doran
e69b5988ec style: fix custom title bar buttons on the legacy theme 2025-12-01 11:48:42 +02:00
Adorian Doran
3cdc1ba794 style/calendar collection: fix colors on the legacy theme 2025-12-01 11:38:48 +02:00
Adorian Doran
25e1008c5c Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-12-01 11:24:52 +02:00
Adorian Doran
a093862311 style/calendar collection: use a separate style for archived notes 2025-12-01 11:24:39 +02:00
Elian Doran
53057ea9fc Translations update from Hosted Weblate (#7907) 2025-12-01 08:09:22 +00:00
Francis C.
94db96de3e Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1638 of 1638 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-12-01 09:04:54 +01:00
Mr Mejri
60e4fbbf75 Translated using Weblate (Persian)
Currently translated at 15.2% (18 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/fa/
2025-12-01 09:04:53 +01:00
green
d35dd67632 Translated using Weblate (Japanese)
Currently translated at 100.0% (1638 of 1638 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-12-01 07:28:44 +01:00
Francis C.
8813985c68 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1638 of 1638 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-12-01 07:28:44 +01:00
Mr Mejri
538c98b587 Translated using Weblate (Persian)
Currently translated at 5.9% (7 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/fa/
2025-12-01 07:28:44 +01:00
Hosted Weblate
389c7029cf Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-12-01 07:28:44 +01:00
Elian Doran
d47f9e1131 chore(deps): update dependency eslint-plugin-playwright to v2.4.0 (#7908) 2025-12-01 06:28:37 +00:00
Elian Doran
c0a8d29756 fix(deps): update dependency tsx to v4.21.0 (#7909) 2025-12-01 06:26:48 +00:00
SiriusXT
668fd34af6 fix(text): code blocks cannot wrap automatically 2025-12-01 13:55:21 +08:00
renovate[bot]
8aa08cf8fe fix(deps): update dependency tsx to v4.21.0 2025-12-01 01:19:56 +00:00
renovate[bot]
16c04f5ae4 chore(deps): update dependency eslint-plugin-playwright to v2.4.0 2025-12-01 01:19:12 +00:00
Adorian Doran
32c16021c4 style/calendar collection: refactor 2025-12-01 03:00:38 +02:00
Adorian Doran
7713c1173a style/calendar collection: tweak the color of the today column / cell 2025-12-01 02:40:07 +02:00
Adorian Doran
8018f400c3 style/calendar collection: correct a hover color 2025-12-01 02:26:16 +02:00
Adorian Doran
79c8293881 style/calendar collection: handle dot events as normal events 2025-12-01 02:21:19 +02:00
Adorian Doran
db5652623b style/calendar collection: fix broken background color for events without a hue 2025-12-01 02:04:26 +02:00
Adorian Doran
0f7a48b323 style/calendar collection: add basic support for the legacy theme 2025-12-01 01:55:03 +02:00
Elian Doran
309fbab2e6 feat(mobile/split): hide sidebar button for secondary item 2025-11-30 23:34:37 +02:00
Elian Doran
99da145d65 fix(mobile/split): swapping between splits 2025-11-30 23:32:29 +02:00
Adorian Doran
415d2826c6 style/calendar collection: tweak dark theme colors 2025-11-30 23:30:30 +02:00
Adorian Doran
7787e7085e style/calendar collection: tweak dark theme colors 2025-11-30 23:22:41 +02:00
Elian Doran
4ab8417168 feat(forge): add safeguard for ARM64 better-sqlite3 binary 2025-11-30 22:57:14 +02:00
Adorian Doran
a77e76d5c6 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-30 21:33:08 +02:00
Adorian Doran
ca6660e2ff style/calendar collection: tweak appearance 2025-11-30 21:33:00 +02:00
Elian Doran
af94410c55 Merge branch 'main' of github.com:TriliumNext/Trilium 2025-11-30 21:26:50 +02:00
Elian Doran
b47bc50147 fix(revisions): double scrolling on mobile 2025-11-30 21:24:57 +02:00
Elian Doran
5ff77c16ab feat(revisions): improve layout on mobile 2025-11-30 21:13:07 +02:00
Adorian Doran
11618260cf style/calendar collection: tweak the appearance of events without a color 2025-11-30 20:18:16 +02:00
Adorian Doran
63f9006d17 style/calendar collection: improve the support for colored notes 2025-11-30 20:08:24 +02:00
Elian Doran
7779acc7bc refactor(client): split revisions CSS into file 2025-11-30 19:56:13 +02:00
Elian Doran
aacd92eee3 chore(popup-editor): implement switch to full editor button 2025-11-30 19:47:17 +02:00
Adorian Doran
1bf8be2874 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-30 19:46:26 +02:00
Adorian Doran
66f2d0c7dc style/note colors: use a more elegant way to retrieve the theme-aware note color 2025-11-30 19:46:15 +02:00
Elian Doran
597d952254 Add British English (en-GB) translations (#7904) 2025-11-30 17:37:49 +00:00
Adorian Doran
288595ce5d Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-30 19:34:45 +02:00
Elian Doran
c89e8c78d3 Translations update from Hosted Weblate (#7905) 2025-11-30 17:34:39 +00:00
Adorian Doran
81a37e3fc4 client/CSS class manager: fix a bug when handling red hues 2025-11-30 19:34:31 +02:00
Elian Doran
368c590976 Translated using Weblate (English (United Kingdom))
Currently translated at 0.8% (1 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/en_GB/
2025-11-30 18:33:26 +01:00
Elian Doran
6e982e646d Translated using Weblate (English (United Kingdom))
Currently translated at 1.6% (2 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/en_GB/
2025-11-30 18:29:39 +01:00
Elian Doran
030582b2d5 feat(i18n): add English (United Kingdom) 2025-11-30 19:14:21 +02:00
copilot-swe-agent[bot]
7dd4b10a96 Add British English (en-GB) translations for client
Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-30 17:10:30 +00:00
copilot-swe-agent[bot]
b055e79b4c Initial plan 2025-11-30 17:02:01 +00:00
Elian Doran
ba980aa93f Translations update from Hosted Weblate (#7903) 2025-11-30 16:59:52 +00:00
Elian Doran
15baf04ce9 Added translation using Weblate (English (United Kingdom)) 2025-11-30 17:58:03 +01:00
Elian Doran
4dc2587817 Added translation using Weblate (English (United Kingdom)) 2025-11-30 17:58:00 +01:00
Elian Doran
d5e046c289 Added translation using Weblate (English (United Kingdom)) 2025-11-30 17:57:58 +01:00
Elian Doran
ef8073ac58 Added translation using Weblate (English (United Kingdom)) 2025-11-30 17:57:56 +01:00
green
38c9d25214 Translated using Weblate (Japanese)
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-30 17:57:54 +01:00
Elian Doran
e2f0e4089f Merge branch 'main' of github.com:TriliumNext/Trilium 2025-11-30 18:41:43 +02:00
Elian Doran
80ce2c04ed chore(ci): apply platform changes for nightly
See https://github.com/TriliumNext/Trilium/pull/7002/files
2025-11-30 18:41:39 +02:00
Elian Doran
4ebd82beeb feat(ckeditor5): add formatPainter (#7902) 2025-11-30 13:27:15 +00:00
SiriusXT
8cc43cd9a6 docs(user): add format painter 2025-11-30 20:08:27 +08:00
SiriusXT
15190abb69 feat(ckeditor5): add formatPainter 2025-11-30 16:53:14 +08:00
Elian Doran
0b28159e8e fix(ribbon): formatting toolbar overrides edited notes activation (closes #7900) 2025-11-30 10:43:06 +02:00
Elian Doran
d9e8f8e69b refactor(options): remove unnecessary ribbon activation option 2025-11-30 10:41:26 +02:00
Elian Doran
fa224e46bc chore(deps): update dependency typedoc to v0.28.15 (#7897) 2025-11-30 09:41:04 +02:00
Elian Doran
06320953e8 chore(deps): update dependency webdriverio to v9.21.0 (#7898) 2025-11-30 09:40:31 +02:00
SiriusXT
2163334c4f fix(css): the import-markdown icon was displayed as a black square 2025-11-30 15:27:33 +08:00
SiriusXT
f5d180af6b fix(markdown): show 'import successful' when canceling markdown import 2025-11-30 15:27:08 +08:00
renovate[bot]
d676084cb3 chore(deps): update dependency webdriverio to v9.21.0 2025-11-30 02:49:59 +00:00
renovate[bot]
0cb5941be0 chore(deps): update dependency typedoc to v0.28.15 2025-11-30 02:49:23 +00:00
Adorian Doran
732494dfc5 client/keyboard shortcuts cheatsheet: add an edit button 2025-11-30 02:54:51 +02:00
Adorian Doran
b8748b856a client/note menu: use proper style for development-only actions section header 2025-11-30 02:34:09 +02:00
Adorian Doran
cc71f15700 client/quick edit: remove fixed toolbar transparency 2025-11-30 02:17:43 +02:00
Adorian Doran
124ef640b1 client/quick edit: tweak layout 2025-11-30 02:04:40 +02:00
Adorian Doran
f5e3df0cd2 client/quick edit: add placeholder for "open in full editor" custom title bar button 2025-11-30 01:54:28 +02:00
Adorian Doran
c8431181c8 client/dialogs/custom title bar buttons: tweak 2025-11-30 01:52:55 +02:00
Adorian Doran
07fb5ab017 client/dialogs: add support for custom title bar buttons 2025-11-30 01:44:20 +02:00
Adorian Doran
6735b257b4 style/promoted color attributes: fix the layout on narrow width 2025-11-30 01:09:07 +02:00
Adorian Doran
cef242a9ce style/button group: fix the appearance of the active button 2025-11-30 00:55:34 +02:00
Elian Doran
2923d917e5 Translations update from Hosted Weblate (#7891) 2025-11-29 22:58:03 +02:00
Elian Doran
1d1639e5e1 feat(mobile/split): limit to maximum two splits per tab 2025-11-29 21:27:27 +02:00
Elian Doran
6ab05fdb76 chore(mobile/split): improve obtaining of the note context 2025-11-29 21:17:03 +02:00
Elian Doran
91ae8c0aaf feat(mobile/split): add a border between splits 2025-11-29 21:14:03 +02:00
Elian Doran
fcb69c0190 fix(mobile/split): errors due to split 2025-11-29 21:12:55 +02:00
Elian Doran
2cf6fe4352 feat(mobile/split): option to close split 2025-11-29 21:11:16 +02:00
Elian Doran
e3a2623a53 feat(mobile/split): layout horizontally on tablet 2025-11-29 21:06:11 +02:00
Elian Doran
e0c0a423c1 feat(mobile/split): layout vertically on mobile 2025-11-29 21:04:22 +02:00
Elian Doran
fd99246c49 feat(mobile/split): add an option to create new split 2025-11-29 21:04:13 +02:00
Elian Doran
d247edd870 feat(mobile/split): add split container to layout 2025-11-29 21:02:53 +02:00
Hosted Weblate
9a76a9069c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-11-29 20:01:42 +01:00
pythaac
8e1d796870 Translated using Weblate (Korean)
Currently translated at 44.7% (68 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-29 20:01:38 +01:00
Andreas H.
8b0d4e5c3b Translated using Weblate (German)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-11-29 20:01:37 +01:00
Elian Doran
b9e257a39d refactor(client): redundant interface 2025-11-29 20:18:43 +02:00
Elian Doran
e7eaa5fd58 fix(mobile): global menu backdrop on tablet view 2025-11-29 19:49:38 +02:00
Elian Doran
c9aa992e73 fix(read-only-bar): displayed when viewing attachments 2025-11-29 19:40:00 +02:00
Elian Doran
f325930f68 chore(read-only-bar): use in-app help 2025-11-29 19:37:38 +02:00
Adorian Doran
1346ffb77e Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-29 18:50:24 +02:00
Adorian Doran
3378746530 style: disable text selection in UI 2025-11-29 18:50:16 +02:00
Elian Doran
ce2d94f04e Resolve focus issues within split pane (#7877) 2025-11-29 18:34:26 +02:00
Elian Doran
b3c2a1e6c5 fix(insertDateTime): unable to insert date/time via quick editor or s… (#7889) 2025-11-29 18:30:28 +02:00
Elian Doran
dbf63787da Merge branches 'main' and 'main' of ssh://github.com/TriliumNext/trilium 2025-11-29 18:08:19 +02:00
Elian Doran
88a7ebef69 fix(quick-edit): background broke for colors with no hue 2025-11-29 18:07:24 +02:00
Adorian Doran
a716151dd9 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-29 18:04:53 +02:00
Adorian Doran
7462f1b7a5 style/empty tab: improve layout 2025-11-29 18:04:45 +02:00
Elian Doran
ec76b9dc5c chore(quick-edit): increase max-width on mobile 2025-11-29 18:01:07 +02:00
Elian Doran
79cd96ade9 style(context_menu): improve submenu separator style 2025-11-29 17:47:26 +02:00
Elian Doran
a5b84406be style(context_menu): improve submenu bg on mobile 2025-11-29 17:35:37 +02:00
Elian Doran
8c1a04c4b2 fix(mobile): shortcut keyboard + visible 2025-11-29 17:32:32 +02:00
Elian Doran
ee81037173 feat(quick_edit): smooth transition between colors 2025-11-29 17:26:17 +02:00
Elian Doran
453349be26 feat(quick_edit): seamless transition between color changes 2025-11-29 17:19:43 +02:00
Elian Doran
81a9e06b23 feat(quick_edit): basic reactivity to color changes 2025-11-29 17:19:43 +02:00
Elian Doran
7d8af0f252 refactor(client): use var for modal max height 2025-11-29 17:19:43 +02:00
Elian Doran
a68cd7526b style(mobile): improve quick edit max height 2025-11-29 17:19:43 +02:00
Elian Doran
470ca3b6dc style(mobile): improve quick edit max width 2025-11-29 17:19:43 +02:00
Elian Doran
e8bae61afc style(mobile): center modals on tablet view 2025-11-29 17:19:43 +02:00
Elian Doran
c1f663a200 style(mobile): no bottom border radius on modals 2025-11-29 17:19:43 +02:00
Elian Doran
22b2e21df0 Translations update from Hosted Weblate (#7887) 2025-11-29 17:11:15 +02:00
SiriusXT
5f19710791 fix(insertDateTime): unable to insert date/time via quick editor or shortcut 2025-11-29 22:40:49 +08:00
pythaac
d3f3ff4eab Translated using Weblate (Korean)
Currently translated at 43.4% (66 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-29 14:02:26 +00:00
noobhjy
5af7425cae Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-29 14:02:25 +00:00
Elian Doran
fe10c9f8c8 fix(text): strikethrough icon appears disabled 2025-11-29 15:34:43 +02:00
Elian Doran
cd2a085d00 fix(type_widgets/notemap): bottom part not visible 2025-11-29 15:30:17 +02:00
Elian Doran
3c61626370 fix(launch_bar/calendar): tooltip showing over the calendar dropdown 2025-11-29 15:16:43 +02:00
Elian Doran
351fe5848f fix(launch_bar/calendar): clicking on the edges would dismiss modal 2025-11-29 13:26:48 +02:00
Elian Doran
ca7bbefbdc fix(launch_bar/calendar): dropdown remains open when switching years 2025-11-29 13:19:49 +02:00
Elian Doran
7094f71e32 refactor(server): remove now unnecessary attachment without size 2025-11-29 13:08:05 +02:00
Elian Doran
88b5e9db87 fix(server): uploading new attachments doesn't report size 2025-11-29 13:03:08 +02:00
Elian Doran
b4ab07bd78 feat(board): add keyboard navigation for "Add column" button 2025-11-29 12:40:41 +02:00
Elian Doran
fd6ad6dce3 fix(type_widgets): partially prevent wrong note type rendering due to async race condition 2025-11-29 12:40:41 +02:00
Elian Doran
ab97068a1d fix(quick_edit): classic toolbar dropdowns not working 2025-11-29 12:40:41 +02:00
Elian Doran
70fe3b9773 fix(quick_edit): block popup not working 2025-11-29 12:40:41 +02:00
Elian Doran
1fe8079fd5 fix(type_widgets): empty type widget when hot-reloading NoteDetail 2025-11-29 12:40:41 +02:00
Elian Doran
80627997d1 fix(type_widgets): read-only text sometimes rendering wrong blob 2025-11-29 12:40:41 +02:00
Elian Doran
12abdcaf6c fix(ribbon): formatting toolbar disappearing after viewing attachments 2025-11-29 12:40:41 +02:00
Elian Doran
a6ed4d92c9 chore(deps): update dependency stylelint to v16.26.1 (#7881) 2025-11-29 12:39:51 +02:00
Elian Doran
0471640f54 fix(deps): update dependency better-sqlite3 to v12.5.0 (#7882) 2025-11-29 12:39:41 +02:00
Elian Doran
4cf3e82fb5 Translations update from Hosted Weblate (#7880) 2025-11-29 12:38:59 +02:00
noobhjy
fbbe999806 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-29 07:41:54 +00:00
Francis C.
76af488d35 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-29 07:41:54 +00:00
Andreas H.
a54d2a5f22 Translated using Weblate (German)
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-11-29 07:41:53 +00:00
Sam.Lee
a1df075194 Translated using Weblate (Korean)
Currently translated at 2.4% (40 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ko/
2025-11-29 07:41:52 +00:00
Sam.Lee
4de2182b40 Translated using Weblate (Korean)
Currently translated at 42.7% (65 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-29 07:41:51 +00:00
Tomas Adamek
6fa88123f1 Translated using Weblate (Czech)
Currently translated at 5.4% (89 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-11-29 07:41:50 +00:00
Sam.Lee
f81dbde15e Translated using Weblate (Korean)
Currently translated at 21.0% (82 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-11-29 07:41:50 +00:00
Tomas Adamek
484fbc6b9d Translated using Weblate (Czech)
Currently translated at 69.0% (105 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-29 07:41:49 +00:00
green
8ba30135a1 Translated using Weblate (Japanese)
Currently translated at 100.0% (1637 of 1637 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-29 07:41:48 +00:00
Andreas H.
ba5a72fdad Translated using Weblate (German)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-11-29 07:41:47 +00:00
Elian Doran
70b39ddadf fix(mobile/context_menu): global menu not scrollable 2025-11-29 09:40:51 +02:00
Elian Doran
8200c0b0ab style(mobile/context_menu): improve delimiter color in light theme 2025-11-29 09:36:46 +02:00
Elian Doran
59ebfa6cc7 style(mobile/context_menu): alter submenu separator style 2025-11-29 09:33:11 +02:00
Elian Doran
57b694162d style(mobile/context_menu): rounded corners for anchored positioning 2025-11-29 09:29:00 +02:00
Elian Doran
2e6bdc225f style(mobile/context_menu): missing backdrop for global menu 2025-11-29 09:22:51 +02:00
Elian Doran
8ced689432 style(mobile/context_menu): make color picker easier to press 2025-11-29 09:15:28 +02:00
perfectra1n
09df73e125 fix(fts): remove migration statements of old 0236 2025-11-28 21:36:12 -08:00
perfectra1n
f21aa321f6 fix(fts): remove index of components 2025-11-28 21:29:48 -08:00
perfectra1n
7be8b6c71e fix(fts): merge the two migrations into one file 2025-11-28 21:27:01 -08:00
perfectra1n
bb8e5ebd4a fix(fts): fix suggestions from elian 2025-11-28 21:25:24 -08:00
perfectra1n
6b8b71f7d1 feat(fts): implement missing unit tests 2025-11-28 21:12:39 -08:00
perfectra1n
191a18d7f6 feat(fts): add fts to in-memory sqlite for testing 2025-11-28 21:08:49 -08:00
perfectra1n
574a3441ee feat(fts): update imports from breaking up large fts_search file 2025-11-28 20:59:50 -08:00
perfectra1n
9940ee3bee feat(fts): break up the huge fts_search into smaller files 2025-11-28 20:57:18 -08:00
SiriusXT
53a8f6b4c0 Merge branch 'main' into fix/split_pane 2025-11-29 11:39:05 +08:00
SiriusXT
9ae1a55896 chore(react/empty): obtain ntxId via React props instead of DOM query 2025-11-29 11:38:45 +08:00
renovate[bot]
5ecafe214f fix(deps): update dependency better-sqlite3 to v12.5.0 2025-11-29 02:49:33 +00:00
renovate[bot]
8baf0ad6af chore(deps): update dependency stylelint to v16.26.1 2025-11-29 02:49:04 +00:00
Elian Doran
3cc64b5764 fix(mobile/context_menu): note color picker not working 2025-11-28 23:43:16 +02:00
Elian Doran
19cf07564f style(mobile/context_menu): taller height + small animation when expanding items 2025-11-28 23:21:31 +02:00
Elian Doran
5847ce5c14 feat(dev): enable CSS source maps 2025-11-28 23:21:14 +02:00
Elian Doran
a7ad45635e style(mobile/context_menu): clean up border radiuses 2025-11-28 21:27:06 +02:00
Elian Doran
781215394e refactor(mobile/context_menu): unify styles 2025-11-28 21:24:51 +02:00
Elian Doran
0aafdca999 style(mobile/context_menu): improve backdrop 2025-11-28 21:21:07 +02:00
Elian Doran
18d3cb6f0c style(mobile/context_menu): dark submenu style 2025-11-28 21:14:06 +02:00
Elian Doran
263a96e8b7 style(mobile/context_menu): improve submenu style 2025-11-28 20:57:42 +02:00
Elian Doran
27d5009486 style(mobile/context_menu): disable hover color 2025-11-28 20:44:29 +02:00
SiriusXT
4d1a91baa6 Merge branch 'main' into fix/split_pane 2025-11-28 19:49:08 +08:00
SiriusXT
1898efa282 chore(e2e): add Playwright tests for split pane 2025-11-28 19:48:37 +08:00
SiriusXT
648ab4d736 fix(left-pane): only focus the note when toggling left pane visibility if necessary 2025-11-28 19:45:19 +08:00
SiriusXT
407cac588a fix(split): only trigger focusOnDetail when necessary 2025-11-28 19:42:04 +08:00
SiriusXT
210dcfb989 fix(empty): open note in the correct split pane 2025-11-28 19:38:52 +08:00
Elian Doran
2e431b1135 chore(deps): update dependency electron to v38.7.2 (#7873) 2025-11-28 11:26:12 +02:00
Elian Doran
e2ec27250c chore(deps): update dependency happy-dom to v20.0.11 (#7874) 2025-11-28 08:24:15 +02:00
Elian Doran
1228eda5ea chore(deps): update pnpm to v10.24.0 (#7875) 2025-11-28 08:23:01 +02:00
renovate[bot]
435794df73 chore(deps): update pnpm to v10.24.0 2025-11-28 01:16:30 +00:00
renovate[bot]
7e3d0639f7 chore(deps): update dependency happy-dom to v20.0.11 2025-11-28 01:16:18 +00:00
renovate[bot]
86b0005821 chore(deps): update dependency electron to v38.7.2 2025-11-28 01:15:07 +00:00
Elian Doran
2fb78275f7 Translations update from Hosted Weblate (#7871) 2025-11-27 21:52:13 +02:00
Elian Doran
98f421c697 Apply suggestions from code review
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-27 21:49:17 +02:00
Francis C.
a5572b7d45 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-27 20:42:07 +01:00
Manfred Manni
fdecbaaa6a Translated using Weblate (German)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-11-27 20:42:06 +01:00
green
c6afd7fa24 Translated using Weblate (Japanese)
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-27 20:42:06 +01:00
Tomas Adamek
5cad522a60 Translated using Weblate (Czech)
Currently translated at 5.3% (88 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-11-27 20:42:05 +01:00
Tomas Adamek
82f64677cb Translated using Weblate (Czech)
Currently translated at 27.2% (106 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-11-27 20:42:04 +01:00
Manfred Manni
3ee086a063 Translated using Weblate (German)
Currently translated at 99.7% (1631 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-11-27 20:42:03 +01:00
Francis C.
13da444a69 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-27 20:42:02 +01:00
Tomas Adamek
b51ceaaadc Translated using Weblate (Czech)
Currently translated at 65.1% (99 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-27 20:42:01 +01:00
Elian Doran
2024c72209 i18n(client): two missing translations for dialogs 2025-11-27 21:41:24 +02:00
Elian Doran
b5959c55e1 chore(client): remove redundant log 2025-11-27 21:12:47 +02:00
Elian Doran
16f0ac97f4 fix(ckeditor): revert workaround which breaks shift-selection 2025-11-27 20:39:59 +02:00
Elian Doran
073c02ee0c fix(ckeditor): Cmd+Up/Down not working properly 2025-11-27 20:00:15 +02:00
Elian Doran
786f0db4bb fix(ckeditor): move block interfering with normal shortcut (closes #6964) 2025-11-27 19:37:21 +02:00
Elian Doran
6958e4b74f feat(desktop): collapse spacing in full screen 2025-11-27 18:24:00 +02:00
Elian Doran
22c4fba665 docs(user): improve documentation on tree keyboard shortcuts 2025-11-27 14:22:45 +02:00
Elian Doran
f7c0e56cec Translations update from Hosted Weblate (#7867) 2025-11-27 07:35:08 +02:00
Elian Doran
5f423cd22e Apply suggestions from code review
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-27 07:34:46 +02:00
Hosted Weblate
282b3a109c Update translation files
Updated by "Remove blank strings" add-on in Weblate.

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/
2025-11-27 05:14:32 +00:00
Tomas Adamek
dddb051d8b Translated using Weblate (Czech)
Currently translated at 26.3% (40 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-27 05:14:31 +00:00
Vedat Botuk
63d3706003 Translated using Weblate (Turkish)
Currently translated at 7.2% (11 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/tr/
2025-11-27 05:14:30 +00:00
Tomas Adamek
22ca2494f5 Translated using Weblate (Czech)
Currently translated at 18.5% (72 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-11-27 05:14:29 +00:00
Aitanuqui
a0f02b6877 Translated using Weblate (Spanish)
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-11-27 05:14:28 +00:00
Vedat Botuk
487fcff61f Translated using Weblate (Turkish)
Currently translated at 9.3% (11 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/tr/
2025-11-27 05:14:27 +00:00
Elian Doran
bfb8897188 Translated using Weblate (Romanian)
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-11-27 05:14:26 +00:00
Francis C.
ce1ccf378a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-27 05:14:25 +00:00
Francis C.
96d5ee3d46 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1635 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-27 05:14:23 +00:00
Tomas Adamek
6f3771e7cd Translated using Weblate (Czech)
Currently translated at 25.6% (39 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-27 05:14:22 +00:00
Tomas Adamek
e6b00b05a2 Translated using Weblate (Czech)
Currently translated at 3.3% (54 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-11-27 05:14:21 +00:00
Tomas Adamek
148d0afe81 Translated using Weblate (Czech)
Currently translated at 11.0% (43 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/cs/
2025-11-27 05:14:20 +00:00
Aitanuqui
c5d63dbdb9 Translated using Weblate (Spanish)
Currently translated at 99.7% (1631 of 1635 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-11-27 05:14:18 +00:00
Tomas Adamek
1af072b059 Translated using Weblate (Czech)
Currently translated at 36.4% (43 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/cs/
2025-11-27 05:14:17 +00:00
Hosted Weblate
a6a8fdd2f8 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/
2025-11-27 05:14:16 +00:00
Andreas Haan
8836021ff9 Translated using Weblate (German)
Currently translated at 99.9% (1631 of 1632 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/de/
2025-11-27 05:14:14 +00:00
Andreas Haan
915803c5be Translated using Weblate (German)
Currently translated at 99.7% (388 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/de/
2025-11-27 05:14:13 +00:00
green
cd95d43457 Translated using Weblate (Japanese)
Currently translated at 100.0% (1632 of 1632 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-27 05:14:11 +00:00
Andreas Haan
35af5fd13c Translated using Weblate (German)
Currently translated at 39.4% (60 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-11-27 05:14:10 +00:00
Elian Doran
35e602f75f style(mobile/context_menu): increase size and padding 2025-11-27 07:13:23 +02:00
Elian Doran
b4f0a1acc0 style(mobile/context_menu): card-style design on next theme 2025-11-26 21:54:35 +02:00
Elian Doran
7b7e9f6868 fix(context_menu): no bottom padding on mobile 2025-11-26 21:26:52 +02:00
Elian Doran
de3892950c fix(context_menu): 1px overflow in height on mobile 2025-11-26 21:24:03 +02:00
Elian Doran
5c53826da3 fix(context_menu): color picker not dismissing on mobile 2025-11-26 21:20:27 +02:00
Elian Doran
d358073081 fix(global_menu): toggling advanced hides the menu most of the time 2025-11-26 20:44:53 +02:00
Elian Doran
d2d7fd7c4c fix(context_menu): toggling submenu hides the menu most of the time 2025-11-26 20:35:02 +02:00
Elian Doran
706da768e2 chore(collections/board): hide "Add new column" while loading 2025-11-26 19:47:15 +02:00
Elian Doran
408073ee19 fix(note_list): subtree leaking into classic collections 2025-11-26 19:11:43 +02:00
Elian Doran
2695b7fc38 fix(print): included notes not rendering 2025-11-26 15:26:33 +02:00
Elian Doran
c32b6393af refactor(client): split text content rendering to separate module 2025-11-26 15:18:02 +02:00
Elian Doran
abbb4e793f feat(dev): action to open print page easily 2025-11-26 15:10:17 +02:00
Elian Doran
e4fae2d660 docs(user): document expanding/collapsing in list collection 2025-11-26 14:27:12 +02:00
Elian Doran
dc572c3815 fix(ribbon): tooltip for expand button 2025-11-26 11:59:46 +02:00
Elian Doran
c65b03db41 chore(collections/list): use translations for expand depth 2025-11-26 11:57:06 +02:00
Elian Doran
45d2e1f5e2 feat(collections/list): checkboxes for expand depth 2025-11-26 11:54:08 +02:00
Elian Doran
b658f5bd0e feat(collections/list): adjustable expansion depth (closes #7669) 2025-11-26 10:36:53 +02:00
Elian Doran
f199d85d5b chore(react): split button implementation 2025-11-26 10:36:00 +02:00
Elian Doran
445dfaaeb4 chore(deps): update dependency chokidar to v5 (#7866) 2025-11-26 08:07:28 +02:00
Elian Doran
cccd4122c5 chore(deps): update vitest monorepo to v4.0.14 (#7863) 2025-11-26 07:25:42 +02:00
Elian Doran
1fcbe828bd chore(deps): update dependency @playwright/test to v1.57.0 (#7864) 2025-11-26 07:24:59 +02:00
Elian Doran
e94b78a37b chore(deps): update dependency @redocly/cli to v2.12.0 (#7865) 2025-11-26 07:24:30 +02:00
renovate[bot]
af7cecb667 chore(deps): update dependency chokidar to v5 2025-11-26 01:13:15 +00:00
renovate[bot]
4068e9c6b8 chore(deps): update dependency @redocly/cli to v2.12.0 2025-11-26 01:12:23 +00:00
renovate[bot]
185c1fcdac chore(deps): update dependency @playwright/test to v1.57.0 2025-11-26 01:11:33 +00:00
renovate[bot]
29c5d35c08 chore(deps): update vitest monorepo to v4.0.14 2025-11-26 01:10:40 +00:00
Elian Doran
0117f54ef8 fix(shortcuts): default shortcuts for nav in macOS (closes #3708) 2025-11-25 22:30:42 +02:00
Elian Doran
56d41916c4 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-25 21:09:00 +02:00
Elian Doran
fddf73b1bb fix(collections/table): colons in attribute name not working (closes #7860) 2025-11-25 21:03:27 +02:00
Elian Doran
d670c2ae5e Translations update from Hosted Weblate (#7862) 2025-11-25 20:40:30 +02:00
green
6f5c9eb600 Translated using Weblate (Japanese)
Currently translated at 100.0% (1631 of 1631 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-25 17:51:44 +00:00
green
49c416c90d Translated using Weblate (Japanese)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ja/
2025-11-25 17:51:43 +00:00
Giovi
8fef468eb9 Translated using Weblate (Italian)
Currently translated at 100.0% (1631 of 1631 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-11-25 17:51:42 +00:00
Elian Doran
976b1e1e0f fix(note_list): not rendering correctly when switching notes 2025-11-25 19:51:24 +02:00
Elian Doran
d6de7cca96 Search selected text in trilium (#7859) 2025-11-25 19:44:01 +02:00
contributor
fb02751bdd note context menu: change search wording to match other menu items 2025-11-25 16:24:55 +02:00
Elian Doran
3fb5c52af1 Translations update from Hosted Weblate (#7861) 2025-11-25 16:09:39 +02:00
Hosted Weblate
18d17570f6 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-25 14:47:04 +01:00
Elian Doran
fa5eb16054 fix(note_autocomplete): regression in board entry 2025-11-25 15:46:41 +02:00
contributor
b1c77b508a note context menu: cache appContext import call 2025-11-25 13:25:56 +02:00
contributor
b982ca2c5b note context menu: search selected text in Trilium 2025-11-25 13:25:51 +02:00
Elian Doran
219753039d fix(mermaid): one more case of "Matrix is not inversible" 2025-11-25 08:56:31 +02:00
Elian Doran
c16f9af6a9 feat(popup_editor): add read-only bar 2025-11-25 08:34:35 +02:00
Elian Doran
a544b0dc19 chore(popup_editor): improve alignment for read-only text 2025-11-25 08:31:44 +02:00
Elian Doran
a398f07f9f fix(type_widgets): double wrapper for read-only text 2025-11-25 08:31:26 +02:00
Elian Doran
7ecdee7a89 refactor(popup_editor): use simpler mechanism for retrieving note ID 2025-11-25 08:24:26 +02:00
Elian Doran
24361ccd97 fix(popup_editor): respect user's read-only choice (closes #7715) 2025-11-25 08:19:48 +02:00
Elian Doran
3afe6df9f2 Translations update from Hosted Weblate (#7856) 2025-11-25 07:30:04 +02:00
vcodesai
df7f79004d Translated using Weblate (Greek)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/el/
2025-11-25 05:14:44 +00:00
Hosted Weblate
405bce9f82 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-25 05:14:43 +00:00
Elian Doran
b9ef7af791 chore(deps): update dependency @anthropic-ai/sdk to v0.71.0 (#7854) 2025-11-25 07:14:21 +02:00
Elian Doran
761891abe9 chore(deps): update typescript-eslint monorepo to v8.48.0 (#7855) 2025-11-25 07:13:56 +02:00
Elian Doran
6a52637695 chore(deps): update dependency rcedit to v5.0.2 (#7853) 2025-11-25 07:13:33 +02:00
renovate[bot]
b4b957d2c3 chore(deps): update typescript-eslint monorepo to v8.48.0 2025-11-25 01:55:47 +00:00
renovate[bot]
dda4a0a887 chore(deps): update dependency @anthropic-ai/sdk to v0.71.0 2025-11-25 01:54:50 +00:00
renovate[bot]
b069a936ab chore(deps): update dependency rcedit to v5.0.2 2025-11-25 01:53:49 +00:00
perfectra1n
41f6fedc61 feat(fts5): get rid of search comparison code 2025-11-24 14:24:07 -08:00
perfectra1n
0ddf48c460 feat(fts5): add more unit tests for search 2025-11-24 13:30:40 -08:00
Elian Doran
15c088ec21 feat(popup_editor): hide some unwanted floating buttons 2025-11-24 21:56:16 +02:00
Elian Doran
015d70afb6 feat(popup_editor): enable floating buttons 2025-11-24 21:45:33 +02:00
Elian Doran
2158f69c09 feat(popup_editor): seamless mermaid code editor 2025-11-24 21:38:34 +02:00
Elian Doran
c49c5fd58c fix(popup_editor): full-height taller than 100% 2025-11-24 21:33:17 +02:00
Elian Doran
26be131b4b fix(mermaid): matrix not inversible 2025-11-24 21:25:27 +02:00
Elian Doran
f8533eb2c6 feat(popup_editor): immersive code notes editing 2025-11-24 19:50:51 +02:00
Elian Doran
4cc545659b fix(popup_editor): keep in DOM 2025-11-24 19:38:18 +02:00
Elian Doran
70a0b5c22f fix(promoted_attributes): "attribute is not owned" in auto-complete after switching notes 2025-11-24 18:58:52 +02:00
Elian Doran
a2976d9ad5 refactor(mime): proper typechecking of supported MIME types 2025-11-24 18:58:21 +02:00
Elian Doran
01b05f186e chore(options/code): hide tooltip for plain text 2025-11-24 18:43:07 +02:00
Elian Doran
79a4da9db8 docs(dev): refresh documentation on syntax highlighting 2025-11-24 18:39:51 +02:00
Elian Doran
84890fd5ad feat(mime): support SAS ABAP (closes #7851) 2025-11-24 18:39:34 +02:00
Elian Doran
29f9d0c1cd chore(mime): fix MD language code for Batch files 2025-11-24 18:11:31 +02:00
Elian Doran
95169bbc84 feat(mime): support KDL (closes #7848) 2025-11-24 18:06:24 +02:00
Elian Doran
9a2979e577 chore(options/code): improve tooltip positioning & speed 2025-11-24 17:45:19 +02:00
Elian Doran
9f381a7b30 feat(options/code): display tooltip for syntax highlighting support 2025-11-24 17:43:02 +02:00
Elian Doran
c07ad348bd Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-24 10:56:43 +02:00
Elian Doran
d7ae2e4307 fix(search): double results if search has inheritable viewType 2025-11-24 10:56:39 +02:00
Elian Doran
71b86b3cbc Fixes #7826 CORP (Resource Policy) defaults to same-origin (#7830) 2025-11-24 09:21:58 +02:00
Elian Doran
621e8078d9 fix(geomap): map not loading at zero zoom 2025-11-24 09:18:16 +02:00
Lucas
7155ab8bdc Merge branch 'TriliumNext:main' into main 2025-11-23 13:24:24 -08:00
Elian Doran
0a3e788d21 fix(client/collections): collections not visible after viewing attachments 2025-11-23 21:53:47 +02:00
Elian Doran
f83c46d1c7 fix(client/promoted_attributes): unnecessary space when empty 2025-11-23 21:51:48 +02:00
Elian Doran
11932353f7 fix(client/attachments): scroll padding reducing in size after visiting attachments 2025-11-23 21:47:27 +02:00
Elian Doran
ed373107c2 fix(client/attachments): full-height attachment not displayed correctly (closes #7847) 2025-11-23 21:46:04 +02:00
Elian Doran
1cca15ca5d Revert "fix(react/promoted_attributes): removing relation sometimes not refreshing"
This reverts commit 320f064775.
2025-11-23 21:31:40 +02:00
Elian Doran
11e59a970e fix(deps): update dependency mind-elixir to v5.3.7 (#7844) 2025-11-23 18:13:19 +02:00
Elian Doran
5abb69d022 chore(mindmap): add Romanian locale 2025-11-23 17:23:07 +02:00
Elian Doran
dc1d497ff3 Port promoted attributes to React (#7846) 2025-11-23 16:43:52 +02:00
Elian Doran
7f909fa098 chore(promoted_attributes): address review 2025-11-23 16:34:38 +02:00
Elian Doran
320f064775 fix(react/promoted_attributes): removing relation sometimes not refreshing 2025-11-23 14:59:23 +02:00
Elian Doran
c9b1691998 fix(react/promoted_attributes): non-existing attribute ID when deleting relations 2025-11-23 14:42:31 +02:00
Elian Doran
08ade8371c fix(react/promoted_attributes): unable to read trim at server level 2025-11-23 13:55:25 +02:00
Elian Doran
081ac2d109 chore(react/quick_edit): reintegrate promoted attributes 2025-11-23 13:44:24 +02:00
Elian Doran
3fde546b83 feat(react/promoted_attributes): debounce label editing 2025-11-23 13:43:40 +02:00
Elian Doran
a12b3cb51a chore(react/promoted_attributes): fix type issue 2025-11-23 13:40:05 +02:00
Elian Doran
6160945b9e chore(react/promoted_attributes): bring back reacting to changes 2025-11-23 13:35:16 +02:00
Elian Doran
6a126009a8 refactor(react/promoted_attributes): deduplicate server API typings 2025-11-23 13:15:33 +02:00
Elian Doran
891e71aec6 refactor(react/promoted_attributes): remove unnecessary action cell 2025-11-23 13:13:15 +02:00
Elian Doran
cd164049b7 refactor(react/promoted_attributes): use simplified class name handling 2025-11-23 13:12:42 +02:00
Elian Doran
709a47bc6b chore(react/promoted_attributes): handle relations 2025-11-23 13:11:12 +02:00
Elian Doran
9c6cd80867 chore(react/promoted_attributes): improve boolean handling 2025-11-23 12:56:43 +02:00
Elian Doran
832d9a2ab8 chore(react/promoted_attributes): handle URL open button 2025-11-23 12:46:06 +02:00
Elian Doran
8d4e30a2e4 chore(react/promoted_attributes): handle color picker 2025-11-23 12:32:13 +02:00
Elian Doran
baf41eb104 chore(react/promoted_attributes): handle input steps 2025-11-23 12:11:18 +02:00
Elian Doran
7f0fe1681b chore(react/promoted_attributes): integrate value change listener 2025-11-23 11:57:31 +02:00
Elian Doran
49189bc63e chore(react/promoted_attributes): map promoted attribute types 2025-11-23 11:38:53 +02:00
Elian Doran
87f30ed3d5 chore(react/promoted_attributes): add back text label autocomplete 2025-11-23 11:33:14 +02:00
Elian Doran
aca390ee19 chore(react/promoted_attributes): add more attributes to the input 2025-11-23 11:24:44 +02:00
Elian Doran
598bb6d742 chore(react/promoted_attributes): add logic to remove multi labels 2025-11-23 11:19:41 +02:00
Elian Doran
33b19e40e0 chore(react/promoted_attributes): add logic to add new labels 2025-11-23 10:46:56 +02:00
Elian Doran
5b9401fafe chore(react/promoted_attributes): add logic to filter out tables 2025-11-23 10:25:57 +02:00
Elian Doran
9bed6b7e22 chore(react/promoted_attributes): port multiplicity buttons (without implementation) 2025-11-23 10:22:58 +02:00
Elian Doran
aca003c554 Translations update from Hosted Weblate (#7845) 2025-11-23 09:56:04 +02:00
Hosted Weblate
3c806558eb Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-23 07:51:10 +00:00
Elian Doran
d195d46f8f chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.8 (#7843) 2025-11-23 09:50:54 +02:00
renovate[bot]
755abc6487 fix(deps): update dependency mind-elixir to v5.3.7 2025-11-23 00:36:56 +00:00
renovate[bot]
718282bae3 chore(deps): update dependency rollup-plugin-webpack-stats to v2.1.8 2025-11-23 00:36:05 +00:00
lzinga
8cc4d08eae fix(config): update corsResourcePolicy type to string, typecheck did not like previous method 2025-11-22 15:54:21 -08:00
Lucas
0bcc02dfab Merge branch 'TriliumNext:main' into main 2025-11-22 15:53:36 -08:00
Elian Doran
33c3fb7de0 chore(react/promoted_attributes): reintroduce labels 2025-11-22 22:25:32 +02:00
Elian Doran
d99b8f5864 chore(promoted_attributes): build list of cells 2025-11-22 22:10:51 +02:00
Elian Doran
98bf63e94b chore(promoted_attributes): start with empty widget 2025-11-22 21:58:52 +02:00
Elian Doran
2d8b1299b3 Port Quick edit popup to React (#7840) 2025-11-22 21:53:19 +02:00
Elian Doran
5edc4abfb4 chore(quick_edit): address requested changes 2025-11-22 21:37:41 +02:00
Elian Doran
26f7264f3c chore(client): fix typecheck 2025-11-22 21:37:37 +02:00
Elian Doran
56c82d7f0f chore(quick_edit): address requested changes 2025-11-22 21:20:24 +02:00
Elian Doran
6946da3571 chore(mermaid): avoid crash if "Matrix is not invertible" 2025-11-22 21:07:17 +02:00
Elian Doran
2985c762e6 chore(quick_edit): add back most of the components 2025-11-22 21:00:55 +02:00
Elian Doran
8001d940eb chore(quick_edit): bring back coloring 2025-11-22 20:43:57 +02:00
Elian Doran
2f440eba37 chore(quick_edit): bring back focus 2025-11-22 19:34:23 +02:00
Elian Doran
bb9cb2fb75 fix(quick_edit): note context not injected on first render 2025-11-22 19:25:35 +02:00
Elian Doran
5531c15126 chore(quick_edit): get note content to render 2025-11-22 19:19:16 +02:00
Elian Doran
29f049c411 chore(quick_edit): inject note context 2025-11-22 19:11:20 +02:00
Elian Doran
31180afbd1 react(quick_edit): set up empty dialog 2025-11-22 19:07:50 +02:00
Elian Doran
435b856b72 fix(quick_edit): keyboard shortcuts triggering on wrong editor 2025-11-22 18:35:18 +02:00
Adorian Doran
af62526b92 client/context menu: fix data type errors 2025-11-22 13:43:40 +02:00
Adorian Doran
beb7d09aee client/tree context menu: improve handling the case when the note color picker is not available 2025-11-22 13:35:36 +02:00
Adorian Doran
b4b1b7a3fa client/context menus: skip consecutive separators 2025-11-22 13:33:48 +02:00
Elian Doran
d0342598c4 Translations update from Hosted Weblate (#7838) 2025-11-22 12:40:12 +02:00
Francis C.
4a71b00b71 Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1628 of 1628 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-22 10:39:04 +00:00
green
268bbf3b9e Translated using Weblate (Japanese)
Currently translated at 100.0% (1628 of 1628 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-22 10:39:03 +00:00
Marc
24cdeb06e8 Translated using Weblate (French)
Currently translated at 99.2% (1616 of 1628 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/fr/
2025-11-22 10:39:02 +00:00
Marc
6b64d85db0 Translated using Weblate (French)
Currently translated at 97.3% (148 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/fr/
2025-11-22 10:39:01 +00:00
Francis C.
08e542dfb3 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1628 of 1628 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-22 10:39:00 +00:00
Elian Doran
8b997cffdd fix(collections/board): mouse horizontal scroll no longer working 2025-11-22 12:37:08 +02:00
Elian Doran
33aece6f96 fix(collections): flicker when adding new entries 2025-11-22 12:16:48 +02:00
Elian Doran
6040eea3bd fix(text): note with empty table carries over to new notes 2025-11-22 11:52:16 +02:00
Elian Doran
9b3ca65492 fix(text): classic toolbar broken on mobile due to prior change 2025-11-22 11:37:34 +02:00
Elian Doran
c76f368fa0 fix(text): classic toolbar sometimes not showing 2025-11-22 11:21:51 +02:00
Elian Doran
664d28f105 docs(scripting): remove workaround for sidebar visibility 2025-11-22 11:03:00 +02:00
Elian Doran
7daee36d3e fix(toc): table of contents not rendering for doc notes 2025-11-22 10:59:50 +02:00
Elian Doran
5fc10fe041 chore(react/sidebar): basic right panel widget implementation 2025-11-22 10:58:51 +02:00
Elian Doran
6692de33b1 fix(sidebar): not displayed if items are enabled from the start 2025-11-22 10:58:46 +02:00
Elian Doran
494bd425af feat(print): avoid error message for print job cancelled 2025-11-22 10:13:46 +02:00
Elian Doran
135ce2285d feat(collections): don't load all collection types at once 2025-11-22 10:10:37 +02:00
Elian Doran
be2e82788f chore(deps): update dependency @anthropic-ai/sdk to v0.70.1 (#7816) 2025-11-22 09:49:28 +02:00
Elian Doran
e84fb63343 fix(deps): update dependency mime-types to v3.0.2 (#7820) 2025-11-22 09:49:09 +02:00
Elian Doran
97422c1d7a chore(deps): update vitest monorepo to v4.0.13 (#7835) 2025-11-22 09:48:40 +02:00
renovate[bot]
66cc739bb2 chore(deps): update dependency @anthropic-ai/sdk to v0.70.1 2025-11-22 07:12:56 +00:00
renovate[bot]
790454f194 chore(deps): update vitest monorepo to v4.0.13 2025-11-22 07:10:46 +00:00
Elian Doran
d751966078 chore(server/mime): remove mp4 workaround 2025-11-22 09:10:41 +02:00
renovate[bot]
a8e9f7b445 fix(deps): update dependency mime-types to v3.0.2 2025-11-22 07:08:13 +00:00
Elian Doran
144afc346d chore(deps): update dependency express-openid-connect to v2.19.3 (#7834) 2025-11-22 09:07:15 +02:00
Elian Doran
63854156eb chore(deps): update dependency stylelint to v16.26.0 (#7837) 2025-11-22 09:06:15 +02:00
Elian Doran
7800e76b26 fix(deps): update dependency better-sqlite3 to v12.4.6 (#7836) 2025-11-22 09:05:49 +02:00
renovate[bot]
1e5b95f64a fix(deps): update dependency better-sqlite3 to v12.4.6 2025-11-22 06:05:44 +00:00
renovate[bot]
097e36677a chore(deps): update dependency stylelint to v16.26.0 2025-11-22 01:42:35 +00:00
renovate[bot]
7e6e10e3ef chore(deps): update dependency express-openid-connect to v2.19.3 2025-11-22 01:40:32 +00:00
Elian Doran
f72ce697a7 Table printing support (#7833) 2025-11-21 23:11:11 +02:00
Lucas
e6843bc3e0 Merge branch 'main' into main 2025-11-21 12:40:52 -08:00
Elian Doran
5c0cf09c42 chore(print/table): revert back to using the export module only 2025-11-21 22:35:29 +02:00
Elian Doran
ab14bdbb18 chore(print/table): address review 2025-11-21 22:33:48 +02:00
Elian Doran
8dc43dab59 docs(user): update printing documentation 2025-11-21 22:28:43 +02:00
Elian Doran
0c5a6a7548 feat(print/table): integrate with the printing mechanism 2025-11-21 22:17:54 +02:00
Elian Doran
779e2f4633 chore(print/table): monochrome checkboxes 2025-11-21 22:15:56 +02:00
Elian Doran
644e3e200d chore(print/table): stop copying styles and apply own 2025-11-21 22:15:01 +02:00
Elian Doran
670cc474a4 chore(print/table): grayed out table headers 2025-11-21 22:13:55 +02:00
Elian Doran
c43820776f fix(print/table): missing title 2025-11-21 22:12:05 +02:00
Elian Doran
749740242e fix(print/table) formatters not rendering 2025-11-21 22:09:07 +02:00
Elian Doran
f864746b54 feat(print/table): render using internal mechanism 2025-11-21 22:05:22 +02:00
lzinga
42dcd4750a Merge branch 'main' of https://github.com/lzinga/Trilium 2025-11-21 12:00:03 -08:00
lzinga
cb0c6a344f Fixed missing comma 2025-11-21 11:59:57 -08:00
Lucas
d1d652495d Add default value for CORSRESOURCEPOLICY
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-21 11:55:48 -08:00
lzinga
4b574cecf7 feat(config): add CORS Resource Policy environment variable documentation 2025-11-21 11:39:08 -08:00
lzinga
e7dbaf78b5 feat(config): add CORS Resource Policy configuration 2025-11-21 11:30:29 -08:00
Elian Doran
6f83b932b0 feat(print/table): basic implementation using export module 2025-11-21 21:28:42 +02:00
Elian Doran
4552b2b158 fix(geomap): marker color not respected 2025-11-21 20:50:06 +02:00
Elian Doran
5b708e77aa fix(client/text): wrong strike-through of nested TODOs 2025-11-21 20:20:52 +02:00
Elian Doran
a3f1e46107 Merge branch 'main' of https://github.com/TriliumNext/Trilium into feature/print_progress_reporting 2025-11-21 20:16:43 +02:00
Elian Doran
097808752d feat(client/print): report progress for presentation printing 2025-11-21 20:15:27 +02:00
Elian Doran
39be268969 chore(client/print): fix types 2025-11-21 20:14:44 +02:00
Elian Doran
6023d53506 feat(print): report progress on export to PDF as well 2025-11-21 20:05:43 +02:00
Elian Doran
1a6e653600 feat(print): support progress report on electron 2025-11-21 19:57:13 +02:00
Elian Doran
586c707e51 feat(print): display progress in toast 2025-11-21 12:24:01 +02:00
Elian Doran
6ca941e8e9 chore(print): basic infrastructure to support reporting progress 2025-11-21 12:06:32 +02:00
Elian Doran
b83675cdd0 chore(deps): update vitest monorepo to v4.0.12 (#7818) 2025-11-21 09:18:46 +02:00
Elian Doran
1a583913a7 chore(css): fix overly narrow empty tab layout on mobile (#7824) 2025-11-21 09:17:43 +02:00
SiriusXT
d98a644b75 chore(css): fix overly narrow empty tab layout on mobile 2025-11-21 14:44:09 +08:00
renovate[bot]
11c0c93fe2 chore(deps): update vitest monorepo to v4.0.12 2025-11-21 06:41:27 +00:00
Elian Doran
6d78867d69 Translations update from Hosted Weblate (#7815) 2025-11-21 08:38:39 +02:00
Flowerlywind
54813b8b93 Translated using Weblate (Vietnamese)
Currently translated at 3.3% (55 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/vi/
2025-11-21 06:38:13 +00:00
pythaac
6ab31c67fc Translated using Weblate (Korean)
Currently translated at 38.8% (59 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-21 06:38:12 +00:00
green
69af2ff7e8 Translated using Weblate (Japanese)
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-21 06:38:11 +00:00
Elian Doran
b505a2a94d chore(deps): update dependency vite to v7.2.4 (#7817) 2025-11-21 08:38:05 +02:00
Elian Doran
6a5fd0d6f0 fix(deps): update dependency marked to v17.0.1 (#7819) 2025-11-21 08:37:44 +02:00
Elian Doran
e21557645b chore(deps): update pnpm to v10.23.0 (#7821) 2025-11-21 08:36:43 +02:00
Elian Doran
28cab146f3 chore(deps): update actions/checkout action to v6 (#7822) 2025-11-21 08:36:17 +02:00
renovate[bot]
43df4ae0e7 chore(deps): update actions/checkout action to v6 2025-11-21 00:20:47 +00:00
renovate[bot]
5037027030 chore(deps): update pnpm to v10.23.0 2025-11-21 00:20:40 +00:00
renovate[bot]
5e11684665 fix(deps): update dependency marked to v17.0.1 2025-11-21 00:20:02 +00:00
renovate[bot]
c7793beb0f chore(deps): update dependency vite to v7.2.4 2025-11-21 00:18:58 +00:00
Adorian Doran
33b9e6d0c1 Add support for changing note colors via UI (#7795) 2025-11-21 02:16:25 +02:00
Adorian Doran
d87e8b729f client/note color picker/clear color cell: fix icon alignment 2025-11-21 02:12:52 +02:00
Adorian Doran
0db08f4c62 client/note color picker: decrease the debouncer interval 2025-11-21 01:30:45 +02:00
Adorian Doran
e9796c9a35 client/note color picker: fix the custom color picker on Safari 2025-11-21 01:29:54 +02:00
Adorian Doran
36350bd71a Merge branch 'main' of https://github.com/TriliumNext/Trilium into feat/ui/note-color 2025-11-21 00:02:51 +02:00
Adorian Doran
e53a2255a9 client/tree context menu: relocate the note color picker 2025-11-20 23:55:26 +02:00
Adorian Doran
d42f911df9 client/note color picker: dismiss the menu when a color is clicked 2025-11-20 23:43:08 +02:00
Adorian Doran
1b2d922c3f client/note color picker: tweak style 2025-11-20 23:37:03 +02:00
Adorian Doran
a5c5486474 client/note color picker: tweak style 2025-11-20 23:34:37 +02:00
Adorian Doran
926f0f85f3 client/note color picker: refactor 2025-11-20 23:10:36 +02:00
Elian Doran
63d430c3d9 Translations update from Hosted Weblate (#7811) 2025-11-20 21:54:00 +02:00
Elian Doran
26a009b397 Printable list collection (#7812) 2025-11-20 21:52:55 +02:00
Elian Doran
be115c74c3 chore(print/list): address review 2025-11-20 21:42:50 +02:00
Elian Doran
049721bbfe docs(user): update limitations for printing/exporting 2025-11-20 21:32:06 +02:00
Elian Doran
8b4e76832f docs(user): update documentation regarding printing multiple notes 2025-11-20 21:28:55 +02:00
Elian Doran
25a51a71a0 feat(print/list): unlink references to notes that are not printed 2025-11-20 21:20:24 +02:00
Elian Doran
f4d6e98d61 feat(print/list): rewrite links 2025-11-20 21:06:25 +02:00
Elian Doran
eee496a050 chore(print/list): get rid of inner div 2025-11-20 20:59:34 +02:00
Elian Doran
89a83a625b refactor(print/list): extract into functions 2025-11-20 20:58:50 +02:00
Elian Doran
c17df24a19 refactor(print/list): use separate file 2025-11-20 20:56:55 +02:00
Elian Doran
bbcc2f4be4 feat(print/list): rewrite headings while preserving depth 2025-11-20 20:51:41 +02:00
Elian Doran
5e63d9015f feat(print/list): start rewriting headings 2025-11-20 20:48:39 +02:00
Elian Doran
4958b89636 feat(print/list): process notes recursively 2025-11-20 20:31:45 +02:00
Elian Doran
f4b6e9c25a feat(print/list): display parent note title 2025-11-20 20:27:01 +02:00
Elian Doran
a59d407f12 fix(print/list): note content not shown due to race condition 2025-11-20 20:24:19 +02:00
Elian Doran
c95cb79672 chore(print/list): enable print dialog 2025-11-20 20:17:20 +02:00
Elian Doran
73e7fa0f85 chore(print/list): get note content to render 2025-11-20 20:15:44 +02:00
Elian Doran
7f81b83955 chore(print/list): get note titles to render 2025-11-20 20:13:20 +02:00
Hosted Weblate
a42ae62042 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-20 19:03:46 +01:00
Elian Doran
165357f444 fix(global_menu): uncaught exception if update request fails (closes #5700) 2025-11-20 19:52:13 +02:00
Adorian Doran
e4c928ae87 client/note color picker: refactor 2025-11-20 19:11:51 +02:00
Elian Doran
d51e3de674 feat(text): strike-through todo items (closes #4269) 2025-11-20 19:10:54 +02:00
Adorian Doran
b0476c7017 client/note color picker: refactor 2025-11-20 18:49:47 +02:00
Adorian Doran
1de9f715fa client/note color picker: refactor 2025-11-20 18:46:27 +02:00
Adorian Doran
f15e048763 client/note color picker menu item: refactor stylesheet 2025-11-20 18:43:16 +02:00
Adorian Doran
422b324f7c client/note color picker menu item: add tooltips 2025-11-20 18:15:56 +02:00
Adorian Doran
fb163367d4 client/note color picker menu item: refactor 2025-11-20 17:50:32 +02:00
Adorian Doran
c91eec8b3e client/note color picker menu item: add a new color to the palette 2025-11-20 17:42:36 +02:00
Elian Doran
c16eee79d4 fix(share): broken reference links in static HTML export 2025-11-20 14:50:52 +02:00
Elian Doran
1e86d85035 fix(share): some reference links appear with [missing note] 2025-11-20 14:41:00 +02:00
Elian Doran
abfc2fea3e feat(print): render inline mermaid 2025-11-20 14:30:04 +02:00
Elian Doran
991d61600d fix(server): redundant CSS import (closes #7772) 2025-11-20 14:30:04 +02:00
Elian Doran
0f4713bddc chore(deps): update dependency @smithy/middleware-retry to v4.4.12 (#7796) 2025-11-20 11:25:40 +02:00
Elian Doran
51205fffa0 fix(deps): update dependency i18next to v25.6.3 (#7801) 2025-11-20 11:24:27 +02:00
renovate[bot]
9f4fd92452 fix(deps): update dependency i18next to v25.6.3 2025-11-20 06:54:46 +00:00
Elian Doran
354fccab8b Translations update from Hosted Weblate (#7803) 2025-11-20 08:53:02 +02:00
yunus uçan
a6ba87c2f8 Translated using Weblate (Turkish)
Currently translated at 4.3% (70 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/tr/
2025-11-20 07:52:04 +01:00
yunus uçan
ae8aa0374f Translated using Weblate (Turkish)
Currently translated at 3.0% (12 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/tr/
2025-11-20 07:52:03 +01:00
yunus uçan
dc5e073715 Translated using Weblate (Turkish)
Currently translated at 3.2% (5 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/tr/
2025-11-20 07:52:03 +01:00
Hosted Weblate
8c68ff5419 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-20 07:52:02 +01:00
Elian Doran
bc10408729 chore(deps): update dependency @stylistic/eslint-plugin to v5.6.1 (#7797) 2025-11-20 08:51:54 +02:00
renovate[bot]
96b059f657 chore(deps): update dependency @smithy/middleware-retry to v4.4.12 2025-11-20 06:51:48 +00:00
Elian Doran
4db2ae53cb chore(deps): update dependency lint-staged to v16.2.7 (#7799) 2025-11-20 08:51:27 +02:00
Elian Doran
f7308f53d3 chore(deps): update dependency rimraf to v6.1.2 (#7800) 2025-11-20 08:51:00 +02:00
Elian Doran
17fbd78b97 chore(deps): update dependency electron to v38.7.1 (#7798) 2025-11-20 08:50:42 +02:00
Elian Doran
3ad03ebc1d fix(deps): update dependency react-i18next to v16.3.5 (#7802) 2025-11-20 08:49:42 +02:00
renovate[bot]
32e4e69930 fix(deps): update dependency react-i18next to v16.3.5 2025-11-20 02:04:09 +00:00
renovate[bot]
b20f7aca53 chore(deps): update dependency rimraf to v6.1.2 2025-11-20 02:01:35 +00:00
renovate[bot]
e72ee606fd chore(deps): update dependency lint-staged to v16.2.7 2025-11-20 02:01:27 +00:00
renovate[bot]
1386d1ae32 chore(deps): update dependency electron to v38.7.1 2025-11-20 02:00:10 +00:00
renovate[bot]
903d678f30 chore(deps): update dependency @stylistic/eslint-plugin to v5.6.1 2025-11-20 01:59:14 +00:00
Adorian Doran
828a786414 client/note color picker menu item: improve 2025-11-20 01:35:44 +02:00
Elian Doran
3ee8e7b755 fix(server): note type not changed for webview template (closes #7557) 2025-11-19 22:37:41 +02:00
Elian Doran
0d0448d86b fix(scripting): RightPanelWidget requiring async doRenderBody (closes #7778) 2025-11-19 22:10:42 +02:00
Elian Doran
5da4762f40 Translations update from Hosted Weblate (#7793) 2025-11-19 17:20:26 +02:00
Elian Doran
36bcb2ce92 Update apps/client/src/translations/it/translation.json
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-19 17:19:27 +02:00
anotheranonymoususer
151d7c1ba5 Translated using Weblate (Czech)
Currently translated at 3.2% (53 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-11-19 13:51:17 +01:00
Giovi
19d444e387 Translated using Weblate (Italian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/it/
2025-11-19 13:51:16 +01:00
Giovi
e41c718bb3 Translated using Weblate (Italian)
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-11-19 13:51:16 +01:00
Elian Doran
2e5d91a5bc chore(share): fix escape in reference link and handling of attachment links 2025-11-19 09:19:02 +02:00
Elian Doran
ae184ab894 feat(share): display note icon in reference links 2025-11-19 09:07:33 +02:00
Elian Doran
1ceedf2372 fix(share): missing or protected notes leaking through reference links (closes #4801) 2025-11-19 08:59:52 +02:00
Elian Doran
416c05ed3b fix(share): footer navigation doesn't respect #shareHiddenFromTree (closes #7781) 2025-11-19 08:43:57 +02:00
Elian Doran
623da7eade fix(share): syntax highlighting doesn't unescape properly (closes #7783) 2025-11-19 08:34:25 +02:00
Elian Doran
84b3d6db76 fix(tree): fix failure to auto-activate hoisted note (#7782) 2025-11-19 08:20:21 +02:00
Elian Doran
25a27c9b11 fix(tree): keep moved notes always visible (#7776) 2025-11-19 08:19:08 +02:00
Elian Doran
456d59f582 chore(deps): update typescript-eslint monorepo to v8.47.0 (#7789) 2025-11-19 08:12:37 +02:00
Elian Doran
1d641cdf82 chore(deps): update dependency @vitest/coverage-v8 to v4 (#7790) 2025-11-19 07:36:44 +02:00
Elian Doran
4420d7962e chore(deps): update dependency @stylistic/eslint-plugin to v5.6.0 (#7788) 2025-11-19 07:35:25 +02:00
Elian Doran
21e6e3df3f chore(deps): update dependency @anthropic-ai/sdk to v0.70.0 (#7787) 2025-11-19 07:34:19 +02:00
renovate[bot]
7e04098971 chore(deps): update typescript-eslint monorepo to v8.47.0 2025-11-19 05:33:42 +00:00
Elian Doran
24df4dd0c1 fix(deps): update dependency @codemirror/view to v6.38.8 (#7786) 2025-11-19 07:33:27 +02:00
Elian Doran
8ed87e77be chore(deps): update vitest monorepo to v4.0.10 (#7785) 2025-11-19 07:32:35 +02:00
renovate[bot]
10c0ce26dc chore(deps): update vitest monorepo to v4.0.10 2025-11-19 05:32:11 +00:00
Elian Doran
3a38b59dad chore(deps): update dependency webdriverio to v9.20.1 (#7784) 2025-11-19 07:29:49 +02:00
SiriusXT
24820b914c chore(e2e): add tests for tree 2025-11-19 12:15:18 +08:00
renovate[bot]
97339fd45d chore(deps): update dependency @vitest/coverage-v8 to v4 2025-11-19 01:57:00 +00:00
renovate[bot]
a1314d645b chore(deps): update dependency @stylistic/eslint-plugin to v5.6.0 2025-11-19 01:56:29 +00:00
renovate[bot]
571a4dca7a chore(deps): update dependency @anthropic-ai/sdk to v0.70.0 2025-11-19 01:56:25 +00:00
renovate[bot]
36f5e62537 fix(deps): update dependency @codemirror/view to v6.38.8 2025-11-19 01:56:02 +00:00
renovate[bot]
a21b716d0a chore(deps): update dependency webdriverio to v9.20.1 2025-11-19 01:55:11 +00:00
Adorian Doran
c25859cee9 client/debouncer: report pending updates before destroying 2025-11-19 00:57:45 +02:00
Adorian Doran
79dc5e4344 client/note color picker menu item: tweak style 2025-11-19 00:53:18 +02:00
perfectra1n
3957d789da feat(fts5): also create an fts5 index for attributes, and allow them to be searchable using fts5 indexes 2025-11-18 13:08:11 -08:00
perfectra1n
15719a1ee9 fix(fts5): correctly allow for exact word searches with fts5 2025-11-18 13:07:51 -08:00
Adorian Doran
c81aef6d05 client/note color picker menu item: update the color palette 2025-11-18 22:18:15 +02:00
Elian Doran
c744e36f3b fix(deps): update dependency marked to v17 (#7652) 2025-11-18 20:39:02 +02:00
Elian Doran
9d96b3d1d0 Merge branch 'renovate/marked-17.x' of https://github.com/TriliumNext/Trilium into renovate/marked-17.x 2025-11-18 20:17:35 +02:00
Elian Doran
b246c638fd fix(import/markdown): TODO not properly handled after upgrade 2025-11-18 20:17:34 +02:00
renovate[bot]
15dd8dfe8c fix(deps): update dependency marked to v17 2025-11-18 18:11:35 +00:00
Elian Doran
50859fd661 Merge remote-tracking branch 'origin/main' into renovate/marked-17.x 2025-11-18 20:10:33 +02:00
Elian Doran
eada994a82 chore(server): remove unnecessary js-yaml dependency 2025-11-18 20:08:47 +02:00
Elian Doran
3da2046fa0 chore(deps): update vitest monorepo to v4 (major) (#7509) 2025-11-18 20:07:36 +02:00
Elian Doran
989ca08c94 test(server): increase global hook timeout 2025-11-18 19:50:15 +02:00
Elian Doran
e9ccd7120d test(server): mocks in AI service manager 2025-11-18 19:47:45 +02:00
Elian Doran
c15ae293aa test(server): LLM provider tests failing due to mocks 2025-11-18 19:39:11 +02:00
Elian Doran
50501aef56 test: fix typecheck issues by using classes 2025-11-18 19:21:33 +02:00
Adorian Doran
45747183e7 client/refactor: extract the debouncer to a separate module 2025-11-18 19:20:17 +02:00
Elian Doran
c9424d6f8d Merge remote-tracking branch 'origin/main' into renovate/major-vitest-monorepo 2025-11-18 19:09:53 +02:00
Adorian Doran
5ecd8b41e5 client/note color picker menu item: add support to select a custom color 2025-11-18 19:05:20 +02:00
Adorian Doran
01d6dee9fc client/note color picker menu item: improve label handling 2025-11-18 17:23:57 +02:00
renovate[bot]
12865ac7cc fix(deps): update dependency marked to v17 2025-11-18 14:07:16 +00:00
Elian Doran
362f0b2fe5 fix share url can be broken because of extra slash (#7779) 2025-11-18 16:04:23 +02:00
SiriusXT
9f800df5ad fix(tree): fix failure to auto-activate hoisted note 2025-11-18 19:54:50 +08:00
contributor
e937f1b601 shareUrl: use URL interface instead of string manipulations 2025-11-18 10:32:33 +02:00
contributor
5b387a0b11 fix share url can be broken because of extra slash 2025-11-18 10:22:19 +02:00
SiriusXT
9226b165bd fix(tree): fix error when moving a note to its parent node 2025-11-18 15:37:20 +08:00
SiriusXT
a6586c9d1c fix(tree): keep moved notes always visible 2025-11-18 15:33:32 +08:00
Elian Doran
0a36d759e4 fix(board): extra bottom margin 2025-11-18 09:14:39 +02:00
Elian Doran
328bcd0532 feat(collections): display no children warning for empty presentations 2025-11-18 08:51:47 +02:00
Elian Doran
ec76e9cf2a refactor(collections): fix typecheck and remove generics 2025-11-18 08:49:07 +02:00
Elian Doran
88ae996694 fix(collections): view type not refreshing properly 2025-11-18 08:46:00 +02:00
Elian Doran
d1d1d05ce7 fix(collections): children warning stuck when changing view mode 2025-11-18 08:39:58 +02:00
Elian Doran
c62a03c97b fix(collections): no children warning missing for newly created collection 2025-11-18 08:39:11 +02:00
Elian Doran
65cc57ec03 feat(split): allow closing any split pane (#7763) 2025-11-18 07:35:56 +02:00
Elian Doran
806c9a57fc Translations update from Hosted Weblate (#7777) 2025-11-18 07:33:16 +02:00
Yunho Park
3a18ce0cf9 Translated using Weblate (Korean)
Currently translated at 38.1% (58 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-18 06:31:44 +01:00
anotheranonymoususer
4fde6e1293 Translated using Weblate (Czech)
Currently translated at 3.2% (5 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-18 06:31:43 +01:00
anotheranonymoususer
31b43301a4 Translated using Weblate (Czech)
Currently translated at 13.5% (16 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/cs/
2025-11-18 06:31:42 +01:00
anotheranonymoususer
6a77e412fa Translated using Weblate (Czech)
Currently translated at 3.2% (53 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/cs/
2025-11-18 06:31:41 +01:00
federico
53a6424348 Translated using Weblate (Italian)
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-11-18 06:31:40 +01:00
Francis C.
c8d933469a Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-18 06:31:39 +01:00
Francis C.
e456373671 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-18 06:31:38 +01:00
Elian Doran
afdb806083 chore(deps): update dependency openai to v6.9.1 (#7775) 2025-11-18 07:31:30 +02:00
renovate[bot]
02c63dd22f chore(deps): update dependency openai to v6.9.1 2025-11-18 03:00:14 +00:00
SiriusXT
529f9a2fb9 Merge branch 'main' into siriusbcd_close_split 2025-11-18 09:54:59 +08:00
SiriusXT
6b0bcf93d3 feat(split): improve support for closing any split pane 2025-11-18 09:14:50 +08:00
SiriusXT
13afe33244 fix(tab_manager): correct order when reopening split pane 2025-11-18 09:05:18 +08:00
Adorian Doran
d441bccf8b client/note color picker menu item: refactor 2025-11-18 02:18:14 +02:00
Adorian Doran
e6847355e7 client/note color picker menu item: improve the integration with the tree context menu 2025-11-18 02:12:41 +02:00
Adorian Doran
72051c8660 client/note color picker menu item: add a separator to the tree context menu 2025-11-18 01:24:05 +02:00
Adorian Doran
87afc64f16 client/note color picker menu item: fix current selection 2025-11-18 01:21:26 +02:00
Adorian Doran
870fef3ea6 client/note color picker menu item: fix a typo 2025-11-18 01:17:13 +02:00
Adorian Doran
e5ac8a0a67 client/note color picker menu item: refactor 2025-11-18 01:16:32 +02:00
Adorian Doran
87fcc0afe6 client/note color picker menu item: add to the table row context menu 2025-11-18 01:14:05 +02:00
Adorian Doran
79830870dd client/note color picker menu item: add to the geo map item context menu 2025-11-18 01:13:21 +02:00
Adorian Doran
69ad40c27f client/note color picker menu item: add to the board item context menu 2025-11-18 01:12:28 +02:00
Adorian Doran
1ac7ce00fb client/note color picker menu item: add to the calendar item context menu 2025-11-18 01:11:55 +02:00
Adorian Doran
e239bca0f2 client/note color picker menu item: fix data type 2025-11-18 01:10:10 +02:00
Adorian Doran
8729fe48c3 client/note color picker menu item: add support to operate with note IDs as well 2025-11-18 01:09:22 +02:00
Adorian Doran
441c55eb31 client/note color picker menu item: add initial implementation 2025-11-18 00:09:12 +02:00
Adorian Doran
5291a6856e client: create a placeholder for a color picker menu item 2025-11-17 19:14:34 +02:00
Adorian Doran
e011f99161 client: add support for custom menu items 2025-11-17 18:58:40 +02:00
Elian Doran
64a756cc04 fix(share): mermaid breaking in share (closes #7765) 2025-11-17 17:34:52 +02:00
SiriusXT
f57e90b35c Merge branch 'main' into siriusbcd_close_split 2025-11-17 21:03:54 +08:00
SiriusXT
5a5d242ea0 fix(tab_manager): correct order when reopening split pane 2025-11-17 21:01:21 +08:00
SiriusXT
4afea27fa5 fix(tab_manager): correct order when reopening tabs 2025-11-17 21:00:27 +08:00
Elian Doran
fc8042aa25 Add Traefik configuration documentation (#7769) 2025-11-17 08:30:08 +02:00
Elian Doran
2b6220beb8 docs(user): sync 2025-11-17 08:26:06 +02:00
Elian Doran
78426a6c7b Merge remote-tracking branch 'origin/main' into patch-2 2025-11-17 08:20:18 +02:00
Elian Doran
620e53c255 docs(user): fix broken reference link (see #7766) 2025-11-17 08:19:23 +02:00
Elian Doran
753fc6c769 Calendar: Lock calendar initialDate using label (#7694) 2025-11-17 08:10:36 +02:00
Elian Doran
3d6e1dfc0a fix(deps): update dependency mind-elixir to v5.3.6 (#7771) 2025-11-17 07:30:41 +02:00
renovate[bot]
d92431ad65 fix(deps): update dependency mind-elixir to v5.3.6 2025-11-17 02:06:54 +00:00
SiriusXT
be19d1f5b5 fix(split pane): hide the close button when no split panes exist 2025-11-17 09:24:18 +08:00
perfectra1n
334c7dd27a Merge branch 'main' into feat/rice-searching-with-sqlite
Resolved conflicts by:
- Combining imports from both branches in search.ts (added
hoistedNoteService and beccaService alongside existing ftsSearchService
and log imports)
- Integrating FTS5 search optimization from feature branch with flatText
attribute search logic from main in note_content_fulltext.ts
- Maintained backward compatibility by keeping fallback search
implementation for cases where FTS5 is not available or not suitable
2025-11-16 14:23:01 -08:00
perfectra1n
30da95d75a feat(search): update fulltext search and add stress test improvements
- Modified note_content_fulltext.ts for enhanced search capabilities
- Updated becca_mocking.ts for better test support
- Improved stress-test-populate.ts script
2025-11-16 14:20:46 -08:00
Andrea Santoro
ca08a52998 Fix volume path syntax in Traefik documentation 2025-11-16 22:39:50 +01:00
Andrea Santoro
e54822f3b0 Clarify TRILIUM_NETWORK_TRUSTEDREVERSEPROXY config
Added example IP address for TRILIUM_NETWORK_TRUSTEDREVERSEPROXY.
2025-11-16 22:27:14 +01:00
Andrea Santoro
3863e657ef Update docs/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-16 22:25:06 +01:00
Andrea Santoro
341ef79b49 Update docs/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-16 22:23:39 +01:00
Andrea Santoro
335f34b824 Update docs/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-11-16 22:23:15 +01:00
Andrea Santoro
c864863be4 Add Traefik configuration documentation
Added documentation for configuring Traefik as a reverse proxy with HTTPS support, including example docker-compose configuration.
2025-11-16 22:19:46 +01:00
Elian Doran
c3ebef0dde Translations update from Hosted Weblate (#7762) 2025-11-16 22:10:05 +02:00
Elian Doran
7b7058c77b Translated using Weblate (Romanian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-11-16 21:08:43 +01:00
Elian Doran
192cf9bc26 Translated using Weblate (Romanian)
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-11-16 21:08:43 +01:00
Elian Doran
1cccbcfabe Translated using Weblate (Romanian)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ro/
2025-11-16 21:02:49 +01:00
Elian Doran
a85b37985a Translated using Weblate (Romanian)
Currently translated at 100.0% (118 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/ro/
2025-11-16 21:02:48 +01:00
Elian Doran
8b6b1ee315 Translated using Weblate (Romanian)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ro/
2025-11-16 21:02:47 +01:00
Elian Doran
021c655a1a Translated using Weblate (Romanian)
Currently translated at 100.0% (1625 of 1625 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ro/
2025-11-16 21:02:45 +01:00
Elian Doran
8af8968b49 Internationalization v2 (#7767) 2025-11-16 22:02:37 +02:00
Elian Doran
17298edfcc chore: handle requested changes 2025-11-16 21:32:08 +02:00
Elian Doran
5281e8e5b4 docs(dev): document adding a new locale 2025-11-16 21:24:34 +02:00
Elian Doran
cc0e30e3f5 test(ckeditor): test all languages are mapped correctly 2025-11-16 21:18:34 +02:00
Elian Doran
497bb35209 test(canvas): test all languages are mapped correctly 2025-11-16 21:03:53 +02:00
Elian Doran
7d1453ffbd feat(canvas): add support for locales 2025-11-16 17:49:55 +02:00
Elian Doran
89228f264f feat(mindmap): add support for locales 2025-11-16 17:34:56 +02:00
Elian Doran
a10d99f938 feat(ckeditor5): set up multi-language support 2025-11-16 14:24:07 +02:00
Elian Doran
d014ae4fcf chore(ckeditor5): set up dependency to commons 2025-11-16 14:23:48 +02:00
SiriusXT
a22687e2d8 Merge branch 'main' into siriusbcd_close_split 2025-11-16 20:15:43 +08:00
SiriusXT
44475853df feat(split): allow closing any split pane 2025-11-16 20:12:56 +08:00
Elian Doran
bbcc670655 feat(client/link): render reference links same as in editor 2025-11-16 11:01:37 +02:00
Elian Doran
ae58b4af35 feat(help): render reference links with icon 2025-11-16 11:01:37 +02:00
Elian Doran
fbc2ffac59 chore(deps): update dependency i18next-fs-backend to v2.6.1 (#7760) 2025-11-16 09:23:30 +02:00
renovate[bot]
f279839e6f chore(deps): update dependency i18next-fs-backend to v2.6.1 2025-11-16 02:27:29 +00:00
perfectra1n
09ff9ccc65 feat(dev): add new stress test population script 2025-11-15 16:54:09 -08:00
Elian Doran
1844a7d666 fix(calendar): unable to delete in journal (closes #7702) 2025-11-15 22:43:35 +02:00
Elian Doran
c9f648fcb8 fix(tree): #top/#bottom reversed in desc order (closes #7716) 2025-11-15 22:27:02 +02:00
Elian Doran
948688a4ea fix(note_list): no longer displayed in help or search 2025-11-15 22:05:32 +02:00
Elian Doran
35ca295d48 fix(settings/appearance): font size can't be typed out properly (closes #7740) 2025-11-15 21:38:17 +02:00
Elian Doran
cacc4ad01d Translations update from Hosted Weblate (#7756) 2025-11-15 21:32:13 +02:00
Hosted Weblate
b12085f61f Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-15 19:29:45 +00:00
Elian Doran
39dacafa82 Fix #6696 by using shell.openExternal (#7737) 2025-11-15 21:29:30 +02:00
Elian Doran
57deb36027 Merge branch 'main' into patch-1 2025-11-15 21:24:24 +02:00
Elian Doran
2840df82f4 chore(client): fix typecheck issue 2025-11-15 17:52:08 +02:00
Elian Doran
3d971108b8 chore(ci/docker): update nightly version on main branch 2025-11-15 17:47:20 +02:00
Elian Doran
5bcdce72ef chore(client): remove redundant log 2025-11-15 17:33:06 +02:00
Elian Doran
398329a219 fix(text): insert link sometimes occurs in the wrong tab 2025-11-15 17:32:06 +02:00
Elian Doran
754a06343f Translations update from Hosted Weblate (#7751) 2025-11-15 16:44:12 +02:00
minkipark
55a79e5fbf Translated using Weblate (Korean)
Currently translated at 7.8% (12 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-15 15:36:43 +01:00
Yunho Park
c78a97fed1 Translated using Weblate (Korean)
Currently translated at 7.8% (12 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-15 15:36:43 +01:00
Elian Doran
13c8ff5cb3 Kanban board v3 (#7753) 2025-11-15 16:36:39 +02:00
Elian Doran
9e34d3a668 chore(client): fix typecheck issue 2025-11-15 16:01:30 +02:00
Elian Doran
57f220e64c Apply suggestions from code review
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-15 15:37:00 +02:00
Elian Doran
a89756a76c docs(user): improve documentation on promoted attributes 2025-11-15 15:25:36 +02:00
Elian Doran
88c1aa163e docs(user): working with the note tree in board 2025-11-15 13:41:48 +02:00
Elian Doran
d2184682e5 docs(user): grouping by relation in board 2025-11-15 13:37:24 +02:00
Elian Doran
63cc5b21b4 feat(board): scroll snapping on mobile 2025-11-15 13:06:51 +02:00
Elian Doran
b7703fc4df style(next): use main background color on mobile 2025-11-15 12:52:20 +02:00
Elian Doran
254d3a1c8e fix(board): not reacting to external title changes 2025-11-15 12:42:49 +02:00
Elian Doran
8d3892757a fix(board): not refreshing on status attribute change 2025-11-15 12:37:25 +02:00
Elian Doran
a8992d08b3 fix(board): escape not working in "Add column" 2025-11-15 12:35:10 +02:00
Elian Doran
5e35aa8079 fix(board): columns leaking between notes 2025-11-15 12:24:18 +02:00
Elian Doran
df8da0fd4f feat(board): warn when column already exists 2025-11-15 11:34:01 +02:00
Elian Doran
f820c6f23b feat(board/relation): react to column title changes 2025-11-15 11:28:35 +02:00
Elian Doran
0c616fecdf feat(board/relation): improve relation editing experience 2025-11-15 11:21:23 +02:00
Elian Doran
092a84693f feat(board/relation): basic support for editing relations in columns 2025-11-15 11:13:55 +02:00
Elian Doran
d1e80815d5 feat(board/relation): add support for more APIs 2025-11-15 10:50:55 +02:00
Elian Doran
0f000ccd93 fix(board/relation): not reacting to status change 2025-11-15 10:42:32 +02:00
Elian Doran
f90e0767cb feat(board/relation): allow dragging between columns 2025-11-15 10:26:19 +02:00
Elian Doran
ad6d61f1f7 feat(board/relation): display note titles 2025-11-15 10:17:40 +02:00
Elian Doran
47f7968dc4 feat(board/relation): group by relation 2025-11-15 10:15:11 +02:00
Elian Doran
455b190a5b refactor(client): rename to user attributes 2025-11-15 09:36:18 +02:00
Elian Doran
0bc8584c35 chore(deps): update dependency electron to v38.7.0 (#7748) 2025-11-15 09:01:14 +02:00
Elian Doran
da39cdb27f chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v5.0.1 (#7741) 2025-11-15 09:00:57 +02:00
Elian Doran
769c2e9b4e chore(deps): update dependency @smithy/middleware-retry to v4.4.11 (#7742) 2025-11-15 09:00:48 +02:00
Elian Doran
783d2b8843 chore(deps): update dependency @types/yargs to v17.0.35 (#7743) 2025-11-15 09:00:13 +02:00
Elian Doran
baca0a17c3 chore(deps): update dependency rcedit to v5.0.1 (#7744) 2025-11-15 08:59:50 +02:00
Elian Doran
f48d47bac5 fix(deps): update dependency @codemirror/view to v6.38.7 (#7745) 2025-11-15 08:59:29 +02:00
Elian Doran
14fa5d2723 fix(deps): update dependency color to v5.0.3 (#7746) 2025-11-15 08:58:40 +02:00
Elian Doran
70845611a4 chore(deps): update dependency @anthropic-ai/sdk to v0.69.0 (#7747) 2025-11-15 08:58:20 +02:00
Elian Doran
7be11da85f chore(deps): update dependency node-abi to v4.24.0 (#7749) 2025-11-15 08:56:25 +02:00
renovate[bot]
f2f4b0e75b chore(deps): update dependency node-abi to v4.24.0 2025-11-15 01:04:53 +00:00
renovate[bot]
491cd27f2d chore(deps): update dependency electron to v38.7.0 2025-11-15 01:04:10 +00:00
renovate[bot]
7b62881113 chore(deps): update dependency @anthropic-ai/sdk to v0.69.0 2025-11-15 01:03:30 +00:00
renovate[bot]
22f46919f9 fix(deps): update dependency color to v5.0.3 2025-11-15 01:02:49 +00:00
renovate[bot]
1ef7fd401f fix(deps): update dependency @codemirror/view to v6.38.7 2025-11-15 01:02:07 +00:00
renovate[bot]
5f1dbc23b4 chore(deps): update dependency rcedit to v5.0.1 2025-11-15 01:01:27 +00:00
renovate[bot]
8d750417ec chore(deps): update dependency @types/yargs to v17.0.35 2025-11-15 01:01:22 +00:00
renovate[bot]
52f30052d5 chore(deps): update dependency @smithy/middleware-retry to v4.4.11 2025-11-15 01:00:40 +00:00
renovate[bot]
655e6bafd1 chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v5.0.1 2025-11-15 00:59:58 +00:00
Elian Doran
d4dfb0cb53 Translations update from Hosted Weblate (#7738) 2025-11-14 18:19:39 +02:00
Hosted Weblate
8d08973d48 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-14 15:38:37 +00:00
Elian Doran
9b1b56a381 fix NoteLink component is unable to display path for root note (#7736) 2025-11-14 17:38:19 +02:00
laund
f709c27329 use shell.openExternal for URI protocol handling, clean up and unify logic 2025-11-14 15:31:51 +01:00
contributor
02859039ec fix NoteLink component is unable to display path for root note 2025-11-14 16:02:43 +02:00
Elian Doran
e6810ef753 Fix toggle tray wont restore from tray (#7735) 2025-11-14 11:57:31 +02:00
contributor
ef86e195c6 remove constant and import, it is type safe as is #7730 2025-11-14 11:45:44 +02:00
contributor
d69dd2a83f handle toggleTray global shortcut differently from other global shortcuts #7730 2025-11-14 11:45:39 +02:00
Elian Doran
5dd21ac539 fix(flake): upgrade to Nodejs 24 (#7732) 2025-11-14 10:53:47 +02:00
FliegendeWurst
bd6575982b fix(flake): revert pname to just trilium-* 2025-11-14 08:54:25 +01:00
FliegendeWurst
80313527c5 fix(flake): upgrade to Nodejs 24
This ensures consistency with the main server build.
2025-11-14 08:53:40 +01:00
Elian Doran
78901e03d7 fix markdown headings are rendered with extra character (#7720) 2025-11-14 08:28:56 +02:00
Elian Doran
01c1b19601 chore(deps): update dependency openai to v6.9.0 (#7727) 2025-11-14 08:27:10 +02:00
Elian Doran
1d837092a2 Translations update from Hosted Weblate (#7731) 2025-11-14 08:26:47 +02:00
Elian Doran
bde04919fe chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v5 (#7729) 2025-11-14 08:26:14 +02:00
Hosted Weblate
0dd0416346 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-14 06:25:56 +00:00
Yunho Park
711dd64093 Translated using Weblate (Korean)
Currently translated at 3.9% (6 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/ko/
2025-11-14 06:25:47 +00:00
Hosted Weblate
db7b4829b5 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-14 06:25:46 +00:00
Elian Doran
f97c63fe93 chore(deps): update ckeditor5 config packages to v13 (major) (#7728) 2025-11-14 08:25:38 +02:00
renovate[bot]
cb5fe95768 chore(deps): update dependency openai to v6.9.0 2025-11-14 06:25:29 +00:00
Elian Doran
34359dd7b6 fix(deps): update dependency react-i18next to v16.3.3 (#7725) 2025-11-14 08:24:40 +02:00
Elian Doran
476d1d274e chore(deps): update dependency node-abi to v4.23.0 (#7726) 2025-11-14 08:24:07 +02:00
Elian Doran
c52265c046 fix(deps): update dependency @mind-elixir/node-menu to v5.0.1 (#7724) 2025-11-14 08:23:26 +02:00
Elian Doran
4fbf3d79c7 chore(deps): update dependency ollama to v0.6.3 (#7723) 2025-11-14 08:22:51 +02:00
renovate[bot]
e8cc92db95 chore(deps): update dependency @ckeditor/ckeditor5-package-tools to v5 2025-11-14 02:38:29 +00:00
renovate[bot]
40e969bab9 chore(deps): update ckeditor5 config packages to v13 2025-11-14 02:37:48 +00:00
renovate[bot]
3df2105016 chore(deps): update dependency node-abi to v4.23.0 2025-11-14 02:36:26 +00:00
renovate[bot]
0aa3cc3d6f fix(deps): update dependency react-i18next to v16.3.3 2025-11-14 02:35:52 +00:00
renovate[bot]
666f26f516 fix(deps): update dependency @mind-elixir/node-menu to v5.0.1 2025-11-14 02:35:12 +00:00
renovate[bot]
7662dde294 chore(deps): update dependency ollama to v0.6.3 2025-11-14 02:34:31 +00:00
contributor
d28dda876c fix markdown headings are rendered with extra character 2025-11-13 23:18:38 +02:00
Elian Doran
1ca46e3505 Fix enex import stores wrong format in database for dateCreated, dateModified (#7718) 2025-11-13 20:48:09 +02:00
Elian Doran
6b6dc47f2b Translations update from Hosted Weblate (#7714) 2025-11-13 20:43:39 +02:00
contributor
98b5b81d7d add typing and improve readability 2025-11-13 20:33:03 +02:00
contributor
48a20500f8 explicit param to keep or convert local date for enex import 2025-11-13 20:13:46 +02:00
contributor
a3bd15e102 move date conversion function to enex directly
to protect from future potential refactoring
2025-11-13 17:41:45 +00:00
contributor
f728b2b0e7 fix enex import saves local dates in wrong format (with Z, like UTC fields)
the proper format for dateCreated, dateModified is: +0000
2025-11-13 17:41:45 +00:00
Magnus Johansson
50dfd1d329 Translated using Weblate (Swedish)
Currently translated at 4.2% (5 of 118 strings)

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/sv/
2025-11-13 13:47:27 +00:00
kamykO
c0375b34fd Translated using Weblate (Polish)
Currently translated at 100.0% (152 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/pl/
2025-11-13 13:47:27 +00:00
Dong-ha, Lee
d8e7832f07 Translated using Weblate (Korean)
Currently translated at 15.6% (61 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-11-13 13:47:26 +00:00
green
f2415916aa Translated using Weblate (Japanese)
Currently translated at 100.0% (1624 of 1624 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-13 13:47:25 +00:00
Francis C.
7f67b2a1ee Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hant/
2025-11-13 13:47:23 +00:00
Francis C.
bc9ad5012e Translated using Weblate (Chinese (Traditional Han script))
Currently translated at 100.0% (1624 of 1624 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hant/
2025-11-13 13:47:23 +00:00
Francis C.
096deda23c Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/zh_Hans/
2025-11-13 13:47:22 +00:00
qingmo_dev
8b5544268b Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1624 of 1624 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-13 13:47:21 +00:00
Francis C.
d492c0e091 Translated using Weblate (Chinese (Simplified Han script))
Currently translated at 100.0% (1624 of 1624 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/zh_Hans/
2025-11-13 13:47:20 +00:00
Elian Doran
20b301ac0e fix(collections/list): archived notes not shown on first render 2025-11-13 10:59:56 +02:00
Elian Doran
bacbe9f47c chore(collections/list): style archived notes differently 2025-11-13 10:35:39 +02:00
Elian Doran
4ecb693be5 chore(collections/list): use more performant mechanism for searching by note ID 2025-11-13 10:26:47 +02:00
Elian Doran
454310c3e4 feat(collections/list): enable "Show archived notes" checkmark in collections 2025-11-13 10:24:57 +02:00
Elian Doran
e51daad5da feat(collections/list): filter archived notes 2025-11-13 10:21:45 +02:00
Elian Doran
b13c0fe7a2 refactor(board/promoted_attributes): reduce duplication 2025-11-13 09:56:47 +02:00
Elian Doran
3036d18df5 feat(board/promoted_attributes): improve rendering for color badge 2025-11-13 09:56:47 +02:00
Elian Doran
5dbe9e7da6 feat(board/promoted_attributes): render non-promoted attribute defs too 2025-11-13 09:56:47 +02:00
Elian Doran
fd9b6e9e67 fix(board/promoted_attributes): status attribute displayed when it shouldn't 2025-11-13 09:56:46 +02:00
Elian Doran
4f580a37a3 fix(quick_search): resolve word issues to not trigger substring matches (#7708) 2025-11-13 09:53:14 +02:00
Elian Doran
f64d11b7c8 chore(deps): update dependency @smithy/middleware-retry to v4.4.10 (#7709) 2025-11-13 09:42:30 +02:00
Elian Doran
2bf9e0edd9 chore(deps): update dependency js-yaml to v4.1.1 (#7710) 2025-11-13 09:42:18 +02:00
Elian Doran
b807079c55 chore: add class name to content-header (#7713) 2025-11-13 09:41:35 +02:00
SiriusXT
2cc5b896e0 Merge branch 'main' into share 2025-11-13 14:24:04 +08:00
SiriusXT
7c79caba78 chore: add class name to content-header 2025-11-13 14:21:07 +08:00
Elian Doran
fbf4a910fa Merge branch 'main' into renovate/smithy-middleware-retry-4.x 2025-11-13 08:07:46 +02:00
Elian Doran
95947a9f8c chore(deps): update node.js to v24.11.1 (#7697) 2025-11-13 07:43:55 +02:00
Elian Doran
1c05acf5ed fix(deps): update dependency react-i18next to v16.3.1 (#7712) 2025-11-13 07:43:18 +02:00
Elian Doran
5cc5f3ffae chore(deps): update pnpm to v10.22.0 (#7711) 2025-11-13 07:42:47 +02:00
renovate[bot]
54556c73e2 fix(deps): update dependency react-i18next to v16.3.1 2025-11-13 01:08:04 +00:00
renovate[bot]
5aa63ac50c chore(deps): update pnpm to v10.22.0 2025-11-13 01:07:17 +00:00
renovate[bot]
38eaa94a53 chore(deps): update node.js to v24.11.1 2025-11-13 01:07:05 +00:00
renovate[bot]
7810f6c8da chore(deps): update dependency js-yaml to v4.1.1 2025-11-13 01:06:16 +00:00
renovate[bot]
6d94efb6c8 chore(deps): update dependency @smithy/middleware-retry to v4.4.10 2025-11-13 01:05:36 +00:00
perfectra1n
e89646ee7c fix(quick_search): centralize the repeated exactWordMatch function, per Gemini's suggestion 2025-11-12 16:49:43 -08:00
perfectra1n
dee8c115ab fix(quick_search): resolve word issues to not trigger substring matches 2025-11-12 16:43:59 -08:00
Elian Doran
54d3936c7b feat(board/promoted_attributes): support multiple values 2025-11-12 21:06:44 +02:00
Elian Doran
02452a0513 feat(board/promoted_attributes): display relations with icon 2025-11-12 21:01:53 +02:00
Elian Doran
e9f40c48e3 feat(board/promoted_attributes): basic support for color attributes 2025-11-12 20:56:15 +02:00
Elian Doran
6b74b227cb feat(board/promoted_attributes): format URL 2025-11-12 20:50:01 +02:00
Elian Doran
00874840b7 feat(board/promoted_attributes): format time 2025-11-12 20:48:45 +02:00
Elian Doran
d79a23bc9e feat(board/promoted_attributes): format boolean 2025-11-12 20:42:30 +02:00
Elian Doran
3015576d7e feat(board/promoted_attributes): format date & time 2025-11-12 20:34:48 +02:00
Elian Doran
46c2e162f0 feat(board/promoted_attributes): format number with precision 2025-11-12 20:31:27 +02:00
Elian Doran
3c42577da4 feat(board/promoted_attributes): react to changes 2025-11-12 20:27:13 +02:00
Elian Doran
76f791da93 Merge branch 'main' of https://github.com/TriliumNext/Trilium 2025-11-12 19:59:36 +02:00
Elian Doran
0c5adcee2d fix(board): no promoted attributes creates margin 2025-11-12 19:58:42 +02:00
Elian Doran
b11b3ff67f refactor(board): use hook for obtaining the list of attributes 2025-11-12 19:57:28 +02:00
Elian Doran
e006afc5a2 feat(board): display in chip format 2025-11-12 19:38:56 +02:00
Elian Doran
40dbb818c5 feat(board): ignore status attribute 2025-11-12 19:09:59 +02:00
Elian Doran
62dc570d38 feat(board): display promoted attributes 2025-11-12 19:07:23 +02:00
Elian Doran
b759c5e7d2 feat(board): display number of items in column 2025-11-12 18:47:29 +02:00
Diego Herrera
309d7e704c Add feature to docs 2025-11-12 12:58:56 -03:00
Diego Herrera
ecf9ce586c Use NoteLabel instead of CustomisableLabel 2025-11-12 12:43:37 -03:00
Elian Doran
3f93d191b3 Translations update from Hosted Weblate (#7701) 2025-11-12 08:27:40 +02:00
green
3a83e7f632 Translated using Weblate (Japanese)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ja/
2025-11-12 07:18:19 +01:00
green
2acede95d7 Translated using Weblate (Japanese)
Currently translated at 100.0% (1623 of 1623 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/ja/
2025-11-12 07:18:18 +01:00
Unknown
052a60ba58 Translated using Weblate (Spanish)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/es/
2025-11-12 07:18:17 +01:00
Unknown
a633c6eecd Translated using Weblate (Spanish)
Currently translated at 100.0% (1623 of 1623 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/es/
2025-11-12 07:18:16 +01:00
Elian Doran
b6561e6375 "Open note on server" menu item (#7477) 2025-11-12 08:17:53 +02:00
Elian Doran
7af9df2ee3 chore(deps): update dependency @redocly/cli to v2.11.1 (#7695) 2025-11-12 08:08:29 +02:00
Elian Doran
3c4b7fd490 chore(deps): update dependency @smithy/middleware-retry to v4.4.7 (#7696) 2025-11-12 08:08:15 +02:00
Elian Doran
f5ed4007e3 chore(deps): update typescript-eslint monorepo to v8.46.4 (#7698) 2025-11-12 08:07:55 +02:00
Elian Doran
f26469bdc2 fix(deps): update dependency i18next to v25.6.2 (#7699) 2025-11-12 08:07:38 +02:00
Elian Doran
3326d803a0 Translations update from Hosted Weblate (#7700) 2025-11-12 08:07:15 +02:00
Hosted Weblate
b60a28c52c Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-12 05:55:12 +00:00
Elian Doran
139c60ac73 Hotfix (#7679) 2025-11-12 07:54:54 +02:00
renovate[bot]
c7ad6131cb fix(deps): update dependency i18next to v25.6.2 2025-11-12 02:54:22 +00:00
renovate[bot]
86e2a762a4 chore(deps): update typescript-eslint monorepo to v8.46.4 2025-11-12 02:53:34 +00:00
renovate[bot]
bf9f880a21 chore(deps): update dependency @smithy/middleware-retry to v4.4.7 2025-11-12 02:51:14 +00:00
renovate[bot]
5491aaab85 chore(deps): update dependency @redocly/cli to v2.11.1 2025-11-12 02:50:29 +00:00
Diego Herrera
d0de9e5e21 calendar: Lock calendar initialDate using label 2025-11-11 18:06:11 -03:00
Elian Doran
40568ac547 Translations update from Hosted Weblate (#7689) 2025-11-11 13:56:40 +02:00
hulmgulm
0039e5e60c Translated using Weblate (German)
Currently translated at 21.7% (33 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/de/
2025-11-11 11:51:35 +01:00
Ondřej Soldát
813e2e8c9b Translated using Weblate (Czech)
Currently translated at 1.9% (3 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/cs/
2025-11-11 11:51:34 +01:00
Dong-ha, Lee
f186e929b2 Translated using Weblate (Korean)
Currently translated at 10.5% (41 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/ko/
2025-11-11 11:51:25 +01:00
Giovi
31d2abf954 Translated using Weblate (Italian)
Currently translated at 100.0% (389 of 389 strings)

Translation: Trilium Notes/Server
Translate-URL: https://hosted.weblate.org/projects/trilium/server/it/
2025-11-11 11:51:23 +01:00
Giovi
bd69280735 Translated using Weblate (Italian)
Currently translated at 100.0% (1623 of 1623 strings)

Translation: Trilium Notes/Client
Translate-URL: https://hosted.weblate.org/projects/trilium/client/it/
2025-11-11 11:51:21 +01:00
Elian Doran
b86c656895 Note info ribbon flex layout (#7678) 2025-11-10 22:18:05 +02:00
Elian Doran
bc32fe749d chore(deps): update pnpm to v10.21.0 (#7672) 2025-11-10 22:12:20 +02:00
Elian Doran
5970a242c9 chore(deps): update dependency esbuild to v0.27.0 (#7671) 2025-11-10 22:11:36 +02:00
Elian Doran
4fc9848a3b Translations update from Hosted Weblate (#7682) 2025-11-10 20:36:02 +02:00
Hosted Weblate
b8de5b3348 Update translation files
Updated by "Cleanup translation files" add-on in Weblate.

Translation: Trilium Notes/README
Translate-URL: https://hosted.weblate.org/projects/trilium/readme/
2025-11-10 18:29:41 +00:00
Elian Doran
5a01f75d67 edited notes: better sql like statement (#7681) 2025-11-10 20:29:25 +02:00
contributor
d0a994c102 fix sql like pattern 2025-11-10 20:15:08 +02:00
contributor
e883f32f89 edited notes: better sql like statement 2025-11-10 20:04:50 +02:00
Elian Doran
a6fc54cb81 fix(mindmap): switching between read-only and editable mode 2025-11-10 19:59:01 +02:00
Elian Doran
76bd6a5ab9 refactor(mindmap): unnecessary content logic 2025-11-10 19:44:45 +02:00
Elian Doran
3b5d749d86 docs(dev): branching strategy 2025-11-10 19:31:10 +02:00
renovate[bot]
6761f741ca chore(deps): update dependency esbuild to v0.27.0 2025-11-10 13:48:16 +00:00
contributor
a1c959aabd use class instead of inline style for note info calculate button 2025-11-10 13:18:07 +02:00
contributor
4d1ebd011c ribbon Note Info in flex layout instead of table 2025-11-10 13:18:07 +02:00
renovate[bot]
2947967b79 chore(deps): update pnpm to v10.21.0 2025-11-10 02:58:46 +00:00
Adorian Doran
52691b9e88 style/empty note: fix alignment 2025-11-10 03:05:05 +02:00
Adorian Doran
daba806e12 close #7668 2025-11-10 02:09:14 +02:00
Adorian Doran
d7f7049b5d fix #7667 2025-11-10 02:01:45 +02:00
contributor
e811db3651 only show "Open note on server" for electron app 2025-11-10 00:26:28 +02:00
contributor
a1d38b6bb8 add 'Open note on server' menu item to NoteActions drop-down 2025-11-10 00:26:28 +02:00
Elian Doran
c781eab061 Translations update from Hosted Weblate (#7664) 2025-11-09 22:53:15 +02:00
Elian Doran
fb91d4fbd4 docs(user): mention updates after react improvements 2025-11-09 22:52:02 +02:00
Sir-Ivysaur
cd6fcbd283 Translated using Weblate (Indonesian)
Currently translated at 9.8% (15 of 152 strings)

Translation: Trilium Notes/Website
Translate-URL: https://hosted.weblate.org/projects/trilium/website/id/
2025-11-09 20:32:53 +00:00
Elian Doran
0ccc350ddf Port type widgets to React (#7044) 2025-11-09 22:32:35 +02:00
Elian Doran
efa7fd0b7d chore(client): use backward-compatible hiding mechanism 2025-11-09 22:20:49 +02:00
Elian Doran
5f4d0325aa Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-11-09 21:37:56 +02:00
Elian Doran
763fa0b515 fix(client/type_widgets): empty tab not working when closing last tab 2025-11-09 20:41:29 +02:00
Elian Doran
7ba91b7a9d chore(desktop): fix import 2025-11-09 19:36:58 +02:00
Elian Doran
7fc9f08843 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-11-09 19:30:46 +02:00
Elian Doran
e28794d706 chore(edit-docs): fix typecheck 2025-11-09 19:28:08 +02:00
Elian Doran
ae1c8f0a0b chore(client): review from Copilot 2025-11-09 15:13:57 +02:00
Elian Doran
1257e46852 chore(client): review from Gemini 2025-11-09 15:10:40 +02:00
Elian Doran
40a7f286a3 fix(client): typecheck issues 2025-11-09 15:04:29 +02:00
Elian Doran
652cccadd7 fix(type_widgets/code): read-only bar not visible for dark themes 2025-11-09 14:59:47 +02:00
Elian Doran
308fd00508 fix(type_widgets/code): not reacting to language changes 2025-11-09 14:48:31 +02:00
Elian Doran
35f413505c fix(type_widgets/code): background color leaking in SQLite 2025-11-09 14:40:14 +02:00
Elian Doran
a82d15e83d fix(type_widgets/attachments): attachments not refreshing when uploading new revision 2025-11-09 14:26:32 +02:00
Elian Doran
24b169d667 fix(type_widgets): "empty" note type displayed on refresh 2025-11-09 13:52:07 +02:00
Elian Doran
b36ef54507 fix(type_widgets): code background leaking when switching types 2025-11-09 13:37:31 +02:00
Elian Doran
c772430dd0 fix(type_widgets): switching between note types shows wrong content 2025-11-09 13:24:12 +02:00
Elian Doran
d4194c503c fix(type_widgets/relation_map): map emptied when switching fast 2025-11-09 12:38:12 +02:00
Elian Doran
33a41d2f86 Merge remote-tracking branch 'origin/main' into react/type_widgets
; Conflicts:
;	apps/client/src/layouts/desktop_layout.tsx
;	apps/client/src/layouts/mobile_layout.tsx
;	apps/client/src/widgets/note_detail.ts
;	apps/client/src/widgets/react/hooks.tsx
2025-11-09 12:08:50 +02:00
Elian Doran
319e28387f refactor(react/type_widgets): separate persistence from canvas 2025-11-06 15:44:09 +02:00
Elian Doran
0b740bb007 chore(react/type_widgets): remove logging 2025-11-06 12:05:38 +02:00
Elian Doran
bb7fa9a2e6 fix(react/type_widgets): unable to switch to notes of same note type 2025-11-06 12:02:48 +02:00
Elian Doran
5e83e6fa34 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-11-06 11:40:04 +02:00
Elian Doran
2154a5e1db Merge remote-tracking branch 'origin/main' into renovate/major-vitest-monorepo 2025-11-05 21:24:45 +02:00
Elian Doran
dbe51ccaf3 Fix LLM streaming test race conditions after Vite update (#7629) 2025-11-05 21:20:11 +02:00
copilot-swe-agent[bot]
993d53ed97 Complete vi.waitFor() migration for all async streaming tests
Replaced all remaining setTimeout calls with vi.waitFor() for consistency and reliability.

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-05 18:21:48 +00:00
copilot-swe-agent[bot]
730e2da932 Improve test reliability by using vi.waitFor() for async checks
Replaced hardcoded timeouts with vi.waitFor() for better test reliability.

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-05 18:19:55 +00:00
copilot-swe-agent[bot]
18a198496b Fix syntax errors in LLM service test mocks
Fixed vi.mock() syntax errors that were preventing tests from running.

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-05 18:16:47 +00:00
copilot-swe-agent[bot]
5eb791fd65 Fix LLM streaming test race conditions after Vite update
Added waits for async streaming operations in tests and reduced concurrent request count to 2 for reliability.

Co-authored-by: eliandoran <21236836+eliandoran@users.noreply.github.com>
2025-11-05 18:12:52 +00:00
copilot-swe-agent[bot]
27cc022fb8 Initial plan 2025-11-05 17:46:45 +00:00
perf3ct
5f1773609f fix(tests): rename some of the silly-ily named tests 2025-11-04 15:56:49 -08:00
perf3ct
da0302066d fix(tests): resolve issues with new search tests not passing 2025-11-04 15:55:42 -08:00
perf3ct
942647ab9c fix(search): get rid of exporting dbConnection 2025-11-04 14:47:46 -08:00
perf3ct
b8aa7402d8 feat(tests): create a ton of tests for the various search capabilities that we support 2025-11-04 14:34:50 -08:00
perf3ct
052e28ab1b feat(search): if the search is empty, return all notes 2025-11-04 11:59:41 -08:00
perf3ct
16912e606e fix(search): resolve compilation issue due to performance log in new search 2025-11-03 12:04:00 -08:00
Jon Fuller
321752ac18 Merge branch 'main' into feat/rice-searching-with-sqlite 2025-11-03 11:47:44 -08:00
Elian Doran
35f244cf50 chore(deps): adapt most of the tests 2025-11-01 19:21:57 +02:00
Elian Doran
fa30bfc04b chore(deps): fix typecheck issues 2025-11-01 18:26:43 +02:00
Elian Doran
a072466f75 chore(deps): adapt to vite major upgrade 2025-11-01 18:18:49 +02:00
Elian Doran
ae5c898537 Merge branch 'main' into renovate/major-vitest-monorepo 2025-11-01 16:51:38 +02:00
renovate[bot]
921a37f4a2 chore(deps): update vitest monorepo to v4 2025-11-01 12:11:35 +00:00
perf3ct
10988095c2 feat(search): get the correct comparison and rice out the fts5 search 2025-10-27 14:37:44 -07:00
Elian Doran
8828e36624 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-10-26 20:19:47 +02:00
perf3ct
253da139de feat(search): try again to get fts5 searching done well 2025-10-24 21:47:06 -07:00
Jon Fuller
d992a5e4a2 Merge branch 'main' into feat/rice-searching-with-sqlite 2025-10-24 09:18:11 -07:00
Elian Doran
bca0846565 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-10-10 23:05:45 +03:00
Elian Doran
8fef28dcc7 chore(docs): revert changes to documentation 2025-10-10 22:48:20 +03:00
Elian Doran
040ffe945a Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-10-10 22:46:53 +03:00
Elian Doran
4997543fc7 doc(guide): interaction on relation map, including tree operation 2025-10-05 20:19:18 +03:00
Elian Doran
63c91b6741 Revert "fix(deps): downgrade mind-elixir (closes #7170)"
This reverts commit 5969815ed1.
2025-10-05 20:00:08 +03:00
Elian Doran
27b6e26fa5 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-10-05 19:59:46 +03:00
Elian Doran
7930745a01 chore(react/type_widgets): fix type errors 2025-10-05 19:55:25 +03:00
Elian Doran
6ffe8a2eb5 chore(react/type_widgets): save on window closing 2025-10-05 18:12:36 +03:00
Elian Doran
0dcaa8719f chore(react/type_widgets): save code note if needed 2025-10-05 17:56:31 +03:00
Elian Doran
608605af12 chore(react/type_widgets): save if needed 2025-10-05 17:53:19 +03:00
Elian Doran
3f7b8447d0 refactor(react/type_widgets): bring back executeInActiveNoteDetailWidget 2025-10-05 17:34:45 +03:00
Elian Doran
d3594e4a05 refactor(react/type_widgets): bring back printing and exporting to PDF 2025-10-05 17:07:34 +03:00
Elian Doran
156b4101a5 refactor(react/type_widgets): bring back cut to note 2025-10-05 17:05:05 +03:00
Elian Doran
73213d2a17 refactor(react/type_widgets): bring back execute with type widget 2025-10-05 16:59:46 +03:00
Elian Doran
763bcbd394 refactor(react/type_widgets): extract full height to note types 2025-10-05 16:45:26 +03:00
Elian Doran
d90043e586 chore(react/type_widgets): bring back launch bar fixed effect 2025-10-05 16:42:58 +03:00
Elian Doran
c209a699ea refactor(react/type_widgets): deduplicate containers 2025-10-05 16:36:59 +03:00
Elian Doran
22069d0aef refactor(react/type_widgets): extract note types to different file 2025-10-05 15:55:25 +03:00
Elian Doran
3248654820 chore(react/type_widgets): cache note types 2025-10-05 15:47:27 +03:00
Elian Doran
269c7c9ce7 feat(ai_chat): allow viewing source of the ai chat 2025-10-05 14:25:08 +03:00
Elian Doran
b0c984decd chore(react/type_widgets): fix refresh on first start 2025-10-05 14:15:51 +03:00
Elian Doran
cebb54ddf6 chore(react/type_widgets): get LLM note to load 2025-10-05 12:40:55 +03:00
Elian Doran
22f8929da6 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-10-05 12:14:14 +03:00
Elian Doran
7192d40e80 chore(react/type_widgets): get ai chat widget to render 2025-10-05 10:21:52 +03:00
Elian Doran
df9d481a93 refactor(mindmap): use proper way to detect direction
See https://github.com/SSShooter/mind-elixir-core/issues/150.
2025-10-04 19:17:13 +03:00
Elian Doran
cf37549f19 refactor(notemap): use proper types 2025-10-04 18:55:26 +03:00
Elian Doran
d2dda95654 fix(notemap): invisible hover color on light theme 2025-10-04 18:28:03 +03:00
Elian Doran
0770f97010 Merge remote-tracking branch 'origin/main' into react/type_widgets
; Conflicts:
;	apps/client/src/widgets/type_widgets/read_only_code.ts
2025-10-04 18:18:11 +03:00
Elian Doran
3caaf2ab79 chore(react/type_widgets): port note map type widget 2025-10-04 18:16:45 +03:00
Elian Doran
8f819a7786 chore(react): reintroduce reactivity to mapRootIdLabel 2025-10-04 18:09:40 +03:00
Elian Doran
0da66617a8 chore(react): reintroduce link distance 2025-10-04 14:14:02 +03:00
Elian Doran
5efe05490d chore(react): reintroduce force configuration 2025-10-04 13:58:29 +03:00
Elian Doran
656b234740 chore(react): reintroduce centering i note map 2025-10-04 13:55:22 +03:00
Elian Doran
e6e9cd3f35 chore(react): improve style of buttons 2025-10-04 13:44:11 +03:00
Elian Doran
845c76fc42 chore(react): bring back fixing nodes 2025-10-04 13:37:36 +03:00
Elian Doran
a4d6da72a1 chore(react): bring back interaction with nodes 2025-10-04 13:17:57 +03:00
Elian Doran
35438d2599 refactor(react): integrate get color for node in rendering 2025-10-04 13:15:13 +03:00
Elian Doran
9a1e7ca3ae chore(react): bring back node pointer & link configuration 2025-10-04 13:10:18 +03:00
Elian Doran
2d29d1b41f chore(react): add back note map link configuration 2025-10-04 13:04:40 +03:00
Elian Doran
ad5ff6e41a refactor(react): use component for map type switcher 2025-10-04 12:58:24 +03:00
Elian Doran
20dcbff68f chore(react): reintroduce map type toggles 2025-10-04 12:55:08 +03:00
Elian Doran
c127e19cfa chore(react): fix obtaining of CSS data for note map 2025-10-04 12:31:35 +03:00
Elian Doran
e32237559e chore(react): start rendering nodes in note map 2025-10-04 12:29:48 +03:00
Elian Doran
09811d23f6 chore(react): port data part of server API 2025-10-04 11:40:31 +03:00
Elian Doran
b41042fec4 chore(react):start porting note map 2025-10-04 11:07:16 +03:00
Elian Doran
08fae19d19 fix(react/type_widgets): crash when switching between relation maps 2025-10-04 10:37:28 +03:00
Elian Doran
9cceff4f02 chore(react/type_widgets): finalize porting relation map 2025-10-04 10:32:23 +03:00
Elian Doran
67d9154795 chore(react/type_widgets): reintroduce relation note dragging 2025-10-04 10:15:38 +03:00
Elian Doran
1eca9f6541 chore(react/type_widgets): reintroduce relation context menu 2025-10-04 09:54:47 +03:00
Elian Doran
c469fffb6e chore(react/type_widgets): reintroduce relation creation 2025-10-04 09:37:14 +03:00
Elian Doran
d076d54170 refactor(react/type_widgets): extract context menu to separate file 2025-10-04 09:15:15 +03:00
Elian Doran
3256c14a20 chore(react/type_widgets): accidental double source config 2025-10-04 09:06:24 +03:00
Elian Doran
460e01a2d6 refactor(react/type_widgets): split note box into separate file 2025-10-04 09:04:22 +03:00
Elian Doran
1913355069 chore(react/type_widgets): relation map source/target config 2025-10-04 08:58:06 +03:00
Elian Doran
f687d91201 chore(react/type_widgets): bring back dragging notes in relation map 2025-10-03 22:40:22 +03:00
Elian Doran
e8e93e985d fix(react/type_widgets): relation map getting occassionally wiped 2025-10-03 13:16:20 +03:00
Elian Doran
c5c304f85b chore(react/type_widgets): add dragigng logic for jsplumb 2025-10-03 11:58:00 +03:00
Elian Doran
58aea03114 fix(react/type_widgets): unable to add new items on existing map 2025-10-03 11:38:05 +03:00
Elian Doran
4af842d2f2 refactor(react/type_widgets): use dedicated component for items 2025-10-03 11:02:33 +03:00
Elian Doran
3b2f5bb09d refactor(react/type_widgets): extract JSPlumb into a separate file 2025-10-03 10:17:45 +03:00
Elian Doran
2d67aab288 fix(react/type_widgets): unable to add new items if the map is empty 2025-10-03 10:11:21 +03:00
Elian Doran
838d761b50 Merge remote-tracking branch 'origin/main' into react/type_widgets
; Conflicts:
;	apps/client/src/widgets/react/hooks.tsx
;	apps/client/src/widgets/type_widgets/abstract_text_type_widget.ts
2025-10-03 09:28:17 +03:00
Elian Doran
7a2d91e7de chore(type_widgets): get relations to render 2025-09-29 22:31:53 +03:00
Elian Doran
082ea7b5c1 chore(type_widgets): port relation map overlays 2025-09-29 21:35:44 +03:00
Elian Doran
c58414bbc1 chore(type_widgets): relation map rename title 2025-09-29 21:11:40 +03:00
Elian Doran
1c1243912b refactor(type_widgets): use API architecture for relation map 2025-09-29 21:05:29 +03:00
Elian Doran
614fc66890 refactor(type_widgets): move relation map to dedicated folder 2025-09-29 20:34:30 +03:00
Elian Doran
0937ef72e2 chore(type_widgets): start porting context menu 2025-09-29 20:33:15 +03:00
Elian Doran
3571023685 chore(type_widgets): bring back relation map zoom controls 2025-09-29 20:16:45 +03:00
Elian Doran
2cd3e3f9c8 chore(type_widgets): bring back relation map note creation 2025-09-29 20:06:22 +03:00
Elian Doran
3d08f686cf feat(code): pretty-print JSON in view source 2025-09-29 19:47:56 +03:00
Elian Doran
d2bf972305 chore(type_widgets): save pan & zoom 2025-09-29 19:41:08 +03:00
Elian Doran
39bd236799 refactor(type_widgets): use editorspaced update for data 2025-09-29 19:32:50 +03:00
Elian Doran
d8b9d14712 chore(type_widgets): introduce panzoom 2025-09-29 19:28:46 +03:00
Elian Doran
9d4127ba6d chore(type_widgets): render note box 2025-09-29 19:04:00 +03:00
Elian Doran
04b678ef4c chore(type_widgets): start porting relation map 2025-09-29 18:50:40 +03:00
Elian Doran
286d7c8228 Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-09-29 17:53:16 +03:00
Elian Doran
5547c3fc2b feat(canvas): read-only mode 2025-09-25 19:28:03 +03:00
Elian Doran
4381399978 feat(mindmap): read-only mode 2025-09-25 19:12:37 +03:00
Elian Doran
5bfa0d13e3 chore(react/type_widgets): refresh on all viewscope changes 2025-09-25 18:44:06 +03:00
Elian Doran
5c21759de9 fix(react/type_widgets): unable to switch view-mode for same note 2025-09-25 18:39:47 +03:00
Elian Doran
e2ef58ed50 chore(react/type_widgets): finalize porting 2025-09-25 18:26:52 +03:00
Elian Doran
7af610a5b4 chore(react/type_widgets): set up image opening 2025-09-25 18:22:58 +03:00
Elian Doran
8a442ba492 chore(react/type_widgets): port executeWithTextEditor 2025-09-25 18:07:47 +03:00
Elian Doran
3ed399a888 chore(react/type_widgets): port text touchbar (untested) 2025-09-25 17:53:48 +03:00
Elian Doran
37d33fb975 chore(react/type_widgets): port @-mention note creation 2025-09-25 17:21:03 +03:00
Elian Doran
d443d79685 chore(react/type_widgets): port and fix follow link under cursor 2025-09-25 14:35:52 +03:00
Elian Doran
a975576214 chore(react/type_widgets): react to snippet changes 2025-09-25 14:21:12 +03:00
Elian Doran
3673162a48 chore(react/type_widgets): bring back add include to note 2025-09-25 13:53:11 +03:00
Elian Doran
0ac428b57a chore(react/type_widgets): remove already integrated file 2025-09-25 13:26:50 +03:00
Elian Doran
45bd9b72b9 chore(react/type_widgets): set up code block word wrap 2025-09-25 13:24:43 +03:00
Elian Doran
cc6ac7d1da chore(react/type_widgets): port text link insertion mechanism 2025-09-25 12:07:06 +03:00
Elian Doran
232fe4e63a refactor(react/type_widgets): move mobile_editor_toolbar 2025-09-25 11:17:55 +03:00
Elian Doran
597426f10d Merge remote-tracking branch 'origin/main' into react/type_widgets 2025-09-25 11:12:28 +03:00
Elian Doran
a0a904766f fix(options/mfa): significant calls to OAuth status endpoint 2025-09-25 10:29:09 +03:00
Elian Doran
db46ca0a76 chore(react/type_widget): insert date/time to text 2025-09-22 18:03:19 +03:00
Elian Doran
a26ee0d769 chore(react/type_widget): hot-pluggable keyboard shortcuts 2025-09-22 17:52:05 +03:00
Elian Doran
46db047fa0 chore(react/type_widget): scroll to end & focus 2025-09-22 13:36:18 +03:00
Elian Doran
efaa1815ec chore(react/type_widget): classic editor & inspector 2025-09-22 13:19:20 +03:00
Elian Doran
2eab8b92d5 chore(react/type_widget): react to content language changes 2025-09-22 12:49:03 +03:00
Elian Doran
8a185262fb chore(react/type_widget): refactor event handling slightly 2025-09-22 12:43:43 +03:00
Elian Doran
f6631b7b9a chore(react/type_widget): save on change 2025-09-22 12:41:32 +03:00
Elian Doran
1e323de01b chore(react/type_widget): port watchdog state change 2025-09-22 12:13:31 +03:00
Elian Doran
f00f2ee5e4 chore(react/type_widget): port notification warning 2025-09-22 12:07:44 +03:00
Elian Doran
78b83cd17b chore(react/type_widget): get editable text to show up 2025-09-22 12:02:45 +03:00
Elian Doran
adea3abff4 chore(react/type_widget): add missing interface 2025-09-22 10:52:03 +03:00
Elian Doran
206618fd54 style(next): improve code block hiehgt in note list 2025-09-22 10:45:55 +03:00
Elian Doran
58a6d70cbb chore(react/type_widget): finalize porting canvas 2025-09-22 10:40:57 +03:00
Elian Doran
44b92a024c chore(react/type_widget): set up self-hosted fonts 2025-09-22 10:14:24 +03:00
Elian Doran
68bf5b7e68 chore(react/type_widget): set up canvas persistence 2025-09-22 09:22:09 +03:00
Elian Doran
8c85aa343c chore(react/type_widget): add more options to canvas 2025-09-22 08:40:56 +03:00
Elian Doran
592a8b2232 chore(react/type_widgets): start porting canvas 2025-09-21 23:33:38 +03:00
Elian Doran
e1ac319a7b chore(react/type_widgets): active note not refreshing 2025-09-21 22:59:16 +03:00
Elian Doran
763c489cd3 feat(render): integrate with search 2025-09-21 22:58:58 +03:00
Elian Doran
b990770e48 feat(render): add a floating button to refresh 2025-09-21 22:44:39 +03:00
Elian Doran
344607d437 chore(react/type_widgets): get render to work 2025-09-21 22:33:11 +03:00
Elian Doran
70d0a5441a chore(react/type_widget): port render note partially 2025-09-21 22:24:51 +03:00
Elian Doran
61278e1f5a chore(react/type_widget): use different loading mechanism 2025-09-21 21:49:23 +03:00
Elian Doran
b73ea6ac4f chore(react/type_widget): reflect note type changes 2025-09-21 21:13:04 +03:00
Elian Doran
5d833c1ac4 chore(react/type_widget): finalize read-only text 2025-09-21 20:50:26 +03:00
Elian Doran
2947682783 chore(react/type_widget): add code block & image integration 2025-09-21 20:47:40 +03:00
Elian Doran
fb46e09428 chore(react/type_widget): render reference links 2025-09-21 20:34:02 +03:00
Elian Doran
ff941b2cb1 chore(react/type_widget): render math in read-only text 2025-09-21 20:29:38 +03:00
Elian Doran
a8007b9063 chore(react/type_widget): render included notes in read-only text 2025-09-21 20:27:58 +03:00
Elian Doran
2f3c2bbac8 chore(react/type_widget): render inline mermaid in read-only text 2025-09-21 20:15:57 +03:00
Elian Doran
e4eb96a1ae chore(react/type_widget): start porting read-only text 2025-09-21 20:03:28 +03:00
Elian Doran
ffe4e9b8de chore(react/type_widget): add deletion widget 2025-09-21 19:43:36 +03:00
Elian Doran
f2b4f49be2 chore(react/type_widget): convert attachment actions 2025-09-21 19:34:03 +03:00
Elian Doran
376ef0c679 chore(react/type_widgets): introduce disabled tooltip 2025-09-21 12:02:02 +03:00
Elian Doran
b7574b3ca7 chore(react/type_widget): start porting attachment actions 2025-09-21 11:06:20 +03:00
Elian Doran
ae1954c320 chore(react/type_widget): port attachment detail 2025-09-21 10:57:08 +03:00
Elian Doran
3171413a18 chore(react/type_widget): react to attachment changes 2025-09-21 10:40:19 +03:00
Elian Doran
dc73467d34 chore(react/type_widget): list attachments with content 2025-09-21 10:32:12 +03:00
Elian Doran
58b14ae31c fix(react/type_widget): mind map attachment incorrect 2025-09-21 10:32:01 +03:00
Elian Doran
e117fbd471 chore(react/type_widget): port atttachment list header 2025-09-21 09:57:09 +03:00
Elian Doran
9a3f675950 chore(react/type_widget): finalize mind map with export PNG/SVG 2025-09-21 09:46:58 +03:00
Elian Doran
26400f2590 fix(mindmap): search not working 2025-09-21 09:35:23 +03:00
Elian Doran
7d99a92bd9 chore(react/type_widget): save mindmap attachment 2025-09-21 09:26:44 +03:00
Elian Doran
3417e37f16 chore(react/type_widget): save direction upon button press 2025-09-21 09:20:00 +03:00
Elian Doran
143e6a556c chore(react/type_widget): persist data 2025-09-20 22:22:20 +03:00
Elian Doran
02259c55f3 chore(react/type_widget): get mindmap to render 2025-09-20 21:52:57 +03:00
Elian Doran
cc19a217ad chore(react/type_widget): finalize SVG split editor 2025-09-20 21:34:56 +03:00
Elian Doran
d95ed4a5d2 chore(react/type_widget): export as SVG/PNG 2025-09-20 21:29:20 +03:00
Elian Doran
469683f30f chore(react/type_widget): reimplement zoom + reset buttons 2025-09-20 21:23:34 +03:00
Elian Doran
42d0cc12b5 chore(react/type_widget): more generic repositioning 2025-09-20 21:19:19 +03:00
Elian Doran
b376842e2d chore(react/type_widget): reposition on split resize 2025-09-20 21:12:29 +03:00
Elian Doran
145ff1a2a5 chore(react/type_widget): restore pan/zoom 2025-09-20 21:07:51 +03:00
Elian Doran
8e9f5fb486 chore(react/type_widget): fix 4px scroll in SVG editor 2025-09-20 14:34:15 +03:00
Elian Doran
3dd757a857 chore(react/type_widget): disable code background change in split 2025-09-20 14:16:34 +03:00
Elian Doran
bde7b753a0 chore(react/type_widget): save SVG attachment 2025-09-20 14:08:50 +03:00
Elian Doran
02017ebd9d chore(react/type_widget): bring back on error opacity 2025-09-20 13:47:12 +03:00
Elian Doran
8caaa99415 chore(react/type_widget): basic SVG rendering 2025-09-20 13:27:58 +03:00
Elian Doran
c49b90d33f chore(react/type_widget): add preview buttons 2025-09-20 13:15:13 +03:00
Elian Doran
6dd939df14 chore(react/type_widget): bring back update interval 2025-09-20 13:04:36 +03:00
Elian Doran
b19da81572 chore(react/type_widget): force line wrapping 2025-09-20 13:00:15 +03:00
Elian Doran
425ffc02d8 chore(react/type_widget): bring back split resizer 2025-09-20 12:54:18 +03:00
Elian Doran
695e8489ad chore(react/type_widget): pass error information 2025-09-20 12:41:39 +03:00
Elian Doran
2f4e13b1bb chore(react/type_widget): bring back order of editor/preview 2025-09-20 12:38:05 +03:00
Elian Doran
c8a9b994d6 chore(react/type_widget): bring back read-only 2025-09-20 12:34:36 +03:00
Elian Doran
3d5b319eb2 chore(react/type_widget): bring back split orientation 2025-09-20 12:31:45 +03:00
Elian Doran
bed3c2dc67 chore(react/type_widget): prepare structure for split editor 2025-09-20 12:25:11 +03:00
Elian Doran
256d1863d2 chore(react/type_widget): port backend log 2025-09-20 12:16:51 +03:00
Elian Doran
4a4502dfea chore(react/type_widget): bring back read-only temporary disable 2025-09-20 11:59:43 +03:00
Elian Doran
91f21e149b chore(react/type_widget): bring back focusing after tab switch 2025-09-20 11:46:23 +03:00
Elian Doran
6ef468adc4 chore(react/type_widget): bring back scroll to end 2025-09-20 11:38:28 +03:00
Elian Doran
e576fa03da chore(react/type_widget): fix sizing 2025-09-20 11:30:40 +03:00
Elian Doran
6bcce08042 chore(react/type_widget): react to line wrapping 2025-09-20 11:25:07 +03:00
Elian Doran
f496caa92c refactor(react/type_widget): separate Trilium-specific implementation 2025-09-20 11:22:48 +03:00
Elian Doran
43dcdf8925 chore(react/type_widget): apply background color for read-only code notes 2025-09-20 11:11:00 +03:00
Elian Doran
2c014fb071 chore(react/type_widget): set up background color for code notes 2025-09-20 11:02:43 +03:00
Elian Doran
2273507ef4 chore(react/type_widget): unnecessary imports 2025-09-20 10:37:34 +03:00
Elian Doran
70a710be79 chore(react/type_widget): react to code theme 2025-09-20 10:14:21 +03:00
Elian Doran
7a3ee7971c chore(react/type_widget): add back keyboard shortcut for editable code 2025-09-20 10:08:46 +03:00
Elian Doran
c86123e3a9 chore(react/type_widget): integrate touch bar for editable code 2025-09-20 10:03:00 +03:00
Elian Doran
9480227b69 chore(react/type_widget): add more options to editable code 2025-09-20 09:59:49 +03:00
Elian Doran
79be13e6c7 chore(react/type_widget): reload content on external change 2025-09-20 09:56:55 +03:00
Elian Doran
63e3a27b34 refactor(react/type_widget): simplify handling of new notes 2025-09-20 09:47:28 +03:00
Elian Doran
9eae6620d0 chore(react/type_widget): basic editable code 2025-09-20 09:44:36 +03:00
Elian Doran
6517dd1190 chore(react/type_widget): finalize readonly code 2025-09-20 09:06:55 +03:00
Elian Doran
f72087acc3 chore(react/type_widget): port read only code basic functionality 2025-09-20 08:57:47 +03:00
Elian Doran
77e7c414b6 chore(react/type_widget): react to note revisions 2025-09-19 22:45:12 +03:00
Elian Doran
3a68395ca7 feat(react/type_widget): add copy image reference floating button to image 2025-09-19 22:42:06 +03:00
Elian Doran
0a0d9775b2 chore(react/type_widget): port image 2025-09-19 22:41:18 +03:00
Elian Doran
aa6e68ad39 chore(react/type_widget): port file 2025-09-19 22:22:45 +03:00
Elian Doran
034073a5e1 chore(react/type_widget): fix missing tbody 2025-09-19 22:18:10 +03:00
Elian Doran
d83ff641d7 chore(react/type_widget): bring back full-height 2025-09-19 21:55:37 +03:00
Elian Doran
071fcb85c9 chore(react/type_widget): basic integration of web view 2025-09-19 21:27:45 +03:00
Elian Doran
daa5ee93e9 chore(react/type_widget): port content widget 2025-09-19 21:18:09 +03:00
Elian Doran
db7cda3fe6 chore(react/type_widget): have book react to reloaded children 2025-09-19 19:06:07 +03:00
Elian Doran
fa55c5720e chore(react/type_widget): port book 2025-09-19 19:03:31 +03:00
Elian Doran
d1a9890932 chore(react/type_widget): port protected session 2025-09-19 18:55:04 +03:00
Elian Doran
c9fe358811 chore(react/type_widget): port none type widget 2025-09-19 18:35:49 +03:00
Elian Doran
bbb927c83f chore(react/type_widget): port doc widget 2025-09-19 18:32:45 +03:00
Elian Doran
07b86c8cf7 chore(react/type_widget): port empty workspace switcher 2025-09-19 18:15:10 +03:00
Elian Doran
3dbf20af52 chore(react/type_widget): port empty search 2025-09-19 18:09:23 +03:00
Elian Doran
1fb329565f chore(react/type_widget): move old widgets 2025-09-19 17:40:24 +03:00
Elian Doran
06bfb0073a chore(react/type_widget): determine note type 2025-09-19 17:31:10 +03:00
Elian Doran
3d64c320fb chore(react/type_widget): start with fresh note detail 2025-09-19 16:53:31 +03:00
perf3ct
58c225237c feat(search): try a ground-up sqlite search approach 2025-09-03 00:34:55 +00:00
perf3ct
d074841885 Revert "feat(search): try to get fts search to work in large environments"
This reverts commit 053f722cb8.
2025-09-02 19:24:50 +00:00
perf3ct
06b2d71b27 Revert "feat(search): try to decrease complexity"
This reverts commit 5b79e0d71e.
2025-09-02 19:24:47 +00:00
perf3ct
0afb8a11c8 Revert "feat(search): try to deal with huge dbs, might need to squash later"
This reverts commit 37d0136c50.
2025-09-02 19:24:46 +00:00
perf3ct
f529ddc601 Revert "feat(search): further improve fts search"
This reverts commit 7c5553bd4b.
2025-09-02 19:24:45 +00:00
perf3ct
8572f82e0a Revert "feat(search): I honestly have no idea what I'm doing"
This reverts commit b09a2c386d.
2025-09-02 19:24:44 +00:00
perf3ct
b09a2c386d feat(search): I honestly have no idea what I'm doing 2025-09-01 22:29:59 -07:00
perf3ct
7c5553bd4b feat(search): further improve fts search 2025-09-01 21:40:05 -07:00
perf3ct
37d0136c50 feat(search): try to deal with huge dbs, might need to squash later 2025-09-01 04:33:10 +00:00
perf3ct
5b79e0d71e feat(search): try to decrease complexity 2025-08-30 22:30:01 -07:00
perf3ct
053f722cb8 feat(search): try to get fts search to work in large environments 2025-08-31 03:15:29 +00:00
perf3ct
21aaec2c38 feat(search): also fix tests for new fts functionality 2025-08-30 20:48:42 +00:00
perf3ct
1db4971da6 feat(search): implement FST5 w/ sqlite for faster and better searching
feat(search): don't limit the number of blobs to put in virtual tables

fix(search): improve FTS triggers to handle all SQL operations correctly

The root cause of FTS index issues during import was that database triggers
weren't properly handling all SQL operations, particularly upsert operations
(INSERT ... ON CONFLICT ... DO UPDATE) that are commonly used during imports.

Key improvements:
- Fixed INSERT trigger to handle INSERT OR REPLACE operations
- Updated UPDATE trigger to fire on ANY change (not just specific columns)
- Improved blob triggers to use INSERT OR REPLACE for atomic updates
- Added proper handling for notes created before their blobs (import scenario)
- Added triggers for protection state changes
- All triggers now use LEFT JOIN to handle missing blobs gracefully

This ensures the FTS index stays synchronized even when:
- Entity events are disabled during import
- Notes are re-imported (upsert operations)
- Blobs are deduplicated across notes
- Notes are created before their content blobs

The solution works entirely at the database level through triggers,
removing the need for application-level workarounds.

fix(search): consolidate FTS trigger fixes into migration 234

- Merged improved trigger logic from migration 235 into 234
- Deleted unnecessary migration 235 since DB version is still 234
- Ensures triggers handle all SQL operations (INSERT OR REPLACE, upserts)
- Fixes FTS indexing for imported notes by handling missing blobs
- Schema.sql and migration 234 now have identical trigger implementations
2025-08-30 20:39:40 +00:00
940 changed files with 59944 additions and 25471 deletions

View File

@@ -1,6 +1,6 @@
root = true
[*.{js,ts,tsx}]
[*.{js,ts,tsx,css}]
charset = utf-8
end_of_line = lf
indent_size = 4

3
.envrc Normal file
View File

@@ -0,0 +1,3 @@
if has nix; then
use flake
fi

View File

@@ -21,7 +21,7 @@ runs:
# Certificate setup
- name: Import Apple certificates
if: inputs.os == 'macos'
uses: apple-actions/import-codesign-certs@v5
uses: apple-actions/import-codesign-certs@v6
with:
p12-file-base64: ${{ env.APPLE_APP_CERTIFICATE_BASE64 }}
p12-password: ${{ env.APPLE_APP_CERTIFICATE_PASSWORD }}
@@ -30,7 +30,7 @@ runs:
- name: Install Installer certificate
if: inputs.os == 'macos'
uses: apple-actions/import-codesign-certs@v5
uses: apple-actions/import-codesign-certs@v6
with:
p12-file-base64: ${{ env.APPLE_INSTALLER_CERTIFICATE_BASE64 }}
p12-password: ${{ env.APPLE_INSTALLER_CERTIFICATE_PASSWORD }}

View File

@@ -44,7 +44,7 @@ runs:
steps:
# Checkout branch to compare to [required]
- name: Checkout base branch
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
ref: ${{ inputs.branch }}
path: br-base

334
.github/copilot-instructions.md vendored Normal file
View File

@@ -0,0 +1,334 @@
# Trilium Notes - AI Coding Agent Instructions
## Project Overview
Trilium Notes is a hierarchical note-taking application with advanced features like synchronization, scripting, and rich text editing. Built as a TypeScript monorepo using pnpm, it implements a three-layer caching architecture (Becca/Froca/Shaca) with a widget-based UI system and supports extensive user scripting capabilities.
## Essential Architecture Patterns
### Three-Layer Cache System (Critical to Understand)
- **Becca** (`apps/server/src/becca/`): Server-side entity cache, primary data source
- **Froca** (`apps/client/src/services/froca.ts`): Client-side mirror synchronized via WebSocket
- **Shaca** (`apps/server/src/share/`): Optimized cache for public/shared notes
**Key insight**: Never bypass these caches with direct DB queries. Always use `becca.notes[noteId]`, `froca.getNote()`, or equivalent cache methods.
### Entity Relationship Model
Notes use a **multi-parent tree** via branches:
- `BNote` - The note content and metadata
- `BBranch` - Tree relationships (one note can have multiple parents via cloning)
- `BAttribute` - Key-value metadata attached to notes (labels and relations)
### Entity Change System & Sync
Every entity modification (notes, branches, attributes) creates an `EntityChange` record that drives synchronization:
```typescript
// Entity changes are automatically tracked
note.title = "New Title";
note.save(); // Creates EntityChange record with changeId
// Sync protocol via WebSocket
ws.sendMessage({ type: 'sync-pull-in-progress', ... });
```
**Critical**: This is why you must use Becca/Froca methods instead of direct DB writes - they create the change tracking records needed for sync.
### Entity Lifecycle & Events
The event system (`apps/server/src/services/events.ts`) broadcasts entity lifecycle events:
```typescript
// Subscribe to events in widgets or services
eventService.subscribe('noteChanged', ({ noteId }) => {
// React to note changes
});
// Common events: noteChanged, branchChanged, attributeChanged, noteDeleted
// Widget method: entitiesReloadedEvent({loadResults}) for handling reloads
```
**Becca loader priorities**: Events are emitted in order (notes → branches → attributes) during initial load to ensure referential integrity.
### TaskContext for Long Operations
Use `TaskContext` for operations with progress reporting (imports, exports, bulk operations):
```typescript
const taskContext = new TaskContext("task-id", "import", "Import Notes");
taskContext.increaseProgressCount();
// WebSocket messages: { type: 'taskProgressCount', taskId, taskType, data, progressCount }
**Pattern**: All long-running operations (delete note trees, export, import) use TaskContext to send WebSocket updates to the frontend.
### Protected Session Handling
Protected notes require an active encryption session:
```typescript
// Always check before accessing protected content
if (note.isContentAvailable()) {
const content = note.getContent(); // Safe
} else {
const title = note.getTitleOrProtected(); // Returns "[protected]"
}
// Protected session management
protectedSessionService.isProtectedSessionAvailable() // Check session
protectedSessionService.startProtectedSession() // After password entry
```
**Session timeout**: Protected sessions expire after inactivity. The encryption key is kept in memory only.
### Attribute Inheritance Patterns
Attributes can be inherited through three mechanisms:
```typescript
// 1. Standard inheritance (#hidePromotedAttributes ~hidePromotedAttributes)
note.getInheritableAttributes() // Walks up parent tree
// 2. Child prefix inheritance (child:label copies to children)
parentNote.setLabel("child:icon", "book") // All children inherit this
// 3. Template relation inheritance (#template=templateNoteId)
note.setRelation("template", templateNoteId)
note.getInheritedAttributes() // Includes template's inheritable attributes
```
**Cycle prevention**: Inheritance tracking prevents infinite loops when notes reference each other.
### Widget-Based UI Architecture
All UI components extend from widget base classes (`apps/client/src/widgets/`):
```typescript
// Right panel widget (sidebar)
class MyWidget extends RightPanelWidget {
get position() { return 100; } // Order in panel
get parentWidget() { return 'right-pane'; }
isEnabled() { return this.note && this.note.hasLabel('myLabel'); }
async refreshWithNote(note) { /* Update UI */ }
}
// Note-aware widget (responds to note changes)
class MyNoteWidget extends NoteContextAwareWidget {
async refreshWithNote(note) { /* Refresh when note changes */ }
async entitiesReloadedEvent({loadResults}) { /* Handle entity updates */ }
}
```
**Important**: Widgets use jQuery (`this.$widget`) for DOM manipulation. Don't mix React patterns here.
## Development Workflow
### Running & Testing
```bash
# From root directory
pnpm install # Install dependencies
corepack enable # Enable pnpm if not available
pnpm server:start # Dev server (http://localhost:8080)
pnpm server:start-prod # Production mode server
pnpm desktop:start # Desktop app development
pnpm server:test spec/etapi/search.spec.ts # Run specific test
pnpm test:parallel # Client tests (can run parallel)
pnpm test:sequential # Server tests (sequential due to shared DB)
pnpm test:all # All tests (parallel + sequential)
pnpm coverage # Generate coverage reports
pnpm typecheck # Type check all projects
```
### Building
```bash
pnpm client:build # Build client application
pnpm server:build # Build server application
pnpm desktop:build # Build desktop application
```
### Test Organization
- **Server tests** (`apps/server/spec/`): Must run sequentially (shared database state)
- **Client tests** (`apps/client/src/`): Can run in parallel
- **E2E tests** (`apps/server-e2e/`): Use Playwright for integration testing
- **ETAPI tests** (`apps/server/spec/etapi/`): External API contract tests
**Pattern**: When adding new API endpoints, add tests in `spec/etapi/` following existing patterns (see `search.spec.ts`).
### Monorepo Navigation
```
apps/
client/ # Frontend (shared by server & desktop)
server/ # Node.js backend with REST API
desktop/ # Electron wrapper
web-clipper/ # Browser extension for saving web content
db-compare/ # Database comparison tool
dump-db/ # Database export utility
edit-docs/ # Documentation editing tools
packages/
commons/ # Shared types and utilities
ckeditor5/ # Custom rich text editor with Trilium-specific plugins
codemirror/ # Code editor integration
highlightjs/ # Syntax highlighting
share-theme/ # Theme for shared/published notes
ckeditor5-admonition/ # Admonition blocks plugin
ckeditor5-footnotes/ # Footnotes plugin
ckeditor5-math/ # Math equations plugin
ckeditor5-mermaid/ # Mermaid diagrams plugin
```
**Filter commands**: Use `pnpm --filter server test` to run commands in specific packages.
## Critical Code Patterns
### ETAPI Backwards Compatibility
When adding query parameters to ETAPI endpoints (`apps/server/src/etapi/`), maintain backwards compatibility by checking if new params exist before changing response format.
**Pattern**: ETAPI consumers expect specific response shapes. Always check for breaking changes.
### Frontend-Backend Communication
- **REST API**: `apps/server/src/routes/api/` - Internal endpoints (no auth required when `noAuthentication=true`)
- **ETAPI**: `apps/server/src/etapi/` - External API with authentication
- **WebSocket**: Real-time sync via `apps/server/src/services/ws.ts`
**Auth note**: ETAPI uses basic auth with tokens. Internal API endpoints trust the frontend.
### Database Migrations
- Add scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
- Update schema in `apps/server/src/assets/db/schema.sql`
- Never bypass Becca cache after migrations
## Common Pitfalls
1. **Never bypass the cache layers** - Always use `becca.notes[noteId]`, `froca.getNote()`, or equivalent cache methods. Direct database queries will cause sync issues between Becca/Froca/Shaca and won't create EntityChange records needed for synchronization.
2. **Protected notes require session check** - Before accessing `note.title` or `note.getContent()` on protected notes, check `note.isContentAvailable()` or use `note.getTitleOrProtected()` which handles this automatically.
3. **Widget lifecycle matters** - Override `refreshWithNote()` for note changes, `doRenderBody()` for initial render, `entitiesReloadedEvent()` for entity updates. Widgets use jQuery (`this.$widget`) - don't mix React patterns.
4. **Tests run differently** - Server tests must run sequentially (shared database state), client tests can run in parallel. Use `pnpm test:sequential` for backend, `pnpm test:parallel` for frontend.
5. **ETAPI requires authentication** - ETAPI endpoints use basic auth with tokens. Internal API endpoints (`apps/server/src/routes/api/`) trust the frontend when `noAuthentication=true`.
6. **Search expressions are evaluated in memory** - The search service loads all matching notes, scores them in JavaScript, then sorts. You cannot add SQL-level LIMIT/OFFSET without losing scoring functionality.
7. **Documentation edits have rules** - `docs/Script API/` is auto-generated (never edit directly). `docs/User Guide/` should be edited via `pnpm edit-docs:edit-docs`, not manually. Only `docs/Developer Guide/` and `docs/Release Notes/` are safe for direct Markdown editing.
8. **pnpm workspace filtering** - Use `pnpm --filter server <command>` or shorthand `pnpm server:test` defined in root `package.json`. Note the `--filter` syntax, not `-F` or other shortcuts.
9. **Event subscription cleanup** - When subscribing to events in widgets, unsubscribe in `cleanup()` or `doDestroy()` to prevent memory leaks.
10. **Attribute inheritance can be complex** - When checking for labels/relations, use `note.getOwnedAttribute()` for direct attributes or `note.getAttribute()` for inherited ones. Don't assume attributes are directly on the note.
## TypeScript Configuration
- **Project references**: Monorepo uses TypeScript project references (`tsconfig.json`)
- **Path mapping**: Use relative imports, not path aliases
- **Build order**: `pnpm typecheck` builds all projects in dependency order
- **Build system**: Uses Vite for fast development, ESBuild for production optimization
- **Patches**: Custom patches in `patches/` directory for CKEditor and other dependencies
## Key Files for Context
- `apps/server/src/becca/entities/bnote.ts` - Note entity methods
- `apps/client/src/services/froca.ts` - Frontend cache API
- `apps/server/src/services/search/services/search.ts` - Search implementation
- `apps/server/src/routes/routes.ts` - API route registration
- `apps/client/src/widgets/basic_widget.ts` - Widget base class
- `apps/server/src/main.ts` - Server startup entry point
- `apps/client/src/desktop.ts` - Client initialization
- `apps/server/src/services/backend_script_api.ts` - Scripting API
- `apps/server/src/assets/db/schema.sql` - Database schema
## Note Types and Features
Trilium supports multiple note types with specialized widgets in `apps/client/src/widgets/type_widgets/`:
- **Text**: Rich text with CKEditor5 (markdown import/export)
- **Code**: Syntax-highlighted code editing with CodeMirror
- **File**: Binary file attachments
- **Image**: Image display with editing capabilities
- **Canvas**: Drawing/diagramming with Excalidraw
- **Mermaid**: Diagram generation
- **Relation Map**: Visual note relationship mapping
- **Web View**: Embedded web pages
- **Doc/Book**: Hierarchical documentation structure
### Collections
Notes can be marked with the `#collection` label to enable collection view modes. Collections support multiple view types:
- **List**: Standard list view
- **Grid**: Card/grid layout
- **Calendar**: Calendar-based view
- **Table**: Tabular data view
- **GeoMap**: Geographic map view
- **Board**: Kanban-style board
- **Presentation**: Slideshow presentation mode
View types are configured via `#viewType` label (e.g., `#viewType=table`). Each view mode stores its configuration in a separate attachment (e.g., `table.json`). Collections are organized separately from regular note type templates in the note creation menu.
## Common Development Tasks
### Adding New Note Types
1. Create widget in `apps/client/src/widgets/type_widgets/`
2. Register in `apps/client/src/services/note_types.ts`
3. Add backend handling in `apps/server/src/services/notes.ts`
### Extending Search
- Search expressions handled in `apps/server/src/services/search/`
- Add new search operators in search context files
- Remember: scoring happens in-memory, not at database level
### Custom CKEditor Plugins
- Create new package in `packages/` following existing plugin structure
- Register in `packages/ckeditor5/src/plugins.ts`
- See `ckeditor5-admonition`, `ckeditor5-footnotes`, `ckeditor5-math`, `ckeditor5-mermaid` for examples
### Database Migrations
- Add migration scripts in `apps/server/src/migrations/YYMMDD_HHMM__description.sql`
- Update schema in `apps/server/src/assets/db/schema.sql`
- Never bypass Becca cache after migrations
## Security & Features
### Security Considerations
- Per-note encryption with granular protected sessions
- CSRF protection for API endpoints
- OpenID and TOTP authentication support
- Sanitization of user-generated content
### Scripting System
Trilium provides powerful user scripting capabilities:
- **Frontend scripts**: Run in browser context with UI access
- **Backend scripts**: Run in Node.js context with full API access
- Script API documentation in `docs/Script API/`
- Backend API available via `api` object in script context
### Internationalization
- Translation files in `apps/client/src/translations/`
- Use translation system via `t()` function
- Automatic pluralization: Add `_other` suffix to translation keys (e.g., `item` and `item_other` for singular/plural)
## Testing Conventions
```typescript
// ETAPI test pattern
describe("etapi/feature", () => {
beforeAll(async () => {
config.General.noAuthentication = false;
app = await buildApp();
token = await login(app);
});
it("should test feature", async () => {
const response = await supertest(app)
.get("/etapi/notes?search=test")
.auth(USER, token, { type: "basic" })
.expect(200);
expect(response.body.results).toBeDefined();
});
});
```
## Questions to Verify Understanding
Before implementing significant changes, confirm:
- Is this touching the cache layer? (Becca/Froca/Shaca must stay in sync via EntityChange records)
- Does this change API response shape? (Check backwards compatibility for ETAPI)
- Are you adding search features? (Understand expression-based architecture and in-memory scoring first)
- Is this a new widget? (Know which base class and lifecycle methods to use)
- Does this involve protected notes? (Check `isContentAvailable()` before accessing content)
- Is this a long-running operation? (Use TaskContext for progress reporting)
- Are you working with attributes? (Understand inheritance patterns: direct, child-prefix, template)

View File

@@ -57,7 +57,7 @@ jobs:
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`

View File

@@ -42,7 +42,7 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Setup pnpm
uses: pnpm/action-setup@v4

View File

@@ -24,7 +24,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
@@ -46,7 +46,7 @@ jobs:
needs:
- test_dev
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install --frozen-lockfile
@@ -80,7 +80,7 @@ jobs:
- dockerfile: Dockerfile
steps:
- name: Checkout the repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Install dependencies

View File

@@ -32,7 +32,7 @@ jobs:
- dockerfile: Dockerfile
steps:
- name: Checkout the repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Set IMAGE_NAME to lowercase
run: echo "IMAGE_NAME=${IMAGE_NAME,,}" >> $GITHUB_ENV
@@ -86,12 +86,12 @@ jobs:
- name: Upload Playwright trace
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: Playwright trace (${{ matrix.dockerfile }})
path: test-output/playwright/output
- uses: actions/upload-artifact@v5
- uses: actions/upload-artifact@v6
if: ${{ !cancelled() }}
with:
name: Playwright report (${{ matrix.dockerfile }})
@@ -141,7 +141,7 @@ jobs:
run: echo "TEST_TAG=${TEST_TAG,,}" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
@@ -155,6 +155,10 @@ jobs:
- name: Update build info
run: pnpm run chore:update-build-info
- name: Update nightly version
if: ${{ !startsWith(github.ref, 'refs/tags/v') }}
run: pnpm run chore:ci-update-nightly-version
- name: Run the TypeScript build
run: pnpm run server:build
@@ -209,7 +213,7 @@ jobs:
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: digests-${{ env.PLATFORM_PAIR }}-${{ matrix.dockerfile }}
path: /tmp/digests/*
@@ -223,7 +227,7 @@ jobs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v6
uses: actions/download-artifact@v7
with:
path: /tmp/digests
pattern: digests-*

View File

@@ -45,9 +45,22 @@ jobs:
image: win-signing
shell: cmd
forge_platform: win32
# Exclude ARM64 Linux from default matrix to use native runner
exclude:
- arch: arm64
os:
name: linux
# Add ARM64 Linux with native ubuntu-24.04-arm runner for better-sqlite3 compatibility
include:
- arch: arm64
os:
name: linux
image: ubuntu-24.04-arm
shell: bash
forge_platform: linux
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
@@ -57,7 +70,7 @@ jobs:
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Update nightly version
run: npm run chore:ci-update-nightly-version
run: pnpm run chore:ci-update-nightly-version
- name: Run the build
uses: ./.github/actions/build-electron
with:
@@ -77,7 +90,7 @@ jobs:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
- name: Publish release
uses: softprops/action-gh-release@v2.4.2
uses: softprops/action-gh-release@v2.5.0
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false
@@ -89,7 +102,7 @@ jobs:
name: Nightly Build
- name: Publish artifacts
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
if: ${{ github.event_name == 'pull_request' }}
with:
name: TriliumNotes ${{ matrix.os.name }} ${{ matrix.arch }}
@@ -109,7 +122,7 @@ jobs:
runs-on: ubuntu-24.04-arm
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Run the build
uses: ./.github/actions/build-server
@@ -118,7 +131,7 @@ jobs:
arch: ${{ matrix.arch }}
- name: Publish release
uses: softprops/action-gh-release@v2.4.2
uses: softprops/action-gh-release@v2.5.0
if: ${{ github.event_name != 'pull_request' }}
with:
make_latest: false

View File

@@ -33,7 +33,7 @@ jobs:
TRILIUM_DATA_DIR: "${{ github.workspace }}/apps/server/spec/db"
TRILIUM_INTEGRATION_TEST: memory
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
filter: tree:0
fetch-depth: 0
@@ -77,9 +77,9 @@ jobs:
- name: Upload test report
if: failure()
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: e2e report
name: e2e report ${{ matrix.arch }}
path: apps/server-e2e/test-output
- name: Kill the server

View File

@@ -45,7 +45,7 @@ jobs:
forge_platform: linux
runs-on: ${{ matrix.os.image }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6
@@ -73,7 +73,7 @@ jobs:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGN_KEY }}
- name: Upload the artifact
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: release-desktop-${{ matrix.os.name }}-${{ matrix.arch }}
path: apps/desktop/upload/*.*
@@ -91,7 +91,7 @@ jobs:
runs-on: ubuntu-24.04-arm
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- name: Run the build
uses: ./.github/actions/build-server
@@ -100,7 +100,7 @@ jobs:
arch: ${{ matrix.arch }}
- name: Upload the artifact
uses: actions/upload-artifact@v5
uses: actions/upload-artifact@v6
with:
name: release-server-linux-${{ matrix.arch }}
path: upload/*.*
@@ -114,20 +114,20 @@ jobs:
steps:
- run: mkdir upload
- uses: actions/checkout@v5
- uses: actions/checkout@v6
with:
sparse-checkout: |
docs/Release Notes
- name: Download all artifacts
uses: actions/download-artifact@v6
uses: actions/download-artifact@v7
with:
merge-multiple: true
pattern: release-*
path: upload
- name: Publish stable release
uses: softprops/action-gh-release@v2.4.2
uses: softprops/action-gh-release@v2.5.0
with:
draft: false
body_path: docs/Release Notes/Release Notes/${{ github.ref_name }}.md

View File

@@ -25,7 +25,7 @@ jobs:
pull-requests: write # For PR preview comments
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
- name: Set up node & dependencies
uses: actions/setup-node@v6

2
.gitignore vendored
View File

@@ -44,8 +44,10 @@ upload
.rollup.cache
*.tsbuildinfo
/.direnv
/result
.svelte-kit
# docs
site/
apps/*/coverage

2
.nvmrc
View File

@@ -1 +1 @@
24.11.0
24.12.0

View File

@@ -9,7 +9,6 @@
"tobermory.es6-string-html",
"vitest.explorer",
"yzhang.markdown-all-in-one",
"svelte.svelte-vscode",
"bradlc.vscode-tailwindcss"
"usernamehw.errorlens"
]
}

View File

@@ -36,5 +36,11 @@
"docs/**/*.png": true,
"apps/server/src/assets/doc_notes/**": true,
"apps/edit-docs/demo/**": true
}
},
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
},
"eslint.rules.customizations": [
{ "rule": "*", "severity": "warn" }
]
}

View File

@@ -16,13 +16,14 @@
![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/triliumnext/trilium/total)
[![RelativeCI](https://badges.relative-ci.com/badges/Di5q7dz9daNDZ9UXi0Bp?branch=develop)](https://app.relative-ci.com/projects/Di5q7dz9daNDZ9UXi0Bp) [![Translation status](https://hosted.weblate.org/widget/trilium/svg-badge.svg)](https://hosted.weblate.org/engage/trilium/)
[English](./README.md) | [Chinese (Simplified)](./docs/README-ZH_CN.md) | [Chinese (Traditional)](./docs/README-ZH_TW.md) | [Russian](./docs/README-ru.md) | [Japanese](./docs/README-ja.md) | [Italian](./docs/README-it.md) | [Spanish](./docs/README-es.md)
<!-- translate:off -->
<!-- LANGUAGE SWITCHER -->
[Chinese (Simplified Han script)](./docs/README-ZH_CN.md) | [Chinese (Traditional Han script)](./docs/README-ZH_TW.md) | [English](./docs/README.md) | [French](./docs/README-fr.md) | [German](./docs/README-de.md) | [Greek](./docs/README-el.md) | [Italian](./docs/README-it.md) | [Japanese](./docs/README-ja.md) | [Romanian](./docs/README-ro.md) | [Spanish](./docs/README-es.md)
<!-- translate:on -->
Trilium Notes is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.
See [screenshots](https://triliumnext.github.io/Docs/Wiki/screenshot-tour) for quick overview:
<a href="https://triliumnext.github.io/Docs/Wiki/screenshot-tour"><img src="./docs/app.png" alt="Trilium Screenshot" width="1000"></a>
<img src="./docs/app.png" alt="Trilium Screenshot" width="1000">
## ⏬ Download
- [Latest release](https://github.com/TriliumNext/Trilium/releases/latest) stable version, recommended for most users.
@@ -39,39 +40,39 @@ Our documentation is available in multiple formats:
### Quick Links
- [Getting Started Guide](https://docs.triliumnotes.org/)
- [Installation Instructions](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation.md)
- [Docker Setup](./docs/User%20Guide/User%20Guide/Installation%20&%20Setup/Server%20Installation/1.%20Installing%20the%20server/Using%20Docker.md)
- [Upgrading TriliumNext](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Upgrading%20TriliumNext.md)
- [Basic Concepts and Features](./docs/User%20Guide/User%20Guide/Basic%20Concepts%20and%20Features/Notes.md)
- [Patterns of Personal Knowledge Base](https://triliumnext.github.io/Docs/Wiki/patterns-of-personal-knowledge)
- [Installation Instructions](https://docs.triliumnotes.org/user-guide/setup)
- [Docker Setup](https://docs.triliumnotes.org/user-guide/setup/server/installation/docker)
- [Upgrading TriliumNext](https://docs.triliumnotes.org/user-guide/setup/upgrading)
- [Basic Concepts and Features](https://docs.triliumnotes.org/user-guide/concepts/notes)
- [Patterns of Personal Knowledge Base](https://docs.triliumnotes.org/user-guide/misc/patterns-of-personal-knowledge)
## 🎁 Features
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://triliumnext.github.io/Docs/Wiki/cloning-notes))
* Rich WYSIWYG note editor including e.g. tables, images and [math](https://triliumnext.github.io/Docs/Wiki/text-notes) with markdown [autoformat](https://triliumnext.github.io/Docs/Wiki/text-notes#autoformat)
* Support for editing [notes with source code](https://triliumnext.github.io/Docs/Wiki/code-notes), including syntax highlighting
* Fast and easy [navigation between notes](https://triliumnext.github.io/Docs/Wiki/note-navigation), full text search and [note hoisting](https://triliumnext.github.io/Docs/Wiki/note-hoisting)
* Seamless [note versioning](https://triliumnext.github.io/Docs/Wiki/note-revisions)
* Note [attributes](https://triliumnext.github.io/Docs/Wiki/attributes) can be used for note organization, querying and advanced [scripting](https://triliumnext.github.io/Docs/Wiki/scripts)
* Notes can be arranged into arbitrarily deep tree. Single note can be placed into multiple places in the tree (see [cloning](https://docs.triliumnotes.org/user-guide/concepts/notes/cloning))
* Rich WYSIWYG note editor including e.g. tables, images and [math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown [autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting)
* Support for editing [notes with source code](https://docs.triliumnotes.org/user-guide/note-types/code), including syntax highlighting
* Fast and easy [navigation between notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation), full text search and [note hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting)
* Seamless [note versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions)
* Note [attributes](https://docs.triliumnotes.org/user-guide/advanced-usage/attributes) can be used for note organization, querying and advanced [scripting](https://docs.triliumnotes.org/user-guide/scripts)
* UI available in English, German, Spanish, French, Romanian, and Chinese (simplified and traditional)
* Direct [OpenID and TOTP integration](./docs/User%20Guide/User%20Guide/Installation%20%26%20Setup/Server%20Installation/Multi-Factor%20Authentication.md) for more secure login
* [Synchronization](https://triliumnext.github.io/Docs/Wiki/synchronization) with self-hosted sync server
* there's a [3rd party service for hosting synchronisation server](https://trilium.cc/paid-hosting)
* [Sharing](https://triliumnext.github.io/Docs/Wiki/sharing) (publishing) notes to public internet
* Strong [note encryption](https://triliumnext.github.io/Docs/Wiki/protected-notes) with per-note granularity
* Direct [OpenID and TOTP integration](https://docs.triliumnotes.org/user-guide/setup/server/mfa) for more secure login
* [Synchronization](https://docs.triliumnotes.org/user-guide/setup/synchronization) with self-hosted sync server
* there are [3rd party services for hosting synchronisation server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing) (publishing) notes to public internet
* Strong [note encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes) with per-note granularity
* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type "canvas")
* [Relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map) and [link maps](https://triliumnext.github.io/Docs/Wiki/link-map) for visualizing notes and their relations
* [Relation maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and [note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map) for visualizing notes and their relations
* Mind maps, based on [Mind Elixir](https://docs.mind-elixir.com/)
* [Geo maps](./docs/User%20Guide/User%20Guide/Note%20Types/Geo%20Map.md) with location pins and GPX tracks
* [Scripting](https://triliumnext.github.io/Docs/Wiki/scripts) - see [Advanced showcases](https://triliumnext.github.io/Docs/Wiki/advanced-showcases)
* [REST API](https://triliumnext.github.io/Docs/Wiki/etapi) for automation
* [Geo maps](https://docs.triliumnotes.org/user-guide/collections/geomap) with location pins and GPX tracks
* [Scripting](https://docs.triliumnotes.org/user-guide/scripts) - see [Advanced showcases](https://docs.triliumnotes.org/user-guide/advanced-usage/advanced-showcases)
* [REST API](https://docs.triliumnotes.org/user-guide/advanced-usage/etapi) for automation
* Scales well in both usability and performance upwards of 100 000 notes
* Touch optimized [mobile frontend](https://triliumnext.github.io/Docs/Wiki/mobile-frontend) for smartphones and tablets
* Built-in [dark theme](https://triliumnext.github.io/Docs/Wiki/themes), support for user themes
* [Evernote](https://triliumnext.github.io/Docs/Wiki/evernote-import) and [Markdown import & export](https://triliumnext.github.io/Docs/Wiki/markdown)
* [Web Clipper](https://triliumnext.github.io/Docs/Wiki/web-clipper) for easy saving of web content
* Touch optimized [mobile frontend](https://docs.triliumnotes.org/user-guide/setup/mobile-frontend) for smartphones and tablets
* Built-in [dark theme](https://docs.triliumnotes.org/user-guide/concepts/themes), support for user themes
* [Evernote](https://docs.triliumnotes.org/user-guide/concepts/import-export/evernote) and [Markdown import & export](https://docs.triliumnotes.org/user-guide/concepts/import-export/markdown)
* [Web Clipper](https://docs.triliumnotes.org/user-guide/setup/web-clipper) for easy saving of web content
* Customizable UI (sidebar buttons, user-defined widgets, ...)
* [Metrics](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics.md), along with a [Grafana Dashboard](./docs/User%20Guide/User%20Guide/Advanced%20Usage/Metrics/grafana-dashboard.json)
* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics), along with a Grafana Dashboard.
✨ Check out the following third-party resources/communities for more TriliumNext related goodies:
@@ -131,7 +132,7 @@ Note: It is best to disable automatic updates on your server installation (see b
### Server
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://triliumnext.github.io/Docs/Wiki/server-installation).
To install TriliumNext on your own server (including via Docker from [Dockerhub](https://hub.docker.com/r/triliumnext/trilium)) follow [the server installation docs](https://docs.triliumnotes.org/user-guide/setup/server).
## 💻 Contribute
@@ -198,7 +199,7 @@ Trilium would not be possible without the technologies behind it:
* [Leaflet](https://github.com/Leaflet/Leaflet) - for rendering geographical maps.
* [Tabulator](https://github.com/olifolkerd/tabulator) - for the interactive table used in collections.
* [FancyTree](https://github.com/mar10/fancytree) - feature-rich tree library without real competition.
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://triliumnext.github.io/Docs/Wiki/relation-map.html) and [link maps](https://triliumnext.github.io/Docs/Wiki/note-map.html#link-map)
* [jsPlumb](https://github.com/jsplumb/jsplumb) - visual connectivity library. Used in [relation maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and [link maps](https://docs.triliumnotes.org/user-guide/advanced-usage/note-map#link-map)
## 🤝 Support

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env node
import anonymizationService from "../src/services/anonymization.js";
import fs from "fs";
import path from "path";
fs.writeFileSync(path.resolve(__dirname, "tpl", "anonymize-database.sql"), anonymizationService.getFullAnonymizationScript());

View File

@@ -1,7 +0,0 @@
#!/usr/bin/env bash
SCHEMA_FILE_PATH=db/schema.sql
sqlite3 ./data/document.db .schema | grep -v "sqlite_sequence" > "$SCHEMA_FILE_PATH"
echo "DB schema exported to $SCHEMA_FILE_PATH"

View File

@@ -1,16 +0,0 @@
#!/usr/bin/env bash
if [[ $# -eq 0 ]] ; then
echo "Missing argument of new version"
exit 1
fi
VERSION=$1
SERIES=${VERSION:0:4}-latest
docker push zadam/trilium:$VERSION
docker push zadam/trilium:$SERIES
if [[ $1 != *"beta"* ]]; then
docker push zadam/trilium:latest
fi

View File

@@ -1,57 +0,0 @@
#!/usr/bin/env bash
if [[ $# -eq 0 ]] ; then
echo "Missing argument of new version"
exit 1
fi
VERSION=$1
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
then
echo "Version ${VERSION} isn't in format X.Y.Z"
exit 1
fi
VERSION_DATE=$(git log -1 --format=%aI "v${VERSION}" | cut -c -10)
VERSION_COMMIT=$(git rev-list -n 1 "v${VERSION}")
# expecting the directory at a specific path
cd ~/trilium-flathub || exit
if ! git diff-index --quiet HEAD --; then
echo "There are uncommitted changes"
exit 1
fi
BASE_BRANCH=main
if [[ "$VERSION" == *"beta"* ]]; then
BASE_BRANCH=beta
fi
git switch "${BASE_BRANCH}"
git pull
BRANCH=b${VERSION}
git branch "${BRANCH}"
git switch "${BRANCH}"
echo "Updating files with version ${VERSION}, date ${VERSION_DATE} and commit ${VERSION_COMMIT}"
flatpak-node-generator npm ../trilium/package-lock.json
xmlstarlet ed --inplace --update "/component/releases/release/@version" --value "${VERSION}" --update "/component/releases/release/@date" --value "${VERSION_DATE}" ./com.github.zadam.trilium.metainfo.xml
yq --inplace "(.modules[0].sources[0].tag = \"v${VERSION}\") | (.modules[0].sources[0].commit = \"${VERSION_COMMIT}\")" ./com.github.zadam.trilium.yml
git add ./generated-sources.json
git add ./com.github.zadam.trilium.metainfo.xml
git add ./com.github.zadam.trilium.yml
git commit -m "release $VERSION"
git push --set-upstream origin "${BRANCH}"
gh pr create --fill -B "${BASE_BRANCH}"
gh pr merge --auto --merge --delete-branch

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env bash
set -e
if [[ $# -eq 0 ]] ; then
echo "Missing argument of new version"
exit 1
fi
if ! command -v jq &> /dev/null; then
echo "Missing command: jq"
exit 1
fi
VERSION=$1
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
then
echo "Version ${VERSION} isn't in format X.Y.Z"
exit 1
fi
if ! git diff-index --quiet HEAD --; then
echo "There are uncommitted changes"
exit 1
fi
echo "Releasing Trilium $VERSION"
jq '.version = "'$VERSION'"' package.json > package.json.tmp
mv package.json.tmp package.json
git add package.json
npm run chore:update-build-info
git add src/services/build.ts
TAG=v$VERSION
echo "Committing package.json version change"
git commit -m "chore(release): $VERSION"
git push
echo "Tagging commit with $TAG"
git tag $TAG
git push origin $TAG

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
</dict>
</plist>

View File

@@ -1,51 +0,0 @@
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import simpleImportSort from "eslint-plugin-simple-import-sort";
export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommended,
// consider using rules below, once we have a full TS codebase and can be more strict
// tseslint.configs.strictTypeChecked,
// tseslint.configs.stylisticTypeChecked,
// tseslint.configs.recommendedTypeChecked,
{
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: import.meta.dirname
}
}
},
{
plugins: {
"simple-import-sort": simpleImportSort
}
},
{
rules: {
// add rule overrides here
"no-undef": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_"
}
],
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
}
},
{
ignores: [
"build/*",
"dist/*",
"docs/*",
"demo/*",
"src/public/app-dist/*",
"src/public/app/doc_notes/*"
]
}
);

View File

@@ -1,47 +0,0 @@
import stylistic from "@stylistic/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
// eslint config just for formatting rules
// potentially to be merged with the linting rules into one single config,
// once we have fixed the majority of lint errors
// Go to https://eslint.style/rules/default/${rule_without_prefix} to check the rule details
export const stylisticRules = {
"@stylistic/indent": [ "error", 4 ],
"@stylistic/quotes": [ "error", "double", { avoidEscape: true, allowTemplateLiterals: "always" } ],
"@stylistic/semi": [ "error", "always" ],
"@stylistic/quote-props": [ "error", "consistent-as-needed" ],
"@stylistic/max-len": [ "error", { code: 100 } ],
"@stylistic/comma-dangle": [ "error", "never" ],
"@stylistic/linebreak-style": [ "error", "unix" ],
"@stylistic/array-bracket-spacing": [ "error", "always" ],
"@stylistic/object-curly-spacing": [ "error", "always" ],
"@stylistic/padded-blocks": [ "error", { classes: "always" } ]
};
export default [
{
files: [ "**/*.{js,ts,mjs,cjs}" ],
languageOptions: {
parser: tsParser
},
plugins: {
"@stylistic": stylistic
},
rules: {
...stylisticRules
}
},
{
ignores: [
"build/*",
"dist/*",
"docs/*",
"demo/*",
// TriliumNextTODO: check if we want to format packages here as well - for now skipping it
"packages/*",
"src/public/app-dist/*",
"src/public/app/doc_notes/*"
]
}
];

View File

@@ -1,17 +0,0 @@
import { test as setup, expect } from "@playwright/test";
const authFile = "playwright/.auth/user.json";
const ROOT_URL = "http://localhost:8082";
const LOGIN_PASSWORD = "demo1234";
// Reference: https://playwright.dev/docs/auth#basic-shared-account-in-all-tests
setup("authenticate", async ({ page }) => {
await page.goto(ROOT_URL);
await expect(page).toHaveURL(`${ROOT_URL}/login`);
await page.getByRole("textbox", { name: "Password" }).fill(LOGIN_PASSWORD);
await page.getByRole("button", { name: "Login" }).click();
await page.context().storageState({ path: authFile });
});

View File

@@ -1,9 +0,0 @@
import { test, expect } from "@playwright/test";
test("Can duplicate note with broken links", async ({ page }) => {
await page.goto(`http://localhost:8082/#2VammGGdG6Ie`);
await page.locator(".tree-wrapper .fancytree-active").getByText("Note map").click({ button: "right" });
await page.getByText("Duplicate subtree").click();
await expect(page.locator(".toast-body")).toBeHidden();
await expect(page.locator(".tree-wrapper").getByText("Note map (dup)")).toBeVisible();
});

View File

@@ -1,18 +0,0 @@
import { test, expect } from "@playwright/test";
test("has title", async ({ page }) => {
await page.goto("https://playwright.dev/");
// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});
test("get started link", async ({ page }) => {
await page.goto("https://playwright.dev/");
// Click the get started link.
await page.getByRole("link", { name: "Get started" }).click();
// Expects page to have a heading with the name of Installation.
await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
});

View File

@@ -1,21 +0,0 @@
import test, { expect } from "@playwright/test";
test("Native Title Bar not displayed on web", async ({ page }) => {
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsAppearance");
await expect(page.getByRole("heading", { name: "Theme" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Native Title Bar (requires" })).toBeHidden();
});
test("Tray settings not displayed on web", async ({ page }) => {
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsOther");
await expect(page.getByRole("heading", { name: "Note Erasure Timeout" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Tray" })).toBeHidden();
});
test("Spellcheck settings not displayed on web", async ({ page }) => {
await page.goto("http://localhost:8082/#root/_hidden/_options/_optionsSpellcheck");
await expect(page.getByRole("heading", { name: "Spell Check" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Tray" })).toBeHidden();
await expect(page.getByText("These options apply only for desktop builds")).toBeVisible();
await expect(page.getByText("Enable spellcheck")).toBeHidden();
});

View File

@@ -1,18 +0,0 @@
import test, { expect } from "@playwright/test";
test("Renders on desktop", async ({ page, context }) => {
await page.goto("http://localhost:8082");
await expect(page.locator(".tree")).toContainText("Trilium Integration Test");
});
test("Renders on mobile", async ({ page, context }) => {
await context.addCookies([
{
url: "http://localhost:8082",
name: "trilium-device",
value: "mobile"
}
]);
await page.goto("http://localhost:8082");
await expect(page.locator(".tree")).toContainText("Trilium Integration Test");
});

View File

@@ -1,12 +0,0 @@
import { test, expect } from "@playwright/test";
const expectedVersion = "0.90.3";
test("Displays update badge when there is a version available", async ({ page }) => {
await page.goto("http://localhost:8080");
await page.getByRole("button", { name: "" }).click();
await page.getByText(`Version ${expectedVersion} is available,`).click();
const page1 = await page.waitForEvent("popup");
expect(page1.url()).toBe(`https://github.com/TriliumNext/Trilium/releases/tag/v${expectedVersion}`);
});

View File

@@ -1,56 +0,0 @@
{
"main": "./electron-main.js",
"bin": {
"trilium": "src/main.js"
},
"type": "module",
"scripts": {
"server:start-safe": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nodemon src/main.ts",
"server:start-no-dir": "cross-env TRILIUM_ENV=dev nodemon src/main.ts",
"server:start-test": "npm run server:switch && rimraf ./data-test && cross-env TRILIUM_DATA_DIR=./data-test TRILIUM_ENV=dev TRILIUM_PORT=9999 nodemon src/main.ts",
"server:qstart": "npm run server:switch && npm run server:start",
"server:switch": "rimraf ./node_modules/better-sqlite3 && npm install",
"electron:start-no-dir": "cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 electron --inspect=5858 .",
"electron:start-nix": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
"electron:start-nix-no-dir": "electron-rebuild --version 33.3.1 && cross-env NODE_OPTIONS=\"--import tsx\" TRILIUM_ENV=dev TRILIUM_PORT=37742 nix-shell -p electron_33 --run \"electron ./electron-main.ts --inspect=5858 .\"",
"electron:start-prod-no-dir": "npm run build:prepare-dist && cross-env TRILIUM_ENV=prod electron --inspect=5858 .",
"electron:start-prod-nix": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
"electron:start-prod-nix-no-dir": "electron-rebuild --version 33.3.1 && npm run build:prepare-dist && cross-env TRILIUM_ENV=dev nix-shell -p electron_33 --run \"electron ./dist/electron-main.js --inspect=5858 .\"",
"electron:qstart": "npm run electron:switch && npm run electron:start",
"electron:switch": "electron-rebuild",
"docs:build": "typedoc",
"test": "npm run client:test && npm run server:test",
"client:test": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app",
"client:coverage": "cross-env TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db TRILIUM_INTEGRATION_TEST=memory vitest --root src/public/app --coverage",
"test:playwright": "playwright test --workers 1",
"test:integration-edit-db": "cross-env TRILIUM_INTEGRATION_TEST=edit TRILIUM_PORT=8081 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"test:integration-mem-db": "cross-env nodemon src/main.ts",
"test:integration-mem-db-dev": "cross-env TRILIUM_INTEGRATION_TEST=memory TRILIUM_PORT=8082 TRILIUM_ENV=dev TRILIUM_DATA_DIR=./integration-tests/db nodemon src/main.ts",
"dev:watch-dist": "tsx ./bin/watch-dist.ts",
"dev:format-check": "eslint -c eslint.format.config.js .",
"dev:format-fix": "eslint -c eslint.format.config.js . --fix",
"dev:linter-check": "eslint .",
"dev:linter-fix": "eslint . --fix",
"chore:generate-document": "cross-env nodemon ./bin/generate_document.ts 1000",
"chore:generate-openapi": "tsx bin/generate-openapi.js"
},
"devDependencies": {
"@playwright/test": "1.56.1",
"@stylistic/eslint-plugin": "5.5.0",
"@types/express": "5.0.5",
"@types/node": "24.10.0",
"@types/yargs": "17.0.34",
"@vitest/coverage-v8": "3.2.4",
"eslint": "9.39.1",
"eslint-plugin-simple-import-sort": "12.1.1",
"esm": "3.2.25",
"jsdoc": "4.0.5",
"lorem-ipsum": "2.0.8",
"rcedit": "5.0.0",
"rimraf": "6.1.0",
"tslib": "2.8.1"
},
"optionalDependencies": {
"appdmg": "0.6.6"
}
}

View File

@@ -1,9 +0,0 @@
import etapi from "../support/etapi.js";
/* TriliumNextTODO: port to Vitest
etapi.describeEtapi("app_info", () => {
it("get", async () => {
const appInfo = await etapi.getEtapi("app-info");
expect(appInfo.clipperProtocolVersion).toEqual("1.0");
});
});
*/

View File

@@ -1,10 +0,0 @@
import etapi from "../support/etapi.js";
/* TriliumNextTODO: port to Vitest
etapi.describeEtapi("backup", () => {
it("create", async () => {
const response = await etapi.putEtapiContent("backup/etapi_test");
expect(response.status).toEqual(204);
});
});
*/

View File

@@ -1,26 +0,0 @@
import etapi from "../support/etapi.js";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
/* TriliumNextTODO: port to Vitest
etapi.describeEtapi("import", () => {
// temporarily skip this test since test-export.zip is missing
xit("import", async () => {
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
const zipFileBuffer = fs.readFileSync(path.resolve(scriptDir, "test-export.zip"));
const response = await etapi.postEtapiContent("notes/root/import", zipFileBuffer);
expect(response.status).toEqual(201);
const { note, branch } = await response.json();
expect(note.title).toEqual("test-export");
expect(branch.parentNoteId).toEqual("root");
const content = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
expect(content).toContain("test export content");
});
});
*/

View File

@@ -1,103 +0,0 @@
import crypto from "crypto";
import etapi from "../support/etapi.js";
/* TriliumNextTODO: port to Vitest
etapi.describeEtapi("notes", () => {
it("create", async () => {
const { note, branch } = await etapi.postEtapi("create-note", {
parentNoteId: "root",
type: "text",
title: "Hello World!",
content: "Content",
prefix: "Custom prefix"
});
expect(note.title).toEqual("Hello World!");
expect(branch.parentNoteId).toEqual("root");
expect(branch.prefix).toEqual("Custom prefix");
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
expect(rNote.title).toEqual("Hello World!");
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
expect(rContent).toEqual("Content");
const rBranch = await etapi.getEtapi(`branches/${branch.branchId}`);
expect(rBranch.parentNoteId).toEqual("root");
expect(rBranch.prefix).toEqual("Custom prefix");
});
it("patch", async () => {
const { note } = await etapi.postEtapi("create-note", {
parentNoteId: "root",
type: "text",
title: "Hello World!",
content: "Content"
});
await etapi.patchEtapi(`notes/${note.noteId}`, {
title: "new title",
type: "code",
mime: "text/apl",
dateCreated: "2000-01-01 12:34:56.999+0200",
utcDateCreated: "2000-01-01 10:34:56.999Z"
});
const rNote = await etapi.getEtapi(`notes/${note.noteId}`);
expect(rNote.title).toEqual("new title");
expect(rNote.type).toEqual("code");
expect(rNote.mime).toEqual("text/apl");
expect(rNote.dateCreated).toEqual("2000-01-01 12:34:56.999+0200");
expect(rNote.utcDateCreated).toEqual("2000-01-01 10:34:56.999Z");
});
it("update content", async () => {
const { note } = await etapi.postEtapi("create-note", {
parentNoteId: "root",
type: "text",
title: "Hello World!",
content: "Content"
});
await etapi.putEtapiContent(`notes/${note.noteId}/content`, "new content");
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).text();
expect(rContent).toEqual("new content");
});
it("create / update binary content", async () => {
const { note } = await etapi.postEtapi("create-note", {
parentNoteId: "root",
type: "file",
title: "Hello World!",
content: "ZZZ"
});
const updatedContent = crypto.randomBytes(16);
await etapi.putEtapiContent(`notes/${note.noteId}/content`, updatedContent);
const rContent = await (await etapi.getEtapiContent(`notes/${note.noteId}/content`)).arrayBuffer();
expect(Buffer.from(new Uint8Array(rContent))).toEqual(updatedContent);
});
it("delete note", async () => {
const { note } = await etapi.postEtapi("create-note", {
parentNoteId: "root",
type: "text",
title: "Hello World!",
content: "Content"
});
await etapi.deleteEtapi(`notes/${note.noteId}`);
const resp = await etapi.getEtapiResponse(`notes/${note.noteId}`);
expect(resp.status).toEqual(404);
const error = await resp.json();
expect(error.status).toEqual(404);
expect(error.code).toEqual("NOTE_NOT_FOUND");
expect(error.message).toEqual(`Note '${note.noteId}' not found.`);
});
});
*/

View File

@@ -1,152 +0,0 @@
import { describe, beforeAll, afterAll } from "vitest";
let etapiAuthToken: string | undefined;
const getEtapiAuthorizationHeader = (): string => "Basic " + Buffer.from(`etapi:${etapiAuthToken}`).toString("base64");
const PORT: string = "9999";
const HOST: string = "http://localhost:" + PORT;
type SpecDefinitionsFunc = () => void;
function describeEtapi(description: string, specDefinitions: SpecDefinitionsFunc): void {
describe(description, () => {
beforeAll(async () => {});
afterAll(() => {});
specDefinitions();
});
}
async function getEtapiResponse(url: string): Promise<Response> {
return await fetch(`${HOST}/etapi/${url}`, {
method: "GET",
headers: {
Authorization: getEtapiAuthorizationHeader()
}
});
}
async function getEtapi(url: string): Promise<any> {
const response = await getEtapiResponse(url);
return await processEtapiResponse(response);
}
async function getEtapiContent(url: string): Promise<Response> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "GET",
headers: {
Authorization: getEtapiAuthorizationHeader()
}
});
checkStatus(response);
return response;
}
async function postEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: getEtapiAuthorizationHeader()
},
body: JSON.stringify(data)
});
return await processEtapiResponse(response);
}
async function postEtapiContent(url: string, data: BodyInit): Promise<Response> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
Authorization: getEtapiAuthorizationHeader()
},
body: data
});
checkStatus(response);
return response;
}
async function putEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: getEtapiAuthorizationHeader()
},
body: JSON.stringify(data)
});
return await processEtapiResponse(response);
}
async function putEtapiContent(url: string, data?: BodyInit): Promise<Response> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "PUT",
headers: {
"Content-Type": "application/octet-stream",
Authorization: getEtapiAuthorizationHeader()
},
body: data
});
checkStatus(response);
return response;
}
async function patchEtapi(url: string, data: Record<string, unknown> = {}): Promise<any> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
Authorization: getEtapiAuthorizationHeader()
},
body: JSON.stringify(data)
});
return await processEtapiResponse(response);
}
async function deleteEtapi(url: string): Promise<any> {
const response = await fetch(`${HOST}/etapi/${url}`, {
method: "DELETE",
headers: {
Authorization: getEtapiAuthorizationHeader()
}
});
return await processEtapiResponse(response);
}
async function processEtapiResponse(response: Response): Promise<any> {
const text = await response.text();
if (response.status < 200 || response.status >= 300) {
throw new Error(`ETAPI error ${response.status}: ${text}`);
}
return text?.trim() ? JSON.parse(text) : null;
}
function checkStatus(response: Response): void {
if (response.status < 200 || response.status >= 300) {
throw new Error(`ETAPI error ${response.status}`);
}
}
export default {
describeEtapi,
getEtapi,
getEtapiResponse,
getEtapiContent,
postEtapi,
postEtapiContent,
putEtapi,
putEtapiContent,
patchEtapi,
deleteEtapi
};

View File

@@ -1,22 +0,0 @@
{
"compilerOptions": {
"module": "NodeNext",
"declaration": false,
"sourceMap": true,
"outDir": "./build",
"strict": true,
"noImplicitAny": true,
"resolveJsonModule": true,
"lib": ["ES2023"],
"downlevelIteration": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowJs": true
},
"include": ["./src/public/app/**/*"],
"files": [
"./src/public/app/types.d.ts",
"./src/public/app/types-lib.d.ts",
"./src/types.d.ts"
]
}

View File

@@ -9,14 +9,14 @@
"keywords": [],
"author": "Elian Doran <contact@eliandoran.me>",
"license": "AGPL-3.0-only",
"packageManager": "pnpm@10.20.0",
"packageManager": "pnpm@10.26.2",
"devDependencies": {
"@redocly/cli": "2.11.0",
"@redocly/cli": "2.14.1",
"archiver": "7.0.1",
"fs-extra": "11.3.2",
"react": "19.2.0",
"react-dom": "19.2.0",
"typedoc": "0.28.14",
"fs-extra": "11.3.3",
"react": "19.2.3",
"react-dom": "19.2.3",
"typedoc": "0.28.15",
"typedoc-plugin-missing-exports": "4.1.2"
}
}

View File

@@ -1,5 +0,0 @@
import baseConfig from "../../eslint.config.mjs";
export default [
...baseConfig
];

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/client",
"version": "0.99.5",
"version": "0.101.1",
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
"private": true,
"license": "AGPL-3.0-only",
@@ -12,54 +12,55 @@
"scripts": {
"build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build",
"test": "vitest",
"coverage": "vitest --coverage",
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
},
"dependencies": {
"@eslint/js": "9.39.1",
"@excalidraw/excalidraw": "0.18.0",
"@fullcalendar/core": "6.1.19",
"@fullcalendar/daygrid": "6.1.19",
"@fullcalendar/interaction": "6.1.19",
"@fullcalendar/list": "6.1.19",
"@fullcalendar/multimonth": "6.1.19",
"@fullcalendar/timegrid": "6.1.19",
"@fullcalendar/core": "6.1.20",
"@fullcalendar/daygrid": "6.1.20",
"@fullcalendar/interaction": "6.1.20",
"@fullcalendar/list": "6.1.20",
"@fullcalendar/multimonth": "6.1.20",
"@fullcalendar/timegrid": "6.1.20",
"@maplibre/maplibre-gl-leaflet": "0.1.3",
"@mermaid-js/layout-elk": "0.2.0",
"@mind-elixir/node-menu": "5.0.0",
"@mind-elixir/node-menu": "5.0.1",
"@popperjs/core": "2.11.8",
"@preact/signals": "2.5.1",
"@triliumnext/ckeditor5": "workspace:*",
"@triliumnext/codemirror": "workspace:*",
"@triliumnext/commons": "workspace:*",
"@triliumnext/highlightjs": "workspace:*",
"@triliumnext/share-theme": "workspace:*",
"@triliumnext/split.js": "workspace:*",
"@zumer/snapdom": "2.0.1",
"autocomplete.js": "0.38.1",
"bootstrap": "5.3.8",
"boxicons": "2.1.4",
"color": "5.0.2",
"dayjs": "1.11.19",
"dayjs-plugin-utc": "0.1.2",
"clsx": "2.1.1",
"color": "5.0.3",
"debounce": "3.0.0",
"draggabilly": "3.0.0",
"force-graph": "1.51.0",
"globals": "16.5.0",
"i18next": "25.6.1",
"i18next": "25.7.3",
"i18next-http-backend": "3.0.2",
"jquery": "3.7.1",
"jquery.fancytree": "2.38.5",
"jsplumb": "2.15.6",
"katex": "0.16.25",
"katex": "0.16.27",
"knockout": "3.5.1",
"leaflet": "1.9.4",
"leaflet-gpx": "2.2.0",
"mark.js": "8.11.1",
"marked": "16.4.2",
"mermaid": "11.12.1",
"mind-elixir": "5.3.5",
"marked": "17.0.1",
"mermaid": "11.12.2",
"mind-elixir": "5.3.8",
"normalize.css": "8.0.1",
"panzoom": "9.4.3",
"preact": "10.27.2",
"react-i18next": "16.2.4",
"preact": "10.28.1",
"react-i18next": "16.5.0",
"reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",
@@ -73,10 +74,10 @@
"@types/leaflet": "1.9.21",
"@types/leaflet-gpx": "1.3.8",
"@types/mark.js": "8.11.12",
"@types/reveal.js": "5.2.1",
"@types/tabulator-tables": "6.3.0",
"@types/reveal.js": "5.2.2",
"@types/tabulator-tables": "6.3.1",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.10",
"happy-dom": "20.0.11",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.4"
}

View File

@@ -1,38 +1,41 @@
import froca from "../services/froca.js";
import RootCommandExecutor from "./root_command_executor.js";
import Entrypoints from "./entrypoints.js";
import options from "../services/options.js";
import utils, { hasTouchBar } from "../services/utils.js";
import zoomComponent from "./zoom.js";
import TabManager from "./tab_manager.js";
import Component from "./component.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import linkService, { type ViewScope } from "../services/link.js";
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
import MainTreeExecutors from "./main_tree_executors.js";
import toast from "../services/toast.js";
import ShortcutComponent from "./shortcut_component.js";
import { t, initLocale } from "../services/i18n.js";
import type NoteDetailWidget from "../widgets/note_detail.js";
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
import type LoadResults from "../services/load_results.js";
import type { Attribute } from "../services/attribute_parser.js";
import type NoteTreeWidget from "../widgets/note_tree.js";
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
import type EditableTextTypeWidget from "../widgets/type_widgets/editable_text.js";
import type { NativeImage, TouchBar } from "electron";
import TouchBarComponent from "./touch_bar.js";
import type { CKTextEditor } from "@triliumnext/ckeditor5";
import type CodeMirror from "@triliumnext/codemirror";
import { StartupChecks } from "./startup_checks.js";
import type { CreateNoteOpts } from "../services/note_create.js";
import { ColumnComponent } from "tabulator-tables";
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
import type RootContainer from "../widgets/containers/root_container.js";
import { SqlExecuteResults } from "@triliumnext/commons";
import type { NativeImage, TouchBar } from "electron";
import { ColumnComponent } from "tabulator-tables";
import type { Attribute } from "../services/attribute_parser.js";
import froca from "../services/froca.js";
import { initLocale,t } from "../services/i18n.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import linkService, { type ViewScope } from "../services/link.js";
import type LoadResults from "../services/load_results.js";
import type { CreateNoteOpts } from "../services/note_create.js";
import options from "../services/options.js";
import toast from "../services/toast.js";
import utils, { hasTouchBar } from "../services/utils.js";
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
import type RootContainer from "../widgets/containers/root_container.js";
import { AddLinkOpts } from "../widgets/dialogs/add_link.jsx";
import type { ConfirmWithMessageOptions, ConfirmWithTitleOptions } from "../widgets/dialogs/confirm.js";
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
import { IncludeNoteOpts } from "../widgets/dialogs/include_note.jsx";
import type { InfoProps } from "../widgets/dialogs/info.jsx";
import type { MarkdownImportOpts } from "../widgets/dialogs/markdown_import.jsx";
import { ChooseNoteTypeCallback } from "../widgets/dialogs/note_type_chooser.jsx";
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
import type NoteTreeWidget from "../widgets/note_tree.js";
import Component from "./component.js";
import Entrypoints from "./entrypoints.js";
import MainTreeExecutors from "./main_tree_executors.js";
import MobileScreenSwitcherExecutor, { type Screen } from "./mobile_screen_switcher.js";
import type { default as NoteContext, GetTextEditorCallback } from "./note_context.js";
import RootCommandExecutor from "./root_command_executor.js";
import ShortcutComponent from "./shortcut_component.js";
import { StartupChecks } from "./startup_checks.js";
import TabManager from "./tab_manager.js";
import TouchBarComponent from "./touch_bar.js";
import zoomComponent from "./zoom.js";
interface Layout {
getRootWidget: (appContext: AppContext) => RootContainer;
@@ -123,7 +126,7 @@ export type CommandMappings = {
isNewNote?: boolean;
};
showPromptDialog: PromptDialogOptions;
showInfoDialog: ConfirmWithMessageOptions;
showInfoDialog: InfoProps;
showConfirmDialog: ConfirmWithMessageOptions;
showRecentChanges: CommandData & { ancestorNoteId: string };
showImportDialog: CommandData & { noteId: string };
@@ -199,7 +202,7 @@ export type CommandMappings = {
resetLauncher: ContextMenuCommandData;
executeInActiveNoteDetailWidget: CommandData & {
callback: (value: NoteDetailWidget | PromiseLike<NoteDetailWidget>) => void;
callback: (value: ReactWrappedWidget) => void;
};
executeWithTextEditor: CommandData &
ExecuteCommandData<CKTextEditor> & {
@@ -211,7 +214,7 @@ export type CommandMappings = {
* Generally should not be invoked manually, as it is used by {@link NoteContext.getContentElement}.
*/
executeWithContentElement: CommandData & ExecuteCommandData<JQuery<HTMLElement>>;
executeWithTypeWidget: CommandData & ExecuteCommandData<TypeWidget | null>;
executeWithTypeWidget: CommandData & ExecuteCommandData<ReactWrappedWidget | null>;
addTextToActiveEditor: CommandData & {
text: string;
};
@@ -221,9 +224,9 @@ export type CommandMappings = {
showPasswordNotSet: CommandData;
showProtectedSessionPasswordDialog: CommandData;
showUploadAttachmentsDialog: CommandData & { noteId: string };
showIncludeNoteDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
showAddLinkDialog: CommandData & { textTypeWidget: EditableTextTypeWidget, text: string };
showPasteMarkdownDialog: CommandData & { textTypeWidget: EditableTextTypeWidget };
showIncludeNoteDialog: CommandData & IncludeNoteOpts;
showAddLinkDialog: CommandData & AddLinkOpts;
showPasteMarkdownDialog: CommandData & MarkdownImportOpts;
closeProtectedSessionPasswordDialog: CommandData;
copyImageReferenceToClipboard: CommandData;
copyImageToClipboard: CommandData;
@@ -263,7 +266,7 @@ export type CommandMappings = {
reEvaluateRightPaneVisibility: CommandData;
runActiveNote: CommandData;
scrollContainerToCommand: CommandData & {
scrollContainerTo: CommandData & {
position: number;
};
scrollToEnd: CommandData;
@@ -328,6 +331,7 @@ export type CommandMappings = {
exportAsPdf: CommandData;
openNoteExternally: CommandData;
openNoteCustom: CommandData;
openNoteOnServer: CommandData;
renderActiveNote: CommandData;
unhoist: CommandData;
reloadFrontendApp: CommandData;
@@ -443,6 +447,8 @@ type EventMappings = {
error: string;
};
searchRefreshed: { ntxId?: string | null };
textEditorRefreshed: { ntxId?: string | null, editor: CKTextEditor };
contentElRefreshed: { ntxId?: string | null, contentEl: HTMLElement };
hoistedNoteChanged: {
noteId: string;
ntxId: string | null;
@@ -484,14 +490,9 @@ type EventMappings = {
relationMapResetPanZoom: { ntxId: string | null | undefined };
relationMapResetZoomIn: { ntxId: string | null | undefined };
relationMapResetZoomOut: { ntxId: string | null | undefined };
activeNoteChanged: {};
showAddLinkDialog: {
textTypeWidget: EditableTextTypeWidget;
text: string;
};
showIncludeDialog: {
textTypeWidget: EditableTextTypeWidget;
};
activeNoteChanged: {ntxId: string | null | undefined};
showAddLinkDialog: AddLinkOpts;
showIncludeDialog: IncludeNoteOpts;
openBulkActionsDialog: {
selectedOrActiveNoteIds: string[];
};
@@ -670,6 +671,10 @@ export class AppContext extends Component {
this.beforeUnloadListeners.push(obj);
}
}
removeBeforeUnloadListener(listener: (() => boolean)) {
this.beforeUnloadListeners = this.beforeUnloadListeners.filter(l => l !== listener);
}
}
const appContext = new AppContext(window.glob.isMainWindow);
@@ -692,10 +697,8 @@ $(window).on("beforeunload", () => {
console.log(`Component ${component.componentId} is not finished saving its state.`);
allSaved = false;
}
} else {
if (!listener()) {
allSaved = false;
}
} else if (!listener()) {
allSaved = false;
}
}
@@ -705,7 +708,7 @@ $(window).on("beforeunload", () => {
}
});
$(window).on("hashchange", function () {
$(window).on("hashchange", () => {
const { notePath, ntxId, viewScope, searchString } = linkService.parseNavigationStateFromUrl(window.location.href);
if (notePath || ntxId) {

View File

@@ -65,8 +65,8 @@ export class TypedComponent<ChildT extends TypedComponent<ChildT>> {
// don't create promises if not needed (optimization)
return callMethodPromise && childrenPromise ? Promise.all([callMethodPromise, childrenPromise]) : callMethodPromise || childrenPromise;
} catch (e: any) {
console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error ${e.message} ${e.stack}`);
} catch (e: unknown) {
console.error(`Handling of event '${name}' failed in ${this.constructor.name} with error`, e);
return null;
}

View File

@@ -1,18 +1,19 @@
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import utils from "../services/utils.js";
import appContext, { type EventData, type EventListener } from "./app_context.js";
import treeService from "../services/tree.js";
import Component from "./component.js";
import froca from "../services/froca.js";
import hoistedNoteService from "../services/hoisted_note.js";
import options from "../services/options.js";
import type { ViewScope } from "../services/link.js";
import type FNote from "../entities/fnote.js";
import type TypeWidget from "../widgets/type_widgets/type_widget.js";
import type { CKTextEditor } from "@triliumnext/ckeditor5";
import type CodeMirror from "@triliumnext/codemirror";
import type FNote from "../entities/fnote.js";
import { closeActiveDialog } from "../services/dialog.js";
import froca from "../services/froca.js";
import hoistedNoteService from "../services/hoisted_note.js";
import type { ViewScope } from "../services/link.js";
import options from "../services/options.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import treeService from "../services/tree.js";
import utils from "../services/utils.js";
import { ReactWrappedWidget } from "../widgets/basic_widget.js";
import appContext, { type EventData, type EventListener } from "./app_context.js";
import Component from "./component.js";
export interface SetNoteOpts {
triggerSwitchEvent?: unknown;
@@ -321,6 +322,10 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
return false;
}
if (note.type === "search") {
return false;
}
if (!["default", "contextual-help"].includes(this.viewScope?.viewMode ?? "")) {
return false;
}
@@ -385,7 +390,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
* If no content could be determined `null` is returned instead.
*/
async getContentElement() {
return this.timeout<JQuery<HTMLElement>>(
return this.timeout<JQuery<HTMLElement> | null>(
new Promise((resolve) =>
appContext.triggerCommand("executeWithContentElement", {
resolve,
@@ -397,7 +402,7 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded">
async getTypeWidget() {
return this.timeout(
new Promise<TypeWidget | null>((resolve) =>
new Promise<ReactWrappedWidget | null>((resolve) =>
appContext.triggerCommand("executeWithTypeWidget", {
resolve,
ntxId: this.ntxId

View File

@@ -1,14 +1,14 @@
import Component from "./component.js";
import appContext, { type CommandData, type CommandListenerData } from "./app_context.js";
import dateNoteService from "../services/date_notes.js";
import treeService from "../services/tree.js";
import openService from "../services/open.js";
import protectedSessionService from "../services/protected_session.js";
import options from "../services/options.js";
import froca from "../services/froca.js";
import utils from "../services/utils.js";
import toastService from "../services/toast.js";
import noteCreateService from "../services/note_create.js";
import openService from "../services/open.js";
import options from "../services/options.js";
import protectedSessionService from "../services/protected_session.js";
import toastService from "../services/toast.js";
import treeService from "../services/tree.js";
import utils, { openInReusableSplit } from "../services/utils.js";
import appContext, { type CommandListenerData } from "./app_context.js";
import Component from "./component.js";
export default class RootCommandExecutor extends Component {
editReadOnlyNoteCommand() {
@@ -66,6 +66,13 @@ export default class RootCommandExecutor extends Component {
}
}
openNoteOnServerCommand() {
const noteId = appContext.tabManager.getActiveContextNoteId();
if (noteId) {
openService.openNoteOnServer(noteId);
}
}
enterProtectedSessionCommand() {
protectedSessionService.enterProtectedSession();
}
@@ -186,6 +193,19 @@ export default class RootCommandExecutor extends Component {
appContext.triggerEvent("zenModeChanged", { isEnabled });
}
async toggleRibbonTabNoteMapCommand(data: CommandListenerData<"toggleRibbonTabNoteMap">) {
const { isExperimentalFeatureEnabled } = await import("../services/experimental_features.js");
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
if (!isNewLayout) {
this.triggerEvent("toggleRibbonTabNoteMap", data);
return;
}
const activeContext = appContext.tabManager.getActiveContext();
if (!activeContext?.notePath) return;
openInReusableSplit(activeContext.notePath, "note-map");
}
firstTabCommand() {
this.#goToTab(1);
}
@@ -255,7 +275,7 @@ export default class RootCommandExecutor extends Component {
}
catch (e) {
console.error("Error creating AI Chat note:", e);
toastService.showError("Failed to create AI Chat note: " + (e as Error).message);
toastService.showError(`Failed to create AI Chat note: ${(e as Error).message}`);
}
}
}

View File

@@ -165,7 +165,7 @@ export default class TabManager extends Component {
const activeNoteContext = this.getActiveContext();
this.updateDocumentTitle(activeNoteContext);
this.triggerEvent("activeNoteChanged", {}); // trigger this even in on popstate event
this.triggerEvent("activeNoteChanged", {ntxId:activeNoteContext?.ntxId}); // trigger this even in on popstate event
}
calculateHash(): string {
@@ -265,6 +265,7 @@ export default class TabManager extends Component {
mainNtxId: string | null = null
): Promise<NoteContext> {
const noteContext = new NoteContext(ntxId, hoistedNoteId, mainNtxId);
noteContext.setEmpty();
const existingNoteContext = this.children.find((nc) => nc.ntxId === noteContext.ntxId);
@@ -646,7 +647,32 @@ export default class TabManager extends Component {
...this.noteContexts.slice(-noteContexts.length),
...this.noteContexts.slice(lastClosedTab.position, -noteContexts.length)
];
this.noteContextReorderEvent({ ntxIdsInOrder: ntxsInOrder.map((nc) => nc.ntxId).filter((id) => id !== null) });
// Update mainNtxId if the restored pane is the main pane in the split pane
const { oldMainNtxId, newMainNtxId } = (() => {
if (noteContexts.length !== 1) {
return { oldMainNtxId: undefined, newMainNtxId: undefined };
}
const mainNtxId = noteContexts[0]?.mainNtxId;
const index = this.noteContexts.findIndex(c => c.ntxId === mainNtxId);
// No need to update if the restored position is after mainNtxId
if (index === -1 || lastClosedTab.position > index) {
return { oldMainNtxId: undefined, newMainNtxId: undefined };
}
return {
oldMainNtxId: this.noteContexts[index].ntxId ?? undefined,
newMainNtxId: noteContexts[0]?.ntxId ?? undefined
};
})();
this.triggerCommand("noteContextReorder", {
ntxIdsInOrder: ntxsInOrder.map((nc) => nc.ntxId).filter((id) => id !== null),
oldMainNtxId,
newMainNtxId
});
let mainNtx = noteContexts.find((nc) => nc.isMainContext());
if (mainNtx) {

View File

@@ -22,6 +22,7 @@ bundleService.getWidgetBundlesByParent().then(async (widgetBundles) => {
appContext.setLayout(new DesktopLayout(widgetBundles));
appContext.start().catch((e) => {
toastService.showPersistent({
id: "critical-error",
title: t("toast.critical-error.title"),
icon: "alert",
message: t("toast.critical-error.message", { message: e.message })
@@ -58,10 +59,14 @@ function initOnElectron() {
initDarkOrLightMode(style);
initTransparencyEffects(style, currentWindow);
initFullScreenDetection(currentWindow);
if (options.get("nativeTitleBarVisible") !== "true") {
initTitleBarButtons(style, currentWindow);
}
// Clear navigation history on frontend refresh.
currentWindow.webContents.navigationHistory.clear();
}
function initTitleBarButtons(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) {
@@ -87,6 +92,11 @@ function initTitleBarButtons(style: CSSStyleDeclaration, currentWindow: Electron
}
}
function initFullScreenDetection(currentWindow: Electron.BrowserWindow) {
currentWindow.on("enter-full-screen", () => document.body.classList.add("full-screen"));
currentWindow.on("leave-full-screen", () => document.body.classList.remove("full-screen"));
}
function initTransparencyEffects(style: CSSStyleDeclaration, currentWindow: Electron.BrowserWindow) {
if (window.glob.platform === "win32") {
const material = style.getPropertyValue("--background-material");

View File

@@ -1,16 +1,19 @@
import server from "../services/server.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import { MIME_TYPES_DICT } from "@triliumnext/commons";
import cssClassManager from "../services/css_class_manager.js";
import type { Froca } from "../services/froca-interface.js";
import type FAttachment from "./fattachment.js";
import type { default as FAttribute, AttributeType } from "./fattribute.js";
import noteAttributeCache from "../services/note_attribute_cache.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import search from "../services/search.js";
import server from "../services/server.js";
import utils from "../services/utils.js";
import type FAttachment from "./fattachment.js";
import type { AttributeType,default as FAttribute } from "./fattribute.js";
const LABEL = "label";
const RELATION = "relation";
const NOTE_TYPE_ICONS = {
export const NOTE_TYPE_ICONS = {
file: "bx bx-file",
image: "bx bx-image",
code: "bx bx-code",
@@ -239,7 +242,7 @@ export default class FNote {
const aNote = this.froca.getNoteFromCache(aNoteId);
if (aNote.isArchived || aNote.isHiddenCompletely()) {
if (!aNote || aNote.isArchived || aNote.isHiddenCompletely()) {
return 1;
}
@@ -255,8 +258,24 @@ export default class FNote {
return this.children;
}
async getChildNoteIdsWithArchiveFiltering(includeArchived = false) {
const isHiddenNote = this.noteId.startsWith("_");
const isSearchNote = this.type === "search";
if (!includeArchived && !isHiddenNote && !isSearchNote) {
const unorderedIds = new Set(await search.searchForNoteIds(`note.parents.noteId="${this.noteId}" #!archived`));
const results: string[] = [];
for (const id of this.children) {
if (unorderedIds.has(id)) {
results.push(id);
}
}
return results;
}
return this.children;
}
async getSubtreeNoteIds(includeArchived = false) {
let noteIds: (string | string[])[] = [];
const noteIds: (string | string[])[] = [];
for (const child of await this.getChildNotes()) {
if (child.isArchived && !includeArchived) continue;
@@ -453,9 +472,8 @@ export default class FNote {
return a.isHidden ? 1 : -1;
} else if (a.isSearch !== b.isSearch) {
return a.isSearch ? 1 : -1;
} else {
return a.notePath.length - b.notePath.length;
}
return a.notePath.length - b.notePath.length;
});
return notePaths;
@@ -579,14 +597,13 @@ export default class FNote {
} else if (this.type === "text") {
if (this.isFolder()) {
return "bx bx-folder";
} else {
return "bx bx-note";
}
} else if (this.type === "code" && this.mime.startsWith("text/x-sql")) {
return "bx bx-data";
} else {
return NOTE_TYPE_ICONS[this.type];
return "bx bx-note";
} else if (this.type === "code") {
const correspondingMimeType = MIME_TYPES_DICT.find(m => m.mime === this.mime);
return correspondingMimeType?.icon ?? NOTE_TYPE_ICONS.code;
}
return NOTE_TYPE_ICONS[this.type];
}
getColorClass() {
@@ -599,7 +616,7 @@ export default class FNote {
}
getFilteredChildBranches() {
let childBranches = this.getChildBranches();
const childBranches = this.getChildBranches();
if (!childBranches) {
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
@@ -788,6 +805,16 @@ export default class FNote {
return this.getAttributeValue(LABEL, name);
}
getLabelOrRelation(nameWithPrefix: string) {
if (nameWithPrefix.startsWith("#")) {
return this.getLabelValue(nameWithPrefix.substring(1));
} else if (nameWithPrefix.startsWith("~")) {
return this.getRelationValue(nameWithPrefix.substring(1));
}
return this.getLabelValue(nameWithPrefix);
}
/**
* @param name - relation name
* @returns relation value if relation exists, null otherwise
@@ -839,8 +866,7 @@ export default class FNote {
return [];
}
const promotedAttrs = this.getAttributes()
.filter((attr) => attr.isDefinition())
const promotedAttrs = this.getAttributeDefinitions()
.filter((attr) => {
const def = attr.getDefinition();
@@ -851,15 +877,20 @@ export default class FNote {
promotedAttrs.sort((a, b) => {
if (a.noteId === b.noteId) {
return a.position < b.position ? -1 : 1;
} else {
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
return a.noteId < b.noteId ? -1 : 1;
}
// inherited promoted attributes should stay grouped: https://github.com/zadam/trilium/issues/3761
return a.noteId < b.noteId ? -1 : 1;
});
return promotedAttrs;
}
getAttributeDefinitions() {
return this.getAttributes()
.filter((attr) => attr.isDefinition());
}
hasAncestor(ancestorNoteId: string, followTemplates = false, visitedNoteIds: Set<string> | null = null) {
if (this.noteId === ancestorNoteId) {
return true;
@@ -961,6 +992,10 @@ export default class FNote {
);
}
isJsx() {
return (this.type === "code" && this.mime === "text/jsx");
}
/** @returns true if this note is HTML */
isHtml() {
return (this.type === "code" || this.type === "file" || this.type === "render") && this.mime === "text/html";
@@ -968,7 +1003,7 @@ export default class FNote {
/** @returns JS script environment - either "frontend" or "backend" */
getScriptEnv() {
if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend"))) {
if (this.isHtml() || (this.isJavaScript() && this.mime.endsWith("env=frontend")) || this.isJsx()) {
return "frontend";
}
@@ -990,7 +1025,7 @@ export default class FNote {
* @returns a promise that resolves when the script has been run. Additionally, for front-end notes, the promise will contain the value that is returned by the script.
*/
async executeScript() {
if (!this.isJavaScript()) {
if (!(this.isJavaScript() || this.isJsx())) {
throw new Error(`Note ${this.noteId} is of type ${this.type} and mime ${this.mime} and thus cannot be executed`);
}

View File

@@ -1,49 +1,59 @@
import { applyModals } from "./layout_commons.js";
import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
import type { AppContext } from "../components/app_context.js";
import type { WidgetsByParent } from "../services/bundle.js";
import { isExperimentalFeatureEnabled } from "../services/experimental_features.js";
import options from "../services/options.js";
import utils from "../services/utils.js";
import ApiLog from "../widgets/api_log.jsx";
import ClosePaneButton from "../widgets/buttons/close_pane_button.js";
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
import ContentHeader from "../widgets/containers/content-header.js";
import CreatePaneButton from "../widgets/buttons/create_pane_button.js";
import FindWidget from "../widgets/find.js";
import FlexContainer from "../widgets/containers/flex_container.js";
import FloatingButtons from "../widgets/FloatingButtons.jsx";
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
import HighlightsListWidget from "../widgets/highlights_list.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
import LeftPaneToggle from "../widgets/buttons/left_pane_toggle.js";
import MovePaneButton from "../widgets/buttons/move_pane_button.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import NoteIconWidget from "../widgets/note_icon.jsx";
import RightPaneToggle from "../widgets/buttons/right_pane_toggle.jsx";
import CloseZenModeButton from "../widgets/close_zen_button.jsx";
import NoteList from "../widgets/collections/NoteList.jsx";
import NoteTitleWidget from "../widgets/note_title.jsx";
import NoteTreeWidget from "../widgets/note_tree.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import options from "../services/options.js";
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import QuickSearchWidget from "../widgets/quick_search.js";
import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
import ContentHeader from "../widgets/containers/content_header.js";
import FlexContainer from "../widgets/containers/flex_container.js";
import LeftPaneContainer from "../widgets/containers/left_pane_container.js";
import RightPaneContainer from "../widgets/containers/right_pane_container.js";
import RootContainer from "../widgets/containers/root_container.js";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
import FindWidget from "../widgets/find.js";
import FloatingButtons from "../widgets/FloatingButtons.jsx";
import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.jsx";
import HighlightsListWidget from "../widgets/highlights_list.js";
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
import SpacerWidget from "../widgets/launch_bar/SpacerWidget.jsx";
import InlineTitle from "../widgets/layout/InlineTitle.jsx";
import NoteBadges from "../widgets/layout/NoteBadges.jsx";
import NoteTitleActions from "../widgets/layout/NoteTitleActions.jsx";
import StatusBar from "../widgets/layout/StatusBar.jsx";
import NoteIconWidget from "../widgets/note_icon.jsx";
import NoteTitleWidget from "../widgets/note_title.jsx";
import NoteTreeWidget from "../widgets/note_tree.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import NoteDetail from "../widgets/NoteDetail.jsx";
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
import QuickSearchWidget from "../widgets/quick_search.js";
import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
import { FixedFormattingToolbar } from "../widgets/ribbon/FormattingToolbar.jsx";
import NoteActions from "../widgets/ribbon/NoteActions.jsx";
import Ribbon from "../widgets/ribbon/Ribbon.jsx";
import ScrollPadding from "../widgets/scroll_padding.js";
import SearchResult from "../widgets/search_result.jsx";
import SharedInfo from "../widgets/shared_info.jsx";
import SpacerWidget from "../widgets/spacer.js";
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
import RightPanelContainer from "../widgets/sidebar/RightPanelContainer.jsx";
import SqlResults from "../widgets/sql_result.js";
import SqlTableSchemas from "../widgets/sql_table_schemas.js";
import TabRowWidget from "../widgets/tab_row.js";
import TabHistoryNavigationButtons from "../widgets/TabHistoryNavigationButtons.jsx";
import TitleBarButtons from "../widgets/title_bar_buttons.jsx";
import TocWidget from "../widgets/toc.js";
import type { AppContext } from "../components/app_context.js";
import type { WidgetsByParent } from "../services/bundle.js";
import UploadAttachmentsDialog from "../widgets/dialogs/upload_attachments.js";
import utils from "../services/utils.js";
import WatchedFileUpdateStatusWidget from "../widgets/watched_file_update_status.js";
import { applyModals } from "./layout_commons.js";
export default class DesktopLayout {
@@ -69,17 +79,20 @@ export default class DesktopLayout {
*/
const fullWidthTabBar = launcherPaneIsHorizontal || (isElectron && !hasNativeTitleBar && isMac);
const customTitleBarButtons = !hasNativeTitleBar && !isMac && !isWindows;
const isNewLayout = isExperimentalFeatureEnabled("new-layout");
const rootContainer = new RootContainer(true)
.setParent(appContext)
.class((launcherPaneIsHorizontal ? "horizontal" : "vertical") + "-layout")
.class(`${launcherPaneIsHorizontal ? "horizontal" : "vertical" }-layout`)
.optChild(
fullWidthTabBar,
new FlexContainer("row")
.class("tab-row-container")
.child(new FlexContainer("row").id("tab-row-left-spacer"))
.optChild(launcherPaneIsHorizontal, <LeftPaneToggle isHorizontalLayout={true} />)
.child(<TabHistoryNavigationButtons />)
.child(new TabRowWidget().class("full-width"))
.optChild(isNewLayout, <RightPaneToggle />)
.optChild(customTitleBarButtons, <TitleBarButtons />)
.css("height", "40px")
.css("background-color", "var(--launcher-pane-background-color)")
@@ -101,7 +114,17 @@ export default class DesktopLayout {
new FlexContainer("column")
.id("rest-pane")
.css("flex-grow", "1")
.optChild(!fullWidthTabBar, new FlexContainer("row").child(new TabRowWidget()).optChild(customTitleBarButtons, <TitleBarButtons />).css("height", "40px"))
.optChild(!fullWidthTabBar,
new FlexContainer("row")
.class("tab-row-container")
.child(<TabHistoryNavigationButtons />)
.child(new TabRowWidget())
.optChild(isNewLayout, <RightPaneToggle />)
.optChild(customTitleBarButtons, <TitleBarButtons />)
.css("height", "40px")
.css("align-items", "center")
)
.optChild(isNewLayout, <FixedFormattingToolbar />)
.child(
new FlexContainer("row")
.filling()
@@ -115,34 +138,33 @@ export default class DesktopLayout {
.child(
new SplitNoteContainer(() =>
new NoteWrapperWidget()
.child(
new FlexContainer("row")
.class("title-row")
.css("height", "50px")
.css("min-height", "50px")
.css("align-items", "center")
.cssBlock(".title-row > * { margin: 5px; }")
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
.child(new SpacerWidget(0, 1))
.child(<MovePaneButton direction="left" />)
.child(<MovePaneButton direction="right" />)
.child(<ClosePaneButton />)
.child(<CreatePaneButton />)
)
.child(<Ribbon />)
.child(new FlexContainer("row")
.class("title-row note-split-title")
.cssBlock(".title-row > * { margin: 5px; }")
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />)
.optChild(isNewLayout, <NoteBadges />)
.child(<SpacerWidget baseSize={0} growthFactor={1} />)
.optChild(!isNewLayout, <MovePaneButton direction="left" />)
.optChild(!isNewLayout, <MovePaneButton direction="right" />)
.optChild(!isNewLayout, <ClosePaneButton />)
.optChild(!isNewLayout, <CreatePaneButton />)
.optChild(isNewLayout, <NoteActions />))
.optChild(!isNewLayout, <Ribbon />)
.child(new WatchedFileUpdateStatusWidget())
.child(<FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
.optChild(!isNewLayout, <FloatingButtons items={DESKTOP_FLOATING_BUTTONS} />)
.child(
new ScrollingContainer()
.filling()
.child(new ContentHeader()
.optChild(isNewLayout, <InlineTitle />)
.optChild(isNewLayout, <NoteTitleActions />)
.optChild(!isNewLayout, new ContentHeader()
.child(<ReadOnlyNoteInfoBar />)
.child(<SharedInfo />)
)
.child(new PromotedAttributesWidget())
.optChild(!isNewLayout, <PromotedAttributes />)
.child(<SqlTableSchemas />)
.child(new NoteDetailWidget())
.child(<NoteDetail />)
.child(<NoteList media="screen" />)
.child(<SearchResult />)
.child(<SqlResults />)
@@ -150,23 +172,24 @@ export default class DesktopLayout {
)
.child(<ApiLog />)
.child(new FindWidget())
.child(
...this.customWidgets.get("node-detail-pane"), // typo, let's keep it for a while as BC
...this.customWidgets.get("note-detail-pane")
)
.child(...this.customWidgets.get("note-detail-pane"))
)
)
.child(...this.customWidgets.get("center-pane"))
)
.child(
.optChild(!isNewLayout,
new RightPaneContainer()
.child(new TocWidget())
.child(new HighlightsListWidget())
.child(...this.customWidgets.get("right-pane"))
)
.optChild(isNewLayout, <RightPanelContainer widgetsByParent={this.customWidgets} />)
)
.optChild(!launcherPaneIsHorizontal && isNewLayout, <StatusBar />)
)
)
.optChild(launcherPaneIsHorizontal && isNewLayout, <StatusBar />)
.child(<CloseZenModeButton />)
// Desktop-specific dialogs.
@@ -184,14 +207,14 @@ export default class DesktopLayout {
launcherPane = new FlexContainer("row")
.css("height", "53px")
.class("horizontal")
.child(new LauncherContainer(true))
.child(<LauncherContainer isHorizontalLayout={true} />)
.child(<GlobalMenu isHorizontalLayout={true} />);
} else {
launcherPane = new FlexContainer("column")
.css("width", "53px")
.class("vertical")
.child(<GlobalMenu isHorizontalLayout={false} />)
.child(new LauncherContainer(false))
.child(<LauncherContainer isHorizontalLayout={false} />)
.child(<LeftPaneToggle isHorizontalLayout={false} />);
}

View File

@@ -22,16 +22,9 @@ import RevisionsDialog from "../widgets/dialogs/revisions.js";
import DeleteNotesDialog from "../widgets/dialogs/delete_notes.js";
import InfoDialog from "../widgets/dialogs/info.js";
import IncorrectCpuArchDialog from "../widgets/dialogs/incorrect_cpu_arch.js";
import PopupEditorDialog from "../widgets/dialogs/popup_editor.js";
import FlexContainer from "../widgets/containers/flex_container.js";
import NoteIconWidget from "../widgets/note_icon";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import CallToActionDialog from "../widgets/dialogs/call_to_action.jsx";
import NoteTitleWidget from "../widgets/note_title.jsx";
import FormattingToolbar from "../widgets/ribbon/FormattingToolbar.js";
import NoteList from "../widgets/collections/NoteList.jsx";
import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibbonAdapter.jsx";
import PopupEditorDialog from "../widgets/dialogs/PopupEditor.jsx";
import ToastContainer from "../widgets/Toast.jsx";
export function applyModals(rootContainer: RootContainer) {
rootContainer
@@ -57,16 +50,7 @@ export function applyModals(rootContainer: RootContainer) {
.child(<ConfirmDialog />)
.child(<PromptDialog />)
.child(<IncorrectCpuArchDialog />)
.child(new PopupEditorDialog()
.child(new FlexContainer("row")
.class("title-row")
.css("align-items", "center")
.cssBlock(".title-row > * { margin: 5px; }")
.child(<NoteIconWidget />)
.child(<NoteTitleWidget />))
.child(<StandaloneRibbonAdapter component={FormattingToolbar} />)
.child(new PromotedAttributesWidget())
.child(new NoteDetailWidget())
.child(<NoteList media="screen" displayOnlyCollections />))
.child(<CallToActionDialog />);
.child(<PopupEditorDialog />)
.child(<CallToActionDialog />)
.child(<ToastContainer />);
}

View File

@@ -6,16 +6,12 @@ import FilePropertiesTab from "../widgets/ribbon/FilePropertiesTab.jsx";
import FlexContainer from "../widgets/containers/flex_container.js";
import FloatingButtons from "../widgets/FloatingButtons.jsx";
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
import LauncherContainer from "../widgets/containers/launcher_container.js";
import MobileDetailMenu from "../widgets/mobile_widgets/mobile_detail_menu.js";
import MobileEditorToolbar from "../widgets/type_widgets/ckeditor/mobile_editor_toolbar.js";
import NoteDetailWidget from "../widgets/note_detail.js";
import NoteList from "../widgets/collections/NoteList.jsx";
import NoteTitleWidget from "../widgets/note_title.js";
import ContentHeader from "../widgets/containers/content-header.js";
import ContentHeader from "../widgets/containers/content_header.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import NoteWrapperWidget from "../widgets/note_wrapper.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import QuickSearchWidget from "../widgets/quick_search.js";
import ReadOnlyNoteInfoBar from "../widgets/ReadOnlyNoteInfoBar.jsx";
import RootContainer from "../widgets/containers/root_container.js";
@@ -29,9 +25,15 @@ import StandaloneRibbonAdapter from "../widgets/ribbon/components/StandaloneRibb
import TabRowWidget from "../widgets/tab_row.js";
import ToggleSidebarButton from "../widgets/mobile_widgets/toggle_sidebar_button.jsx";
import type AppContext from "../components/app_context.js";
import NoteDetail from "../widgets/NoteDetail.jsx";
import MobileEditorToolbar from "../widgets/type_widgets/text/mobile_editor_toolbar.jsx";
import PromotedAttributes from "../widgets/PromotedAttributes.jsx";
import SplitNoteContainer from "../widgets/containers/split_note_container.js";
import LauncherContainer from "../widgets/launch_bar/LauncherContainer.jsx";
const MOBILE_CSS = `
<style>
span.keyboard-shortcut,
kbd {
display: none;
}
@@ -141,33 +143,35 @@ export default class MobileLayout {
.id("detail-container")
.class("d-sm-flex d-md-flex d-lg-flex d-xl-flex col-12 col-sm-7 col-md-8 col-lg-9")
.child(
new NoteWrapperWidget()
.child(
new FlexContainer("row")
.contentSized()
.css("font-size", "larger")
.css("align-items", "center")
.child(<ToggleSidebarButton />)
.child(<NoteTitleWidget />)
.child(<MobileDetailMenu />)
)
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
.child(new PromotedAttributesWidget())
.child(
new ScrollingContainer()
.filling()
.contentSized()
.child(new ContentHeader()
.child(<ReadOnlyNoteInfoBar />)
.child(<SharedInfoWidget />)
)
.child(new NoteDetailWidget())
.child(<NoteList media="screen" />)
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
.child(<SearchResult />)
.child(<FilePropertiesWrapper />)
)
.child(<MobileEditorToolbar />)
new SplitNoteContainer(() =>
new NoteWrapperWidget()
.child(
new FlexContainer("row")
.contentSized()
.css("font-size", "larger")
.css("align-items", "center")
.child(<ToggleSidebarButton />)
.child(<NoteTitleWidget />)
.child(<MobileDetailMenu />)
)
.child(<FloatingButtons items={MOBILE_FLOATING_BUTTONS} />)
.child(<PromotedAttributes />)
.child(
new ScrollingContainer()
.filling()
.contentSized()
.child(new ContentHeader()
.child(<ReadOnlyNoteInfoBar />)
.child(<SharedInfoWidget />)
)
.child(<NoteDetail />)
.child(<NoteList media="screen" />)
.child(<StandaloneRibbonAdapter component={SearchDefinitionTab} />)
.child(<SearchResult />)
.child(<FilePropertiesWrapper />)
)
.child(<MobileEditorToolbar />)
)
)
)
)
@@ -179,7 +183,7 @@ export default class MobileLayout {
.child(new FlexContainer("row")
.class("horizontal")
.css("height", "53px")
.child(new LauncherContainer(true))
.child(<LauncherContainer isHorizontalLayout />)
.child(<GlobalMenuWidget isHorizontalLayout />)
.id("launcher-pane"))
)

View File

@@ -2,7 +2,7 @@ import { KeyboardActionNames } from "@triliumnext/commons";
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
import note_tooltip from "../services/note_tooltip.js";
import utils from "../services/utils.js";
import { should } from "vitest";
import { h, JSX, render } from "preact";
export interface ContextMenuOptions<T> {
x: number;
@@ -15,6 +15,11 @@ export interface ContextMenuOptions<T> {
onHide?: () => void;
}
export interface CustomMenuItem {
kind: "custom",
componentFn: () => JSX.Element | null;
}
export interface MenuSeparatorItem {
kind: "separator";
}
@@ -51,7 +56,7 @@ export interface MenuCommandItem<T> {
columns?: number;
}
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem | MenuHeader;
export type MenuItem<T> = MenuCommandItem<T> | CustomMenuItem | MenuSeparatorItem | MenuHeader;
export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void;
export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent;
@@ -160,16 +165,19 @@ class ContextMenu {
let $group = $parent; // The current group or parent element to which items are being appended
let shouldStartNewGroup = false; // If true, the next item will start a new group
let shouldResetGroup = false; // If true, the next item will be the last one from the group
let prevItemKind: string = "";
for (let index = 0; index < items.length; index++) {
const item = items[index];
const itemKind = ("kind" in item) ? item.kind : "";
if (!item) {
continue;
}
// If the current item is a header, start a new group. This group will contain the
// header and the next item that follows the header.
if ("kind" in item && item.kind === "header") {
if (itemKind === "header") {
if (multicolumn && !shouldResetGroup) {
shouldStartNewGroup = true;
}
@@ -195,125 +203,25 @@ class ContextMenu {
shouldStartNewGroup = false;
}
if ("kind" in item && item.kind === "separator") {
if (itemKind === "separator") {
if (prevItemKind === "separator") {
// Skip consecutive separators
continue;
}
$group.append($("<div>").addClass("dropdown-divider"));
shouldResetGroup = true; // End the group after the next item
} else if ("kind" in item && item.kind === "header") {
$group.append($("<h6>").addClass("dropdown-header").text(item.title));
} else if (itemKind === "header") {
$group.append($("<h6>").addClass("dropdown-header").text((item as MenuHeader).title));
shouldResetGroup = true;
} else {
const $icon = $("<span>");
if ("uiIcon" in item || "checked" in item) {
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
if (icon) {
$icon.addClass(icon);
} else {
$icon.append("&nbsp;");
}
if (itemKind === "custom") {
// Custom menu item
$group.append(this.createCustomMenuItem(item as CustomMenuItem));
} else {
// Standard menu item
$group.append(this.createMenuItem(item as MenuCommandItem<any>));
}
const $link = $("<span>")
.append($icon)
.append(" &nbsp; ") // some space between icon and text
.append(item.title);
if ("badges" in item && item.badges) {
for (let badge of item.badges) {
const badgeElement = $(`<span class="badge">`).text(badge.title);
if (badge.className) {
badgeElement.addClass(badge.className);
}
$link.append(badgeElement);
}
}
if ("keyboardShortcut" in item && item.keyboardShortcut) {
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
if (shortcuts) {
const allShortcuts: string[] = [];
for (const effectiveShortcut of shortcuts) {
allShortcuts.push(effectiveShortcut.split("+")
.map(key => `<kbd>${key}</kbd>`)
.join("+"));
}
if (allShortcuts.length) {
const container = $("<span>").addClass("keyboard-shortcut");
container.append($(allShortcuts.join(",")));
$link.append(container);
}
}
} else if ("shortcut" in item && item.shortcut) {
$link.append($("<kbd>").text(item.shortcut));
}
const $item = $("<li>")
.addClass("dropdown-item")
.append($link)
.on("contextmenu", (e) => false)
// important to use mousedown instead of click since the former does not change focus
// (especially important for focused text for spell check)
.on("mousedown", (e) => {
e.stopPropagation();
if (e.which !== 1) {
// only left click triggers menu items
return false;
}
if (this.isMobile && "items" in item && item.items) {
const $item = $(e.target).closest(".dropdown-item");
$item.toggleClass("submenu-open");
$item.find("ul.dropdown-menu").toggleClass("show");
return false;
}
if ("handler" in item && item.handler) {
item.handler(item, e);
}
this.options?.selectMenuItemHandler(item, e);
// it's important to stop the propagation especially for sub-menus, otherwise the event
// might be handled again by top-level menu
return false;
});
$item.on("mouseup", (e) => {
// Prevent submenu from failing to expand on mobile
if (!this.isMobile || !("items" in item && item.items)) {
e.stopPropagation();
// Hide the content menu on mouse up to prevent the mouse event from propagating to the elements below.
this.hide();
return false;
}
});
if ("enabled" in item && item.enabled !== undefined && !item.enabled) {
$item.addClass("disabled");
}
if ("items" in item && item.items) {
$item.addClass("dropdown-submenu");
$link.addClass("dropdown-toggle");
const $subMenu = $("<ul>").addClass("dropdown-menu");
const hasColumns = !!item.columns && item.columns > 1;
if (!this.isMobile && hasColumns) {
$subMenu.css("column-count", item.columns!);
}
this.addItems($subMenu, item.items, hasColumns);
$item.append($subMenu);
}
$group.append($item);
// After adding a menu item, if the previous item was a separator or header,
// reset the group so that the next item will be appended directly to the parent.
if (shouldResetGroup) {
@@ -321,9 +229,126 @@ class ContextMenu {
shouldResetGroup = false;
};
}
prevItemKind = itemKind;
}
}
private createCustomMenuItem(item: CustomMenuItem) {
const element = document.createElement("li");
element.classList.add("dropdown-custom-item");
element.onclick = () => this.hide();
render(h(item.componentFn, {}), element);
return element;
}
private createMenuItem(item: MenuCommandItem<any>) {
const $icon = $("<span>");
if ("uiIcon" in item || "checked" in item) {
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
if (icon) {
$icon.addClass(icon);
} else {
$icon.append("&nbsp;");
}
}
const $link = $("<span>")
.append($icon)
.append(" &nbsp; ") // some space between icon and text
.append(item.title);
if ("badges" in item && item.badges) {
for (let badge of item.badges) {
const badgeElement = $(`<span class="badge">`).text(badge.title);
if (badge.className) {
badgeElement.addClass(badge.className);
}
$link.append(badgeElement);
}
}
if ("keyboardShortcut" in item && item.keyboardShortcut) {
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
if (shortcuts) {
const allShortcuts: string[] = [];
for (const effectiveShortcut of shortcuts) {
allShortcuts.push(effectiveShortcut.split("+")
.map(key => `<kbd>${key}</kbd>`)
.join("+"));
}
if (allShortcuts.length) {
const container = $("<span>").addClass("keyboard-shortcut");
container.append($(allShortcuts.join(",")));
$link.append(container);
}
}
} else if ("shortcut" in item && item.shortcut) {
$link.append($("<kbd>").text(item.shortcut));
}
const $item = $("<li>")
.addClass("dropdown-item")
.append($link)
.on("contextmenu", (e) => false)
// important to use mousedown instead of click since the former does not change focus
// (especially important for focused text for spell check)
.on("mousedown", (e) => {
if (e.which !== 1) {
// only left click triggers menu items
return false;
}
if (this.isMobile && "items" in item && item.items) {
const $item = $(e.target).closest(".dropdown-item");
$item.toggleClass("submenu-open");
$item.find("ul.dropdown-menu").toggleClass("show");
return false;
}
// Prevent submenu from failing to expand on mobile
if (!("items" in item && item.items)) {
this.hide();
}
if ("handler" in item && item.handler) {
item.handler(item, e);
}
this.options?.selectMenuItemHandler(item, e);
// it's important to stop the propagation especially for sub-menus, otherwise the event
// might be handled again by top-level menu
return false;
});
if ("enabled" in item && item.enabled !== undefined && !item.enabled) {
$item.addClass("disabled");
}
if ("items" in item && item.items) {
$item.addClass("dropdown-submenu");
$link.addClass("dropdown-toggle");
const $subMenu = $("<ul>").addClass("dropdown-menu");
const hasColumns = !!item.columns && item.columns > 1;
if (!this.isMobile && hasColumns) {
$subMenu.css("column-count", item.columns!);
}
this.addItems($subMenu, item.items, hasColumns);
$item.append($subMenu);
}
return $item;
}
async hide() {
this.options?.onHide?.();
this.$widget.removeClass("show");

View File

@@ -0,0 +1,21 @@
import { t } from "../services/i18n"
import attributes from "../services/attributes"
import FNote from "../entities/fnote"
export function getArchiveMenuItem(note: FNote) {
if (!note.isArchived) {
return {
title: t("board_view.archive-note"),
uiIcon: "bx bx-archive",
handler: () => attributes.addLabel(note.noteId, "archived")
}
} else {
return {
title: t("board_view.unarchive-note"),
uiIcon: "bx bx-archive-out",
handler: async () => {
attributes.removeOwnedLabelByName(note, "archived")
}
}
}
}

View File

@@ -0,0 +1,86 @@
:root {
--note-color-picker-clear-color-cell-background: var(--primary-button-background-color);
--note-color-picker-clear-color-cell-color: var(--main-background-color);
--note-color-picker-clear-color-cell-selection-outline-color: var(--primary-button-border-color);
}
.note-color-picker {
display: flex;
gap: 8px;
justify-content: space-between;
}
.note-color-picker .color-cell {
--color-picker-cell-size: 14px;
width: var(--color-picker-cell-size);
height: var(--color-picker-cell-size);
border-radius: 4px;
background-color: var(--color);
}
.note-color-picker .color-cell:not(.selected):hover {
transform: scale(1.2);
}
.note-color-picker .color-cell.disabled-color-cell {
cursor: not-allowed;
}
.note-color-picker .color-cell.selected {
outline: 2px solid var(--outline-color, var(--color));
outline-offset: 2px;
}
/*
* RESET COLOR CELL
*/
.note-color-picker .color-cell-reset {
--color: var(--note-color-picker-clear-color-cell-background);
--outline-color: var(--note-color-picker-clear-color-cell-selection-outline-color);
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.note-color-picker .color-cell-reset svg {
width: var(--color-picker-cell-size);
height: var(--color-picker-cell-size);
fill: var(--note-color-picker-clear-color-cell-color);
}
/*
* CUSTOM COLOR CELL
*/
.note-color-picker .custom-color-cell::before {
position: absolute;
content: "\ed35";
display: flex;
top: 0;
left: 0;
right: 0;
bottom: 0;
font-size: calc(var(--color-picker-cell-size) * 1.3);
justify-content: center;
align-items: center;
font-family: boxicons;
font-size: 16px;
color: var(--foreground);
}
.note-color-picker .custom-color-cell {
position: relative;
display: flex;
justify-content: center;
overflow: hidden;
}
.note-color-picker .custom-color-cell.custom-color-cell-empty {
background-image: url(./custom-color.png);
background-size: cover;
--foreground: transparent;
}

View File

@@ -0,0 +1,204 @@
import "./NoteColorPicker.css";
import { t } from "../../services/i18n";
import { useCallback, useEffect, useRef, useState} from "preact/hooks";
import {ComponentChildren} from "preact";
import attributes from "../../services/attributes";
import clsx from "clsx";
import Color, { ColorInstance } from "color";
import Debouncer from "../../utils/debouncer";
import FNote from "../../entities/fnote";
import froca from "../../services/froca";
import { isMobile } from "../../services/utils";
const COLOR_PALETTE = [
"#e64d4d", "#e6994d", "#e5e64d", "#99e64d", "#4de64d", "#4de699",
"#4de5e6", "#4d99e6", "#4d4de6", "#994de6", "#e64db3"
];
export interface NoteColorPickerProps {
/** The target Note instance or its ID string. */
note: FNote | string | null;
}
export default function NoteColorPicker(props: NoteColorPickerProps) {
if (!props.note) return null;
const [note, setNote] = useState<FNote | null>(null);
const [currentColor, setCurrentColor] = useState<string | null>(null);
const [isCustomColor, setIsCustomColor] = useState<boolean>(false);
useEffect(() => {
const retrieveNote = async (noteId: string) => {
const noteInstance = await froca.getNote(noteId, true);
if (noteInstance) {
setNote(noteInstance);
}
}
if (typeof props.note === "string") {
retrieveNote(props.note); // Get the note from the given ID string
} else {
setNote(props.note);
}
}, []);
useEffect(() => {
const colorLabel = note?.getLabel("color")?.value ?? null;
if (colorLabel) {
let color = tryParseColor(colorLabel);
if (color) {
setCurrentColor(color.hex().toLowerCase());
}
}
}, [note]);
useEffect(() => {
setIsCustomColor(currentColor !== null && COLOR_PALETTE.indexOf(currentColor) === -1);
}, [currentColor])
const onColorCellClicked = useCallback((color: string | null) => {
if (note) {
if (color !== null) {
attributes.setLabel(note.noteId, "color", color);
} else {
attributes.removeOwnedLabelByName(note, "color");
}
setCurrentColor(color);
}
}, [note, currentColor]);
return <div className="note-color-picker">
<ColorCell className="color-cell-reset"
tooltip={t("note-color.clear-color")}
color={null}
isSelected={(currentColor === null)}
isDisabled={(note === null)}
onSelect={onColorCellClicked}>
{/* https://pictogrammers.com/library/mdi/icon/close/ */}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z" />
</svg>
</ColorCell>
{COLOR_PALETTE.map((color) => (
<ColorCell key={color}
tooltip={t("note-color.set-color")}
color={color}
isSelected={(color === currentColor)}
isDisabled={(note === null)}
onSelect={onColorCellClicked} />
))}
<CustomColorCell tooltip={t("note-color.set-custom-color")}
color={currentColor}
isSelected={isCustomColor}
isDisabled={(note === null)}
onSelect={onColorCellClicked} />
</div>
}
interface ColorCellProps {
children?: ComponentChildren,
className?: string,
tooltip?: string,
color: string | null,
isSelected: boolean,
isDisabled?: boolean,
onSelect?: (color: string | null) => void
}
function ColorCell(props: ColorCellProps) {
return <div className={clsx(props.className, {
"color-cell": true,
"selected": props.isSelected,
"disabled-color-cell": props.isDisabled
})}
style={`${(props.color !== null) ? `--color: ${props.color}` : ""}`}
title={props.tooltip}
onClick={() => props.onSelect?.(props.color)}>
{props.children}
</div>;
}
function CustomColorCell(props: ColorCellProps) {
const [pickedColor, setPickedColor] = useState<string | null>(null);
const colorInput = useRef<HTMLInputElement>(null);
const colorInputDebouncer = useRef<Debouncer<string | null> | null>(null);
const callbackRef = useRef(props.onSelect);
useEffect(() => {
colorInputDebouncer.current = new Debouncer(250, (color) => {
callbackRef.current?.(color);
setPickedColor(color);
});
return () => {
colorInputDebouncer.current?.destroy();
}
}, []);
useEffect(() => {
if (props.isSelected && pickedColor === null) {
setPickedColor(props.color);
}
}, [props.isSelected])
useEffect(() => {
callbackRef.current = props.onSelect;
}, [props.onSelect]);
const onSelect = useCallback(() => {
if (pickedColor !== null) {
callbackRef.current?.(pickedColor);
}
colorInput.current?.click();
}, [pickedColor]);
return <div style={`--foreground: ${getForegroundColor(props.color)};`}
onClick={isMobile() ? (e) => {
// The color picker dropdown will close on some browser if the parent context menu is
// dismissed, so stop the click propagation to prevent dismissing the menu.
e.stopPropagation();
} : undefined}>
<ColorCell {...props}
color={pickedColor}
className={clsx("custom-color-cell", {
"custom-color-cell-empty": (pickedColor === null)
})}
onSelect={onSelect}>
<input ref={colorInput}
type="color"
value={pickedColor ?? props.color ?? "#40bfbf"}
onChange={() => {colorInputDebouncer.current?.updateValue(colorInput.current?.value ?? null)}}
style="width: 0; height: 0; opacity: 0" />
</ColorCell>
</div>
}
function getForegroundColor(backgroundColor: string | null) {
if (backgroundColor === null) return "inherit";
const colorHsl = tryParseColor(backgroundColor)?.hsl();
if (colorHsl) {
let l = colorHsl.lightness();
return colorHsl.saturationl(0).lightness(l >= 50 ? 0 : 100).hex();
} else {
return "inherit";
}
}
function tryParseColor(colorStr: string): ColorInstance | null {
try {
return new Color(colorStr);
} catch(ex) {
console.error(ex);
}
return null;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -4,7 +4,7 @@ import zoomService from "../components/zoom.js";
import contextMenu, { type MenuItem } from "./context_menu.js";
import { t } from "../services/i18n.js";
import type { BrowserWindow } from "electron";
import type { CommandNames } from "../components/app_context.js";
import type { CommandNames, AppContext } from "../components/app_context.js";
function setupContextMenu() {
const electron = utils.dynamicRequire("electron");
@@ -13,6 +13,8 @@ function setupContextMenu() {
// FIXME: Remove typecast once Electron is properly integrated.
const { webContents } = remote.getCurrentWindow() as BrowserWindow;
let appContext: AppContext;
webContents.on("context-menu", (event, params) => {
const { editFlags } = params;
const hasText = params.selectionText.trim().length > 0;
@@ -119,6 +121,20 @@ function setupContextMenu() {
uiIcon: "bx bx-search-alt",
handler: () => electron.shell.openExternal(searchUrl)
});
items.push({
title: t("electron_context_menu.search_in_trilium", { term: shortenedSelection }),
uiIcon: "bx bx-search",
handler: async () => {
if (!appContext) {
appContext = (await import("../components/app_context.js")).default;
}
await appContext.triggerCommand("searchNotes", {
searchString: params.selectionText
});
}
});
}
if (items.length === 0) {

View File

@@ -1,49 +1,67 @@
import { t } from "../services/i18n.js";
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
import type { LeafletMouseEvent } from "leaflet";
import appContext, { type CommandNames } from "../components/app_context.js";
import { t } from "../services/i18n.js";
import type { ViewScope } from "../services/link.js";
import utils, { isMobile } from "../services/utils.js";
import { getClosestNtxId } from "../widgets/widget_utils.js";
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
function openContextMenu(notePath: string, e: ContextMenuEvent, viewScope: ViewScope = {}, hoistedNoteId: string | null = null) {
contextMenu.show({
x: e.pageX,
y: e.pageY,
items: getItems(),
selectMenuItemHandler: ({ command }) => handleLinkContextMenuItem(command, notePath, viewScope, hoistedNoteId)
items: getItems(e),
selectMenuItemHandler: ({ command }) => handleLinkContextMenuItem(command, e, notePath, viewScope, hoistedNoteId)
});
}
function getItems(): MenuItem<CommandNames>[] {
function getItems(e: ContextMenuEvent | LeafletMouseEvent): MenuItem<CommandNames>[] {
const ntxId = getNtxId(e);
const isMobileSplitOpen = isMobile() && appContext.tabManager.getNoteContextById(ntxId).getMainContext().getSubContexts().length > 1;
return [
{ title: t("link_context_menu.open_note_in_new_tab"), command: "openNoteInNewTab", uiIcon: "bx bx-link-external" },
{ title: t("link_context_menu.open_note_in_new_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right" },
{ title: !isMobileSplitOpen ? t("link_context_menu.open_note_in_new_split") : t("link_context_menu.open_note_in_other_split"), command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right" },
{ title: t("link_context_menu.open_note_in_new_window"), command: "openNoteInNewWindow", uiIcon: "bx bx-window-open" },
{ title: t("link_context_menu.open_note_in_popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit" }
];
}
function handleLinkContextMenuItem(command: string | undefined, notePath: string, viewScope = {}, hoistedNoteId: string | null = null) {
function handleLinkContextMenuItem(command: string | undefined, e: ContextMenuEvent | LeafletMouseEvent, notePath: string, viewScope = {}, hoistedNoteId: string | null = null) {
if (!hoistedNoteId) {
hoistedNoteId = appContext.tabManager.getActiveContext()?.hoistedNoteId ?? null;
}
if (command === "openNoteInNewTab") {
appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope });
return true;
} else if (command === "openNoteInNewSplit") {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
if (!subContexts) {
logError("subContexts is null");
return;
}
const { ntxId } = subContexts[subContexts.length - 1];
const ntxId = getNtxId(e);
if (!ntxId) return false;
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
return true;
} else if (command === "openNoteInNewWindow") {
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
return true;
} else if (command === "openNoteInPopup") {
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
return true;
}
return false;
}
function getNtxId(e: ContextMenuEvent | LeafletMouseEvent) {
if (utils.isDesktop()) {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
if (!subContexts) return null;
return subContexts[subContexts.length - 1].ntxId;
} else if (e.target instanceof HTMLElement) {
return getClosestNtxId(e.target);
}
return null;
}
export default {

View File

@@ -1,3 +1,4 @@
import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
import treeService from "../services/tree.js";
import froca from "../services/froca.js";
import clipboard from "../services/clipboard.js";
@@ -139,7 +140,13 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
uiIcon: "bx bx-rename",
enabled: isNotRoot && parentNotSearch && notOptionsOrHelp
},
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptionsOrHelp },
{
title:
t("tree-context-menu.convert-to-attachment"),
command: "convertNoteToAttachment",
uiIcon: "bx bx-paperclip",
enabled: isNotRoot && !isHoisted && notOptionsOrHelp && selectedNotes.some(note => note.isEligibleForConversionToAttachment())
},
{ kind: "separator" },
@@ -241,6 +248,15 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptionsOrHelp
},
{ kind: "separator"},
(notOptionsOrHelp && selectedNotes.length === 1) ? {
kind: "custom",
componentFn: () => {
return NoteColorPicker({note});
}
} : null,
{ kind: "separator" },
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import", enabled: notSearch && noSelectedNotes && notOptionsOrHelp },

View File

@@ -1,14 +1,25 @@
import FNote from "./entities/fnote";
import { render } from "preact";
import { CustomNoteList } from "./widgets/collections/NoteList";
import { useCallback, useLayoutEffect, useRef } from "preact/hooks";
import FNote from "./entities/fnote";
import content_renderer from "./services/content_renderer";
import { applyInlineMermaid } from "./services/content_renderer_text";
import { dynamicRequire, isElectron } from "./services/utils";
import { CustomNoteList, useNoteViewType } from "./widgets/collections/NoteList";
interface RendererProps {
note: FNote;
onReady: () => void;
onReady: (data: PrintReport) => void;
onProgressChanged?: (progress: number) => void;
}
export type PrintReport = {
type: "single-note";
} | {
type: "collection";
ignoredNoteIds: string[];
};
async function main() {
const notePath = window.location.hash.substring(1);
const noteId = notePath.split("/").at(-1);
@@ -23,15 +34,25 @@ async function main() {
function App({ note, noteId }: { note: FNote | null | undefined, noteId: string }) {
const sentReadyEvent = useRef(false);
const onReady = useCallback(() => {
const onProgressChanged = useCallback((progress: number) => {
if (isElectron()) {
const { ipcRenderer } = dynamicRequire('electron');
ipcRenderer.send("print-progress", progress);
} else {
window.dispatchEvent(new CustomEvent("note-load-progress", { detail: { progress } }));
}
}, []);
const onReady = useCallback((printReport: PrintReport) => {
if (sentReadyEvent.current) return;
window.dispatchEvent(new Event("note-ready"));
window._noteReady = true;
window.dispatchEvent(new CustomEvent("note-ready", {
detail: printReport
}));
window._noteReady = printReport;
sentReadyEvent.current = true;
}, []);
const props: RendererProps | undefined | null = note && { note, onReady };
const props: RendererProps | undefined | null = note && { note, onReady, onProgressChanged };
if (!note || !props) return <Error404 noteId={noteId} />
if (!note || !props) return <Error404 noteId={noteId} />;
useLayoutEffect(() => {
document.body.dataset.noteType = note.type;
@@ -40,8 +61,8 @@ function App({ note, noteId }: { note: FNote | null | undefined, noteId: string
return (
<>
{note.type === "book"
? <CollectionRenderer {...props} />
: <SingleNoteRenderer {...props} />
? <CollectionRenderer {...props} />
: <SingleNoteRenderer {...props} />
}
</>
);
@@ -71,11 +92,18 @@ function SingleNoteRenderer({ note, onReady }: RendererProps) {
})
);
// Initialize mermaid.
if (note.type === "text") {
await applyInlineMermaid(container);
}
// Check custom CSS.
await loadCustomCss(note);
}
load().then(() => requestAnimationFrame(onReady))
load().then(() => requestAnimationFrame(() => onReady({
type: "single-note"
})));
}, [ note ]);
return <>
@@ -84,18 +112,21 @@ function SingleNoteRenderer({ note, onReady }: RendererProps) {
</>;
}
function CollectionRenderer({ note, onReady }: RendererProps) {
function CollectionRenderer({ note, onReady, onProgressChanged }: RendererProps) {
const viewType = useNoteViewType(note);
return <CustomNoteList
viewType={viewType}
isEnabled
note={note}
notePath={note.getBestNotePath().join("/")}
ntxId="print"
highlightedTokens={null}
media="print"
onReady={async () => {
onReady={async (data: PrintReport) => {
await loadCustomCss(note);
onReady();
onReady(data);
}}
onProgressChanged={onProgressChanged}
/>;
}
@@ -105,12 +136,12 @@ function Error404({ noteId }: { noteId: string }) {
<p>The note you are trying to print could not be found.</p>
<small>{noteId}</small>
</main>
)
);
}
async function loadCustomCss(note: FNote) {
const printCssNotes = await note.getRelationTargets("printCss");
let loadPromises: JQueryPromise<void>[] = [];
const loadPromises: JQueryPromise<void>[] = [];
for (const printCssNote of printCssNotes) {
if (!printCssNote || (printCssNote.type !== "code" && printCssNote.mime !== "text/css")) continue;

View File

@@ -90,7 +90,8 @@ const HIDDEN_ATTRIBUTES = [
"viewType",
"geolocation",
"docName",
"webViewSrc"
"webViewSrc",
"archived"
];
async function renderNormalAttributes(note: FNote) {

View File

@@ -22,6 +22,15 @@ export async function setLabel(noteId: string, name: string, value: string = "",
});
}
export async function setRelation(noteId: string, name: string, value: string = "", isInheritable = false) {
await server.put(`notes/${noteId}/set-attribute`, {
type: "relation",
name: name,
value: value,
isInheritable
});
}
async function removeAttributeById(noteId: string, attributeId: string) {
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
}
@@ -51,6 +60,23 @@ function removeOwnedLabelByName(note: FNote, labelName: string) {
return false;
}
/**
* Removes a relation identified by its name from the given note, if it exists. Note that the relation must be owned, i.e.
* it will not remove inherited attributes.
*
* @param note the note from which to remove the relation.
* @param relationName the name of the relation to remove.
* @returns `true` if an attribute was identified and removed, `false` otherwise.
*/
function removeOwnedRelationByName(note: FNote, relationName: string) {
const relation = note.getOwnedRelation(relationName);
if (relation) {
removeAttributeById(note.noteId, relation.attributeId);
return true;
}
return false;
}
/**
* Sets the attribute of the given note to the provided value if its truthy, or removes the attribute if the value is falsy.
* For an attribute with an empty value, pass an empty string instead.
@@ -100,9 +126,7 @@ function isAffecting(attrRow: AttributeRow, affectedNote: FNote | null | undefin
}
}
// TODO: This doesn't seem right.
//@ts-ignore
if (this.isInheritable) {
if (attrRow.isInheritable) {
for (const owningNote of owningNotes) {
if (owningNote.hasAncestor(attrNote.noteId, true)) {
return true;
@@ -116,8 +140,10 @@ function isAffecting(attrRow: AttributeRow, affectedNote: FNote | null | undefin
export default {
addLabel,
setLabel,
setRelation,
setAttribute,
removeAttributeById,
removeOwnedLabelByName,
removeOwnedRelationByName,
isAffecting
};

View File

@@ -1,6 +1,6 @@
import utils from "./utils.js";
import server from "./server.js";
import toastService, { type ToastOptions } from "./toast.js";
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import ws from "./ws.js";
@@ -176,11 +176,6 @@ async function moveNodeUpInHierarchy(node: Fancytree.FancytreeNode) {
toastService.showError(resp.message);
return;
}
if (!hoistedNoteService.isTopLevelNode(node) && node.getParent().getChildren().length <= 1) {
node.getParent().folder = false;
node.getParent().renderTitle();
}
}
function filterSearchBranches(branchIds: string[]) {
@@ -200,11 +195,11 @@ function filterRootNote(branchIds: string[]) {
});
}
function makeToast(id: string, message: string): ToastOptions {
function makeToast(id: string, message: string): ToastOptionsWithRequiredId {
return {
id: id,
id,
title: t("branches.delete-status"),
message: message,
message,
icon: "trash"
};
}
@@ -221,7 +216,7 @@ ws.subscribeToMessages(async (message) => {
toastService.showPersistent(makeToast(message.taskId, t("branches.delete-notes-in-progress", { count: message.progressCount })));
} else if (message.type === "taskSucceeded") {
const toast = makeToast(message.taskId, t("branches.delete-finished-successfully"));
toast.closeAfter = 5000;
toast.timeout = 5000;
toastService.showPersistent(toast);
}
@@ -239,7 +234,7 @@ ws.subscribeToMessages(async (message) => {
toastService.showPersistent(makeToast(message.taskId, t("branches.undeleting-notes-in-progress", { count: message.progressCount })));
} else if (message.type === "taskSucceeded") {
const toast = makeToast(message.taskId, t("branches.undeleting-notes-finished-successfully"));
toast.closeAfter = 5000;
toast.timeout = 5000;
toastService.showPersistent(toast);
}
@@ -247,7 +242,7 @@ ws.subscribeToMessages(async (message) => {
async function cloneNoteToBranch(childNoteId: string, parentBranchId: string, prefix?: string) {
const resp = await server.put<Response>(`notes/${childNoteId}/clone-to-branch/${parentBranchId}`, {
prefix: prefix
prefix
});
if (!resp.success) {
@@ -257,7 +252,7 @@ async function cloneNoteToBranch(childNoteId: string, parentBranchId: string, pr
async function cloneNoteToParentNote(childNoteId: string, parentNoteId: string, prefix?: string) {
const resp = await server.put<Response>(`notes/${childNoteId}/clone-to-note/${parentNoteId}`, {
prefix: prefix
prefix
});
if (!resp.success) {

View File

@@ -0,0 +1,44 @@
import { describe, expect, it } from "vitest";
import { Bundle, executeBundle } from "./bundle";
import { buildNote } from "../test/easy-froca";
describe("Script bundle", () => {
it("dayjs is available", async () => {
const script = /* js */`return api.dayjs().format("YYYY-MM-DD");`;
const bundle = getBundle(script);
const result = await executeBundle(bundle, null, $());
expect(result).toMatch(/^\d{4}-\d{2}-\d{2}$/);
});
it("dayjs is-same-or-before plugin exists", async () => {
const script = /* js */`return api.dayjs("2023-10-01").isSameOrBefore(api.dayjs("2023-10-02"));`;
const bundle = getBundle(script);
const result = await executeBundle(bundle, null, $());
expect(result).toBe(true);
});
});
function getBundle(script: string) {
const id = buildNote({
title: "Script note"
}).noteId;
const bundle: Bundle = {
script: [
'',
`apiContext.modules['${id}'] = { exports: {} };`,
`return await ((async function(exports, module, require, api) {`,
`try {`,
`${script}`,
`;`,
`} catch (e) { throw new Error(\"Load of script note \\\"Client\\\" (${id}) failed with: \" + e.message); }`,
`for (const exportKey in exports) module.exports[exportKey] = exports[exportKey];`,
`return module.exports;`,
`}).call({}, {}, apiContext.modules['${id}'], apiContext.require([]), apiContext.apis['${id}']));`,
''
].join('\n'),
html: "",
noteId: id,
allNoteIds: [ id ]
};
return bundle;
}

View File

@@ -1,10 +1,15 @@
import { h, VNode } from "preact";
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
import RightPanelWidget from "../widgets/right_panel_widget.js";
import froca from "./froca.js";
import type { Entity } from "./frontend_script_api.js";
import { WidgetDefinitionWithType } from "./frontend_script_api_preact.js";
import { t } from "./i18n.js";
import ScriptContext from "./script_context.js";
import server from "./server.js";
import toastService, { showError } from "./toast.js";
import froca from "./froca.js";
import utils from "./utils.js";
import { t } from "./i18n.js";
import type { Entity } from "./frontend_script_api.js";
import toastService, { showErrorForScriptNote } from "./toast.js";
import utils, { getErrorMessage } from "./utils.js";
// TODO: Deduplicate with server.
export interface Bundle {
@@ -14,9 +19,13 @@ export interface Bundle {
allNoteIds: string[];
}
interface Widget {
type LegacyWidget = (BasicWidget | RightPanelWidget) & {
parentWidget?: string;
}
};
type WithNoteId<T> = T & {
_noteId: string;
};
export type Widget = WithNoteId<(LegacyWidget | WidgetDefinitionWithType)>;
async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) {
const bundle = await server.post<Bundle>(`script/bundle/${noteId}`, {
@@ -27,7 +36,9 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script =
return await executeBundle(bundle, originEntity);
}
async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane";
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container);
try {
@@ -35,17 +46,14 @@ async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $cont
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
}.call(apiContext);
} catch (e: any) {
const note = await froca.getNote(bundle.noteId);
const message = `Execution of JS note "${note?.title}" with ID ${bundle.noteId} failed with error: ${e?.message}`;
showError(message);
logError(message);
showErrorForScriptNote(bundle.noteId, t("toast.bundle-error.message", { message: e.message }));
logError("Widget initialization failed: ", e);
}
}
async function executeStartupBundles() {
const isMobile = utils.isMobile();
const scriptBundles = await server.get<Bundle[]>("script/startup" + (isMobile ? "?mobile=true" : ""));
const scriptBundles = await server.get<Bundle[]>(`script/startup${ isMobile ? "?mobile=true" : ""}`);
for (const bundle of scriptBundles) {
await executeBundle(bundle);
@@ -53,67 +61,99 @@ async function executeStartupBundles() {
}
export class WidgetsByParent {
private byParent: Record<string, Widget[]>;
private legacyWidgets: Record<string, WithNoteId<LegacyWidget>[]>;
private preactWidgets: Record<string, WithNoteId<WidgetDefinitionWithType>[]>;
constructor() {
this.byParent = {};
this.legacyWidgets = {};
this.preactWidgets = {};
}
add(widget: Widget) {
if (!widget.parentWidget) {
console.log(`Custom widget does not have mandatory 'parentWidget' property defined`);
return;
let hasParentWidget = false;
let isPreact = false;
if ("type" in widget && widget.type === "preact-widget") {
// React-based script.
const reactWidget = widget as WithNoteId<WidgetDefinitionWithType>;
this.preactWidgets[reactWidget.parent] = this.preactWidgets[reactWidget.parent] || [];
this.preactWidgets[reactWidget.parent].push(reactWidget);
isPreact = true;
hasParentWidget = !!reactWidget.parent;
} else if ("parentWidget" in widget && widget.parentWidget) {
this.legacyWidgets[widget.parentWidget] = this.legacyWidgets[widget.parentWidget] || [];
this.legacyWidgets[widget.parentWidget].push(widget);
hasParentWidget = !!widget.parentWidget;
}
this.byParent[widget.parentWidget] = this.byParent[widget.parentWidget] || [];
this.byParent[widget.parentWidget].push(widget);
if (!hasParentWidget) {
showErrorForScriptNote(widget._noteId, t("toast.widget-missing-parent", {
property: isPreact ? "parent" : "parentWidget"
}));
}
}
get(parentName: string) {
if (!this.byParent[parentName]) {
return [];
get(parentName: ParentName) {
const widgets: (BasicWidget | VNode)[] = this.getLegacyWidgets(parentName);
for (const preactWidget of this.getPreactWidgets(parentName)) {
const el = h(preactWidget.render, {});
const widget = new ReactWrappedWidget(el);
widget.contentSized();
if (preactWidget.position) {
widget.position = preactWidget.position;
}
widgets.push(widget);
}
return widgets;
}
getLegacyWidgets(parentName: ParentName): (BasicWidget | RightPanelWidget)[] {
if (!this.legacyWidgets[parentName]) return [];
return (
this.byParent[parentName]
this.legacyWidgets[parentName]
// previously, custom widgets were provided as a single instance, but that has the disadvantage
// for splits where we actually need multiple instaces and thus having a class to instantiate is better
// https://github.com/zadam/trilium/issues/4274
.map((w: any) => (w.prototype ? new w() : w))
);
}
getPreactWidgets(parentName: ParentName) {
return this.preactWidgets[parentName] ?? [];
}
}
async function getWidgetBundlesByParent() {
const scriptBundles = await server.get<Bundle[]>("script/widgets");
const widgetsByParent = new WidgetsByParent();
for (const bundle of scriptBundles) {
let widget;
try {
const scriptBundles = await server.get<Bundle[]>("script/widgets");
try {
widget = await executeBundle(bundle);
if (widget) {
widget._noteId = bundle.noteId;
widgetsByParent.add(widget);
for (const bundle of scriptBundles) {
let widget;
try {
widget = await executeBundle(bundle);
if (widget) {
widget._noteId = bundle.noteId;
widgetsByParent.add(widget);
}
} catch (e: any) {
const noteId = bundle.noteId;
showErrorForScriptNote(noteId, t("toast.bundle-error.message", { message: e.message }));
logError("Widget initialization failed: ", e);
continue;
}
} catch (e: any) {
const noteId = bundle.noteId;
const note = await froca.getNote(noteId);
toastService.showPersistent({
title: t("toast.bundle-error.title"),
icon: "alert",
message: t("toast.bundle-error.message", {
id: noteId,
title: note?.title,
message: e.message
})
});
logError("Widget initialization failed: ", e);
continue;
}
} catch (e) {
toastService.showPersistent({
id: `custom-widget-list-failure`,
title: t("toast.widget-list-error.title"),
message: getErrorMessage(e),
icon: "bx bx-error-circle"
});
}
return widgetsByParent;

View File

@@ -2,24 +2,21 @@ import renderService from "./render.js";
import protectedSessionService from "./protected_session.js";
import protectedSessionHolder from "./protected_session_holder.js";
import openService from "./open.js";
import froca from "./froca.js";
import utils from "./utils.js";
import linkService from "./link.js";
import treeService from "./tree.js";
import FNote from "../entities/fnote.js";
import FAttachment from "../entities/fattachment.js";
import imageContextMenuService from "../menus/image_context_menu.js";
import { applySingleBlockSyntaxHighlight, formatCodeBlocks } from "./syntax_highlight.js";
import { applySingleBlockSyntaxHighlight } from "./syntax_highlight.js";
import { loadElkIfNeeded, postprocessMermaidSvg } from "./mermaid.js";
import renderDoc from "./doc_renderer.js";
import { t } from "../services/i18n.js";
import WheelZoom from 'vanilla-js-wheel-zoom';
import { renderMathInElement } from "./math.js";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
import renderText from "./content_renderer_text.js";
let idCounter = 1;
interface Options {
export interface RenderOptions {
tooltip?: boolean;
trim?: boolean;
imageHasZoom?: boolean;
@@ -29,7 +26,7 @@ interface Options {
const CODE_MIME_TYPES = new Set(["application/json"]);
export async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: Options = {}) {
export async function getRenderedContent(this: {} | { ctx: string }, entity: FNote | FAttachment, options: RenderOptions = {}) {
options = Object.assign(
{
@@ -116,32 +113,6 @@ export async function getRenderedContent(this: {} | { ctx: string }, entity: FNo
};
}
async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: Options = {}) {
// entity must be FNote
const blob = await note.getBlob();
if (blob && !utils.isHtmlEmpty(blob.content)) {
$renderedContent.append($('<div class="ck-content">').html(blob.content));
if ($renderedContent.find("span.math-tex").length > 0) {
renderMathInElement($renderedContent[0], { trust: true });
}
const getNoteIdFromLink = (el: HTMLElement) => treeService.getNoteIdFromUrl($(el).attr("href") || "");
const referenceLinks = $renderedContent.find("a.reference-link");
const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el));
await froca.getNotes(noteIdsToPrefetch);
for (const el of referenceLinks) {
await linkService.loadReferenceLinkTitle($(el));
}
await formatCodeBlocks($renderedContent);
} else if (note instanceof FNote && !options.noChildrenList) {
await renderChildrenList($renderedContent, note);
}
}
/**
* Renders a code note, by displaying its content and applying syntax highlighting based on the selected MIME type.
*/
@@ -163,7 +134,7 @@ async function renderCode(note: FNote | FAttachment, $renderedContent: JQuery<HT
await applySingleBlockSyntaxHighlight($codeBlock, normalizeMimeTypeForCKEditor(note.mime));
}
function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: Options = {}) {
function renderImage(entity: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
const encodedTitle = encodeURIComponent(entity.title);
let url;
@@ -305,40 +276,6 @@ async function renderMermaid(note: FNote | FAttachment, $renderedContent: JQuery
}
}
/**
* @param {jQuery} $renderedContent
* @param {FNote} note
* @returns {Promise<void>}
*/
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote) {
let childNoteIds = note.getChildNoteIds();
if (!childNoteIds.length) {
return;
}
$renderedContent.css("padding", "10px");
$renderedContent.addClass("text-with-ellipsis");
if (childNoteIds.length > 10) {
childNoteIds = childNoteIds.slice(0, 10);
}
// just load the first 10 child notes
const childNotes = await froca.getNotes(childNoteIds);
for (const childNote of childNotes) {
$renderedContent.append(
await linkService.createLink(`${note.noteId}/${childNote.noteId}`, {
showTooltip: false,
showNoteIcon: true
})
);
$renderedContent.append("<br>");
}
}
function getRenderingType(entity: FNote | FAttachment) {
let type: string = "";
if ("type" in entity) {

View File

@@ -0,0 +1,128 @@
import FAttachment from "../entities/fattachment.js";
import FNote from "../entities/fnote.js";
import { default as content_renderer, type RenderOptions } from "./content_renderer.js";
import froca from "./froca.js";
import link from "./link.js";
import { renderMathInElement } from "./math.js";
import { getMermaidConfig } from "./mermaid.js";
import { formatCodeBlocks } from "./syntax_highlight.js";
import tree from "./tree.js";
import { isHtmlEmpty } from "./utils.js";
export default async function renderText(note: FNote | FAttachment, $renderedContent: JQuery<HTMLElement>, options: RenderOptions = {}) {
// entity must be FNote
const blob = await note.getBlob();
if (blob && !isHtmlEmpty(blob.content)) {
$renderedContent.append($('<div class="ck-content">').html(blob.content));
await renderIncludedNotes($renderedContent[0]);
if ($renderedContent.find("span.math-tex").length > 0) {
renderMathInElement($renderedContent[0], { trust: true });
}
const getNoteIdFromLink = (el: HTMLElement) => tree.getNoteIdFromUrl($(el).attr("href") || "");
const referenceLinks = $renderedContent.find<HTMLAnchorElement>("a.reference-link");
const noteIdsToPrefetch = referenceLinks.map((i, el) => getNoteIdFromLink(el));
await froca.getNotes(noteIdsToPrefetch);
for (const el of referenceLinks) {
const innerSpan = document.createElement("span");
await link.loadReferenceLinkTitle($(innerSpan), el.href);
el.replaceChildren(innerSpan);
}
await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement);
await formatCodeBlocks($renderedContent);
} else if (note instanceof FNote && !options.noChildrenList) {
await renderChildrenList($renderedContent, note);
}
}
async function renderIncludedNotes(contentEl: HTMLElement) {
// TODO: Consider duplicating with server's share/content_renderer.ts.
const includeNoteEls = contentEl.querySelectorAll("section.include-note");
// Gather the list of items to load.
const noteIds: string[] = [];
for (const includeNoteEl of includeNoteEls) {
const noteId = includeNoteEl.getAttribute("data-note-id");
if (noteId) {
noteIds.push(noteId);
}
}
// Load the required notes.
await froca.getNotes(noteIds);
// Render and integrate the notes.
for (const includeNoteEl of includeNoteEls) {
const noteId = includeNoteEl.getAttribute("data-note-id");
if (!noteId) continue;
const note = froca.getNoteFromCache(noteId);
if (!note) {
console.warn(`Unable to include ${noteId} because it could not be found.`);
continue;
}
const renderedContent = (await content_renderer.getRenderedContent(note)).$renderedContent;
includeNoteEl.replaceChildren(...renderedContent);
}
}
/** Rewrite the code block from <pre><code> to <div> in order not to apply a codeblock style to it. */
export async function rewriteMermaidDiagramsInContainer(container: HTMLDivElement) {
const mermaidBlocks = container.querySelectorAll('pre:has(code[class="language-mermaid"])');
if (!mermaidBlocks.length) return;
const nodes: HTMLElement[] = [];
for (const mermaidBlock of mermaidBlocks) {
const div = document.createElement("div");
div.classList.add("mermaid-diagram");
div.innerHTML = mermaidBlock.querySelector("code")?.innerHTML ?? "";
mermaidBlock.replaceWith(div);
nodes.push(div);
}
}
export async function applyInlineMermaid(container: HTMLDivElement) {
// Initialize mermaid
const mermaid = (await import("mermaid")).default;
mermaid.initialize(getMermaidConfig());
const nodes = Array.from(container.querySelectorAll<HTMLElement>("div.mermaid-diagram"));
try {
await mermaid.run({ nodes });
} catch (e) {
console.log(e);
}
}
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote) {
let childNoteIds = note.getChildNoteIds();
if (!childNoteIds.length) {
return;
}
$renderedContent.css("padding", "10px");
$renderedContent.addClass("text-with-ellipsis");
if (childNoteIds.length > 10) {
childNoteIds = childNoteIds.slice(0, 10);
}
// just load the first 10 child notes
const childNotes = await froca.getNotes(childNoteIds);
for (const childNote of childNotes) {
$renderedContent.append(
await link.createLink(`${note.noteId}/${childNote.noteId}`, {
showTooltip: false,
showNoteIcon: true
})
);
$renderedContent.append("<br>");
}
}

View File

@@ -1,7 +1,9 @@
import clsx from "clsx";
import {readCssVar} from "../utils/css-var";
import Color, { ColorInstance } from "color";
const registeredClasses = new Set<string>();
const colorsWithHue = new Set<string>();
// Read the color lightness limits defined in the theme as CSS variables
@@ -26,19 +28,24 @@ function createClassForColor(colorString: string | null) {
if (!registeredClasses.has(className)) {
const adjustedColor = adjustColorLightness(color, lightThemeColorMaxLightness!,
darkThemeColorMinLightness!);
const hue = getHue(color);
$("head").append(`<style>
.${className}, span.fancytree-active.${className} {
--original-custom-color: ${color.hex()};
--light-theme-custom-color: ${adjustedColor.lightThemeColor};
--dark-theme-custom-color: ${adjustedColor.darkThemeColor};
--custom-color-hue: ${getHue(color) ?? 'unset'};
--custom-color-hue: ${hue ?? 'unset'};
}
</style>`);
registeredClasses.add(className);
if (hue !== undefined) {
colorsWithHue.add(className);
}
}
return className;
return clsx("use-note-color", className, colorsWithHue.has(className) && "with-hue");
}
function parseColor(color: string) {
@@ -76,6 +83,11 @@ function getHue(color: ColorInstance) {
}
}
export function getReadableTextColor(bgColor: string) {
const colorInstance = Color(bgColor);
return colorInstance.isLight() ? "#000" : "#fff";
}
export default {
createClassForColor
};

View File

@@ -1,4 +1,4 @@
import dayjs from "dayjs";
import { dayjs } from "@triliumnext/commons";
import type { FNoteRow } from "../entities/fnote.js";
import froca from "./froca.js";
import server from "./server.js";

View File

@@ -12,7 +12,7 @@
* @param whether to execute at the beginning (`false`)
* @api public
*/
function debounce<T>(func: (...args: unknown[]) => T, waitMs: number, immediate: boolean = false) {
function debounce<T>(func: (...args: any[]) => T, waitMs: number, immediate: boolean = false) {
let timeout: any; // TODO: fix once we split client and server.
let args: unknown[] | null;
let context: unknown;

View File

@@ -1,8 +1,9 @@
import { Modal } from "bootstrap";
import appContext from "../components/app_context.js";
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions } from "../widgets/dialogs/confirm.js";
import type { ConfirmDialogOptions, ConfirmDialogResult, ConfirmWithMessageOptions, MessageType } from "../widgets/dialogs/confirm.js";
import type { PromptDialogOptions } from "../widgets/dialogs/prompt.js";
import { focusSavedElement, saveFocusedElement } from "./focus.js";
import { InfoExtraProps } from "../widgets/dialogs/info.jsx";
export async function openDialog($dialog: JQuery<HTMLElement>, closeActDialog = true, config?: Partial<Modal.Options>) {
if (closeActDialog) {
@@ -37,8 +38,8 @@ export function closeActiveDialog() {
}
}
async function info(message: string) {
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { message, callback: res }));
async function info(message: MessageType, extraProps?: InfoExtraProps) {
return new Promise((res) => appContext.triggerCommand("showInfoDialog", { ...extraProps, message, callback: res }));
}
/**

View File

@@ -1,4 +1,5 @@
import type FNote from "../entities/fnote.js";
import { applyReferenceLinks } from "../widgets/type_widgets/text/read_only_helper.js";
import { getCurrentLanguage } from "./i18n.js";
import { formatCodeBlocks } from "./syntax_highlight.js";
@@ -10,18 +11,18 @@ export default function renderDoc(note: FNote) {
if (docName) {
// find doc based on language
const url = getUrl(docName, getCurrentLanguage());
$content.load(url, (response, status) => {
$content.load(url, async (response, status) => {
// fallback to english doc if no translation available
if (status === "error") {
const fallbackUrl = getUrl(docName, "en");
$content.load(fallbackUrl, () => {
processContent(fallbackUrl, $content)
$content.load(fallbackUrl, async () => {
await processContent(fallbackUrl, $content)
resolve($content);
});
return;
}
processContent(url, $content);
await processContent(url, $content);
resolve($content);
});
} else {
@@ -32,7 +33,7 @@ export default function renderDoc(note: FNote) {
});
}
function processContent(url: string, $content: JQuery<HTMLElement>) {
async function processContent(url: string, $content: JQuery<HTMLElement>) {
const dir = url.substring(0, url.lastIndexOf("/"));
// Images are relative to the docnote but that will not work when rendered in the application since the path breaks.
@@ -42,6 +43,9 @@ function processContent(url: string, $content: JQuery<HTMLElement>) {
});
formatCodeBlocks($content);
// Apply reference links.
await applyReferenceLinks($content[0]);
}
function getUrl(docNameValue: string, language: string) {

View File

@@ -0,0 +1,60 @@
import { t } from "./i18n";
import options from "./options";
export interface ExperimentalFeature {
id: string;
name: string;
description: string;
}
export const experimentalFeatures = [
{
id: "new-layout",
name: t("experimental_features.new_layout_name"),
description: t("experimental_features.new_layout_description"),
}
] as const satisfies ExperimentalFeature[];
export type ExperimentalFeatureId = typeof experimentalFeatures[number]["id"];
let enabledFeatures: Set<ExperimentalFeatureId> | null = null;
export function isExperimentalFeatureEnabled(featureId: ExperimentalFeatureId): boolean {
if (featureId === "new-layout") {
return options.is("newLayout");
}
return getEnabledFeatures().has(featureId);
}
export function getEnabledExperimentalFeatureIds() {
const values = [ ...getEnabledFeatures().values() ];
if (options.is("newLayout")) {
values.push("new-layout");
}
return values;
}
export async function toggleExperimentalFeature(featureId: ExperimentalFeatureId, enable: boolean) {
const features = new Set(getEnabledFeatures());
if (enable) {
features.add(featureId);
} else {
features.delete(featureId);
}
await options.save("experimentalFeatures", JSON.stringify(Array.from(features)));
}
function getEnabledFeatures() {
if (!enabledFeatures) {
let features: ExperimentalFeatureId[] = [];
try {
features = JSON.parse(options.get("experimentalFeatures")) as ExperimentalFeatureId[];
} catch (e) {
console.warn("Failed to parse experimental features from options:", e);
}
enabledFeatures = new Set(features);
enabledFeatures.delete("new-layout"); // handled separately.
}
return enabledFeatures;
}

View File

@@ -13,7 +13,7 @@ export interface Froca {
getBlob(entityType: string, entityId: string): Promise<FBlob | null>;
getNote(noteId: string, silentNotFoundError?: boolean): Promise<FNote | null>;
getNoteFromCache(noteId: string): FNote;
getNoteFromCache(noteId: string): FNote | undefined;
getNotesFromCache(noteIds: string[], silentNotFoundError?: boolean): FNote[];
getNotes(noteIds: string[], silentNotFoundError?: boolean): Promise<FNote[]>;

View File

@@ -288,7 +288,7 @@ class FrocaImpl implements Froca {
return (await this.getNotes([noteId], silentNotFoundError))[0];
}
getNoteFromCache(noteId: string) {
getNoteFromCache(noteId: string): FNote | undefined {
if (!noteId) {
throw new Error("Empty noteId");
}

View File

@@ -1,27 +1,27 @@
import server from "./server.js";
import utils from "./utils.js";
import toastService from "./toast.js";
import linkService from "./link.js";
import { dayjs, formatLogMessage } from "@triliumnext/commons";
import appContext from "../components/app_context.js";
import type Component from "../components/component.js";
import type NoteContext from "../components/note_context.js";
import type FNote from "../entities/fnote.js";
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import RightPanelWidget from "../widgets/right_panel_widget.js";
import dateNotesService from "./date_notes.js";
import dialogService from "./dialog.js";
import froca from "./froca.js";
import { preactAPI } from "./frontend_script_api_preact.js";
import { t } from "./i18n.js";
import linkService from "./link.js";
import noteTooltipService from "./note_tooltip.js";
import protectedSessionService from "./protected_session.js";
import dateNotesService from "./date_notes.js";
import searchService from "./search.js";
import RightPanelWidget from "../widgets/right_panel_widget.js";
import ws from "./ws.js";
import appContext from "../components/app_context.js";
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
import BasicWidget from "../widgets/basic_widget.js";
import SpacedUpdate from "./spaced_update.js";
import server from "./server.js";
import shortcutService from "./shortcuts.js";
import dialogService from "./dialog.js";
import type FNote from "../entities/fnote.js";
import { t } from "./i18n.js";
import dayjs from "dayjs";
import type NoteContext from "../components/note_context.js";
import type NoteDetailWidget from "../widgets/note_detail.js";
import type Component from "../components/component.js";
import { formatLogMessage } from "@triliumnext/commons";
import SpacedUpdate from "./spaced_update.js";
import toastService from "./toast.js";
import utils from "./utils.js";
import ws from "./ws.js";
/**
* A whole number
@@ -78,6 +78,10 @@ export interface Api {
/**
* Entity whose event triggered this execution.
*
* <p>
* For front-end scripts, generally there's no origin entity specified since the scripts are run by the user or automatically by the UI (widgets).
* If there is an origin entity specified, then it's going to be a note entity.
*/
originEntity: unknown | null;
@@ -279,12 +283,16 @@ export interface Api {
getActiveContextNote(): FNote;
/**
* @returns returns active context (split)
* Obtains the currently active/focused split in the current tab.
*
* Note that this method does not return the note context of the "Quick edit" panel, it will return the note context behind it.
*/
getActiveContext(): NoteContext;
/**
* @returns returns active main context (first split in a tab, represents the tab as a whole)
* Obtains the main context of the current tab. This is the left-most split.
*
* Note that this method does not return the note context of the "Quick edit" panel, it will return the note context behind it.
*/
getActiveMainContext(): NoteContext;
@@ -317,7 +325,7 @@ export interface Api {
* Get access to the widget handling note detail. Methods like `getWidgetType()` and `getTypeWidget()` to get to the
* implementation of actual widget type.
*/
getActiveNoteDetailWidget(): Promise<NoteDetailWidget>;
getActiveNoteDetailWidget(): Promise<ReactWrappedWidget>;
/**
* @returns returns a note path of active note or null if there isn't active note
*/
@@ -457,6 +465,8 @@ export interface Api {
* Log given message to the log pane in UI
*/
log(message: string | object): void;
preact: typeof preactAPI;
}
/**
@@ -526,9 +536,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
return params.map((p) => {
if (typeof p === "function") {
return `!@#Function: ${p.toString()}`;
} else {
return p;
}
return p;
});
}
@@ -555,9 +564,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
await ws.waitForMaxKnownEntityChangeId();
return ret.executionResult;
} else {
throw new Error(`server error: ${ret.error}`);
}
throw new Error(`server error: ${ret.error}`);
};
this.runOnBackend = async (func, params = []) => {
@@ -714,6 +722,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
this.logMessages[noteId].push(message);
this.logSpacedUpdates[noteId].scheduleUpdate();
};
this.preact = preactAPI;
}
export default FrontendScriptApi as any as {

View File

@@ -0,0 +1,101 @@
import { Fragment, h, VNode } from "preact";
import * as hooks from "preact/hooks";
import ActionButton from "../widgets/react/ActionButton";
import Admonition from "../widgets/react/Admonition";
import Button from "../widgets/react/Button";
import CKEditor from "../widgets/react/CKEditor";
import Collapsible from "../widgets/react/Collapsible";
import Dropdown from "../widgets/react/Dropdown";
import FormCheckbox from "../widgets/react/FormCheckbox";
import FormDropdownList from "../widgets/react/FormDropdownList";
import { FormFileUploadActionButton, FormFileUploadButton } from "../widgets/react/FormFileUpload";
import FormGroup from "../widgets/react/FormGroup";
import { FormDropdownDivider, FormDropdownSubmenu, FormListItem } from "../widgets/react/FormList";
import FormRadioGroup from "../widgets/react/FormRadioGroup";
import FormText from "../widgets/react/FormText";
import FormTextArea from "../widgets/react/FormTextArea";
import FormTextBox from "../widgets/react/FormTextBox";
import FormToggle from "../widgets/react/FormToggle";
import * as triliumHooks from "../widgets/react/hooks";
import Icon from "../widgets/react/Icon";
import LinkButton from "../widgets/react/LinkButton";
import LoadingSpinner from "../widgets/react/LoadingSpinner";
import Modal from "../widgets/react/Modal";
import NoteAutocomplete from "../widgets/react/NoteAutocomplete";
import NoteLink from "../widgets/react/NoteLink";
import RawHtml from "../widgets/react/RawHtml";
import Slider from "../widgets/react/Slider";
import RightPanelWidget from "../widgets/sidebar/RightPanelWidget";
export interface WidgetDefinition {
parent: "right-pane",
render: () => VNode,
position?: number,
}
export interface WidgetDefinitionWithType extends WidgetDefinition {
type: "preact-widget"
}
export interface LauncherWidgetDefinitionWithType {
type: "preact-launcher-widget"
render: () => VNode
}
export const preactAPI = Object.freeze({
// Core
h,
Fragment,
/**
* Method that must be run for widget scripts that run on Preact, using JSX. The method just returns the same definition, reserved for future typechecking and perhaps validation purposes.
*
* @param definition the widget definition.
*/
defineWidget(definition: WidgetDefinition) {
return {
type: "preact-widget",
...definition
};
},
defineLauncherWidget(definition: Omit<LauncherWidgetDefinitionWithType, "type">) {
return {
type: "preact-launcher-widget",
...definition
};
},
// Basic widgets
ActionButton,
Admonition,
Button,
CKEditor,
Collapsible,
Dropdown,
FormCheckbox,
FormDropdownList,
FormFileUploadButton, FormFileUploadActionButton,
FormGroup,
FormListItem, FormDropdownDivider, FormDropdownSubmenu,
FormRadioGroup,
FormText,
FormTextArea,
FormTextBox,
FormToggle,
Icon,
LinkButton,
LoadingSpinner,
Modal,
NoteAutocomplete,
NoteLink,
RawHtml,
Slider,
// Specialized widgets
RightPanelWidget,
...hooks,
...triliumHooks
});

View File

@@ -2,7 +2,7 @@ import options from "./options.js";
import i18next from "i18next";
import i18nextHttpBackend from "i18next-http-backend";
import server from "./server.js";
import type { Locale } from "@triliumnext/commons";
import { LOCALE_IDS, setDayjsLocale, type Locale } from "@triliumnext/commons";
import { initReactI18next } from "react-i18next";
let locales: Locale[] | null;
@@ -13,7 +13,7 @@ let locales: Locale[] | null;
export let translationsInitializedPromise = $.Deferred();
export async function initLocale() {
const locale = (options.get("locale") as string) || "en";
const locale = ((options.get("locale") as string) || "en") as LOCALE_IDS;
locales = await server.get<Locale[]>("options/locales");
@@ -27,6 +27,7 @@ export async function initLocale() {
returnEmptyString: false
});
await setDayjsLocale(locale);
translationsInitializedPromise.resolve();
}

View File

@@ -1,4 +1,4 @@
import toastService, { type ToastOptions } from "./toast.js";
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
import server from "./server.js";
import ws from "./ws.js";
import utils from "./utils.js";
@@ -57,11 +57,11 @@ export async function uploadFiles(entityType: string, parentNoteId: string, file
}
}
function makeToast(id: string, message: string): ToastOptions {
function makeToast(id: string, message: string): ToastOptionsWithRequiredId {
return {
id: id,
id,
title: t("import.import-status"),
message: message,
message,
icon: "plus"
};
}
@@ -78,7 +78,7 @@ ws.subscribeToMessages(async (message) => {
toastService.showPersistent(makeToast(message.taskId, t("import.in-progress", { progress: message.progressCount })));
} else if (message.type === "taskSucceeded") {
const toast = makeToast(message.taskId, t("import.successful"));
toast.closeAfter = 5000;
toast.timeout = 5000;
toastService.showPersistent(toast);
@@ -100,7 +100,7 @@ ws.subscribeToMessages(async (message: WebSocketMessage) => {
toastService.showPersistent(makeToast(message.taskId, t("import.in-progress", { progress: message.progressCount })));
} else if (message.type === "taskSucceeded") {
const toast = makeToast(message.taskId, t("import.successful"));
toast.closeAfter = 5000;
toast.timeout = 5000;
toastService.showPersistent(toast);

View File

@@ -1,6 +1,6 @@
import server from "./server.js";
import appContext, { type CommandNames } from "../components/app_context.js";
import shortcutService from "./shortcuts.js";
import appContext from "../components/app_context.js";
import shortcutService, { ShortcutBinding } from "./shortcuts.js";
import type Component from "../components/component.js";
import type { ActionKeyboardShortcut } from "@triliumnext/commons";
@@ -28,14 +28,24 @@ async function getActionsForScope(scope: string) {
return actions.filter((action) => action.scope === scope);
}
async function setupActionsForElement(scope: string, $el: JQuery<HTMLElement>, component: Component) {
async function setupActionsForElement(scope: string, $el: JQuery<HTMLElement>, component: Component, ntxId: string | null | undefined) {
if (!$el[0]) return [];
const actions = await getActionsForScope(scope);
const bindings: ShortcutBinding[] = [];
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts ?? []) {
shortcutService.bindElShortcut($el, shortcut, () => component.triggerCommand(action.actionName, { ntxId: appContext.tabManager.activeNtxId }));
const binding = shortcutService.bindElShortcut($el, shortcut, () => {
component.triggerCommand(action.actionName, { ntxId });
});
if (binding) {
bindings.push(binding);
}
}
}
return bindings;
}
getActionsForScope("window").then((actions) => {

View File

@@ -1,10 +1,11 @@
import treeService from "./tree.js";
import linkContextMenuService from "../menus/link_context_menu.js";
import appContext, { type NoteCommandData } from "../components/app_context.js";
import froca from "./froca.js";
import utils from "./utils.js";
import { ALLOWED_PROTOCOLS } from "@triliumnext/commons";
import appContext, { type NoteCommandData } from "../components/app_context.js";
import { openInCurrentNoteContext } from "../components/note_context.js";
import linkContextMenuService from "../menus/link_context_menu.js";
import froca from "./froca.js";
import treeService from "./tree.js";
import utils from "./utils.js";
function getNotePathFromUrl(url: string) {
const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url);
@@ -27,7 +28,7 @@ async function getLinkIcon(noteId: string, viewMode: ViewMode | undefined) {
return icon;
}
export type ViewMode = "default" | "source" | "attachments" | "contextual-help";
export type ViewMode = "default" | "source" | "attachments" | "contextual-help" | "note-map";
export interface ViewScope {
/**
@@ -99,7 +100,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
const viewMode = viewScope.viewMode || "default";
let linkTitle = options.title;
if (!linkTitle) {
if (linkTitle === undefined) {
if (viewMode === "attachments" && viewScope.attachmentId) {
const attachment = await froca.getAttachment(viewScope.attachmentId);
@@ -122,7 +123,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
const $container = $("<span>");
if (showNoteIcon) {
let icon = await getLinkIcon(noteId, viewMode);
const icon = await getLinkIcon(noteId, viewMode);
if (icon) {
$container.append($("<span>").addClass(`bx ${icon}`)).append(" ");
@@ -131,7 +132,7 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
const hash = calculateHash({
notePath,
viewScope: viewScope
viewScope
});
const $noteLink = $("<a>", {
@@ -150,11 +151,16 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
$container.append($noteLink);
if (showNotePath) {
const resolvedPathSegments = (await treeService.resolveNotePathToSegments(notePath)) || [];
resolvedPathSegments.pop(); // Remove last element
let pathSegments: string[];
if (notePath == "root") {
pathSegments = ["⌂"];
} else {
const resolvedPathSegments = (await treeService.resolveNotePathToSegments(notePath)) || [];
resolvedPathSegments.pop(); // Remove last element
const resolvedPath = resolvedPathSegments.join("/");
const pathSegments = await treeService.getNotePathTitleComponents(resolvedPath);
const resolvedPath = resolvedPathSegments.join("/");
pathSegments = await treeService.getNotePathTitleComponents(resolvedPath);
}
if (pathSegments) {
if (pathSegments.length) {
@@ -166,11 +172,11 @@ async function createLink(notePath: string | undefined, options: CreateLinkOptio
return $container;
}
function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
export function calculateHash({ notePath, ntxId, hoistedNoteId, viewScope = {} }: NoteCommandData) {
notePath = notePath || "";
const params = [
ntxId ? { ntxId: ntxId } : null,
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId: hoistedNoteId } : null,
ntxId ? { ntxId } : null,
hoistedNoteId && hoistedNoteId !== "root" ? { hoistedNoteId } : null,
viewScope.viewMode && viewScope.viewMode !== "default" ? { viewMode: viewScope.viewMode } : null,
viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null
].filter((p) => !!p);
@@ -214,7 +220,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
}
const hash = url.substr(hashIdx + 1); // strip also the initial '#'
let [notePath, paramString] = hash.split("?");
const [notePath, paramString] = hash.split("?");
const viewScope: ViewScope = {
viewMode: "default"
@@ -247,7 +253,7 @@ export function parseNavigationStateFromUrl(url: string | undefined) {
}
if (searchString) {
return { searchString }
return { searchString };
}
if (!notePath.match(/^[_a-z0-9]{4,}(\/[_a-z0-9]{4,})*$/i)) {
@@ -280,7 +286,7 @@ function goToLink(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent) {
* @param $link the jQuery element of the link that was clicked, used to determine if the link is an anchor link (e.g., `#fn1` or `#fnref1`) and to handle it accordingly.
* @returns `true` if the link was handled (i.e., the element was found and scrolled to), or a falsy value otherwise.
*/
function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
export function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent<HTMLCanvasElement> | null, hrefLink: string | undefined, $link?: JQuery<HTMLElement> | null) {
if (hrefLink?.startsWith("data:")) {
return true;
}
@@ -302,7 +308,8 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
// Right click is handled separately.
const isMiddleClick = evt && "which" in evt && evt.which === 2;
const targetIsBlank = ($link?.attr("target") === "_blank");
const openInNewTab = (isLeftClick && ctrlKey) || isMiddleClick || targetIsBlank;
const isDoubleClick = isLeftClick && evt?.type === "dblclick";
const openInNewTab = (isLeftClick && ctrlKey) || isDoubleClick || isMiddleClick || targetIsBlank;
const activate = (isLeftClick && ctrlKey && shiftKey) || (isMiddleClick && shiftKey);
const openInNewWindow = isLeftClick && evt?.shiftKey && !ctrlKey;
@@ -323,16 +330,18 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent
const withinEditLink = $link?.hasClass("ck-link-actions__preview");
const outsideOfCKEditor = !$link || $link.closest("[contenteditable]").length === 0;
if (openInNewTab || (withinEditLink && (isLeftClick || isMiddleClick)) || (outsideOfCKEditor && (isLeftClick || isMiddleClick))) {
if (openInNewTab || openInNewWindow || (isLeftClick && (withinEditLink || outsideOfCKEditor))) {
if (hrefLink.toLowerCase().startsWith("http") || hrefLink.startsWith("api/")) {
window.open(hrefLink, "_blank");
} else if ((hrefLink.toLowerCase().startsWith("file:") || hrefLink.toLowerCase().startsWith("geo:")) && utils.isElectron()) {
const electron = utils.dynamicRequire("electron");
electron.shell.openPath(hrefLink);
} else {
// Enable protocols supported by CKEditor 5 to be clickable.
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(protocol + ":"))) {
window.open(hrefLink, "_blank");
if (ALLOWED_PROTOCOLS.some((protocol) => hrefLink.toLowerCase().startsWith(`${protocol}:`))) {
if ( utils.isElectron()) {
const electron = utils.dynamicRequire("electron");
electron.shell.openExternal(hrefLink);
} else {
window.open(hrefLink, "_blank");
}
}
}
}
@@ -387,7 +396,7 @@ async function loadReferenceLinkTitle($el: JQuery<HTMLElement>, href: string | n
href = href || $link.attr("href");
if (!href) {
console.warn("Empty URL for parsing: " + $el[0].outerHTML);
console.warn(`Empty URL for parsing: ${$el[0].outerHTML}`);
return;
}
@@ -430,9 +439,9 @@ async function getReferenceLinkTitle(href: string) {
const attachment = await note.getAttachmentById(viewScope.attachmentId);
return attachment ? attachment.title : "[missing attachment]";
} else {
return note.title;
}
return note.title;
}
function getReferenceLinkTitleSync(href: string) {
@@ -454,42 +463,35 @@ function getReferenceLinkTitleSync(href: string) {
const attachment = note.attachments.find((att) => att.attachmentId === viewScope.attachmentId);
return attachment ? attachment.title : "[missing attachment]";
} else {
return note.title;
}
return note.title;
}
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("click", "a", goToLink);
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("auxclick", "a", goToLink); // to handle the middle button
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("contextmenu", "a", linkContextMenu);
$(document).on("dblclick", "a", (e) => {
e.preventDefault();
e.stopPropagation();
if (glob.device !== "print") {
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("click", "a", goToLink);
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("auxclick", "a", goToLink); // to handle the middle button
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("contextmenu", "a", linkContextMenu);
// TODO: Check why the event is not supported.
//@ts-ignore
$(document).on("dblclick", "a", goToLink);
const $link = $(e.target).closest("a");
const address = $link.attr("href");
if (address && address.startsWith("http")) {
window.open(address, "_blank");
}
});
$(document).on("mousedown", "a", (e) => {
if (e.which === 2) {
// prevent paste on middle click
// https://github.com/zadam/trilium/issues/2995
// https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event#preventing_default_actions
e.preventDefault();
return false;
}
});
$(document).on("mousedown", "a", (e) => {
if (e.which === 2) {
// prevent paste on middle click
// https://github.com/zadam/trilium/issues/2995
// https://developer.mozilla.org/en-US/docs/Web/API/Element/auxclick_event#preventing_default_actions
e.preventDefault();
return false;
}
});
}
export default {
getNotePathFromUrl,

View File

@@ -1,11 +1,21 @@
import type { AttachmentRow, EtapiTokenRow, OptionNames } from "@triliumnext/commons";
import type { AttachmentRow, EtapiTokenRow, NoteType, OptionNames } from "@triliumnext/commons";
import type { AttributeType } from "../entities/fattribute.js";
import type { EntityChange } from "../server_types.js";
// TODO: Deduplicate with server.
interface NoteRow {
blobId: string;
dateCreated: string;
dateModified: string;
isDeleted?: boolean;
isProtected?: boolean;
mime: string;
noteId: string;
title: string;
type: NoteType;
utcDateCreated: string;
utcDateModified: string;
}
// TODO: Deduplicate with BranchRow from `rows.ts`/

View File

@@ -1,4 +1,5 @@
import utils from "./utils.js";
import options from "./options.js";
import server from "./server.js";
type ExecFunction = (command: string, cb: (err: string, stdout: string, stderror: string) => void) => void;
@@ -126,7 +127,7 @@ function downloadRevision(noteId: string, revisionId: string) {
/**
* @param url - should be without initial slash!!!
*/
function getUrlForDownload(url: string) {
export function getUrlForDownload(url: string) {
if (utils.isElectron()) {
// electron needs absolute URL, so we extract current host, port, protocol
return `${getHost()}/${url}`;
@@ -171,6 +172,21 @@ function getHost() {
return `${url.protocol}//${url.hostname}:${url.port}`;
}
async function openNoteOnServer(noteId: string) {
// Get the sync server host from options
const syncServerHost = options.get("syncServerHost");
if (!syncServerHost) {
console.error("No sync server host configured");
return;
}
const url = new URL(`#root/${noteId}`, syncServerHost).toString();
// Use window.open to ensure link opens in external browser in Electron
window.open(url, '_blank', 'noopener,noreferrer');
}
async function openDirectory(directory: string) {
try {
if (utils.isElectron()) {
@@ -198,5 +214,6 @@ export default {
openAttachmentExternally,
openNoteCustom,
openAttachmentCustom,
openNoteOnServer,
openDirectory
};

View File

@@ -41,6 +41,17 @@ function parse(value: string) {
return defObj;
}
/**
* For an attribute definition name (e.g. `label:TEST:TEST1`), extracts its type (label) and name (TEST:TEST1).
* @param definitionAttrName the attribute definition name, without the leading `#` (e.g. `label:TEST:TEST1`)
* @return a tuple of [type, name].
*/
export function extractAttributeDefinitionTypeAndName(definitionAttrName: string): [ "label" | "relation", string ] {
const valueType = definitionAttrName.startsWith("label:") ? "label" : "relation";
const valueName = definitionAttrName.substring(valueType.length + 1);
return [ valueType, valueName ];
}
export default {
parse
};

View File

@@ -1,7 +1,7 @@
import server from "./server.js";
import protectedSessionHolder from "./protected_session_holder.js";
import toastService from "./toast.js";
import type { ToastOptions } from "./toast.js";
import type { ToastOptionsWithRequiredId } from "./toast.js";
import ws from "./ws.js";
import appContext from "../components/app_context.js";
import froca from "./froca.js";
@@ -97,7 +97,7 @@ async function protectNote(noteId: string, protect: boolean, includingSubtree: b
await server.put(`notes/${noteId}/protect/${protect ? 1 : 0}?subtree=${includingSubtree ? 1 : 0}`);
}
function makeToast(message: Message, title: string, text: string): ToastOptions {
function makeToast(message: Message, title: string, text: string): ToastOptionsWithRequiredId {
return {
id: message.taskId,
title,
@@ -124,7 +124,7 @@ ws.subscribeToMessages(async (message) => {
} else if (message.type === "taskSucceeded") {
const text = isProtecting ? t("protected_session.protecting-finished-successfully") : t("protected_session.unprotecting-finished-successfully");
const toast = makeToast(message, title, text);
toast.closeAfter = 3000;
toast.timeout = 3000;
toastService.showPersistent(toast);
}

View File

@@ -1,6 +1,10 @@
import server from "./server.js";
import bundleService, { type Bundle } from "./bundle.js";
import { h, VNode } from "preact";
import type FNote from "../entities/fnote.js";
import { renderReactWidgetAtElement } from "../widgets/react/react_utils.jsx";
import bundleService, { type Bundle } from "./bundle.js";
import froca from "./froca.js";
import server from "./server.js";
async function render(note: FNote, $el: JQuery<HTMLElement>) {
const relations = note.getRelations("renderNote");
@@ -17,12 +21,34 @@ async function render(note: FNote, $el: JQuery<HTMLElement>) {
$scriptContainer.append(bundle.html);
// async so that scripts cannot block trilium execution
bundleService.executeBundle(bundle, note, $scriptContainer);
bundleService.executeBundle(bundle, note, $scriptContainer).then(result => {
// Render JSX
if (bundle.html === "") {
renderIfJsx(bundle, result, $el);
}
});
}
return renderNoteIds.length > 0;
}
async function renderIfJsx(bundle: Bundle, result: unknown, $el: JQuery<HTMLElement>) {
// Ensure the root script note is actually a JSX.
const rootScriptNoteId = await froca.getNote(bundle.noteId);
if (rootScriptNoteId?.mime !== "text/jsx") return;
// Ensure the output is a valid el.
if (typeof result !== "function") return;
// Obtain the parent component.
const closestComponent = glob.getComponentByEl($el.closest(".component")[0]);
if (!closestComponent) return;
// Render the element.
const el = h(result as () => VNode, {});
renderReactWidgetAtElement(closestComponent, el, $el[0]);
}
export default {
render
};

View File

@@ -133,11 +133,11 @@ async function call<T>(method: string, url: string, componentId?: string, option
};
ipc.send("server-request", {
requestId: requestId,
headers: headers,
method: method,
requestId,
headers,
method,
url: `/${window.glob.baseApiUrl}${url}`,
data: data
data
});
})) as any;
} else {
@@ -161,7 +161,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
const options: JQueryAjaxSettings = {
url: window.glob.baseApiUrl + url,
type: method,
headers: headers,
headers,
timeout: 60000,
success: (body, textStatus, jqXhr) => {
const respHeaders: Headers = {};
@@ -263,7 +263,7 @@ async function reportError(method: string, url: string, statusCode: number, resp
const toastService = (await import("./toast.js")).default;
const messageStr = typeof message === "string" ? message : JSON.stringify(message);
const messageStr = (typeof message === "string" ? message : JSON.stringify(message)) || "-";
if ([400, 404].includes(statusCode) && response && typeof response === "object") {
toastService.showError(messageStr);
@@ -274,10 +274,22 @@ async function reportError(method: string, url: string, statusCode: number, resp
...response
});
} else {
const title = `${statusCode} ${method} ${url}`;
toastService.showErrorTitleAndMessage(title, messageStr);
const { throwError } = await import("./ws.js");
throwError(`${title} - ${message}`);
const { t } = await import("./i18n.js");
if (statusCode === 400 && (url.includes("%23") || url.includes("%2F"))) {
toastService.showPersistent({
id: "trafik-blocked",
icon: "bx bx-unlink",
title: t("server.unknown_http_error_title"),
message: t("server.traefik_blocks_requests")
});
} else {
toastService.showErrorTitleAndMessage(
t("server.unknown_http_error_title"),
t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }),
15_000);
}
const { logError } = await import("./ws.js");
logError(`${statusCode} ${method} ${url} - ${message}`);
}
}

View File

@@ -1,9 +1,9 @@
import utils from "./utils.js";
type ElementType = HTMLElement | Document;
type Handler = (e: KeyboardEvent) => void;
export type Handler = (e: KeyboardEvent) => void;
interface ShortcutBinding {
export interface ShortcutBinding {
element: HTMLElement | Document;
shortcut: string;
handler: Handler;
@@ -127,10 +127,20 @@ function bindElShortcut($el: JQuery<ElementType | Element>, keyboardShortcut: st
activeBindings.set(key, []);
}
activeBindings.get(key)!.push(binding);
return binding;
}
}
}
export function removeIndividualBinding(binding: ShortcutBinding) {
const key = binding.namespace ?? "global";
const activeBindingsInNamespace = activeBindings.get(key);
if (activeBindingsInNamespace) {
activeBindings.set(key, activeBindingsInNamespace.filter(aBinding => aBinding.handler === binding.handler));
}
binding.element.removeEventListener("keydown", binding.listener);
}
function removeNamespaceBindings(namespace: string) {
const bindings = activeBindings.get(namespace);
if (bindings) {

View File

@@ -1,116 +1,111 @@
import utils from "./utils.js";
import { signal } from "@preact/signals";
import appContext from "../components/app_context.js";
import froca from "./froca.js";
import { t } from "./i18n.js";
import utils, { randomString } from "./utils.js";
export interface ToastOptions {
id?: string;
icon: string;
title?: string;
message: string;
delay?: number;
autohide?: boolean;
closeAfter?: number;
timeout?: number;
progress?: number;
buttons?: {
text: string;
onClick: (api: { dismissToast: () => void }) => void;
}[];
}
function toast(options: ToastOptions) {
const $toast = $(options.title
? `\
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">
<span class="bx bx-${options.icon}"></span>
<span class="toast-title"></span>
</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body"></div>
</div>`
: `
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-icon">
<span class="bx bx-${options.icon}"></span>
</div>
<div class="toast-body"></div>
<div class="toast-header">
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>`
);
export type ToastOptionsWithRequiredId = Omit<ToastOptions, "id"> & Required<Pick<ToastOptions, "id">>;
$toast.toggleClass("no-title", !options.title);
$toast.find(".toast-title").text(options.title ?? "");
$toast.find(".toast-body").html(options.message);
if (options.id) {
$toast.attr("id", `toast-${options.id}`);
}
$("#toast-container").append($toast);
$toast.toast({
delay: options.delay || 3000,
autohide: !!options.autohide
});
$toast.on("hidden.bs.toast", (e) => e.target.remove());
$toast.toast("show");
return $toast;
}
function showPersistent(options: ToastOptions) {
let $toast = $(`#toast-${options.id}`);
if ($toast.length > 0) {
$toast.find(".toast-body").html(options.message);
function showPersistent(options: ToastOptionsWithRequiredId) {
const existingToast = toasts.value.find(toast => toast.id === options.id);
if (existingToast) {
updateToast(options.id, options);
} else {
options.autohide = false;
$toast = toast(options);
}
if (options.closeAfter) {
setTimeout(() => $toast.remove(), options.closeAfter);
addToast(options);
}
}
function closePersistent(id: string) {
$(`#toast-${id}`).remove();
removeToastFromStore(id);
}
function showMessage(message: string, delay = 2000) {
function showMessage(message: string, timeout = 2000, icon = "bx bx-check") {
console.debug(utils.now(), "message:", message);
toast({
icon: "check",
message: message,
autohide: true,
delay
addToast({
icon,
message,
timeout
});
}
export function showError(message: string, delay = 10000) {
export function showError(message: string, timeout = 10000) {
console.log(utils.now(), "error: ", message);
toast({
icon: "alert",
message: message,
autohide: true,
delay
addToast({
icon: "bx bx-error-circle",
message,
timeout
});
}
function showErrorTitleAndMessage(title: string, message: string, delay = 10000) {
function showErrorTitleAndMessage(title: string, message: string, timeout = 10000) {
console.log(utils.now(), "error: ", message);
toast({
title: title,
icon: "alert",
message: message,
autohide: true,
delay
addToast({
title,
icon: "bx bx-error-circle",
message,
timeout
});
}
export async function showErrorForScriptNote(noteId: string, message: string) {
const note = await froca.getNote(noteId, true);
showPersistent({
id: `custom-widget-failure-${noteId}`,
title: t("toast.scripting-error", { title: note?.title ?? "" }),
icon: note?.getIcon() ?? "bx bx-error-circle",
message,
timeout: 15_000,
buttons: [
{
text: t("toast.open-script-note"),
onClick: () => appContext.tabManager.openInNewTab(noteId, null, true)
}
]
});
}
//#region Toast store
export const toasts = signal<ToastOptionsWithRequiredId[]>([]);
function addToast(opts: ToastOptions) {
const id = opts.id ?? randomString();
const toast = { ...opts, id };
toasts.value = [ ...toasts.value, toast ];
return id;
}
function updateToast(id: string, partial: Partial<ToastOptions>) {
toasts.value = toasts.value.map(toast => {
if (toast.id === id) {
return { ...toast, ...partial };
}
return toast;
});
}
export function removeToastFromStore(id: string) {
toasts.value = toasts.value.filter(toast => toast.id !== id);
}
//#endregion
export default {
showMessage,
showError,

View File

@@ -4,6 +4,8 @@ import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import appContext from "../components/app_context.js";
export const NOTE_PATH_TITLE_SEPARATOR = " ";
async function resolveNotePath(notePath: string, hoistedNoteId = "root") {
const runPath = await resolveNotePathToSegments(notePath, hoistedNoteId);
@@ -89,7 +91,7 @@ async function resolveNotePathToSegments(notePath: string, hoistedNoteId = "root
effectivePathSegments.reverse();
if (effectivePathSegments.includes(hoistedNoteId)) {
if (effectivePathSegments.includes(hoistedNoteId) && effectivePathSegments.includes('root')) {
return effectivePathSegments;
} else {
const noteId = getNoteIdFromUrl(notePath);
@@ -254,7 +256,7 @@ async function getNotePathTitle(notePath: string) {
const titlePath = await getNotePathTitleComponents(notePath);
return titlePath.join(" / ");
return titlePath.join(NOTE_PATH_TITLE_SEPARATOR);
}
async function getNoteTitleWithPathAsSuffix(notePath: string) {

View File

@@ -1,6 +1,8 @@
import dayjs from "dayjs";
import type { ViewScope } from "./link.js";
import { dayjs } from "@triliumnext/commons";
import { snapdom } from "@zumer/snapdom";
import FNote from "../entities/fnote";
import type { ViewMode, ViewScope } from "./link.js";
const SVG_MIME = "image/svg+xml";
@@ -112,9 +114,8 @@ function formatDateISO(date: Date) {
export function formatDateTime(date: Date, userSuppliedFormat?: string): string {
if (userSuppliedFormat?.trim()) {
return dayjs(date).format(userSuppliedFormat);
} else {
return `${formatDate(date)} ${formatTime(date)}`;
}
return `${formatDate(date)} ${formatTime(date)}`;
}
function localNowDateTime() {
@@ -150,7 +151,7 @@ export function isMac() {
export const hasTouchBar = (isMac() && isElectron());
function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent | React.PointerEvent<HTMLCanvasElement> | JQueryEventObject) {
export function isCtrlKey(evt: KeyboardEvent | MouseEvent | JQuery.ClickEvent | JQuery.ContextMenuEvent | JQuery.TriggeredEvent | React.PointerEvent<HTMLCanvasElement> | JQueryEventObject) {
return (!isMac() && evt.ctrlKey) || (isMac() && evt.metaKey);
}
@@ -173,7 +174,7 @@ const entityMap: Record<string, string> = {
"=": "&#x3D;"
};
function escapeHtml(str: string) {
export function escapeHtml(str: string) {
return str.replace(/[&<>"'`=\/]/g, (s) => entityMap[s]);
}
@@ -190,9 +191,9 @@ export function formatSize(size: number | null | undefined) {
if (size < 1024) {
return `${size} KiB`;
} else {
return `${Math.round(size / 102.4) / 10} MiB`;
}
return `${Math.round(size / 102.4) / 10} MiB`;
}
function toObject<T, R>(array: T[], fn: (arg0: T) => [key: string, value: R]) {
@@ -207,7 +208,7 @@ function toObject<T, R>(array: T[], fn: (arg0: T) => [key: string, value: R]) {
return obj;
}
function randomString(len: number) {
export function randomString(len: number = 16) {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@@ -236,7 +237,7 @@ export function isIOS() {
return /iPad|iPhone|iPod/.test(navigator.userAgent);
}
function isDesktop() {
export function isDesktop() {
return (
window.glob?.device === "desktop" ||
// window.glob.device is not available in setup
@@ -274,7 +275,7 @@ function getMimeTypeClass(mime: string) {
return `mime-${mime.toLowerCase().replace(/[\W_]+/g, "-")}`;
}
function isHtmlEmpty(html: string) {
export function isHtmlEmpty(html: string) {
if (!html) {
return true;
} else if (typeof html !== "string") {
@@ -296,18 +297,18 @@ function formatHtml(html: string) {
let indent = "\n";
const tab = "\t";
let i = 0;
let pre: { indent: string; tag: string }[] = [];
const pre: { indent: string; tag: string }[] = [];
html = html
.replace(new RegExp("<pre>([\\s\\S]+?)?</pre>"), function (x) {
.replace(new RegExp("<pre>([\\s\\S]+?)?</pre>"), (x) => {
pre.push({ indent: "", tag: x });
return "<--TEMPPRE" + i++ + "/-->";
return `<--TEMPPRE${i++}/-->`;
})
.replace(new RegExp("<[^<>]+>[^<]?", "g"), function (x) {
.replace(new RegExp("<[^<>]+>[^<]?", "g"), (x) => {
let ret;
const tagRegEx = /<\/?([^\s/>]+)/.exec(x);
let tag = tagRegEx ? tagRegEx[1] : "";
let p = new RegExp("<--TEMPPRE(\\d+)/-->").exec(x);
const tag = tagRegEx ? tagRegEx[1] : "";
const p = new RegExp("<--TEMPPRE(\\d+)/-->").exec(x);
if (p) {
const pInd = parseInt(p[1]);
@@ -317,24 +318,22 @@ function formatHtml(html: string) {
if (["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "menuitem", "meta", "param", "source", "track", "wbr"].indexOf(tag) >= 0) {
// self closing tag
ret = indent + x;
} else if (x.indexOf("</") < 0) {
//open tag
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + tab + x.substr(x.length - 1, x.length);
else ret = indent + x;
!p && (indent += tab);
} else {
if (x.indexOf("</") < 0) {
//open tag
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + tab + x.substr(x.length - 1, x.length);
else ret = indent + x;
!p && (indent += tab);
} else {
//close tag
indent = indent.substr(0, indent.length - 1);
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + x.substr(x.length - 1, x.length);
else ret = indent + x;
}
//close tag
indent = indent.substr(0, indent.length - 1);
if (x.charAt(x.length - 1) !== ">") ret = indent + x.substr(0, x.length - 1) + indent + x.substr(x.length - 1, x.length);
else ret = indent + x;
}
return ret;
});
for (i = pre.length; i--;) {
html = html.replace("<--TEMPPRE" + i + "/-->", pre[i].tag.replace("<pre>", "<pre>\n").replace("</pre>", pre[i].indent + "</pre>"));
html = html.replace(`<--TEMPPRE${i}/-->`, pre[i].tag.replace("<pre>", "<pre>\n").replace("</pre>", `${pre[i].indent}</pre>`));
}
return html.charAt(0) === "\n" ? html.substr(1, html.length - 1) : html;
@@ -363,11 +362,11 @@ type dynamicRequireMappings = {
export function dynamicRequire<T extends keyof dynamicRequireMappings>(moduleName: T): Awaited<dynamicRequireMappings[T]>{
if (typeof __non_webpack_require__ !== "undefined") {
return __non_webpack_require__(moduleName);
} else {
// explicitly pass as string and not as expression to suppress webpack warning
// 'Critical dependency: the request of a dependency is an expression'
return require(`${moduleName}`);
}
// explicitly pass as string and not as expression to suppress webpack warning
// 'Critical dependency: the request of a dependency is an expression'
return require(`${moduleName}`);
}
function timeLimit<T>(promise: Promise<T>, limitMs: number, errorMessage?: string) {
@@ -438,7 +437,20 @@ async function openInAppHelp($button: JQuery<HTMLElement>) {
* @param inAppHelpPage the ID of the help note (excluding the `_help_` prefix).
* @returns a promise that resolves once the help has been opened.
*/
export async function openInAppHelpFromUrl(inAppHelpPage: string) {
export function openInAppHelpFromUrl(inAppHelpPage: string) {
return openInReusableSplit(`_help_${inAppHelpPage}`, "contextual-help");
}
/**
* Similar to opening a new note in a split, but re-uses an existing split if there is already one open with the same view mode.
*
* @param targetNoteId the note ID to open in the split.
* @param targetViewMode the view mode of the split to open the note in.
* @param openOpts additional options for opening the note.
*/
export async function openInReusableSplit(targetNoteId: string, targetViewMode: ViewMode, openOpts: {
hoistedNoteId?: string;
} = {}) {
// Dynamic import to avoid import issues in tests.
const appContext = (await import("../components/app_context.js")).default;
const activeContext = appContext.tabManager.getActiveContext();
@@ -446,23 +458,20 @@ export async function openInAppHelpFromUrl(inAppHelpPage: string) {
return;
}
const subContexts = activeContext.getSubContexts();
const targetNote = `_help_${inAppHelpPage}`;
const helpSubcontext = subContexts.find((s) => s.viewScope?.viewMode === "contextual-help");
const viewScope: ViewScope = {
viewMode: "contextual-help",
};
if (!helpSubcontext) {
// The help is not already open, open a new split with it.
const existingSubcontext = subContexts.find((s) => s.viewScope?.viewMode === targetViewMode);
const viewScope: ViewScope = { viewMode: targetViewMode };
if (!existingSubcontext) {
// The target split is not already open, open a new split with it.
const { ntxId } = subContexts[subContexts.length - 1];
appContext.triggerCommand("openNewNoteSplit", {
ntxId,
notePath: targetNote,
hoistedNoteId: "_help",
notePath: targetNoteId,
hoistedNoteId: openOpts.hoistedNoteId,
viewScope
})
});
} else {
// There is already a help window open, make sure it opens on the right note.
helpSubcontext.setNote(targetNote, { viewScope });
// There is already a target split open, make sure it opens on the right note.
existingSubcontext.setNote(targetNoteId, { viewScope });
}
}
@@ -498,8 +507,8 @@ export function escapeRegExp(str: string) {
function areObjectsEqual(...args: unknown[]) {
let i;
let l;
let leftChain: Object[];
let rightChain: Object[];
let leftChain: object[];
let rightChain: object[];
function compare2Objects(x: unknown, y: unknown) {
let p;
@@ -628,16 +637,69 @@ export function createImageSrcUrl(note: FNote) {
return `api/images/${note.noteId}/${encodeURIComponent(note.title)}?timestamp=${Date.now()}`;
}
/**
* Given a string representation of an SVG, triggers a download of the file on the client device.
* Helper function to prepare an element for snapdom rendering.
* Handles string parsing and temporary DOM attachment for style computation.
*
* @param source - Either an SVG/HTML string to be parsed, or an existing SVG/HTML element.
* @returns An object containing the prepared element and a cleanup function.
* The cleanup function removes temporarily attached elements from the DOM,
* or is a no-op if the element was already in the DOM.
*/
function prepareElementForSnapdom(source: string | SVGElement | HTMLElement): {
element: SVGElement | HTMLElement;
cleanup: () => void;
} {
if (typeof source === 'string') {
const parser = new DOMParser();
// Detect if content is SVG or HTML
const isSvg = source.trim().startsWith('<svg');
const mimeType = isSvg ? SVG_MIME : 'text/html';
const doc = parser.parseFromString(source, mimeType);
const element = doc.documentElement;
// Temporarily attach to DOM for proper style computation
element.style.position = 'absolute';
element.style.left = '-9999px';
element.style.top = '-9999px';
document.body.appendChild(element);
return {
element,
cleanup: () => document.body.removeChild(element)
};
}
return {
element: source,
cleanup: () => {} // No-op for existing elements
};
}
/**
* Downloads an SVG using snapdom for proper rendering. Can accept either an SVG string, an SVG element, or an HTML element.
*
* @param nameWithoutExtension the name of the file. The .svg suffix is automatically added to it.
* @param svgContent the content of the SVG file download.
* @param svgSource either an SVG string, an SVGElement, or an HTMLElement to be downloaded.
*/
function downloadSvg(nameWithoutExtension: string, svgContent: string) {
const filename = `${nameWithoutExtension}.svg`;
const dataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
triggerDownload(filename, dataUrl);
async function downloadAsSvg(nameWithoutExtension: string, svgSource: string | SVGElement | HTMLElement) {
const { element, cleanup } = prepareElementForSnapdom(svgSource);
try {
const result = await snapdom(element, {
backgroundColor: "transparent",
scale: 2
});
triggerDownload(`${nameWithoutExtension}.svg`, result.url);
} finally {
cleanup();
}
}
/**
@@ -658,62 +720,26 @@ function triggerDownload(fileName: string, dataUrl: string) {
document.body.removeChild(element);
}
/**
* Given a string representation of an SVG, renders the SVG to PNG and triggers a download of the file on the client device.
*
* Note that the SVG must specify its width and height as attributes in order for it to be rendered.
* Downloads an SVG as PNG using snapdom. Can accept either an SVG string, an SVG element, or an HTML element.
*
* @param nameWithoutExtension the name of the file. The .png suffix is automatically added to it.
* @param svgContent the content of the SVG file download.
* @returns a promise which resolves if the operation was successful, or rejects if it failed (permissions issue or some other issue).
* @param svgSource either an SVG string, an SVGElement, or an HTMLElement to be converted to PNG.
*/
function downloadSvgAsPng(nameWithoutExtension: string, svgContent: string) {
return new Promise<void>((resolve, reject) => {
// First, we need to determine the width and the height from the input SVG.
const result = getSizeFromSvg(svgContent);
if (!result) {
reject();
return;
}
async function downloadAsPng(nameWithoutExtension: string, svgSource: string | SVGElement | HTMLElement) {
const { element, cleanup } = prepareElementForSnapdom(svgSource);
// Convert the image to a blob.
const { width, height } = result;
// Create an image element and load the SVG.
const imageEl = new Image();
imageEl.width = width;
imageEl.height = height;
imageEl.crossOrigin = "anonymous";
imageEl.onload = () => {
try {
// Draw the image with a canvas.
const canvasEl = document.createElement("canvas");
canvasEl.width = imageEl.width;
canvasEl.height = imageEl.height;
document.body.appendChild(canvasEl);
const ctx = canvasEl.getContext("2d");
if (!ctx) {
reject();
}
ctx?.drawImage(imageEl, 0, 0);
const imgUri = canvasEl.toDataURL("image/png")
triggerDownload(`${nameWithoutExtension}.png`, imgUri);
document.body.removeChild(canvasEl);
resolve();
} catch (e) {
console.warn(e);
reject();
}
};
imageEl.onerror = (e) => reject(e);
imageEl.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgContent)}`;
});
try {
const result = await snapdom(element, {
backgroundColor: "transparent",
scale: 2
});
const pngImg = await result.toPng();
await triggerDownload(`${nameWithoutExtension}.png`, pngImg.src);
} finally {
cleanup();
}
}
export function getSizeFromSvg(svgContent: string) {
const svgDocument = (new DOMParser()).parseFromString(svgContent, SVG_MIME);
@@ -735,11 +761,11 @@ export function getSizeFromSvg(svgContent: string) {
return {
width: parseFloat(width),
height: parseFloat(height)
}
} else {
console.warn("SVG export error", svgDocument.documentElement);
return null;
};
}
console.warn("SVG export error", svgDocument.documentElement);
return null;
}
/**
@@ -868,9 +894,9 @@ export function mapToKeyValueArray<K extends string | number | symbol, V>(map: R
export function getErrorMessage(e: unknown) {
if (e && typeof e === "object" && "message" in e && typeof e.message === "string") {
return e.message;
} else {
return "Unknown error";
}
return "Unknown error";
}
/**
@@ -925,8 +951,8 @@ export default {
areObjectsEqual,
copyHtmlToClipboard,
createImageSrcUrl,
downloadSvg,
downloadSvgAsPng,
downloadAsSvg,
downloadAsPng,
compareVersions,
isUpdateAvailable,
isLaunchBarConfig

View File

@@ -24,8 +24,12 @@
--bs-body-font-family: var(--main-font-family) !important;
--bs-body-font-weight: var(--main-font-weight) !important;
--bs-body-color: var(--main-text-color) !important;
--bs-body-bg: var(--main-background-color) !important;
--bs-body-bg: var(--main-background-color) !important;
--ck-mention-list-max-height: 500px;
--tn-modal-max-height: 90vh;
--tree-item-light-theme-max-color-lightness: 50;
--tree-item-dark-theme-min-color-lightness: 75;
}
body#trilium-app.motion-disabled *,
@@ -212,6 +216,16 @@ input::placeholder,
background-color: var(--modal-backdrop-color) !important;
}
body.mobile .modal .modal-dialog {
left: 50%;
transform: translateX(-50%);
width: 100%;
}
body.mobile .modal .modal-content {
border-radius: var(--bs-modal-border-radius) var(--bs-modal-border-radius) 0 0;
}
.component {
contain: size;
}
@@ -243,6 +257,11 @@ button.close:hover {
color: var(--hover-item-text-color);
}
button.custom-title-bar-button {
background: transparent;
border: unset;
}
.modal-content {
background-color: var(--modal-background-color) !important;
}
@@ -404,20 +423,19 @@ body.desktop .tabulator-popup-container,
pointer-events: none;
}
.dropdown-menu .disabled .disabled-tooltip {
.dropdown-menu .disabled .contextual-help {
pointer-events: all;
margin-inline-start: 8px;
font-size: 0.5em;
color: var(--disabled-tooltip-icon-color);
font-size: 0.75rem;
color: var(--contextual-help-icon-color);
cursor: help;
opacity: 0.75;
}
.dropdown-menu .disabled .disabled-tooltip:hover {
.dropdown-menu .disabled .contextual-help:hover {
opacity: 1;
}
.dropdown-menu a:hover:not(.disabled),
.dropdown-item:hover:not(.disabled, .dropdown-container-item),
.tabulator-menu-item:hover,
:root .excalidraw .context-menu .context-menu-item:hover {
@@ -439,7 +457,9 @@ body.desktop .tabulator-popup-container,
}
body.desktop .dropdown-menu:not(#context-menu-container) .dropdown-item,
body #context-menu-container .dropdown-item > span {
body.desktop .dropdown-menu .dropdown-toggle,
body #context-menu-container .dropdown-item > span,
body.mobile .dropdown .dropdown-submenu > span {
display: flex;
align-items: center;
}
@@ -451,7 +471,7 @@ body #context-menu-container .dropdown-item > span {
padding-inline-start: 12px;
}
.dropdown-menu kbd {
.dropdown-menu kbd {
color: var(--muted-text-color);
border: none;
background-color: transparent;
@@ -467,7 +487,7 @@ body #context-menu-container .dropdown-item > span {
border: 1px solid transparent !important;
}
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
/* This is a workaround for Firefox not supporting break-before / break-after: avoid on columns.
* It usually wraps a menu item followed by a separator / header and another menu item. */
.dropdown-no-break {
break-inside: avoid;
@@ -494,12 +514,14 @@ body #context-menu-container .dropdown-item > span {
width: 100%;
}
.dropdown-menu .note-color-picker {
padding: 4px 12px 8px 12px;
}
.cm-editor {
height: 100%;
outline: none !important;
border-radius: 6px;
overflow: hidden;
margin: 4px;
font-size: var(--monospace-font-size);
}
@@ -576,11 +598,6 @@ button.btn-sm {
color: var(--left-pane-text-color);
}
.btn.active:not(.btn-primary) {
background-color: var(--button-disabled-background-color) !important;
opacity: 0.4;
}
.ck.ck-block-toolbar-button {
transform: translateX(7px);
color: var(--muted-text-color);
@@ -610,6 +627,11 @@ pre:not(.hljs) {
padding: var(--padding-size);
}
pre:has(> .cm-editor) {
padding: 0;
margin: 0;
}
pre > button.copy-button {
position: absolute;
top: var(--copy-button-margin-size);
@@ -701,9 +723,8 @@ table.promoted-attributes-in-tooltip th {
z-index: 32767 !important;
}
.tooltip-trigger {
background: transparent;
pointer-events: none;
.pre-wrap-text {
white-space: pre-wrap;
}
.bs-tooltip-bottom .tooltip-arrow::before {
@@ -1001,7 +1022,7 @@ div[data-notify="container"] {
font-family: var(--monospace-font-family);
}
svg.ck-icon .note-icon {
svg.ck-icon.note-icon {
color: var(--main-text-color);
font-size: 20px;
}
@@ -1112,10 +1133,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
display: inline-block;
}
.note-detail-empty {
margin: 50px;
}
.modal-header {
padding: 0.5rem 1rem 0.5rem 1rem !important; /* make modal header padding slightly smaller */
}
@@ -1125,50 +1142,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
margin: 0 12px;
}
#toast-container {
position: absolute;
width: 100%;
top: 20px;
pointer-events: none;
}
.toast {
--bs-toast-bg: var(--accented-background-color);
--bs-toast-color: var(--main-text-color);
z-index: 9999999999 !important;
pointer-events: all;
}
.toast-header {
background-color: var(--more-accented-background-color) !important;
color: var(--main-text-color) !important;
}
.toast-body {
white-space: preserve-breaks;
overflow: hidden;
}
.toast.no-title {
display: flex;
flex-direction: row;
}
.toast.no-title .toast-icon {
display: flex;
align-items: center;
padding: var(--bs-toast-padding-y) var(--bs-toast-padding-x);
}
.toast.no-title .toast-body {
padding-inline-start: 0;
padding-inline-end: 0;
}
.toast.no-title .toast-header {
background-color: unset !important;
}
.ck-mentions .ck-button {
font-size: var(--detail-font-size) !important;
padding: 5px;
@@ -1300,11 +1273,11 @@ body.mobile #context-menu-container.mobile-bottom-menu {
inset-inline-end: 0 !important;
bottom: 0 !important;
top: unset !important;
max-height: 70vh;
max-height: var(--tn-modal-max-height);
overflow: auto !important;
user-select: none;
-webkit-user-select: none;
padding-bottom: env(safe-area-inset-bottom) !important;
padding-bottom: max(env(safe-area-inset-bottom), var(--padding, var(--menu-padding-size))) !important;
}
body.mobile .dropdown-menu {
@@ -1349,12 +1322,21 @@ body.desktop li.dropdown-submenu:hover > ul.dropdown-menu {
top: 0;
inset-inline-start: calc(100% - 2px); /* -2px, otherwise there's a small gap between menu and submenu where the hover can disappear */
margin-top: -10px;
min-width: 15rem;
/* to make submenu scrollable https://github.com/zadam/trilium/issues/3136 */
max-height: 600px;
overflow: auto;
}
body.desktop .dropdown-submenu > .dropdown-menu {
min-width: max-content;
max-width: 300px;
}
.dropdown-submenu.dropstart > .dropdown-menu {
inset-inline-start: auto;
inset-inline-end: calc(100% - 2px);
}
body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
inset-inline-start: calc(-100% + 10px);
}
@@ -1363,6 +1345,20 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
flex-shrink: 0;
}
.right-dropdown-widget .right-dropdown-button {
position: relative;
}
.tooltip-trigger {
background: transparent;
pointer-events: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
#launcher-pane.horizontal .right-dropdown-widget {
width: 53px;
}
@@ -1387,6 +1383,10 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
background-color: var(--scrollbar-background-color);
}
::-webkit-scrollbar-button {
display: none;
}
::-webkit-scrollbar-corner {
background-color: inherit;
}
@@ -1538,12 +1538,15 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
@media (max-width: 991px) {
body.mobile #launcher-pane .dropdown.global-menu > .dropdown-menu.show,
body.mobile #launcher-container .dropdown > .dropdown-menu.show {
--dropdown-bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size));
position: fixed !important;
bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size)) !important;
bottom: var(--dropdown-bottom) !important;
top: unset !important;
inset-inline-start: 0 !important;
inset-inline-end: 0 !important;
transform: unset !important;
overflow-y: auto;
max-height: calc(var(--tn-modal-max-height) - var(--dropdown-bottom));
}
#mobile-sidebar-container {
@@ -1578,6 +1581,14 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
width: 100%;
}
.note-split.empty-note {
--max-content-width: var(--preferred-max-content-width);
}
.note-detail-empty {
margin: 15px;
}
#mobile-sidebar-container.show #mobile-sidebar-wrapper {
transform: translateX(0);
}
@@ -1600,7 +1611,7 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
inset-inline-start: 0;
inset-inline-end: 0;
margin: 0 !important;
max-height: 85vh;
max-height: 85vh;
display: flex;
}
@@ -1640,46 +1651,6 @@ body:not(.mobile) #launcher-pane.horizontal .dropdown-submenu > .dropdown-menu {
body.mobile .modal-dialog.modal-dialog-scrollable {
height: unset;
}
body.mobile .revisions-dialog .modal-dialog {
height: 95vh;
}
body.mobile .revisions-dialog .modal-body {
height: 100% !important;
flex-direction: column;
padding: 0;
}
body.mobile .revisions-dialog .revision-list {
height: unset;
max-height: 20vh;
border-bottom: 1px solid var(--main-border-color) !important;
padding: 0 1em;
}
body.mobile .revisions-dialog .modal-body > .revision-content-wrapper {
flex-grow: 1;
height: 100%;
overflow: auto;
margin: 0;
}
body.mobile .revisions-dialog .modal-body > .revision-content-wrapper > div:first-of-type {
flex-direction: column;
}
body.mobile .revisions-dialog .revision-title {
font-size: 1rem;
}
body.mobile .revisions-dialog .revision-title-buttons {
text-align: center;
}
body.mobile .revisions-dialog .revision-content {
padding: 0.5em;
}
}
/* Mobile, tablet mode */
@@ -1980,16 +1951,20 @@ body.electron.platform-darwin:not(.native-titlebar) .tab-row-container {
padding-inline-start: 1em;
}
.tab-row-widget {
contain: inline-size;
}
#tab-row-left-spacer {
width: env(titlebar-area-x);
-webkit-app-region: drag;
}
body.electron.platform-darwin:not(.native-titlebar) #tab-row-left-spacer {
body.electron.platform-darwin:not(.native-titlebar):not(.full-screen) #tab-row-left-spacer {
width: 80px;
}
.tab-row-widget {
body.electron:not(.platform-darwin) .tab-row-container {
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw));
}
@@ -2040,8 +2015,10 @@ body.zen .shared-info-widget,
body.zen .ribbon-container:not(:has(.classic-toolbar-widget)),
body.zen .ribbon-container:has(.classic-toolbar-widget) .ribbon-top-row,
body.zen .ribbon-container .ribbon-body:not(:has(.classic-toolbar-widget)),
body.zen .note-icon-widget,
body.zen .title-row .icon-action,
body.zen .note-badges > *:not(.read-only-badge),
body.zen .ribbon-button-container,
body.zen .inline-title,
body.zen .promoted-attributes-widget,
body.zen .floating-buttons-children > *:not(.bx-edit-alt),
body.zen .action-button,
@@ -2064,11 +2041,11 @@ body.zen #launcher-pane {
}
body.zen .title-row {
display: block !important;
height: unset !important;
-webkit-app-region: drag;
padding-inline-start: env(titlebar-area-x);
padding-inline-end: calc(100vw - env(titlebar-area-width, 100vw) + 2.5em);
border-bottom: none !important;
}
body.zen .floating-buttons {
@@ -2088,8 +2065,6 @@ body.zen .floating-buttons-children .button-widget {
body.zen .note-title-widget,
body.zen .note-title-widget input {
font-size: 1rem !important;
background: transparent !important;
pointer-events: none;
}
body.zen #detail-container {
@@ -2142,65 +2117,114 @@ body.zen .note-split.type-text .scrolling-container {
body.zen:not(.backdrop-effects-disabled) .note-split.type-text .scrolling-container {
--padding-top: 50px; /* Should be enough to cover the title row */
padding-top: var(--padding-top);
scroll-padding-top: var(--padding-top);
}
/* Fixed formatting toolbar */
body.zen .note-split .ribbon-container {
position: fixed;
left: 0;
bottom: 20px;
width: 100%;
z-index: 1000;
opacity: 0; /* Hidden unless the current note split is focused */
pointer-events: none;
transition: opacity 100ms linear;
}
body.zen .note-split:focus-within .ribbon-container {
opacity: 1; /* Show when the note split is focused */
}
body.zen .note-split .ribbon-container .ribbon-body {
border: 0;
}
body.zen .note-split .ribbon-container .classic-toolbar-widget {
margin: auto;
width: fit-content;
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
border-radius: 8px;
border: 1px solid var(--main-border-color);
padding: 4px;
background: var(--menu-background-color);
}
body.zen .note-split .ribbon-container .classic-toolbar-widget:not(:has(> .ck-toolbar)) {
/* Hide the toolbar wrapper if the toolbar is missing */
display: none;
}
body.zen .note-split:focus-within .ribbon-container .classic-toolbar-widget {
pointer-events: all;
}
@media (max-width: 1300px) {
body.zen .note-split .ribbon-container .classic-toolbar-widget {
/* Set the toolbar to full with */
body.zen:not(.experimental-feature-new-layout) {
.note-split .ribbon-container {
position: fixed;
left: 0;
bottom: 20px;
width: 100%;
z-index: 1000;
opacity: 0; /* Hidden unless the current note split is focused */
pointer-events: none;
transition: opacity 100ms linear;
}
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
body.zen .classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
/* Force toolbar items overflow dropdowns open upwards */
top: auto;
bottom: 100%;
.note-split:focus-within .ribbon-container {
opacity: 1; /* Show when the note split is focused */
}
.note-split .ribbon-container .ribbon-body {
border: 0;
}
.note-split .ribbon-container .classic-toolbar-widget {
margin: auto;
width: fit-content;
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
border-radius: 8px;
border: 1px solid var(--main-border-color);
padding: 4px;
background: var(--menu-background-color);
}
.note-split .ribbon-container .classic-toolbar-widget:not(:has(> .ck-toolbar)) {
/* Hide the toolbar wrapper if the toolbar is missing */
display: none;
}
.note-split:focus-within .ribbon-container .classic-toolbar-widget {
pointer-events: all;
}
@media (max-width: 1300px) {
.note-split .ribbon-container .classic-toolbar-widget {
/* Set the toolbar to full with */
width: 100%;
}
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
/* Force toolbar items overflow dropdowns open upwards */
top: auto;
bottom: 100%;
}
}
}
body.zen.experimental-feature-new-layout {
.status-bar {
display: none;
}
.classic-toolbar-widget {
position: fixed;
left: 50%;
bottom: 20px;
z-index: 1000;
opacity: 0; /* Hidden unless the current note split is focused */
pointer-events: none;
transition: opacity 100ms linear;
width: fit-content;
box-shadow: 0px 10px 20px rgba(0, 0, 0, .1);
border-radius: 8px;
border: 1px solid var(--main-border-color);
padding: 4px;
background: var(--menu-background-color) !important;
transform: translateX(-50%);
backdrop-filter: blur(6px);
}
#root-widget:has(.note-split.type-text:focus-within) .classic-toolbar-widget,
.classic-toolbar-widget:focus-within {
opacity: 1; /* Show when the note split is focused */
pointer-events: all;
}
@media (max-width: 1300px) {
.classic-toolbar-widget {
/* Set the toolbar to full with */
width: 100%;
}
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_se,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sw,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_smw,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_sme,
.classic-toolbar-widget .ck.ck-dropdown .ck-dropdown__panel.ck-dropdown__panel_s {
/* Force toolbar items overflow dropdowns open upwards */
top: auto;
bottom: 100%;
}
}
}
@@ -2414,7 +2438,7 @@ footer.webview-footer button {
margin-bottom: 0;
}
.admonition::before {
.admonition::before {
color: var(--accent-color);
font-family: boxicons !important;
position: absolute;
@@ -2434,6 +2458,15 @@ footer.webview-footer button {
.admonition.caution::before { content: "\eac7"; }
.admonition.warning::before { content: "\eac5"; }
.ck-content ul.todo-list li span.todo-list__label__description {
transition: opacity 200ms ease;
}
.ck-content ul.todo-list li:has(> span.todo-list__label input[type="checkbox"]:checked) > span.todo-list__label span.todo-list__label__description {
text-decoration: line-through;
opacity: 0.6;
}
.chat-options-container {
display: flex;
margin: 5px 0;
@@ -2498,6 +2531,11 @@ footer.webview-footer button {
inset-inline-start: 10px;
}
.content-floating-buttons.top-right {
top: 10px;
inset-inline-end: 10px;
}
.content-floating-buttons.bottom-left {
bottom: 10px;
inset-inline-start: 10px;
@@ -2559,9 +2597,45 @@ iframe.print-iframe {
flex-direction: column;
}
.scrolling-container > .note-detail.full-height,
.note-detail.full-height,
.scrolling-container > .note-list-widget.full-height {
position: relative;
flex-grow: 1;
width: 100%;
}
overflow: hidden;
}
/* Calendar collection */
.calendar-view a.fc-timegrid-event,
.calendar-view a.fc-daygrid-event {
/* Workaround: set font weight only if the theme-next is not active */
font-weight: var(--root-background, 800);
}
@media (max-width: 991px) {
body.mobile {
.split-note-container-widget {
flex-direction: column !important;
.note-split {
width: 100%;
}
.note-split.visible + .note-split.visible {
border-top: 1px solid var(--main-border-color);
}
}
#root-widget.virtual-keyboard-opened .note-split:not(:focus-within) {
max-height: 80px;
opacity: 0.4;
}
}
}
body.desktop .title-row {
height: 50px;
min-height: 50px;
align-items: center;
}

View File

@@ -19,7 +19,7 @@
--dropdown-border-color: #555;
--dropdown-shadow-opacity: 0.4;
--dropdown-item-icon-destructive-color: #de6e5b;
--disabled-tooltip-icon-color: #7fd2ef;
--contextual-help-icon-color: #7fd2ef;
--accented-background-color: #555;
--more-accented-background-color: #777;
@@ -76,6 +76,9 @@
--mermaid-theme: dark;
--native-titlebar-background: #00000000;
--calendar-coll-event-background-saturation: 30%;
--calendar-coll-event-background-lightness: 30%;
}
body ::-webkit-calendar-picker-indicator {
@@ -109,3 +112,10 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.6) !important;
}
.use-note-color {
--custom-color: var(--dark-theme-custom-color);
}
span.fancytree-active {
color: var(--dark-theme-custom-color, var(--active-item-text-color));
}

View File

@@ -23,7 +23,7 @@ html {
--dropdown-border-color: #ccc;
--dropdown-shadow-opacity: 0.2;
--dropdown-item-icon-destructive-color: #ec5138;
--disabled-tooltip-icon-color: #004382;
--contextual-help-icon-color: #004382;
--accented-background-color: #f5f5f5;
--more-accented-background-color: #ddd;
@@ -80,15 +80,26 @@ html {
--mermaid-theme: default;
--native-titlebar-background: #ffffff00;
--calendar-coll-event-background-lightness: 95%;
--calendar-coll-event-background-saturation: 80%;
}
#left-pane .fancytree-node.tinted {
--custom-color: var(--light-theme-custom-color);
}
:root .reference-link,
:root .reference-link:hover,
.ck-content a.reference-link > span,
.board-note {
:root .reference-link.use-note-color,
:root .reference-link.use-note-color:hover,
.ck-content a.reference-link.use-note-color > span,
.board-note.use-note-color {
color: var(--light-theme-custom-color, inherit);
}
}
.use-note-color {
--custom-color: var(--light-theme-custom-color);
}
span.fancytree-active {
color: var(--light-theme-custom-color, var(--active-item-text-color));
}

View File

@@ -6,7 +6,7 @@
*/
:root {
/*
/*
* ⚠️ NOTICE: This theme is currently in the beta stage of development.
* The names and purposes of these CSS variables are subject to frequent changes.
*/
@@ -21,8 +21,8 @@
--subtle-border-color: #313131;
--dropdown-border-color: #404040;
--dropdown-shadow-opacity: 0.6;
--dropdown-item-icon-destructive-color: #de6e5b;
--disabled-tooltip-icon-color: #7fd2ef;
--dropdown-item-icon-destructive-color: #d58477;
--contextual-help-icon-color: #7fd2ef;
--accented-background-color: #555;
@@ -41,6 +41,9 @@
--cmd-button-keyboard-shortcut-color: white;
--cmd-button-disabled-opacity: 0.5;
--button-group-active-button-background: #ffffff4e;
--button-group-active-button-text-color: white;
--icon-button-color: currentColor;
--icon-button-hover-background: var(--hover-item-background-color);
--icon-button-hover-color: var(--hover-item-text-color);
@@ -71,11 +74,13 @@
--select-arrow-svg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='transparent' stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");
--select-group-heading-text-color: gray;
--link-hover-background: #ffffff26;
--link-hover-color: white;
--link-color: #95c3d9;
--link-hover-background: #75c2e324;
--link-hover-color: var(--link-color);
--link-selection-outline-color: #75c2e385;
--hover-item-text-color: #efefef;
--hover-item-background-color: #ffffff24;
--hover-item-background-color: #ffffff16;
--hover-item-border-color: transparent;
--active-item-text-color: var(--left-pane-text-color);
@@ -98,6 +103,7 @@
--menu-item-delimiter-color: #ffffff1c;
--menu-item-group-header-color: #ffffff91;
--menu-section-background-color: #fefefe08;
--menu-submenu-mobile-background-color: rgba(0, 0, 0, 0.15);
--modal-backdrop-color: #000;
--modal-shadow-color: rgba(0, 0, 0, .5);
@@ -166,6 +172,9 @@
--protected-session-active-icon-color: #8edd8e;
--sync-status-error-pulse-color: #f47871;
--classic-toolbar-vert-layout-background-color: #ffffff0d;
--classic-toolbar-horiz-layout-background-color: var(--main-background-color);
--center-pane-vert-layout-background-color-bgfx: #0c0c0c69;
--center-pane-horiz-layout-background-color-bgfx: #1e1e1ec7;
@@ -178,7 +187,7 @@
--tab-close-button-hover-background: #a45353;
--tab-close-button-hover-color: white;
--active-tab-background-color: #ffffff1c;
--active-tab-hover-background-color: var(--active-tab-background-color);
--active-tab-icon-color: #a9a9a9;
@@ -195,9 +204,19 @@
--badge-background-color: #ffffff1a;
--badge-text-color: var(--muted-text-color);
--badge-temporaraily-editable-background-color: #297331;
--badge-read-only-background-color: #af4340;
--badge-share-background-color: #4d4d4d;
--badge-clipped-note-background-color: #295773;
--badge-execute-background-color: #604180;
--note-icon-background-color: #444444;
--note-icon-color: #d4d4d4;
--note-icon-hover-background-color: #555555;
--promoted-attribute-card-background-color: #ffffff21;
--promoted-attribute-card-shadow: none;
--floating-button-shadow-color: #00000080;
--floating-button-background-color: #494949d2;
--floating-button-color: var(--button-text-color);
@@ -216,14 +235,17 @@
--right-pane-item-hover-background: #ffffff26;
--right-pane-item-hover-color: white;
--bottom-panel-background-color: #11111180;
--bottom-panel-title-bar-background-color: #3F3F3F80;
--status-bar-border-color: var(--main-border-color);
--scrollbar-thumb-color: #fdfdfd5c;
--scrollbar-thumb-hover-color: #ffffff7d;
--scrollbar-background-color: transparent;
--scrollbar-border-color: unset; /* Deprecated */
--selection-background-color: #3399FF70;
--link-color: lightskyblue;
--mermaid-theme: dark;
@@ -266,6 +288,14 @@
--ck-editor-toolbar-button-on-color: white;
--ck-editor-toolbar-button-on-shadow: 1px 1px 2px rgba(0, 0, 0, .75);
--ck-editor-toolbar-dropdown-button-open-background: #ffffff14;
--calendar-coll-event-background-saturation: 25%;
--calendar-coll-event-background-lightness: 20%;
--calendar-coll-event-background-color: #3c3c3c;
--calendar-coll-event-text-color: white;
--calendar-coll-event-hover-filter: brightness(1.25);
--callendar-coll-event-archived-sripe-color: #00000026;
--calendar-coll-today-background-color: #ffffff08;
}
/*
@@ -281,10 +311,10 @@
--custom-bg-color: hsl(var(--custom-color-hue), 20%, 33%, 0.4);
}
:root .reference-link,
:root .reference-link:hover,
.ck-content a.reference-link > span,
.board-note {
:root .reference-link.use-note-color,
:root .reference-link.use-note-color:hover,
.ck-content a.reference-link.use-note-color > span,
.board-note.use-note-color {
color: var(--dark-theme-custom-color, inherit);
}
@@ -300,8 +330,24 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
border-color: var(--muted-text-color) !important;
}
.tinted-quick-edit-dialog {
.quick-edit-dialog-wrapper.with-hue {
--modal-background-color: hsl(var(--custom-color-hue), 8.8%, 11.2%);
--modal-border-color: hsl(var(--custom-color-hue), 9.4%, 25.1%);
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 13.2%, 20.8%);
}
.use-note-color {
--custom-color: var(--dark-theme-custom-color);
}
.note-split.with-hue,
.quick-edit-dialog-wrapper.with-hue {
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%);
--note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%);
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%);
}
.note-split.with-hue *::selection,
.quick-edit-dialog-wrapper.with-hue *::selection {
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
}

View File

@@ -6,7 +6,7 @@
*/
:root {
/*
/*
* ⚠️ NOTICE: This theme is currently in the beta stage of development.
* The names and purposes of these CSS variables are subject to frequent changes.
*/
@@ -21,8 +21,8 @@
--subtle-border-color: rgba(0, 0, 0, 0.1);
--dropdown-border-color: #ccc;
--dropdown-shadow-opacity: 0.2;
--dropdown-item-icon-destructive-color: #ec5138;
--disabled-tooltip-icon-color: #004382;
--dropdown-item-icon-destructive-color: #de4027;
--contextual-help-icon-color: #004382;
--accented-background-color: #f5f5f5;
@@ -41,6 +41,9 @@
--cmd-button-keyboard-shortcut-color: black;
--cmd-button-disabled-opacity: 0.5;
--button-group-active-button-background: #00000026;
--button-group-active-button-text-color: black;
--icon-button-color: currentColor;
--icon-button-hover-background: var(--hover-item-background-color);
--icon-button-hover-color: var(--hover-item-text-color);
@@ -71,8 +74,10 @@
--select-arrow-svg: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='transparent' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>");
--select-group-heading-text-color: gray;
--link-hover-background: #00000012;
--link-hover-color: black;
--link-color: #0076af;
--link-hover-background: #3c7fa017;
--link-hover-color: var(--link-color);
--link-selection-outline-color: #95c3d9db;
--hover-item-text-color: black;
--hover-item-background-color: #0000001a;
@@ -135,7 +140,7 @@
/* Deprecated: now local variables in #launcher, with the values dependent on the current layout. */
--launcher-pane-background-color: unset;
--launcher-pane-text-color: unset;
--launcher-pane-vert-background-color: #e8e8e8;
--launcher-pane-vert-text-color: #000000bd;
--launcher-pane-vert-button-hover-color: black;
@@ -159,6 +164,9 @@
--protected-session-active-icon-color: #16b516;
--sync-status-error-pulse-color: #ff5528;
--classic-toolbar-vert-layout-background-color: #ffffffa1;
--classic-toolbar-horiz-layout-background-color: var(--main-background-color);
--center-pane-vert-layout-background-color-bgfx: #ffffff75;
--center-pane-horiz-layout-background-color-bgfx: #ffffffd6;
@@ -171,7 +179,7 @@
--tab-close-button-hover-background: #c95a5a;
--tab-close-button-hover-color: white;
--active-tab-background-color: white;
--active-tab-hover-background-color: var(--active-tab-background-color);
--active-tab-icon-color: gray;
@@ -188,6 +196,16 @@
--badge-background-color: #00000011;
--badge-text-color: var(--muted-text-color);
--badge-temporaraily-editable-background-color: #35a64c;
--badge-read-only-background-color: #c8302c;
--badge-share-background-color: #6b6b6b;
--badge-clipped-note-background-color: #2284c0;
--badge-execute-background-color: #7b47af;
--note-icon-background-color: #4f4f4f;
--note-icon-color: white;
--note-icon-hover-background-color: #737373;
--promoted-attribute-card-background-color: #00000014;
--promoted-attribute-card-shadow: none;
@@ -215,6 +233,11 @@
--right-pane-item-hover-background: #00000013;
--right-pane-item-hover-color: inherit;
--bottom-panel-background-color: #ffffff8c;
--bottom-panel-title-bar-background-color: #94949414;
--status-bar-border-color: #0000003a;
--scrollbar-thumb-color: #0000005c;
--scrollbar-thumb-hover-color: #00000066;
--scrollbar-background-color: transparent;
@@ -222,8 +245,6 @@
--selection-background-color: #3399FF70;
--link-color: blue;
--mermaid-theme: default;
--code-block-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1), 0px 0px 2px rgba(0, 0, 0, 0.2);
@@ -265,6 +286,14 @@
--ck-editor-toolbar-button-on-color: black;
--ck-editor-toolbar-button-on-shadow: none;
--ck-editor-toolbar-dropdown-button-open-background: #0000000f;
--calendar-coll-event-background-lightness: 95%;
--calendar-coll-event-background-saturation: 80%;
--calendar-coll-event-background-color: #eaeaea;
--calendar-coll-event-text-color: black;
--calendar-coll-event-hover-filter: brightness(.95) saturate(1.25);
--callendar-coll-event-archived-sripe-color: #0000000a;
--calendar-coll-today-background-color: #00000006;
}
#left-pane .fancytree-node.tinted {
@@ -276,8 +305,20 @@
--custom-bg-color: hsl(var(--custom-color-hue), 37%, 89%, 1);
}
.tinted-quick-edit-dialog {
.quick-edit-dialog-wrapper.with-hue {
--modal-background-color: hsl(var(--custom-color-hue), 56%, 96%);
--modal-border-color: hsl(var(--custom-color-hue), 33%, 41%);
--promoted-attribute-card-background-color: hsl(var(--custom-color-hue), 40%, 88%);
}
.note-split.with-hue,
.quick-edit-dialog-wrapper.with-hue {
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%);
--note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%);
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%);
}
.note-split.with-hue *::selection,
.quick-edit-dialog-wrapper.with-hue *::selection {
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
}

View File

@@ -50,7 +50,7 @@
--tab-bar-height: 50px;
--tab-height: 36px;
--tab-first-item-horiz-offset: 1px;
--tab-first-item-horiz-offset: 0;
--new-tab-button-size: 24px;
--center-pane-border-radius: 10px;
@@ -62,6 +62,7 @@
--menu-padding-size: 8px;
--menu-item-icon-vert-offset: -2px;
--menu-submenu-mobile-background-color: rgba(255, 255, 255, 0.15);
--more-accented-background-color: var(--card-background-hover-color);
@@ -88,17 +89,25 @@
* the color is adjusted based on the current color scheme (light or dark). The lightness
* component of the color represented in the CIELAB color space, will be
* constrained to a certain percentage defined below.
*
*
* Note: the tree background may vary when background effects are enabled, so it is recommended
* to maintain a higher contrast margin than on the usual note tree solid background. */
/* The maximum perceptual lightness for the custom color in the light theme (%): */
--tree-item-light-theme-max-color-lightness: 60;
/* The minimum perceptual lightness for the custom color in the dark theme (%): */
--tree-item-dark-theme-min-color-lightness: 65;
}
body {
user-select: none;
}
.selectable-text {
user-select: text;
}
body.backdrop-effects-disabled {
/* Backdrop effects are disabled, replace the menu background color with the
* no-backdrop fallback color */
@@ -119,15 +128,20 @@ body.backdrop-effects-disabled {
font-size: 0.9rem !important;
}
body.mobile .dropdown-menu {
backdrop-filter: var(--dropdown-backdrop-filter);
border-radius: var(--dropdown-border-radius);
position: relative;
/* Use this class for non-legacy menus */
.dropdown-menu.tn-dropdown-menu {
--menu-item-icon-vert-offset: 0;
white-space-collapse: discard;
}
body.mobile .dropdown-menu .dropdown-menu {
backdrop-filter: unset !important;
border-radius: unset !important;
.dropdown-menu.tn-dropdown-menu .bx {
margin-inline-end: 6px;
}
.dropdown-menu.tn-dropdown-menu-scrollable {
/* Note: scrollable dropdowns does not support submenus */
max-height: 90vh;
overflow-y: auto;
}
body.desktop .dropdown-menu::before,
@@ -149,16 +163,12 @@ body.desktop .dropdown-menu.tn-dropdown-list {
backdrop-filter: var(--dropdown-backdrop-filter);
}
body.desktop .dropdown-menu.tn-dropdown-list::before {
display: none;
}
body.desktop .dropdown-submenu .dropdown-menu::before {
content: unset;
}
body.mobile .dropdown-submenu .dropdown-menu {
background: transparent !important;
body.desktop .dropdown-menu.tn-dropdown-list::before {
display: none;
}
body.desktop .dropdown-submenu .dropdown-menu {
@@ -167,22 +177,39 @@ body.desktop .dropdown-submenu .dropdown-menu {
}
.dropdown-item,
body.mobile .dropdown-submenu .dropdown-toggle,
.excalidraw .context-menu .context-menu-item {
--menu-item-start-padding: 8px;
--menu-item-end-padding: 22px;
--menu-item-vertical-padding: 2px;
padding-top: var(--menu-item-vertical-padding) !important;
padding-bottom: var(--menu-item-vertical-padding) !important;
padding-inline-start: var(--menu-item-start-padding) !important;
padding-inline-end: var(--menu-item-end-padding) !important;
/* Note: the right padding should also accommodate the submenu arrow. */
border-radius: 6px;
cursor: default !important;
}
.dropdown-item:not(.dropdown-submenu),
body.desktop .dropdown-item.dropdown-submenu .dropdown-toggle,
.excalidraw .context-menu .context-menu-item {
padding-top: var(--menu-item-vertical-padding) !important;
padding-bottom: var(--menu-item-vertical-padding) !important;
padding-inline-start: var(--menu-item-start-padding) !important;
padding-inline-end: var(--menu-item-end-padding) !important;
}
.dropdown-item.dropdown-submenu {
padding: 0 !important;
.dropdown-toggle {
flex-grow: 1;
}
}
body.desktop .dropdown-menu:has(> .dropdown-submenu.dropstart) > .dropdown-item:not(.dropdown-submenu),
body.desktop .dropdown-menu:has(> .dropdown-submenu.dropstart) > .dropdown-item.dropdown-submenu .dropdown-toggle {
padding-inline-end: var(--menu-item-start-padding) !important;
padding-inline-start: var(--menu-item-end-padding) !important;
}
:root .dropdown-item:focus-visible {
outline: 2px solid var(--input-focus-outline-color) !important;
background-color: transparent;
@@ -201,16 +228,16 @@ body.mobile .dropdown-item:not(:last-of-type) {
margin-bottom: 0.5em;
}
body.mobile .dropdown-submenu:hover {
background: transparent !important;
}
html body .dropdown-item.disabled,
html body .dropdown-item[disabled] {
color: var(--menu-text-color) !important;
opacity: var(--menu-item-disabled-opacity);
}
.dropdown-item:not(.disabled) .destructive-action-icon,
.dropdown-item:not(.disabled) .bx-trash {
--menu-item-icon-color: var(--dropdown-item-icon-destructive-color);
}
/* Badges */
:root .badge {
--bs-badge-color: var(--badge-text-color);
@@ -260,7 +287,8 @@ html body .dropdown-item[disabled] {
}
/* Menu item arrow */
.dropdown-menu .dropdown-toggle::after {
body.mobile .dropdown-submenu .dropdown-toggle::after,
body.desktop .dropdown-submenu:not(.dropstart) .dropdown-toggle::after {
content: "\ed3b" !important;
position: absolute;
display: flex !important;
@@ -276,6 +304,26 @@ html body .dropdown-item[disabled] {
color: var(--menu-item-arrow-color) !important;
}
body.mobile .dropdown-submenu.dropstart .dropdown-toggle::before {
content: unset;
}
body.desktop .dropdown-submenu.dropstart .dropdown-toggle::before {
content: "\ea4d" !important;
position: absolute;
display: flex !important;
align-items: center;
justify-content: center;
top: 0;
inset-inline-start: 0;
margin: unset !important;
border: unset !important;
padding: 0 4px;
font-family: boxicons;
font-size: 1.2em;
color: var(--menu-item-arrow-color) !important;
}
body[dir=rtl] .dropdown-menu:not([data-popper-placement="bottom-start"]) .dropdown-toggle::after {
content: "\ea4d" !important;
}
@@ -321,17 +369,126 @@ body.desktop .dropdown-menu.static .dropdown-item.active {
--active-item-text-color: var(--menu-text-color);
}
/* #region Mobile tweaks for dropdown menus */
body.mobile #context-menu-cover {
transition: background-color 150ms ease-in;
&.show {
background: rgba(0, 0, 0, 0.7);
}
&.global-menu-cover {
bottom: calc(var(--mobile-bottom-offset) + var(--launcher-pane-size));
@media (min-width: 992px) {
bottom: 0;
}
}
}
body.mobile .dropdown-menu.mobile-bottom-menu,
body.mobile .dropdown.global-menu .dropdown-menu {
border-radius: var(--dropdown-border-radius) var(--dropdown-border-radius) 0 0;
}
body.mobile .dropdown-menu {
--dropdown-menu-padding-vertical: 0.7em;
--dropdown-menu-padding-horizontal: 1em;
--hover-item-background-color: var(--card-background-color);
font-size: 1em !important;
backdrop-filter: var(--dropdown-backdrop-filter);
position: relative;
.dropdown-toggle::after {
top: 0.5em;
right: var(--dropdown-menu-padding-horizontal);
transform: translateX(50%) rotate(90deg);
}
.dropdown-item.submenu-open .dropdown-toggle::after {
transform: rotate(270deg);
}
.dropdown-item,
.dropdown-custom-item {
margin-bottom: 0;
padding: var(--dropdown-menu-padding-vertical) var(--dropdown-menu-padding-horizontal) !important;
background: var(--card-background-color);
border-bottom: 1px solid var(--menu-item-delimiter-color) !important;
border-radius: 0;
}
.dropdown-item:first-of-type,
.dropdown-divider + .dropdown-item,
.dropdown-custom-item:first-of-type,
.dropdown-divider + .dropdown-custom-item {
border-top-left-radius: 6px;
border-top-right-radius: 6px;
}
.dropdown-item:last-of-type,
.dropdown-item:has(+ .dropdown-divider),
.dropdown-custom-item:last-of-type,
.dropdown-custom-item:has(+ .dropdown-divider) {
border-bottom-left-radius: 6px;
border-bottom-right-radius: 6px;
border-bottom: 0 !important;
}
.dropdown-divider {
visibility: hidden;
}
.dropdown-submenu {
padding: 0 !important;
backdrop-filter: unset !important;
.dropdown-toggle {
padding: var(--dropdown-menu-padding-vertical) var(--dropdown-menu-padding-horizontal);
}
.dropdown-menu {
--menu-background-color: --menu-submenu-mobile-background-color;
--bs-dropdown-divider-margin-y: 0.25rem;
border-radius: 0;
max-height: 0;
transition: max-height 100ms ease-in;
display: block !important;
&.show {
max-height: 1000px;
padding: 0.5rem 0.75rem !important;
}
}
&.submenu-open {
.dropdown-toggle {
padding-bottom: var(--dropdown-menu-padding-vertical);
}
}
}
.dropdown-custom-item:has(.note-color-picker) {
overflow-x: auto;
}
.note-color-picker {
padding: 0;
width: fit-content;
.color-cell {
--color-picker-cell-size: 26px;
flex-shrink: 0;
}
}
}
/* #endregion */
body.desktop .dropdown-menu .dropdown-toggle::after {
height: 100%;
}
body.mobile .dropdown-menu .dropdown-toggle::after {
transform: rotate(90deg);
}
body.mobile .dropdown-menu .dropdown-item.submenu-open .dropdown-toggle::after {
transform: rotate(270deg);
}
/* Dropdown item button (used in zoom buttons in global menu) */
@@ -347,6 +504,12 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
outline: 2px solid var(--input-focus-outline-color) !important;
}
:root .dropdown-menu .note-color-picker {
padding: 4px 10px;
--note-color-picker-clear-color-cell-background: var(--main-text-color);
--note-color-picker-clear-color-cell-selection-outline-color: var(--main-text-color);
}
/*
* TOASTS
*/
@@ -581,9 +744,14 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
padding: 0;
}
.note-list-wrapper .note-book-card .note-book-content.type-code {
height: 100%;
}
.note-list-wrapper .note-book-card .note-book-content.type-code pre {
height: 100%;
padding: 1em;
margin-bottom: 0;
}
.note-list-wrapper .note-book-card .bx {
@@ -594,11 +762,6 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
filter: contrast(105%);
}
.note-list.grid-view .note-book-card img {
object-fit: cover !important;
width: 100%;
}
.note-list.grid-view .ck-content {
line-height: 1.3;
}
@@ -634,4 +797,4 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
.note-detail-empty .aa-suggestions div.aa-cursor {
background: var(--hover-item-background-color);
color: var(--hover-item-text-color);
}
}

View File

@@ -25,6 +25,7 @@
.modal .modal-header .btn-close,
.modal .modal-header .help-button,
.modal .modal-header .custom-title-bar-button,
#toast-container .toast .toast-header .btn-close {
display: flex;
justify-content: center;
@@ -55,15 +56,17 @@
font-family: boxicons;
}
.modal .modal-header .help-button {
.modal .modal-header .help-button,
.modal .modal-header .custom-title-bar-button {
margin-inline-end: 0;
font-size: calc(var(--modal-control-button-size) * .75);
font-size: calc(var(--modal-control-button-size) * .70);
font-family: unset;
font-weight: bold;
}
.modal .modal-header .btn-close:hover,
.modal .modal-header .help-button:hover,
.modal .modal-header .custom-title-bar-button:hover,
#toast-container .toast .toast-header .btn-close:hover {
background: var(--modal-control-button-hover-background);
color: var(--modal-control-button-hover-color);
@@ -71,6 +74,7 @@
.modal .modal-header .btn-close:active,
.modal .modal-header .help-button:active,
.modal .modal-header .custom-title-bar-button:active,
#toast-container .toast .toast-header .btn-close:active {
transform: scale(.85);
}

View File

@@ -17,6 +17,10 @@ button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .c
padding: 4px 16px;
background: var(--cmd-button-background-color);
color: var(--cmd-button-text-color);
&.dropdown-toggle-split {
min-width: unset;
}
}
button.btn.btn-primary:hover,
@@ -52,7 +56,8 @@ button.btn.btn-primary:focus-visible,
button.btn.btn-secondary:focus-visible,
button.btn.btn-sm:not(.select-button):focus-visible,
button.btn.btn-success:focus-visible,
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):focus-visible {
button.ck.ck-button:is(.ck-button-action, .ck-button-save, .ck-button-cancel, .ck-button-replaceall, .ck-button-replace).ck-button_with-text:not(.ck-disabled):focus-visible,
.tn-focusable-button:focus-visible {
outline: 2px solid var(--input-focus-outline-color);
}
@@ -142,7 +147,15 @@ button.btn.btn-success kbd {
outline: 2px solid var(--input-focus-outline-color);
}
/*
/* Button groups */
/* Active button */
:root .btn-group button.btn.active {
background-color: var(--button-group-active-button-background);
color: var(--button-group-active-button-text-color);
}
/*
* Input boxes
*/
@@ -340,6 +353,11 @@ label.input-group.tn-number-unit-pair input {
padding-inline-end: 0;
}
:root .input-group > pre[aria-hidden="true"] {
margin: 0;
padding: 0;
}
/* Combo box-like dropdown buttons */
.select-button.dropdown-toggle::after {
@@ -387,7 +405,8 @@ button.select-button.dropdown-toggle.btn:active {
select:focus,
select.form-select:focus,
select.form-control:focus,
.select-button.dropdown-toggle.btn:focus {
.select-button.dropdown-toggle.btn:focus,
.select-button.focus-outline:focus {
box-shadow: unset;
outline: 3px solid var(--input-focus-outline-color);
outline-offset: 0;
@@ -410,7 +429,7 @@ optgroup {
line-height: 40px;
}
/*
/*
* File input
*
* <label class="tn-file-input tn-input-field">
@@ -623,8 +642,8 @@ body a.tn-link:visited,
border-radius: 4px;
background: var(--background);
color: var(--link-color);
font-weight: normal;
text-decoration: underline;
font-weight: 500;
text-decoration: none;
transition:
background-color 200ms ease-out,
@@ -639,10 +658,12 @@ body a.tn-link:focus-visible,
}
body a.tn-link:hover,
.use-tn-links a:hover {
.use-tn-links a:hover,
.use-tn-links a.ck-widget_selected {
box-shadow: 0 0 0 4px var(--link-hover-background);
--background: var(--link-hover-background);
color: var(--link-hover-color);
text-decoration: underline;
transition:
background-color 100ms ease-in,
@@ -772,4 +793,4 @@ input[type="range"] {
scrollbar-color: unset;
scrollbar-width: unset;
}
}
}

Some files were not shown because too many files have changed in this diff Show More