Compare commits

...

248 Commits

Author SHA1 Message Date
renovate[bot]
8f73d3228d
chore(deps): update dependency electron to v39
Some checks are pending
Checks / main (push) Waiting to run
2025-12-03 17:28:43 +00:00
Elian Doran
67d2175ce9
Translations update from Hosted Weblate (#7924)
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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)
Some checks failed
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Has been cancelled
Deploy website / Build & deploy website (push) Has been cancelled
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
Some checks failed
Checks / main (push) Has been cancelled
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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
Some checks failed
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy website / Build & deploy website (push) Has been cancelled
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)
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy website / Build & deploy website (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy website / Build & deploy website (push) Waiting to run
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Documentation / Build and Deploy Documentation (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
Deploy website / Build & deploy website (push) Waiting to run
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
SiriusXT
53a8f6b4c0 Merge branch 'main' into fix/split_pane
Some checks failed
Checks / main (push) Has been cancelled
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
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run
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
166 changed files with 3782 additions and 3342 deletions

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

@ -45,6 +45,19 @@ 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@v6

View File

@ -79,7 +79,7 @@ jobs:
if: failure()
uses: actions/upload-artifact@v5
with:
name: e2e report
name: e2e report ${{ matrix.arch }}
path: apps/server-e2e/test-output
- name: Kill the server

View File

@ -16,7 +16,7 @@
"fs-extra": "11.3.2",
"react": "19.2.0",
"react-dom": "19.2.0",
"typedoc": "0.28.14",
"typedoc": "0.28.15",
"typedoc-plugin-missing-exports": "4.1.2"
}
}

View File

@ -487,7 +487,7 @@ type EventMappings = {
relationMapResetPanZoom: { ntxId: string | null | undefined };
relationMapResetZoomIn: { ntxId: string | null | undefined };
relationMapResetZoomOut: { ntxId: string | null | undefined };
activeNoteChanged: {};
activeNoteChanged: {ntxId: string | null | undefined};
showAddLinkDialog: AddLinkOpts;
showIncludeDialog: IncludeNoteOpts;
openBulkActionsDialog: {

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 {

View File

@ -29,9 +29,11 @@ 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";
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(<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 />)
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 />)
)
)
)
)

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

@ -8,6 +8,7 @@ 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",
@ -62,13 +63,13 @@ export default function NoteColorPicker(props: NoteColorPickerProps) {
} 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}
@ -81,8 +82,8 @@ export default function NoteColorPicker(props: NoteColorPickerProps) {
<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")}
@ -128,7 +129,6 @@ function CustomColorCell(props: ColorCellProps) {
const colorInput = useRef<HTMLInputElement>(null);
const colorInputDebouncer = useRef<Debouncer<string | null> | null>(null);
const callbackRef = useRef(props.onSelect);
const isSafari = useRef(/^((?!chrome|android).)*safari/i.test(navigator.userAgent));
useEffect(() => {
colorInputDebouncer.current = new Debouncer(250, (color) => {
@ -160,13 +160,13 @@ function CustomColorCell(props: ColorCellProps) {
}, [pickedColor]);
return <div style={`--foreground: ${getForegroundColor(props.color)};`}
onClick={(e) => {
// The color picker dropdown will close on Safari if the parent context menu is
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.
isSafari.current && e.stopPropagation();
}}>
e.stopPropagation();
} : undefined}>
<ColorCell {...props}
color={pickedColor}
color={pickedColor}
className={clsx("custom-color-cell", {
"custom-color-cell-empty": (pickedColor === null)
})}
@ -201,4 +201,4 @@ function tryParseColor(colorStr: string): ColorInstance | null {
}
return null;
}
}

View File

@ -2,26 +2,32 @@ import { t } from "../services/i18n.js";
import contextMenu, { type ContextMenuEvent, type MenuItem } from "./context_menu.js";
import appContext, { type CommandNames } from "../components/app_context.js";
import type { ViewScope } from "../services/link.js";
import utils, { isMobile } from "../services/utils.js";
import { getClosestNtxId } from "../widgets/widget_utils.js";
import type { LeafletMouseEvent } from "leaflet";
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;
}
@ -29,15 +35,8 @@ function handleLinkContextMenuItem(command: string | undefined, notePath: string
if (command === "openNoteInNewTab") {
appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope });
} 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;
appContext.triggerCommand("openNewNoteSplit", { ntxId, notePath, hoistedNoteId, viewScope });
} else if (command === "openNoteInNewWindow") {
appContext.triggerCommand("openInWindow", { notePath, hoistedNoteId, viewScope });
@ -46,6 +45,18 @@ function handleLinkContextMenuItem(command: string | undefined, notePath: string
}
}
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);
} else {
return null;
}
}
export default {
getItems,
handleLinkContextMenuItem,

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,23 @@ 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} {
--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) {

View File

@ -207,7 +207,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) {
let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

View File

@ -4,6 +4,10 @@
box-sizing: border-box;
}
.dropdown-menu:not(.static).calendar-dropdown-menu {
padding: 0 !important;
}
.calendar-dropdown-widget {
margin: 0 auto;
overflow: hidden;

View File

@ -25,7 +25,11 @@
--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;
--ck-mention-list-max-height: 500px;
--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;
}
@ -581,11 +600,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);
@ -706,11 +720,6 @@ table.promoted-attributes-in-tooltip th {
z-index: 32767 !important;
}
.tooltip-trigger {
background: transparent;
pointer-events: none;
}
.bs-tooltip-bottom .tooltip-arrow::before {
border-bottom-color: var(--main-border-color) !important;
}
@ -1006,9 +1015,15 @@ div[data-notify="container"] {
font-family: var(--monospace-font-family);
}
svg.ck-icon .note-icon {
color: var(--main-text-color);
font-size: 20px;
svg.ck-icon {
&.ck-icon_inherit-color path[fill="#333"] {
fill: currentColor;
}
&.note-icon {
color: var(--main-text-color);
font-size: 20px;
}
}
.ck-content {
@ -1117,10 +1132,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 */
}
@ -1316,7 +1327,7 @@ 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;
@ -1379,6 +1390,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;
}
@ -1554,12 +1579,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 {
@ -1664,46 +1692,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 */
@ -2597,4 +2585,33 @@ iframe.print-iframe {
position: relative;
flex-grow: 1;
width: 100%;
}
/* 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;
}
}
}

View File

@ -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,6 @@ 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);
}

View File

@ -80,6 +80,9 @@ 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 {
@ -91,4 +94,8 @@ html {
.ck-content a.reference-link > span,
.board-note {
color: var(--light-theme-custom-color, inherit);
}
.use-note-color {
--custom-color: var(--light-theme-custom-color);
}

View File

@ -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);
@ -98,6 +101,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);
@ -266,6 +270,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;
}
/*
@ -300,8 +312,12 @@ 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);
}

View File

@ -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);
@ -265,6 +268,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,7 +287,7 @@
--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%);

View File

@ -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);
@ -99,6 +100,14 @@
--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,17 +128,6 @@ 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;
}
body.mobile .dropdown-menu .dropdown-menu {
backdrop-filter: unset !important;
border-radius: unset !important;
}
body.desktop .dropdown-menu::before,
:root .ck.ck-dropdown__panel::before,
:root .excalidraw .popover::before,
@ -157,17 +155,12 @@ body.desktop .dropdown-submenu .dropdown-menu::before {
content: unset;
}
body.mobile .dropdown-submenu .dropdown-menu {
background: transparent !important;
}
body.desktop .dropdown-submenu .dropdown-menu {
backdrop-filter: var(--dropdown-backdrop-filter);
background: transparent;
}
.dropdown-item,
body.mobile .dropdown-submenu .dropdown-toggle,
.excalidraw .context-menu .context-menu-item {
--menu-item-start-padding: 8px;
--menu-item-end-padding: 22px;
@ -201,10 +194,6 @@ 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;
@ -322,13 +311,37 @@ body.desktop .dropdown-menu.static .dropdown-item.active {
}
/* #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: var(--dropdown-menu-padding-vertical);
top: 0.5em;
right: var(--dropdown-menu-padding-horizontal);
transform: translateX(50%) rotate(90deg);
}
@ -342,8 +355,8 @@ body.mobile .dropdown-menu {
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(--main-border-color) !important;
border-radius: 0;
border-bottom: 1px solid var(--menu-item-delimiter-color) !important;
border-radius: 0;
}
.dropdown-item:first-of-type,
@ -366,6 +379,49 @@ body.mobile .dropdown-menu {
.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 */

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

@ -146,6 +146,14 @@ 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
*/

View File

@ -643,7 +643,7 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
}
}
.note-detail-printable:not(.word-wrap) pre code {
.ck-content:not(.word-wrap) pre code {
white-space: pre;
}

View File

@ -124,12 +124,8 @@
/* The container */
.note-split.empty-note {
--max-content-width: 70%;
}
.note-split.empty-note div.note-detail {
margin: 50px auto;
margin-inline: auto;
}
/* The search results list */

View File

@ -345,7 +345,7 @@ body[dir=ltr] #launcher-container {
*/
.calendar-dropdown-widget {
padding: 12px;
padding: 18px;
color: var(--calendar-color);
user-select: none;
}
@ -1448,6 +1448,14 @@ div.promoted-attribute-cell .multiplicity:has(span) span {
justify-content: center;
}
div.promoted-attribute-cell.promoted-attribute-label-color {
justify-content: space-between;
}
div.promoted-attribute-cell.promoted-attribute-label-color .input-group {
width: auto;
}
/*
* Floating buttons
*/

View File

@ -201,8 +201,12 @@
},
"zpetne_odkazy": {
"relation": "العلاقة",
"backlink": "{{count}} رابط راجع",
"backlinks": "{{count}} روابط راجعة"
"backlink_zero": "",
"backlink_one": "{{count}} رابط راجع",
"backlink_two": "",
"backlink_few": "",
"backlink_many": "{{count}} روابط راجعة",
"backlink_other": ""
},
"note_icon": {
"category": "الفئة:",

View File

@ -1,185 +1,187 @@
{
"about": {
"title": "Sobre Trilium Notes",
"homepage": "Pàgina principal:"
},
"add_link": {
"note": "Nota"
},
"branch_prefix": {
"prefix": "Prefix: ",
"save": "Desa"
},
"bulk_actions": {
"labels": "Etiquetes",
"relations": "Relacions",
"notes": "Notes",
"other": "Altres"
},
"confirm": {
"confirmation": "Confirmació",
"cancel": "Cancel·la",
"ok": "OK"
},
"delete_notes": {
"close": "Tanca",
"cancel": "Cancel·la",
"ok": "OK"
},
"export": {
"close": "Tanca",
"export": "Exporta"
},
"help": {
"troubleshooting": "Solució de problemes",
"other": "Altres"
},
"import": {
"options": "Opcions",
"import": "Importa"
},
"include_note": {
"label_note": "Nota"
},
"info": {
"closeButton": "Tanca",
"okButton": "OK"
},
"note_type_chooser": {
"templates": "Plantilles:"
},
"prompt": {
"title": "Sol·licitud",
"defaultTitle": "Sol·licitud"
},
"protected_session_password": {
"close_label": "Tanca"
},
"recent_changes": {
"undelete_link": "recuperar"
},
"revisions": {
"restore_button": "Restaura",
"delete_button": "Suprimeix",
"download_button": "Descarrega",
"mime": "MIME: ",
"preview": "Vista prèvia:"
},
"sort_child_notes": {
"title": "títol",
"ascending": "ascendent",
"descending": "descendent",
"folders": "Carpetes"
},
"upload_attachments": {
"options": "Opcions",
"upload": "Puja"
},
"attribute_detail": {
"name": "Nom",
"value": "Valor",
"promoted": "Destacat",
"promoted_alias": "Àlies",
"multiplicity": "Multiplicitat",
"label_type": "Tipus",
"text": "Text",
"number": "Número",
"boolean": "Booleà",
"date": "Data",
"time": "Hora",
"url": "URL",
"precision": "Precisió",
"digits": "dígits",
"inheritable": "Heretable",
"delete": "Suprimeix",
"color_type": "Color"
},
"rename_label": {
"to": "Per"
},
"move_note": {
"to": "a"
},
"add_relation": {
"to": "a"
},
"rename_relation": {
"to": "Per"
},
"update_relation_target": {
"to": "a"
},
"attachments_actions": {
"download": "Descarrega"
},
"calendar": {
"mon": "Dl",
"tue": "Dt",
"wed": "dc",
"thu": "Dj",
"fri": "Dv",
"sat": "Ds",
"sun": "Dg",
"january": "Gener",
"february": "Febrer",
"march": "Març",
"april": "Abril",
"may": "Maig",
"june": "Juny",
"july": "Juliol",
"august": "Agost",
"september": "Setembre",
"october": "Octubre",
"november": "Novembre",
"december": "Desembre"
},
"global_menu": {
"menu": "Menú",
"options": "Opcions",
"zoom": "Zoom",
"advanced": "Avançat",
"logout": "Tanca la sessió"
},
"zpetne_odkazy": {
"relation": "relació"
},
"note_icon": {
"category": "Categoria:",
"search": "Cerca:"
},
"basic_properties": {
"editable": "Editable",
"language": "Llengua"
},
"book_properties": {
"grid": "Graella",
"list": "Llista",
"collapse": "Replega",
"expand": "Desplega",
"calendar": "Calendari",
"table": "Taula",
"board": "Tauler"
},
"edited_notes": {
"deleted": "(suprimit)"
},
"file_properties": {
"download": "Descarrega",
"open": "Obre",
"title": "Fitxer"
},
"image_properties": {
"download": "Descarrega",
"open": "Obre",
"title": "Imatge"
},
"note_info_widget": {
"created": "Creat",
"modified": "Modificat",
"type": "Tipus",
"calculate": "calcula"
},
"note_paths": {
"archived": "Arxivat"
}
"about": {
"title": "Sobre Trilium Notes",
"homepage": "Pàgina principal:",
"app_version": "Versió de l'aplicació:",
"db_version": "Versió de la base de dades:"
},
"add_link": {
"note": "Nota"
},
"branch_prefix": {
"prefix": "Prefix: ",
"save": "Desa"
},
"bulk_actions": {
"labels": "Etiquetes",
"relations": "Relacions",
"notes": "Notes",
"other": "Altres"
},
"confirm": {
"confirmation": "Confirmació",
"cancel": "Cancel·la",
"ok": "OK"
},
"delete_notes": {
"close": "Tanca",
"cancel": "Cancel·la",
"ok": "OK"
},
"export": {
"close": "Tanca",
"export": "Exporta"
},
"help": {
"troubleshooting": "Solució de problemes",
"other": "Altres"
},
"import": {
"options": "Opcions",
"import": "Importa"
},
"include_note": {
"label_note": "Nota"
},
"info": {
"closeButton": "Tanca",
"okButton": "OK"
},
"note_type_chooser": {
"templates": "Plantilles:"
},
"prompt": {
"title": "Sol·licitud",
"defaultTitle": "Sol·licitud"
},
"protected_session_password": {
"close_label": "Tanca"
},
"recent_changes": {
"undelete_link": "recuperar"
},
"revisions": {
"restore_button": "Restaura",
"delete_button": "Suprimeix",
"download_button": "Descarrega",
"mime": "MIME: ",
"preview": "Vista prèvia:"
},
"sort_child_notes": {
"title": "títol",
"ascending": "ascendent",
"descending": "descendent",
"folders": "Carpetes"
},
"upload_attachments": {
"options": "Opcions",
"upload": "Puja"
},
"attribute_detail": {
"name": "Nom",
"value": "Valor",
"promoted": "Destacat",
"promoted_alias": "Àlies",
"multiplicity": "Multiplicitat",
"label_type": "Tipus",
"text": "Text",
"number": "Número",
"boolean": "Booleà",
"date": "Data",
"time": "Hora",
"url": "URL",
"precision": "Precisió",
"digits": "dígits",
"inheritable": "Heretable",
"delete": "Suprimeix",
"color_type": "Color"
},
"rename_label": {
"to": "Per"
},
"move_note": {
"to": "a"
},
"add_relation": {
"to": "a"
},
"rename_relation": {
"to": "Per"
},
"update_relation_target": {
"to": "a"
},
"attachments_actions": {
"download": "Descarrega"
},
"calendar": {
"mon": "Dl",
"tue": "Dt",
"wed": "dc",
"thu": "Dj",
"fri": "Dv",
"sat": "Ds",
"sun": "Dg",
"january": "Gener",
"february": "Febrer",
"march": "Març",
"april": "Abril",
"may": "Maig",
"june": "Juny",
"july": "Juliol",
"august": "Agost",
"september": "Setembre",
"october": "Octubre",
"november": "Novembre",
"december": "Desembre"
},
"global_menu": {
"menu": "Menú",
"options": "Opcions",
"zoom": "Zoom",
"advanced": "Avançat",
"logout": "Tanca la sessió"
},
"zpetne_odkazy": {
"relation": "relació"
},
"note_icon": {
"category": "Categoria:",
"search": "Cerca:"
},
"basic_properties": {
"editable": "Editable",
"language": "Llengua"
},
"book_properties": {
"grid": "Graella",
"list": "Llista",
"collapse": "Replega",
"expand": "Desplega",
"calendar": "Calendari",
"table": "Taula",
"board": "Tauler"
},
"edited_notes": {
"deleted": "(suprimit)"
},
"file_properties": {
"download": "Descarrega",
"open": "Obre",
"title": "Fitxer"
},
"image_properties": {
"download": "Descarrega",
"open": "Obre",
"title": "Imatge"
},
"note_info_widget": {
"created": "Creat",
"modified": "Modificat",
"type": "Tipus",
"calculate": "calcula"
},
"note_paths": {
"archived": "Arxivat"
}
}

View File

@ -162,7 +162,8 @@
"inPageSearch": "页面内搜索",
"newTabWithActivationNoteLink": "在新标签页打开笔记链接并激活该标签页",
"title": "资料表",
"newTabNoteLink": "在新标签页开启链接"
"newTabNoteLink": "在新标签页开启链接",
"editShortcuts": "编辑键盘快捷键"
},
"import": {
"importIntoNote": "导入到笔记",
@ -735,9 +736,8 @@
"zoom_out_title": "缩小"
},
"zpetne_odkazy": {
"backlink": "{{count}} 个反链",
"backlinks": "{{count}} 个反链",
"relation": "关系"
"relation": "关系",
"backlink_other": "{{count}} 个反链"
},
"mobile_detail_menu": {
"insert_child_note": "插入子笔记",
@ -1557,7 +1557,8 @@
"refresh-saved-search-results": "刷新保存的搜索结果",
"create-child-note": "创建子笔记",
"unhoist": "取消聚焦",
"toggle-sidebar": "切换侧边栏"
"toggle-sidebar": "切换侧边栏",
"dropping-not-allowed": "不允许移动笔记到此处。"
},
"title_bar_buttons": {
"window-on-top": "保持此窗口置顶"
@ -1660,7 +1661,8 @@
"duplicate-launcher": "复制启动器 <kbd data-command=\"duplicateSubtree\">"
},
"editable-text": {
"auto-detect-language": "自动检测"
"auto-detect-language": "自动检测",
"keeps-crashing": "编辑组件时持续崩溃。请尝试重启 Trilium。如果问题仍然存在请考虑提交错误报告。"
},
"highlighting": {
"title": "代码块",
@ -1895,9 +1897,7 @@
"indexing_stopped": "索引已停止",
"indexing_in_progress": "索引进行中...",
"last_indexed": "最后索引时间",
"n_notes_queued_0": "{{ count }} 条笔记已加入索引队列",
"note_chat": "笔记聊天",
"notes_indexed_0": "{{ count }} 条笔记已索引",
"sources": "来源",
"start_indexing": "开始索引",
"use_advanced_context": "使用高级上下文",
@ -2096,12 +2096,14 @@
"read-only-info": {
"read-only-note": "当前正在查看一个只读笔记。",
"auto-read-only-note": "这条笔记以只读模式显示便于快速加载。",
"auto-read-only-learn-more": "了解更多",
"edit-note": "编辑笔记"
},
"note-color": {
"clear-color": "清除笔记颜色",
"set-color": "设置笔记颜色",
"set-custom-color": "设置自定义笔记颜色"
},
"popup-editor": {
"maximize": "切换至完整编辑器"
}
}

View File

@ -24,14 +24,6 @@
"message": "Uživatelský skript z poznámky s ID \"{{id}}\" a názvem \"{{title}}\" nemohl být spuštěn z důvodu: \n\n{{message}}"
}
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} poznámka ve frontě k indexaci",
"n_notes_queued_1": "{{ count }} poznámky ve frontě k indexaci",
"n_notes_queued_2": "{{ count }} poznámek ve frontě k indexaci",
"notes_indexed_0": "{{ count }} poznámka indexována",
"notes_indexed_1": "{{ count }} poznámky indexovány",
"notes_indexed_2": "{{ count }} poznámek indexováno"
},
"add_link": {
"add_link": "Přidat odkaz",
"help_on_links": "Nápověda k odkazům",
@ -70,7 +62,7 @@
"cancel": "Zrušit",
"ok": "OK",
"confirmation": "Potvrzení",
"are_you_sure_remove_note": "Opravdu chcete odstranit poznámku „{{title}}“ z mapy vztahů?",
"are_you_sure_remove_note": "Opravdu chcete odstranit poznámku „{{title}}“ z mapy vztahů? ",
"if_you_dont_check": "Pokud tuto možnost nezaškrtnete, poznámka bude odstraněna pouze z mapy vztahů.",
"also_delete_note": "Odstraňte také poznámku"
},

View File

@ -21,7 +21,7 @@
},
"bundle-error": {
"title": "Benutzerdefiniertes Skript konnte nicht geladen werden",
"message": "Skript von der Notiz mit der ID \"{{id}}\", und dem Titel \"{{title}}\" konnte nicht ausgeführt werden wegen:\n\n{{message}}"
"message": "Skript aus der Notiz \"{{title}}\" mit der ID \"{{id}}\", konnte nicht ausgeführt werden wegen:\n\n{{message}}"
}
},
"add_link": {
@ -41,7 +41,8 @@
"save": "Speichern",
"branch_prefix_saved": "Zweigpräfix wurde gespeichert.",
"branch_prefix_saved_multiple": "Der Zweigpräfix wurde für {{count}} Zweige gespeichert.",
"edit_branch_prefix_multiple": "Präfix für {{count}} Zweige bearbeiten"
"edit_branch_prefix_multiple": "Branch-Präfix für {{count}} Zweige bearbeiten",
"affected_branches": "Betroffene Zweige ({{count}}):"
},
"bulk_actions": {
"bulk_actions": "Massenaktionen",
@ -731,9 +732,9 @@
"zoom_out_title": "Herauszoomen"
},
"zpetne_odkazy": {
"backlink": "{{count}} Rückverlinkung",
"backlinks": "{{count}} Rückverlinkungen",
"relation": "Beziehung"
"relation": "Beziehung",
"backlink_one": "{{count}} Rückverlinkung",
"backlink_other": "{{count}} Rückverlinkungen"
},
"mobile_detail_menu": {
"insert_child_note": "Untergeordnete Notiz einfügen",
@ -770,7 +771,10 @@
"board": "Tafel",
"include_archived_notes": "Zeige archivierte Notizen",
"presentation": "Präsentation",
"expand_all_levels": "Alle Ebenen erweitern"
"expand_all_levels": "Alle Ebenen erweitern",
"expand_tooltip": "Erweitert die direkten Unterelemente dieser Sammlung (eine Ebene tiefer). Für weitere Optionen auf den Pfeil rechts klicken.",
"expand_first_level": "Direkte Unterelemente erweitern",
"expand_nth_level": "{{depth}} Ebenen erweitern"
},
"edited_notes": {
"no_edited_notes_found": "An diesem Tag wurden noch keine Notizen bearbeitet...",
@ -1517,7 +1521,8 @@
"refresh-saved-search-results": "Gespeicherte Suchergebnisse aktualisieren",
"create-child-note": "Unternotiz anlegen",
"unhoist": "Fokus verlassen",
"toggle-sidebar": "Seitenleiste ein-/ausblenden"
"toggle-sidebar": "Seitenleiste ein-/ausblenden",
"dropping-not-allowed": "Ablegen von Notizen an dieser Stelle ist nicht zulässig."
},
"title_bar_buttons": {
"window-on-top": "Dieses Fenster immer oben halten"
@ -1620,7 +1625,8 @@
"duplicate-launcher": "Launcher duplizieren <kbd data-command=\"duplicateSubtree\">"
},
"editable-text": {
"auto-detect-language": "Automatisch erkannt"
"auto-detect-language": "Automatisch erkannt",
"keeps-crashing": "Die Bearbeitungskomponente stürzt immer wieder ab. Bitte starten Sie Trilium neu. Wenn das Problem weiterhin besteht, erstellen Sie einen Fehlerbericht."
},
"highlighting": {
"description": "Steuert die Syntaxhervorhebung für Codeblöcke in Textnotizen, Code-Notizen sind nicht betroffen.",
@ -1723,10 +1729,6 @@
"help_title": "Zeige mehr Informationen zu diesem Fenster"
},
"ai_llm": {
"n_notes_queued": "{{ count }} Notiz zur Indizierung vorgemerkt",
"n_notes_queued_plural": "{{ count }} Notizen zur Indizierung vorgemerkt",
"notes_indexed": "{{ count }} Notiz indiziert",
"notes_indexed_plural": "{{ count }} Notizen indiziert",
"not_started": "Nicht gestartet",
"title": "KI Einstellungen",
"processed_notes": "Verarbeitete Notizen",
@ -2089,9 +2091,8 @@
"slide-overview": "Übersicht der Folien ein-/ausblenden"
},
"read-only-info": {
"read-only-note": "Aktuell wird eine Notiz nur im Lese-Modus angezeigt.",
"read-only-note": "Aktuelle Notiz wird im Lese-Modus angezeigt.",
"auto-read-only-note": "Diese Notiz wird im Nur-Lesen-Modus angezeigt, um ein schnelleres Laden zu ermöglichen.",
"auto-read-only-learn-more": "Mehr erfahren",
"edit-note": "Notiz bearbeiten"
},
"calendar_view": {

View File

@ -14,11 +14,5 @@
"title": "Κρίσιμο σφάλμα",
"message": "Συνέβη κάποιο κρίσιμο σφάλμα, το οποίο δεν επιτρέπει στην εφαρμογή χρήστη να ξεκινήσει:\n\n{{message}}\n\nΤο πιθανότερο είναι να προκλήθηκε από κάποιο script που απέτυχε απρόοπτα. Δοκιμάστε να ξεκινήσετε την εφαρμογή σε ασφαλή λειτουργία για να λύσετε το πρόβλημα."
}
},
"ai_llm": {
"n_notes_queued": "{{ count }} σημείωση στην ουρά για εύρεση",
"n_notes_queued_plural": "{{ count }} σημειώσεις στην ουρά για εύρεση",
"notes_indexed": "{{ count }} σημείωση με ευρετήριο",
"notes_indexed_plural": "{{ count }} σημειώσεις με ευρετήριο"
}
}

View File

@ -0,0 +1,73 @@
{
"import": {
"safeImportTooltip": "Trilium <code>.zip</code> export files can contain executable scripts which may contain harmful behaviour. Safe import will deactivate automatic execution of all imported scripts. Uncheck \"Safe import\" only if the imported archive is supposed to contain executable scripts and you completely trust the contents of the import file.",
"shrinkImagesTooltip": "<p>If you check this option, Trilium will attempt to shrink the imported images by scaling and optimisation which may affect the perceived image quality. If unchecked, images will be imported without changes.</p><p>This doesn't apply to <code>.zip</code> imports with metadata since it is assumed these files are already optimised.</p>",
"codeImportedAsCode": "Import recognised code files (e.g. <code>.json</code>) as code notes if it's unclear from metadata"
},
"upload_attachments": {
"tooltip": "If you check this option, Trilium will attempt to shrink the uploaded images by scaling and optimisation which may affect the perceived image quality. If unchecked, images will be uploaded without changes."
},
"attribute_detail": {
"auto_read_only_disabled": "text/code notes can be set automatically into read mode when they are too large. You can disable this behaviour on per-note basis by adding this label to the note",
"workspace_tab_background_color": "CSS colour used in the note tab when hoisted to this note",
"color": "defines colour of the note in note tree, links etc. Use any valid CSS colour value like 'red' or #a13d5f",
"color_type": "Colour"
},
"mobile_detail_menu": {
"error_unrecognized_command": "Unrecognised command {{command}}"
},
"promoted_attributes": {
"remove_color": "Remove the colour label"
},
"max_content_width": {
"centerContent": "Keep content centred"
},
"theme": {
"auto_theme": "Legacy (Follow system colour scheme)",
"triliumnext": "Trilium (Follow system colour scheme)"
},
"search_engine": {
"custom_name_placeholder": "Customise search engine name",
"custom_url_placeholder": "Customise search engine url"
},
"highlights_list": {
"description": "You can customise the highlights list displayed in the right panel:",
"color": "Coloured text",
"bg_color": "Text with background colour"
},
"table_of_contents": {
"description": "Table of contents will appear in text notes when the note has more than a defined number of headings. You can customise this number:"
},
"custom_date_time_format": {
"description": "Customise the format of the date and time inserted via <shortcut /> or the toolbar. See <doc>Day.js docs</doc> for available format tokens."
},
"i18n": {
"title": "Localisation"
},
"attachment_detail_2": {
"unrecognized_role": "Unrecognised attachment role '{{role}}'."
},
"ai_llm": {
"reprocess_index_started": "Search index optimisation started in the background",
"index_rebuilding": "Optimising index ({{percentage}}%)",
"index_rebuild_complete": "Index optimisation complete"
},
"highlighting": {
"color-scheme": "Colour Scheme"
},
"code_theme": {
"color-scheme": "Colour scheme"
},
"call_to_action": {
"background_effects_message": "On Windows devices, background effects are now fully stable. The background effects adds a touch of colour to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer."
},
"settings_appearance": {
"related_code_blocks": "Colour scheme for code blocks in text notes",
"related_code_notes": "Colour scheme for code notes"
},
"note-color": {
"clear-color": "Clear note colour",
"set-color": "Set note colour",
"set-custom-color": "Set custom note colour"
}
}

View File

@ -112,6 +112,7 @@
},
"help": {
"title": "Cheatsheet",
"editShortcuts": "Edit keyboard shortcuts",
"noteNavigation": "Note navigation",
"goUpDown": "go up/down in the list of notes",
"collapseExpand": "collapse/expand node",
@ -735,8 +736,8 @@
"zoom_out_title": "Zoom Out"
},
"zpetne_odkazy": {
"backlink": "{{count}} Backlink",
"backlinks": "{{count}} Backlinks",
"backlink_one": "{{count}} Backlink",
"backlink_other": "{{count}} Backlinks",
"relation": "relation"
},
"mobile_detail_menu": {
@ -1270,11 +1271,7 @@
"indexing_stopped": "Indexing stopped",
"indexing_in_progress": "Indexing in progress...",
"last_indexed": "Last Indexed",
"n_notes_queued": "{{ count }} note queued for indexing",
"n_notes_queued_plural": "{{ count }} notes queued for indexing",
"note_chat": "Note Chat",
"notes_indexed": "{{ count }} note indexed",
"notes_indexed_plural": "{{ count }} notes indexed",
"sources": "Sources",
"start_indexing": "Start Indexing",
"use_advanced_context": "Use Advanced Context",
@ -1647,7 +1644,6 @@
"read-only-info": {
"read-only-note": "Currently viewing a read-only note.",
"auto-read-only-note": "This note is shown in a read-only mode for faster loading.",
"auto-read-only-learn-more": "Learn more",
"edit-note": "Edit note"
},
"note_types": {
@ -1883,6 +1879,7 @@
"link_context_menu": {
"open_note_in_new_tab": "Open note in a new tab",
"open_note_in_new_split": "Open note in a new split",
"open_note_in_other_split": "Open note in the other split",
"open_note_in_new_window": "Open note in a new window",
"open_note_in_popup": "Quick edit"
},
@ -2107,5 +2104,8 @@
"clear-color": "Clear note color",
"set-color": "Set note color",
"set-custom-color": "Set custom note color"
},
"popup-editor": {
"maximize": "Switch to full editor"
}
}

View File

@ -735,9 +735,10 @@
"zoom_out_title": "Alejar"
},
"zpetne_odkazy": {
"backlink": "{{count}} Vínculo de retroceso",
"backlinks": "{{count}} vínculos de retroceso",
"relation": "relación"
"relation": "relación",
"backlink_one": "{{count}} Vínculo de retroceso",
"backlink_many": "",
"backlink_other": "{{count}} vínculos de retroceso"
},
"mobile_detail_menu": {
"insert_child_note": "Insertar subnota",
@ -1262,12 +1263,7 @@
"indexing_stopped": "Indexado detenido",
"indexing_in_progress": "Indexado en progreso...",
"last_indexed": "Último indexado",
"n_notes_queued_0": "{{ count }} nota agregada a la cola para indexar",
"n_notes_queued_1": "{{ count }} notas agregadas a la cola para indexar",
"n_notes_queued_2": "",
"note_chat": "Chat de nota",
"notes_indexed": "{{ count }} nota indexada",
"notes_indexed_plural": "{{ count }} notas indexadas",
"sources": "Fuentes",
"start_indexing": "Comenzar indexado",
"use_advanced_context": "Usar contexto avanzado",
@ -2096,7 +2092,6 @@
"read-only-info": {
"read-only-note": "Actualmente, está viendo una nota de solo lectura.",
"auto-read-only-note": "Esta nota se muestra en modo de solo lectura para una carga más rápida.",
"auto-read-only-learn-more": "Para saber más",
"edit-note": "Editar nota"
},
"calendar_view": {

View File

@ -733,9 +733,10 @@
"zoom_out_title": "Zoom arrière"
},
"zpetne_odkazy": {
"backlink": "{{count}} Lien inverse",
"backlinks": "{{count}} Liens inverses",
"relation": "relation"
"relation": "relation",
"backlink_one": "{{count}} Lien inverse",
"backlink_many": "",
"backlink_other": "{{count}} Liens inverses"
},
"mobile_detail_menu": {
"insert_child_note": "Insérer une note enfant",
@ -1766,12 +1767,6 @@
"not_started": "Non démarré",
"title": "Paramètres IA",
"processed_notes": "Notes traitées",
"n_notes_queued_0": "{{ count }} note en attente dindexation",
"n_notes_queued_1": "{{ count }} notes en attente dindexation",
"n_notes_queued_2": "",
"notes_indexed_0": "{{ count }} note indexée",
"notes_indexed_1": "{{ count }} notes indexées",
"notes_indexed_2": "",
"anthropic_url_description": "URL de base pour l'API Anthropic (par défaut : https ://api.anthropic.com)",
"anthropic_model_description": "Modèles Anthropic Claude pour la complétion",
"voyage_settings": "Réglages d'IA Voyage",

View File

@ -324,7 +324,8 @@
"copy-link": "Copia collegamento",
"paste-as-plain-text": "Incolla come testo semplice",
"add-term-to-dictionary": "Aggiungi \"{{term}}\" al dizionario",
"search_online": "Cerca \"{{term}}\" con {{searchEngine}}"
"search_online": "Cerca \"{{term}}\" con {{searchEngine}}",
"search_in_trilium": "Cerca \"{{term}}\" in Trilium"
},
"editing": {
"editor_type": {
@ -614,7 +615,8 @@
"showSQLConsole": "mostra console SQL",
"other": "Altro",
"quickSearch": "concentrati sull'input della ricerca rapida",
"inPageSearch": "ricerca all'interno della pagina"
"inPageSearch": "ricerca all'interno della pagina",
"editShortcuts": "Modifica scorciatoie da tastiera"
},
"i18n": {
"saturday": "Sabato",
@ -638,12 +640,6 @@
"friday": "Venerdì"
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} nota in coda per l'indicizzazione",
"n_notes_queued_1": "{{ count }} note in coda per l'indicizzazione",
"n_notes_queued_2": "{{ count }} note in coda per l'indicizzazione",
"notes_indexed_0": "{{ count }} nota indicizzata",
"notes_indexed_1": "{{ count }} note indicizzate",
"notes_indexed_2": "{{ count }} note indicizzate",
"not_started": "Non iniziato",
"title": "Impostazioni AI",
"processed_notes": "Note elaborate",
@ -1308,9 +1304,10 @@
"zoom_out_title": "Rimpicciolisci"
},
"zpetne_odkazy": {
"backlink": "{{count}} Backlink",
"backlinks": "{{count}} Backlinks",
"relation": "relazione"
"relation": "relazione",
"backlink_one": "{{count}} Backlink",
"backlink_many": "{{count}} Backlinks",
"backlink_other": "{{count}} Backlinks"
},
"mobile_detail_menu": {
"insert_child_note": "Inserisci nota secondaria",
@ -1346,7 +1343,11 @@
"geo-map": "Mappa geografica",
"board": "Asse",
"presentation": "Presentazione",
"include_archived_notes": "Mostra note archiviate"
"include_archived_notes": "Mostra note archiviate",
"expand_tooltip": "Espande i figli diretti di questa raccolta (a un livello di profondità). Per ulteriori opzioni, premere la freccia a destra.",
"expand_first_level": "Espandi figli diretti",
"expand_nth_level": "Espandi {{depth}} livelli",
"expand_all_levels": "Espandi tutti i livelli"
},
"edited_notes": {
"no_edited_notes_found": "Nessuna nota modificata per questo giorno...",
@ -1800,8 +1801,8 @@
"relation-map": "Mappa delle relazioni",
"note-map": "Nota Mappa",
"render-note": "Nota di rendering",
"book": "Collezione",
"mermaid-diagram": "Diagramma della sirena",
"book": "Raccolta",
"mermaid-diagram": "Diagramma Mermaid",
"canvas": "Tela",
"web-view": "Visualizzazione Web",
"mind-map": "Mappa mentale",
@ -1852,7 +1853,8 @@
"refresh-saved-search-results": "Aggiorna i risultati della ricerca salvati",
"create-child-note": "Crea nota figlio",
"unhoist": "Sganciare",
"toggle-sidebar": "Attiva/disattiva la barra laterale"
"toggle-sidebar": "Attiva/disattiva la barra laterale",
"dropping-not-allowed": "Non è consentito lasciare appunti in questa posizione."
},
"title_bar_buttons": {
"window-on-top": "Mantieni la finestra in primo piano"
@ -1936,7 +1938,8 @@
"duplicate-launcher": "Duplica il launcher <kbd data-command=\"duplicateSubtree\">"
},
"editable-text": {
"auto-detect-language": "Rilevato automaticamente"
"auto-detect-language": "Rilevato automaticamente",
"keeps-crashing": "Il componente di modifica continua a bloccarsi. Prova a riavviare Trilium. Se il problema persiste, valuta la possibilità di creare una segnalazione di bug."
},
"highlighting": {
"title": "Blocchi di codice",
@ -1964,7 +1967,8 @@
"open_note_in_new_tab": "Apri la nota in una nuova scheda",
"open_note_in_new_split": "Apri nota in una nuova divisione",
"open_note_in_new_window": "Apri la nota in una nuova finestra",
"open_note_in_popup": "Modifica rapida"
"open_note_in_popup": "Modifica rapida",
"open_note_in_other_split": "Apri nota nell'altra divisione"
},
"help-button": {
"title": "Apri la pagina di aiuto pertinente"
@ -2092,7 +2096,6 @@
"read-only-info": {
"read-only-note": "Stai visualizzando una nota di sola lettura.",
"auto-read-only-note": "Questa nota viene visualizzata in modalità di sola lettura per un caricamento più rapido.",
"auto-read-only-learn-more": "Per saperne di più",
"edit-note": "Modifica nota"
},
"calendar_view": {
@ -2102,5 +2105,8 @@
"set-color": "Imposta colore nota",
"set-custom-color": "Imposta colore personalizzato per le note",
"clear-color": "Pulisci colore della nota"
},
"popup-editor": {
"maximize": "Passa all'editor completo"
}
}

View File

@ -312,7 +312,8 @@
"moveNoteUpDown": "ノートリストでノートを上/下に移動",
"notSet": "未設定",
"goUpDown": "ノートのリストで上下する",
"editBranchPrefix": "アクティブノートのクローンの <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">プレフィックス</a> を編集する"
"editBranchPrefix": "アクティブノートのクローンの <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">プレフィックス</a> を編集する",
"editShortcuts": "キーボードショートカットを編集"
},
"import": {
"importIntoNote": "ノートにインポート",
@ -1157,7 +1158,8 @@
"open_note_in_popup": "クイック編集",
"open_note_in_new_tab": "新しいタブでノートを開く",
"open_note_in_new_split": "新しく分割してノートを開く",
"open_note_in_new_window": "新しいウィンドウでノートを開く"
"open_note_in_new_window": "新しいウィンドウでノートを開く",
"open_note_in_other_split": "他の分割画面でノートを開く"
},
"note_tooltip": {
"quick-edit": "クイック編集",
@ -1212,7 +1214,8 @@
"unhoist": "ホイスト解除",
"saved-search-note-refreshed": "保存した検索ノートが更新されました。",
"refresh-saved-search-results": "保存した検索結果を更新",
"toggle-sidebar": "サイドバーを切り替え"
"toggle-sidebar": "サイドバーを切り替え",
"dropping-not-allowed": "この場所にノートをドロップすることはできません。"
},
"bulk_actions": {
"bulk_actions": "一括操作",
@ -1266,7 +1269,8 @@
"reset_launcher_confirm": "本当に「{{title}}」をリセットしますか? このノート(およびその子ノート)のすべてのデータと設定が失われ、ランチャーは元の場所に戻ります。"
},
"editable-text": {
"auto-detect-language": "自動検出"
"auto-detect-language": "自動検出",
"keeps-crashing": "編集コンポーネントがクラッシュし続けます。Trilium を再起動してください。問題が解決しない場合は、バグレポートの作成をご検討ください。"
},
"highlighting": {
"title": "コードブロック",
@ -1504,9 +1508,7 @@
"indexing_stopped": "インデックス登録を停止しました",
"indexing_in_progress": "インデックス登録中です...",
"last_indexed": "最終インデックス作成日時",
"n_notes_queued_0": "{{ count }} 件のノートがインデックス作成待ちです",
"note_chat": "ノートチャット",
"notes_indexed_0": "{{ count }} 件のノートをインデックスしました",
"sources": "ソース",
"start_indexing": "インデックス作成を開始",
"use_advanced_context": "高度なコンテキストを使用",
@ -1587,9 +1589,8 @@
"this_launcher_doesnt_define_target_note": "このランチャーはターゲットノートを定義していません。"
},
"zpetne_odkazy": {
"backlink": "{{count}} バックリンク",
"backlinks": "{{count}} バックリンク",
"relation": "リレーション"
"relation": "リレーション",
"backlink_other": "{{count}} 個のバックリンク"
},
"mobile_detail_menu": {
"delete_this_note": "このノートを削除",
@ -2096,12 +2097,14 @@
"read-only-info": {
"read-only-note": "現在、読み取り専用のノートを表示しています。",
"auto-read-only-note": "このノートは読み込みを高速化するために読み取り専用モードで表示されています。",
"auto-read-only-learn-more": "さらに詳しく",
"edit-note": "ノートを編集"
},
"note-color": {
"clear-color": "ノートの色をクリア",
"set-color": "ノートの色を設定",
"set-custom-color": "ノートの色をカスタム設定"
},
"popup-editor": {
"maximize": "フルエディターに切り替え"
}
}

View File

@ -39,7 +39,9 @@
"edit_branch_prefix": "브랜치 접두사 편집",
"help_on_tree_prefix": "트리 접두사에 대한 도움말",
"prefix": "접두사: ",
"branch_prefix_saved": "브랜치 접두사가 저장되었습니다."
"branch_prefix_saved": "브랜치 접두사가 저장되었습니다.",
"edit_branch_prefix_multiple": "{{count}}개의 지점 접두사 편집",
"branch_prefix_saved_multiple": "{{count}}개의 지점에 대해 지점 접두사가 저장되었습니다."
},
"bulk_actions": {
"bulk_actions": "대량 작업",

View File

@ -16,10 +16,12 @@
},
"widget-error": {
"title": "Starten widget mislukt",
"message-unknown": "Onbekende widget kan niet gestart worden omdat:\n\n{{message}}"
"message-unknown": "Onbekende widget kan niet gestart worden omdat:\n\n{{message}}",
"message-custom": "Aangepaste widget van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden geïnitialiseerd vanwege:\n\n{{message}}"
},
"bundle-error": {
"title": "Custom script laden mislukt"
"title": "Custom script laden mislukt",
"message": "Script van notitie met ID \"{{id}}\", getiteld \"{{title}}\" kon niet worden uitgevoerd vanwege:\n\n{{message}}"
}
},
"add_link": {
@ -29,14 +31,17 @@
"search_note": "zoek voor notitie op naam",
"link_title_mirrors": "De link titel is hetzelfde als de notitie's huidige titel",
"link_title": "Link titel",
"button_add_link": "Link toevoegen"
"button_add_link": "Link toevoegen",
"link_title_arbitrary": "snelkoppelingsnaam kan willekeurig worden aangepast"
},
"branch_prefix": {
"edit_branch_prefix": "Bewerk branch prefix",
"save": "Opslaan",
"branch_prefix_saved": "Branch prefix is opgeslagen.",
"help_on_tree_prefix": "Help bij boomvoorvoegsel",
"prefix": "Voorvoegsel: "
"prefix": "Voorvoegsel: ",
"edit_branch_prefix_multiple": "Bewerk zijtakvoorvoegsel voor {{count}} zijtakken",
"branch_prefix_saved_multiple": "Vertakkingsvoorvoegsel opgeslagen voor {{count}} vertakkingen."
},
"bulk_actions": {
"bulk_actions": "Bulk acties",

View File

@ -750,9 +750,6 @@
"indexing_stopped": "Indeksowanie zatrzymane",
"indexing_in_progress": "Indeksowanie w trakcie...",
"last_indexed": "Ostatnio zindeksowane",
"n_notes_queued_0": "{{ count }} notatka zakolejkowana do indeksowania",
"n_notes_queued_1": "{{ count }} notatek zakolejkowanych do indeksowania",
"n_notes_queued_2": "{{ count }} notatek zakolejkowanych do indeksowania",
"note_chat": "Czat notatki",
"note_title": "Tytuł notatki",
"error": "Błąd",
@ -860,9 +857,6 @@
"enter_message": "Wpisz swoją wiadomość...",
"error_contacting_provider": "Błąd kontaktu z dostawcą AI. Sprawdź ustawienia i połączenie internetowe.",
"error_generating_response": "Błąd generowania odpowiedzi AI",
"notes_indexed_0": "{{ count }} notatka zaindeksowana",
"notes_indexed_1": "{{ count }} notatek zaindeksowanych",
"notes_indexed_2": "",
"sources": "Źródła",
"start_indexing": "Rozpocznij indeksowanie",
"use_advanced_context": "Użyj zaawansowanego kontekstu",
@ -1237,9 +1231,10 @@
"zoom_out_title": "Pomniejsz"
},
"zpetne_odkazy": {
"backlink": "{{count}} Backlink",
"backlinks": "{{count}} Backlinków",
"relation": "relacja"
"relation": "relacja",
"backlink_one": "{{count}} Backlink",
"backlink_few": "",
"backlink_many": "{{count}} Backlinków"
},
"mobile_detail_menu": {
"insert_child_note": "Wstaw notatkę podrzędną",

View File

@ -711,9 +711,10 @@
"zoom_out_title": "Reduzir"
},
"zpetne_odkazy": {
"backlink": "{{count}} Ligação Reversa",
"backlinks": "{{count}} Ligações Reversas",
"relation": "relação"
"relation": "relação",
"backlink_one": "{{count}} Ligação Reversa",
"backlink_many": "",
"backlink_other": "{{count}} Ligações Reversas"
},
"mobile_detail_menu": {
"insert_child_note": "Inserir nota filha",
@ -1234,13 +1235,7 @@
"indexing_stopped": "Indexação interrompida",
"indexing_in_progress": "Indexação em andamento…",
"last_indexed": "Última Indexada",
"n_notes_queued_0": "{{ count }} nota enfileirada para indexação",
"n_notes_queued_1": "{{ count }} notas enfileiradas para indexação",
"n_notes_queued_2": "{{ count }} notas enfileiradas para indexação",
"note_chat": "Conversa de Nota",
"notes_indexed_0": "{{ count }} nota indexada",
"notes_indexed_1": "{{ count }} notas indexadas",
"notes_indexed_2": "{{ count }} notas indexadas",
"sources": "Origens",
"start_indexing": "Iniciar Indexação",
"use_advanced_context": "Usar Contexto Avançado",

View File

@ -75,12 +75,6 @@
"note_cloned": "A nota \"{{clonedTitle}}\" foi clonada para \"{{targetTitle}}\""
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} nota enfileirada para indexação",
"n_notes_queued_1": "{{ count }} notas enfileiradas para indexação",
"n_notes_queued_2": "{{ count }} notas enfileiradas para indexação",
"notes_indexed_0": "{{ count }} nota indexada",
"notes_indexed_1": "{{ count }} notas indexadas",
"notes_indexed_2": "{{ count }} notas indexadas",
"temperature": "Temperatura",
"retry_queued": "Nota enfileirada para nova tentativa",
"queued_notes": "Notas Enfileiradas",
@ -976,9 +970,10 @@
"reset_pan_zoom_title": "Redefinir pan & zoom para coordenadas e ampliação iniciais"
},
"zpetne_odkazy": {
"backlink": "{{count}} Links Reversos",
"backlinks": "{{count}} Links Reversos",
"relation": "relação"
"relation": "relação",
"backlink_one": "",
"backlink_many": "",
"backlink_other": "{{count}} Links Reversos"
},
"mobile_detail_menu": {
"insert_child_note": "Inserir nota filha",

View File

@ -1362,8 +1362,9 @@
"title": "Factorul de zoom (doar pentru versiunea desktop)"
},
"zpetne_odkazy": {
"backlink": "{{count}} legături de retur",
"backlinks": "{{count}} legături de retur",
"backlink_one": "{{count}} legătură de retur",
"backlink_few": "{{count}} legături de retur",
"backlink_other": "{{count}} de legături de retur",
"relation": "relație"
},
"svg_export_button": {
@ -1887,13 +1888,7 @@
"indexing_stopped": "Indexarea s-a oprit",
"indexing_in_progress": "Indexare în curs...",
"last_indexed": "Ultima indexare",
"n_notes_queued_0": "O notiță adăugată în coada de indexare",
"n_notes_queued_1": "{{ count }} notițe adăugate în coada de indexare",
"n_notes_queued_2": "{{ count }} de notițe adăugate în coada de indexare",
"note_chat": "Discuție pe baza notițelor",
"notes_indexed_0": "O notiță indexată",
"notes_indexed_1": "{{ count }} notițe indexate",
"notes_indexed_2": "{{ count }} de notițe indexate",
"sources": "Surse",
"start_indexing": "Indexează",
"use_advanced_context": "Folosește context îmbogățit",
@ -2097,7 +2092,6 @@
"read-only-info": {
"read-only-note": "Vizualizați o notiță în modul doar în citire.",
"auto-read-only-note": "Această notiță este afișată în modul doar în citire din motive de performanță.",
"auto-read-only-learn-more": "Mai multe detalii",
"edit-note": "Editează notița"
},
"calendar_view": {

View File

@ -984,9 +984,10 @@
"new-version-available": "Доступно обновление"
},
"zpetne_odkazy": {
"backlink": "{{count}} ссылки",
"backlinks": "{{count}} ссылок",
"relation": "отношение"
"relation": "отношение",
"backlink_one": "{{count}} ссылки",
"backlink_few": "",
"backlink_many": "{{count}} ссылок"
},
"note_icon": {
"category": "Категория:",
@ -1334,16 +1335,10 @@
"error_fetching": "Ошибка получения списка моделей: {{error}}",
"index_rebuild_status_error": "Ошибка проверки статуса перестроения индекса",
"enhanced_context_description": "Предоставляет ИИ больше контекста из заметки и связанных с ней заметок для более точных ответов",
"n_notes_queued_0": "{{ count }} заметка в очереди на индексирование",
"n_notes_queued_1": "{{ count }} заметки в очереди на индексирование",
"n_notes_queued_2": "{{ count }} заметок в очереди на индексирование",
"no_models_found_ollama": "Модели Ollama не найдены. Проверьте, запущена ли Ollama.",
"no_models_found_online": "Модели не найдены. Проверьте ваш ключ API и настройки.",
"experimental_warning": "Функция LLM в настоящее время является экспериментальной — вы предупреждены.",
"ollama_no_url": "Ollama не настроена. Введите корректный URL-адрес.",
"notes_indexed_0": "{{ count }} заметка проиндексирована",
"notes_indexed_1": "{{ count }} заметки проиндексировано",
"notes_indexed_2": "{{ count }} заметок проиндексировано",
"show_thinking_description": "Показать цепочку мыслительного процесса ИИ",
"api_key_tooltip": "API-ключ для доступа к сервису",
"all_notes_queued_for_retry": "Все неудачные заметки поставлены в очередь на повторную попытку",

View File

@ -1,496 +1,488 @@
{
"about": {
"title": "O Trilium Belеškama",
"homepage": "Početna stranica:",
"app_version": "Verzija aplikacije:",
"db_version": "Verzija baze podataka:",
"sync_version": "Verzija sinhronizacije:",
"build_date": "Datum izgradnje:",
"build_revision": "Revizija izgradnje:",
"data_directory": "Direktorijum sa podacima:"
"about": {
"title": "O Trilium Belеškama",
"homepage": "Početna stranica:",
"app_version": "Verzija aplikacije:",
"db_version": "Verzija baze podataka:",
"sync_version": "Verzija sinhronizacije:",
"build_date": "Datum izgradnje:",
"build_revision": "Revizija izgradnje:",
"data_directory": "Direktorijum sa podacima:"
},
"toast": {
"critical-error": {
"title": "Kritična greška",
"message": "Došlo je do kritične greške koja sprečava pokretanje klijentske aplikacije.\n\n{{message}}\n\nOva greška je najverovatnije izazvana neočekivanim problemom prilikom izvršavanja skripte. Pokušajte da pokrenete aplikaciju u bezbednom režimu i da pronađete šta izaziva grešku."
},
"toast": {
"critical-error": {
"title": "Kritična greška",
"message": "Došlo je do kritične greške koja sprečava pokretanje klijentske aplikacije.\n\n{{message}}\n\nOva greška je najverovatnije izazvana neočekivanim problemom prilikom izvršavanja skripte. Pokušajte da pokrenete aplikaciju u bezbednom režimu i da pronađete šta izaziva grešku."
},
"widget-error": {
"title": "Pokretanje vidžeta nije uspelo",
"message-custom": "Prilagođeni viđet sa beleške sa ID-jem \"{{id}}\", nazivom \"{{title}}\" nije uspeo da se pokrene zbog:\n\n{{message}}",
"message-unknown": "Nepoznati vidžet nije mogao da se pokrene zbog:\n\n{{message}}"
},
"bundle-error": {
"title": "Pokretanje prilagođene skripte neuspešno",
"message": "Skripta iz beleške sa ID-jem \"{{id}}\", naslovom \"{{title}}\" nije mogla da se izvrši zbog:\n\n{{message}}"
}
"widget-error": {
"title": "Pokretanje vidžeta nije uspelo",
"message-custom": "Prilagođeni viđet sa beleške sa ID-jem \"{{id}}\", nazivom \"{{title}}\" nije uspeo da se pokrene zbog:\n\n{{message}}",
"message-unknown": "Nepoznati vidžet nije mogao da se pokrene zbog:\n\n{{message}}"
},
"add_link": {
"add_link": "Dodaj link",
"help_on_links": "Pomoć na linkovima",
"note": "Beleška",
"search_note": "potražite belešku po njenom imenu",
"link_title_mirrors": "naziv linka preslikava trenutan naziv beleške",
"link_title_arbitrary": "naziv linka se može proizvoljno menjati",
"link_title": "Naziv linka",
"button_add_link": "Dodaj link <kbd>enter</kbd>"
},
"branch_prefix": {
"edit_branch_prefix": "Izmeni prefiks grane",
"help_on_tree_prefix": "Pomoć na prefiksu Drveta",
"prefix": "Prefiks: ",
"save": "Sačuvaj",
"branch_prefix_saved": "Prefiks grane je sačuvan."
},
"bulk_actions": {
"bulk_actions": "Grupne akcije",
"affected_notes": "Pogođene beleške",
"include_descendants": "Obuhvati potomke izabranih beleški",
"available_actions": "Dostupne akcije",
"chosen_actions": "Izabrane akcije",
"execute_bulk_actions": "Izvrši grupne akcije",
"bulk_actions_executed": "Grupne akcije su uspešno izvršene.",
"none_yet": "Nijedna za sad... dodajte akciju tako što ćete pritisnuti na neku od dostupnih akcija iznad.",
"labels": "Oznake",
"relations": "Odnosi",
"notes": "Beleške",
"other": "Ostalo"
},
"clone_to": {
"clone_notes_to": "Klonirajte beleške u...",
"help_on_links": "Pomoć na linkovima",
"notes_to_clone": "Beleške za kloniranje",
"target_parent_note": "Ciljna nadređena beleška",
"search_for_note_by_its_name": "potražite belešku po njenom imenu",
"cloned_note_prefix_title": "Klonirana beleška će biti prikazana u drvetu beleški sa datim prefiksom",
"prefix_optional": "Prefiks (opciono)",
"clone_to_selected_note": "Kloniranje u izabranu belešku <kbd>enter</kbd>",
"no_path_to_clone_to": "Nema putanje za kloniranje.",
"note_cloned": "Beleška \"{{clonedTitle}}\" je klonirana u \"{{targetTitle}}\""
},
"confirm": {
"confirmation": "Potvrda",
"cancel": "Otkaži",
"ok": "U redu",
"are_you_sure_remove_note": "Da li ste sigurni da želite da uklonite belešku \"{{title}}\" iz mape odnosa? ",
"if_you_dont_check": "Ako ne izaberete ovo, beleška će biti uklonjena samo sa mape odnosa.",
"also_delete_note": "Takođe obriši belešku"
},
"delete_notes": {
"delete_notes_preview": "Obriši pregled beleške",
"close": "Zatvori",
"delete_all_clones_description": "Obriši i sve klonove (može biti poništeno u skorašnjim izmenama)",
"erase_notes_description": "Normalno (blago) brisanje samo označava beleške kao obrisane i one mogu biti vraćene (u dijalogu skorašnjih izmena) u određenom vremenskom periodu. Biranje ove opcije će momentalno obrisati beleške i ove beleške neće biti moguće vratiti.",
"erase_notes_warning": "Trajno obriši beleške (ne može se opozvati), uključujući sve klonove. Ovo će prisiliti aplikaciju da se ponovo pokrene.",
"notes_to_be_deleted": "Sledeće beleške će biti obrisane ({{- noteCount}})",
"no_note_to_delete": "Nijedna beleška neće biti obrisana (samo klonovi).",
"broken_relations_to_be_deleted": "Sledeći odnosi će biti prekinuti i obrisani ({{- relationCount}})",
"cancel": "Otkaži",
"ok": "U redu",
"deleted_relation_text": "Beleška {{- note}} (za brisanje) je referencirana sa odnosom {{- relation}} koji potiče iz {{- source}}."
},
"export": {
"export_note_title": "Izvezi belešku",
"close": "Zatvori",
"export_type_subtree": "Ova beleška i svi njeni potomci",
"format_html": "HTML - preporučuje se jer čuva formatiranje",
"format_html_zip": "HTML u ZIP arhivi - ovo se preporučuje jer se na taj način čuva celokupno formatiranje.",
"format_markdown": "Markdown - ovo čuva većinu formatiranja.",
"format_opml": "OPML - format za razmenu okvira samo za tekst. Formatiranje, slike i datoteke nisu uključeni.",
"opml_version_1": "OPML v1.0 - samo običan tekst",
"opml_version_2": "OPML v2.0 - dozvoljava i HTML",
"export_type_single": "Samo ovu belešku bez njenih potomaka",
"export": "Izvoz",
"choose_export_type": "Molimo vas da prvo izaberete tip izvoza",
"export_status": "Status izvoza",
"export_in_progress": "Izvoz u toku: {{progressCount}}",
"export_finished_successfully": "Izvoz je uspešno završen.",
"format_pdf": "PDF - za namene štampanja ili deljenja."
},
"help": {
"noteNavigation": "Navigacija beleški",
"goUpDown": "<kbd>UP</kbd>, <kbd>DOWN</kbd> - kretanje gore/dole u listi sa beleškama",
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - sakupi/proširi čvor",
"notSet": "nije podešeno",
"goBackForwards": "idi u nazad/napred kroz istoriju",
"showJumpToNoteDialog": "prikaži <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Idi na\" dijalog</a>",
"scrollToActiveNote": "skroluj do aktivne beleške",
"jumpToParentNote": "idi do nadređene beleške",
"collapseWholeTree": "sakupi celo drvo beleški",
"collapseSubTree": "sakupi pod-drvo",
"tabShortcuts": "Prečice na karticama",
"newTabNoteLink": "na link beleške otvara belešku u novoj kartici",
"newTabWithActivationNoteLink": "na link beleške otvara i aktivira belešku u novoj kartici",
"onlyInDesktop": "Samo na dektop-u (Electron verzija)",
"openEmptyTab": "otvori praznu karticu",
"closeActiveTab": "zatvori aktivnu karticu",
"activateNextTab": "aktiviraj narednu karticu",
"activatePreviousTab": "aktiviraj prethodnu karticu",
"creatingNotes": "Pravljenje beleški",
"createNoteAfter": "napravi novu belešku nakon aktivne beleške",
"createNoteInto": "napravi novu pod-belešku u aktivnoj belešci",
"editBranchPrefix": "izmeni <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">prefiks</a> klona aktivne beleške",
"movingCloningNotes": "Premeštanje / kloniranje beleški",
"moveNoteUpDown": "pomeri belešku gore/dole u listi beleški",
"moveNoteUpHierarchy": "pomeri belešku na gore u hijerarhiji",
"multiSelectNote": "višestruki izbor beleški iznad/ispod",
"selectAllNotes": "izaberi sve beleške u trenutnom nivou",
"selectNote": "izaberi belešku",
"copyNotes": "kopiraj aktivnu belešku (ili trenutni izbor) u privremenu memoriju (koristi se za <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">kloniranje</a>)",
"cutNotes": "iseci trenutnu belešku (ili trenutni izbor) u privremenu memoriju (koristi se za premeštanje beleški)",
"pasteNotes": "nalepi belešku/e kao podbelešku u aktivnoj belešci (koja se ili premešta ili klonira u zavisnosti od toga da li je beleška kopirana ili isečena u privremenu memoriju)",
"deleteNotes": "obriši belešku / podstablo",
"editingNotes": "Izmena beleški",
"editNoteTitle": "u ravni drveta će se prebaciti sa ravni drveta na naslov beleške. Ulaz sa naslova beleške će prebaciti fokus na uređivač teksta. <kbd>Ctrl+.</kbd> će se vratiti sa uređivača na ravan drveta.",
"createEditLink": "napravi / izmeni spoljašnji link",
"createInternalLink": "napravi unutrašnji link",
"followLink": "prati link ispod kursora",
"insertDateTime": "ubaci trenutan datum i vreme na poziciju kursora",
"jumpToTreePane": "idi na ravan stabla i pomeri se do aktivne beleške",
"markdownAutoformat": "Autoformatiranje kao u Markdown-u",
"headings": "<code>##</code>, <code>###</code>, <code>####</code> itd. praćeno razmakom za naslove",
"bulletList": "<code>*</code> ili <code>-</code> praćeno razmakom za listu sa tačkama",
"numberedList": "<code>1.</code> ili <code>1)</code> praćeno razmakom za numerisanu listu",
"blockQuote": "započnite liniju sa <code>></code> praćeno sa razmakom za blok citat",
"troubleshooting": "Rešavanje problema",
"reloadFrontend": "ponovo učitaj Trilium frontend",
"showDevTools": "prikaži alate za programere",
"showSQLConsole": "prikaži SQL konzolu",
"other": "Ostalo",
"quickSearch": "fokus na unos za brzu pretragu",
"inPageSearch": "pretraga unutar stranice"
},
"import": {
"importIntoNote": "Uvezi u belešku",
"chooseImportFile": "Izaberi datoteku za uvoz",
"importDescription": "Sadržaj izabranih datoteka će biti uvezen kao podbeleške u",
"options": "Opcije",
"safeImportTooltip": "Trilium <code>.zip</code> izvozne datoteke mogu da sadrže izvršne skripte koje mogu imati štetno ponašanje. Bezbedan uvoz će deaktivirati automatsko izvršavanje svih uvezenih skripti. Isključite \"Bezbedan uvoz\" samo ako uvezena arhiva treba da sadrži izvršne skripte i ako potpuno verujete sadržaju uvezene datoteke.",
"safeImport": "Bezbedan uvoz",
"explodeArchivesTooltip": "Ako je ovo označeno onda će Trilium pročitati <code>.zip</code>, <code>.enex</code> i <code>.opml</code> datoteke i napraviti beleške od datoteka unutar tih arhiva. Ako nije označeno, Trilium će same arhive priložiti belešci.",
"explodeArchives": "Pročitaj sadržaj <code>.zip</code>, <code>.enex</code> i <code>.opml</code> arhiva.",
"shrinkImagesTooltip": "<p>Ako označite ovu opciju, Trilium će pokušati da smanji uvezene slike skaliranjem i optimizacijom što će možda uticati na kvalitet slike. Ako nije označeno, slike će biti uvezene bez promena.</p><p>Ovo se ne primenjuje na <code>.zip</code> uvoze sa metapodacima jer se tada podrazumeva da su te datoteke već optimizovane.</p>",
"shrinkImages": "Smanji slike",
"textImportedAsText": "Uvezi HTML, Markdown i TXT kao tekstualne beleške ako je nejasno iz metapodataka",
"codeImportedAsCode": "Uvezi prepoznate datoteke sa kodom (poput <code>.json</code>) ako beleške sa kodom ako nije jasno iz metapodataka",
"replaceUnderscoresWithSpaces": "Zameni podvlake sa razmacima u nazivima uvezenih beleški",
"import": "Uvezi",
"failed": "Uvoz nije uspeo: {{message}}.",
"html_import_tags": {
"title": "HTML oznake za uvoz",
"description": "Podesite koje HTML oznake trebaju biti sačuvane kada se uvoze beleške. Oznake koje se ne nalaze na listi će biti uklonjene tokom uvoza. Pojedine oznake (poput 'script') se uvek uklanjaju zbog bezbednosti.",
"placeholder": "Unesite HTML oznake, po jednu u svaki red",
"reset_button": "Vrati na podrazumevanu listu"
},
"import-status": "Status uvoza",
"in-progress": "Uvoz u toku: {{progress}}",
"successful": "Uvoz je uspešno završen."
},
"include_note": {
"dialog_title": "Uključi belešku",
"label_note": "Beleška",
"placeholder_search": "pretraži belešku po njenom imenu",
"box_size_prompt": "Veličina kutije priložene beleške:",
"box_size_small": "mala (~ 10 redova)",
"box_size_medium": "srednja (~ 30 redova)",
"box_size_full": "puna (kutija prikazuje ceo tekst)",
"button_include": "Uključi belešku"
},
"info": {
"modalTitle": "Informativna poruka",
"closeButton": "Zatvori",
"okButton": "U redu"
},
"jump_to_note": {
"search_placeholder": "Pretraži belešku po njenom imenu ili unesi > za komande...",
"search_button": "Pretraga u punom tekstu <kbd>Ctrl+Enter</kbd>"
},
"markdown_import": {
"dialog_title": "Uvoz za Markdown",
"modal_body_text": "Zbog Sandbox-a pretraživača nije moguće direktno učitati privremenu memoriju iz JavaScript-a. Molimo vas da nalepite Markdown za uvoz u tekstualno polje ispod i kliknete na dugme za uvoz",
"import_button": "Uvoz",
"import_success": "Markdown sadržaj je učitan u dokument."
},
"move_to": {
"dialog_title": "Premesti beleške u ...",
"notes_to_move": "Beleške za premeštanje",
"target_parent_note": "Ciljana nadbeleška",
"search_placeholder": "potraži belešku po njenom imenu",
"move_button": "Pređi na izabranu belešku",
"error_no_path": "Nema putanje za premeštanje.",
"move_success_message": "Izabrane beleške su premeštene u "
},
"note_type_chooser": {
"change_path_prompt": "Promenite gde će se napraviti nova beleška:",
"search_placeholder": "pretraži putanju po njenom imenu (podrazumevano ako je prazno)",
"modal_title": "Izaberite tip beleške",
"modal_body": "Izaberite tip beleške / šablon za novu belešku:",
"templates": "Šabloni"
},
"password_not_set": {
"title": "Lozinka nije podešena",
"body1": "Zaštićene beleške su enkriptovane sa korisničkom lozinkom, ali lozinka još uvek nije podešena.",
"body2": "Za biste mogli da sačuvate beleške, kliknite <a class=\"open-password-options-button\" href=\"javascript:\">ovde</a> da otvorite dijalog sa Opcijama i podesite svoju lozinku."
},
"prompt": {
"title": "Upit",
"ok": "U redu <kbd>enter</kbd>",
"defaultTitle": "Upit"
},
"protected_session_password": {
"modal_title": "Zaštićena sesija",
"help_title": "Pomoć za Zaštićene beleške",
"close_label": "Zatvori",
"form_label": "Da biste nastavili sa traženom akcijom moraćete započeti zaštićenu sesiju tako što ćete uneti lozinku:",
"start_button": "Započni zaštićenu sesiju"
},
"recent_changes": {
"title": "Nedavne promene",
"erase_notes_button": "Obriši izabrane beleške odmah",
"deleted_notes_message": "Obrisane beleške su uklonjene.",
"no_changes_message": "Još uvek nema izmena...",
"undelete_link": "poništi brisanje",
"confirm_undelete": "Da li želite da poništite brisanje ove beleške i njenih podbeleški?"
},
"revisions": {
"note_revisions": "Revizije beleški",
"delete_all_revisions": "Obriši sve revizije ove beleške",
"delete_all_button": "Obriši sve revizije",
"help_title": "Pomoć za Revizije beleški",
"confirm_delete_all": "Da li želite da obrišete sve revizije ove beleške?",
"no_revisions": "Još uvek nema revizija za ovu belešku...",
"restore_button": "Vrati",
"confirm_restore": "Da li želite da vratite ovu reviziju? Ovo će prepisati trenutan naslov i sadržaj beleške sa ovom revizijom.",
"delete_button": "Obriši",
"confirm_delete": "Da li želite da obrišete ovu reviziju?",
"revisions_deleted": "Revizije beleške su obrisane.",
"revision_restored": "Revizija beleške je vraćena.",
"revision_deleted": "Revizija beleške je obrisana.",
"snapshot_interval": "Interval snimanja revizije beleške: {{seconds}}s.",
"maximum_revisions": "Ograničenje broja slika revizije beleške: {{number}}.",
"settings": "Podešavanja revizija beleški",
"download_button": "Preuzmi",
"mime": "MIME: ",
"file_size": "Veličina datoteke:",
"preview": "Pregled:",
"preview_not_available": "Pregled nije dostupan za ovaj tip beleške."
},
"sort_child_notes": {
"sort_children_by": "Sortiranje podbeleški po...",
"sorting_criteria": "Kriterijum za sortiranje",
"title": "naslov",
"date_created": "datum kreiranja",
"date_modified": "datum izmene",
"sorting_direction": "Smer sortiranja",
"ascending": "uzlazni",
"descending": "silazni",
"folders": "Fascikle",
"sort_folders_at_top": "sortiraj fascikle na vrh",
"natural_sort": "Prirodno sortiranje",
"sort_with_respect_to_different_character_sorting": "sortiranje sa poštovanjem različitih pravila sortiranja karaktera i kolacija u različitim jezicima ili regionima.",
"natural_sort_language": "Jezik za prirodno sortiranje",
"the_language_code_for_natural_sort": "Kod jezika za prirodno sortiranje, npr. \"zh-CN\" za Kineski.",
"sort": "Sortiraj"
},
"upload_attachments": {
"upload_attachments_to_note": "Otpremite priloge uz belešku",
"choose_files": "Izaberite datoteke",
"files_will_be_uploaded": "Datoteke će biti otpremljene kao prilozi u {{noteTitle}}",
"options": "Opcije",
"shrink_images": "Smanji slike",
"upload": "Otpremi",
"tooltip": "Ako je označeno, Trilium će pokušati da smanji otpremljene slike skaliranjem i optimizacijom što može uticati na kvalitet slike. Ako nije označeno, slike će biti otpremljene bez izmena."
},
"attribute_detail": {
"attr_detail_title": "Naslov detalja atributa",
"close_button_title": "Otkaži izmene i zatvori",
"attr_is_owned_by": "Atribut je u vlasništvu",
"attr_name_title": "Naziv atributa može biti sastavljen samo od alfanumeričkih znakova, dvotačke i donje crte",
"name": "Naziv",
"value": "Vrednost",
"target_note_title": "Relacija je imenovana veza između izvorne beleške i ciljne beleške.",
"target_note": "Ciljna beleška",
"promoted_title": "Promovisani atribut je istaknut na belešci.",
"promoted": "Promovisan",
"promoted_alias_title": "Naziv koji će biti prikazan u korisničkom interfejsu promovisanih atributa.",
"promoted_alias": "Pseudonim",
"multiplicity_title": "Multiplicitet definiše koliko atributa sa istim nazivom se može napraviti - najviše 1 ili više od 1.",
"multiplicity": "Multiplicitet",
"single_value": "Jednostruka vrednost",
"multi_value": "Višestruka vrednost",
"label_type_title": "Tip oznake će pomoći Triliumu da izabere odgovarajući interfejs za unos vrednosti oznake.",
"label_type": "Tip",
"text": "Tekst",
"number": "Broj",
"boolean": "Boolean",
"date": "Datum",
"date_time": "Datum i vreme",
"time": "Vreme",
"url": "URL",
"precision_title": "Broj cifara posle zareza treba biti dostupan u interfejsu za postavljanje vrednosti.",
"precision": "Preciznost",
"digits": "cifre",
"inverse_relation_title": "Opciono podešavanje za definisanje kojoj relaciji je ova suprotna. Primer: Otac - Sin su inverzne relacije jedna drugoj.",
"inverse_relation": "Inverzna relacija",
"inheritable_title": "Atributi koji mogu da se nasleđuju će biti nasleđeni od strane svih potomaka unutar ovog stabla.",
"inheritable": "Nasledno",
"save_and_close": "Sačuvaj i zatvori <kbd>Ctrl+Enter</kbd>",
"delete": "Obriši",
"related_notes_title": "Druge beleške sa ovom oznakom",
"more_notes": "Još beleški",
"label": "Detalji oznake",
"label_definition": "Detalji definicije oznake",
"relation": "Detalji relacije",
"relation_definition": "Detalji definicije relacije",
"disable_versioning": "onemogućava auto-verzionisanje. Korisno za npr. velike, ali nebitne beleške - poput velikih JS biblioteka koje se koriste za skripte",
"calendar_root": "obeležava belešku koju treba koristiti kao osnova za dnevne beleške. Samo jedna beleška treba da bude označena kao takva.",
"archived": "beleške sa ovom oznakom neće biti podrazumevano vidljive u rezultatima pretrage (kao ni u dijalozima za Idi na, Dodaj link, itd.).",
"exclude_from_export": "beleške (sa svojim podstablom) neće biti uključene u bilo koji izvoz beleški",
"run": "definiše u kojim događajima se skripta pokreće. Moguće vrednosti su:\n<ul>\n<li>frontendStartup - kada se pokrene Trilium frontend (ili se osveži), ali ne na mobilnom uređaju.</li>\n<li>mobileStartup - kada se pokrene Trilium frontend (ili se osveži), na mobilnom uređaju..</li>\n<li>backendStartup - kada se Trilium backend pokrene</li>\n<li>hourly - pokreće se svaki sat. Može se koristiti dodatna oznaka <code>runAtHour</code> da se označi u kom satu.</li>\n<li>daily - pokreće se jednom dnevno</li>\n</ul>",
"run_on_instance": "Definiše u kojoj instanci Trilium-a ovo treba da se pokreće. Podrazumevano podešavanje je na svim instancama.",
"run_at_hour": "U kom satu ovo treba da se pokreće. Treba se koristiti zajedno sa <code>#run=hourly</code>. Može biti definisano više puta za više pokretanja u toku dana.",
"disable_inclusion": "skripte sa ovom oznakom neće biti uključene u izvršavanju nadskripte.",
"sorted": "čuva podbeleške sortirane alfabetski po naslovu",
"sort_direction": "Uzlazno (podrazumevano) ili silazno",
"sort_folders_first": "Fascikle (beleške sa podbeleškama) treba da budu sortirane na vrhu",
"top": "zadrži datu belešku na vrhu njene nadbeleške (primenjuje se samo na sortiranim nadbeleškama)",
"hide_promoted_attributes": "Sakrij promovisane atribute na ovoj belešci",
"read_only": "uređivač je u režimu samo za čitanje. Radi samo za tekst i beleške sa kodom.",
"auto_read_only_disabled": "beleške sa tekstom/kodom se mogu automatski podesiti u režim za čitanje kada su prevelike. Ovo ponašanje možete onemogućiti pojedinačno za belešku dodavanjem ove oznake na belešku",
"app_css": "označava CSS beleške koje nisu učitane u Trilium aplikaciju i zbog toga se mogu koristiti za menjanje izgleda Triliuma.",
"app_theme": "označava CSS beleške koje su pune Trilium teme i stoga su dostupne u Trilium podešavanjima.",
"app_theme_base": "podesite na „sledeće“, „sledeće-svetlo“ ili „sledeće-tamno“ da biste koristili odgovarajuću TriliumNext temu (automatsku, svetlu ili tamnu) kao osnovu za prilagođenu temu, umesto podrazumevane teme.",
"css_class": "vrednost ove oznake se zatim dodaje kao CSS klasa čvoru koji predstavlja datu belešku u stablu. Ovo može biti korisno za napredno temiranje. Može se koristiti u šablonima beleški.",
"workspace": "označava ovu belešku kao radni prostor što omogućava lako podizanje",
"workspace_icon_class": "definiše CSS klasu ikone okvira koja će se koristiti u kartici kada se podigne na ovoj belešci",
"workspace_tab_background_color": "CSS boja korišćena u kartici beleške kada se prebaci na ovu belešku",
"workspace_calendar_root": "Definiše koren kalendara za svaki radni prostor",
"workspace_template": "Ova beleška će se pojaviti u izboru dostupnih šablona prilikom kreiranja nove beleške, ali samo kada se podigne u radni prostor koji sadrži ovaj šablon",
"search_home": "nove beleške o pretrazi biće kreirane kao podređeni delovi ove beleške",
"workspace_search_home": "nove beleške o pretrazi biće kreirane kao podređeni delovi ove beleške kada se podignu na nekog pretka ove beleške iz radnog prostora",
"inbox": "podrazumevana lokacija u prijemnom sandučetu za nove beleške - kada kreirate belešku pomoću dugmeta „nova beleška“ u bočnoj traci, beleške će biti kreirane kao podbeleške u belešci označenoj sa oznakom <code>#inbox</code>.",
"workspace_inbox": "podrazumevana lokacija prijemnog sandučeta za nove beleške kada se prebace na nekog pretka ove beleške iz radnog prostora",
"sql_console_home": "podrazmevana lokacija beleški SQL konzole",
"bookmark_folder": "beleška sa ovom oznakom će se pojaviti u obeleživačima kao fascikla (omogućavajući pristup njenim podređenim fasciklama)",
"share_hidden_from_tree": "ova beleška je skrivena u levom navigacionom stablu, ali je i dalje dostupna preko svoje URL adrese",
"share_external_link": "beleška će služiti kao veza ka eksternoj veb stranici u stablu deljenja",
"share_alias": "definišite alias pomoću kog će beleška biti dostupna na https://your_trilium_host/share/[your_alias]",
"share_omit_default_css": "CSS kod podrazumevane stranice za deljenje će biti izostavljen. Koristite ga kada pravite opsežne promene stila.",
"share_root": "obeležava belešku koja se prikazuje na /share korenu.",
"share_description": "definišite tekst koji će se dodati HTML meta oznaci za opis",
"share_raw": "beleška će biti prikazana u svom sirovom (raw) formatu, bez HTML omotača",
"share_disallow_robot_indexing": "zabraniće robotsko indeksiranje ove beleške putem zaglavlja <code>X-Robots-Tag: noindex</code>",
"share_credentials": "potrebni su kredencijali za pristup ovoj deljenoj belešci. Očekuje se da vrednost bude u formatu „korisničko ime:lozinka“. Ne zaboravite da ovo označite kao nasledno da bi se primenilo na podbeleške/slike.",
"share_index": "beleška sa ovom oznakom će izlistati sve korene deljenih beleški",
"display_relations": "imena relacija razdvojenih zarezima koja treba da budu prikazana. Sva ostala će biti skrivena.",
"hide_relations": "imena relacija razdvojenih zarezima koja treba da budu skrivena. Sva ostala će biti prikazana.",
"title_template": "podrazumevani naslov beleški kreiranih kao deca ove beleške. Vrednost se procenjuje kao JavaScript string \n i stoga se može obogatiti dinamičkim sadržajem putem ubrizganih promenljivih <code>now</code> and <code>parentNote</code>. Primeri:\n \n <ul>\n <li><code>${parentNote.getLabelValue('authorName')}'s literary works</code></li>\n <li><code>Log for ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Pogledati <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">wiki sa detaljima</a>, API dokumentacija za <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> i <a href=\"https://day.js.org/docs/en/display/format\">now</a> za detalje.",
"template": "Ova beleška će biti prikazana u izboru dostupnih šablona prilikom pravljenja nove beleške",
"toc": "<code>#toc</code> ili <code>#toc=show</code> će pristiliti Sadržaj (Table of Contents) da bude prikazan, <code>#toc=hide</code> prisiliti njegovo sakrivanje. Ako oznaka ne postoji, ponašanje će biti usklađeno sa globalnim podešavanjem",
"color": "definiše boju beleške u stablu beleški, linkovima itd. Koristite bilo koju važeću CSS vrednost boje kao što je „crvena“ ili #a13d5f",
"keyboard_shortcut": "Definiše prečicu na tastaturi koja će odmah preći na ovu belešku. Primer: „ctrl+alt+e“. Potrebno je ponovno učitavanje frontenda da bi promena stupila na snagu.",
"keep_current_hoisting": "Otvaranje ove veze neće promeniti podizanje čak i ako beleška nije prikazana u trenutno podignutom podstablu.",
"execute_button": "Naslov dugmeta koje će izvršiti trenutnu belešku sa kodom",
"execute_description": "Duži opis trenutne beleške sa kodom prikazan je zajedno sa dugmetom za izvršavanje",
"exclude_from_note_map": "Beleške sa ovom oznakom biće skrivene sa mape beleški",
"new_notes_on_top": "Nove beleške će biti napravljene na vrhu matične beleške, a ne na dnu.",
"hide_highlight_widget": "Sakrij vidžet sa listom istaknutih",
"run_on_note_creation": "izvršava se kada se beleška napravi na serverskoj strani. Koristite ovu relaciju ako želite da pokrenete skriptu za sve beleške napravljene u okviru određenog podstabla. U tom slučaju, kreirajte je na korenu beleške podstabla i učinite je naslednom. Nova beleška napravljena unutar podstabla (bilo koje dubine) pokrenuće skriptu.",
"run_on_child_note_creation": "izvršava se kada se napravi nova beleška ispod beleške gde je ova relacija definisana",
"run_on_note_title_change": "izvršava se kada se promeni naslov beleške (uključuje i pravljenje beleške)",
"run_on_note_content_change": "izvršava se kada se promeni sadržaj beleške (uključuje i pravljenje beleške).",
"run_on_note_change": "izvršava se kada se promeni beleška (uključuje i pravljenje beleške). Ne uključuje promene sadržaja",
"icon_class": "vrednost ove oznake se dodaje kao CSS klasa ikoni na stablu što može pomoći u vizuelnom razlikovanju beleški u stablu. Primer može biti bx bx-home - ikone su preuzete iz boxicons. Može se koristiti u šablonima beleški.",
"page_size": "broj stavki po stranici u listi beleški",
"custom_request_handler": "pogledajte <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Prilagođeni obrađivač zahteva</a>",
"custom_resource_provider": "pogledajte <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Prilagođeni obrađivač zahteva</a>",
"widget": "označava ovu belešku kao prilagođeni vidžet koji će biti dodat u stablo komponenti Trilijuma",
"run_on_note_deletion": "izvršava se kada se beleška briše",
"run_on_branch_creation": "izvršava se kada se pravi grana. Grana je veza između matične i podređene beleške i pravi se npr. prilikom kloniranja ili premeštanja beleške.",
"run_on_branch_change": "izvršava se kada se grana ažurira.",
"run_on_branch_deletion": "izvršava se kada se grana briše. Grana je veza između nadređene beleške i podređene beleške i briše se npr. prilikom premeštanja beleške (stara grana/veza se briše).",
"run_on_attribute_creation": "izvršava se kada se pravi novi atribut za belešku koji definiše ovu relaciju",
"run_on_attribute_change": " izvršava se kada se promeni atribut beleške koja definiše ovu relaciju. Ovo se pokreće i kada se atribut obriše",
"relation_template": "atributi beleške će biti nasleđeni čak i bez odnosa roditelj-dete, sadržaj i podstablo beleške će biti dodati instanci beleške ako je prazna. Pogledajte dokumentaciju za detalje.",
"inherit": "Atributi beleške će biti nasleđeni čak i bez odnosa roditelj-dete. Pogledajte relaciju šablona za sličan koncept. Pogledajte nasleđivanje atributa u dokumentaciji.",
"render_note": "Beleške tipa „render HTML note“ će biti prikazane korišćenjem beleške za kod (HTML ili skripte) i potrebno je pomoću ove relacije ukazati na to koja beleška treba da se prikaže",
"widget_relation": "meta ove relacije će biti izvršena i prikazana kao vidžet u bočnoj traci",
"share_css": "CSS napomena koja će biti ubrizgana na stranicu za deljenje. CSS napomena mora biti i u deljenom podstablu. Razmotrite i korišćenje „share_hidden_from_tree“ i „share_omit_default_css“.",
"share_js": "JavaScript beleška koja će biti ubrizgana na stranicu za deljenje. JS beleška takođe mora biti u deljenom podstablu. Razmislite o korišćenju „share_hidden_from_tree“.",
"share_template": "Ugrađena JavaScript beleška koja će se koristiti kao šablon za prikazivanje deljene beleške. U slučaju neuspeha vraća se na podrazumevani šablon. Razmislite o korišćenju „share_hidden_from_tree“.",
"share_favicon": "Favicon beleška koju treba postaviti na deljenu stranicu. Obično je potrebno da je podesite da deli koren i učinite je naslednom. Favicon beleška takođe mora biti u deljenom podstablu. Razmislite o korišćenju „share_hidden_from_tree“.",
"is_owned_by_note": "je u vlasništvu beleške",
"other_notes_with_name": "Ostale beleške sa {{attributeType}} nazivom „{{attributeName}}“",
"and_more": "... i još {{count}}.",
"print_landscape": "Prilikom izvoza u PDF, menja orijentaciju stranice u pejzažnu umesto uspravne.",
"print_page_size": "Prilikom izvoza u PDF, menja veličinu stranice. Podržane vrednosti: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
"color_type": "Boja"
},
"ai_llm": {
"n_notes_queued_0": "{{ count }} beleška stavljena u red za indeksiranje",
"n_notes_queued_1": "{{ count }} beleški stavljeno u red za indeksiranje",
"n_notes_queued_2": "{{ count }} beleški stavljeno u red za indeksiranje",
"notes_indexed_0": "{{ count }} beleška je indeksirana",
"notes_indexed_1": "{{ count }} beleški je indeksirano",
"notes_indexed_2": "{{ count }} beleški je indeksirano"
},
"attribute_editor": {
"help_text_body1": "Da biste dodali oznaku, samo unesite npr. <code>#rock</code> ili ako želite da dodate i vrednost, onda npr. <code>#year = 2020</code>",
"help_text_body2": "Za relaciju, unesite <code>~author = @</code> što bi trebalo da otvori automatsko dovršavanje gde možete potražiti željenu belešku.",
"help_text_body3": "Alternativno, možete dodati oznaku i relaciju pomoću dugmeta <code>+</code> sa desne strane.",
"save_attributes": "Sačuvaj atribute <enter>",
"add_a_new_attribute": "Dodajte novi atribut",
"add_new_label": "Dodajte novu oznaku <kbd data-command=\"addNewLabel\"></kbd>",
"add_new_relation": "Dodajte novu relaciju <kbd data-command=\"addNewRelation\"></kbd>",
"add_new_label_definition": "Dodajte novu definiciju oznake",
"add_new_relation_definition": "Dodajte novu definiciju relacije",
"placeholder": "Ovde unesite oznake i relacije"
},
"abstract_bulk_action": {
"remove_this_search_action": "Ukloni ovu radnju pretrage"
},
"execute_script": {
"execute_script": "Izvrši skriptu",
"help_text": "Možete izvršiti jednostavne skripte na podudarnim beleškama.",
"example_1": "Na primer, da biste dodali string u naslov beleške, koristite ovu malu skriptu:",
"example_2": "Složeniji primer bi bio brisanje svih atributa podudarnih beleški:"
},
"add_label": {
"add_label": "Dodaj oznaku",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crta i dvotačka su dozvoljeni znakovi.",
"to_value": "za vrednost",
"new_value_placeholder": "nova vrednost",
"help_text": "Na svim podudarnim beleškama:",
"help_text_item1": "dodajte datu oznaku ako beleška još uvek nema jednu",
"help_text_item2": "ili izmenite vrednost postojeće oznake",
"help_text_note": "Takođe možete pozvati ovu metodu bez vrednosti, u tom slučaju će oznaka biti dodeljena belešci bez vrednosti."
},
"delete_label": {
"delete_label": "Obriši oznaku",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi."
},
"rename_label": {
"rename_label": "Preimenuj oznaku",
"rename_label_from": "Preimenuj oznaku iz",
"old_name_placeholder": "stari naziv",
"to": "U",
"new_name_placeholder": "novi naziv",
"name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi."
},
"update_label_value": {
"update_label_value": "Ažuriraj vrednost oznake",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi.",
"to_value": "u vrednost",
"new_value_placeholder": "nova vrednost",
"help_text": "Na svim podudarnim beleškama, promenite vrednost postojeće oznake.",
"help_text_note": "Takođe možete pozvati ovu metodu bez vrednosti, u tom slučaju će oznaka biti dodeljena belešci bez vrednosti."
},
"delete_note": {
"delete_note": "Obriši belešku",
"delete_matched_notes": "Obriši podudarne beleške",
"delete_matched_notes_description": "Ovo će obrisati podudarne beleške.",
"undelete_notes_instruction": "Nakon brisanja, moguće ga je poništiti iz dijaloga Nedavne izmene."
"bundle-error": {
"title": "Pokretanje prilagođene skripte neuspešno",
"message": "Skripta iz beleške sa ID-jem \"{{id}}\", naslovom \"{{title}}\" nije mogla da se izvrši zbog:\n\n{{message}}"
}
},
"add_link": {
"add_link": "Dodaj link",
"help_on_links": "Pomoć na linkovima",
"note": "Beleška",
"search_note": "potražite belešku po njenom imenu",
"link_title_mirrors": "naziv linka preslikava trenutan naziv beleške",
"link_title_arbitrary": "naziv linka se može proizvoljno menjati",
"link_title": "Naziv linka",
"button_add_link": "Dodaj link <kbd>enter</kbd>"
},
"branch_prefix": {
"edit_branch_prefix": "Izmeni prefiks grane",
"help_on_tree_prefix": "Pomoć na prefiksu Drveta",
"prefix": "Prefiks: ",
"save": "Sačuvaj",
"branch_prefix_saved": "Prefiks grane je sačuvan."
},
"bulk_actions": {
"bulk_actions": "Grupne akcije",
"affected_notes": "Pogođene beleške",
"include_descendants": "Obuhvati potomke izabranih beleški",
"available_actions": "Dostupne akcije",
"chosen_actions": "Izabrane akcije",
"execute_bulk_actions": "Izvrši grupne akcije",
"bulk_actions_executed": "Grupne akcije su uspešno izvršene.",
"none_yet": "Nijedna za sad... dodajte akciju tako što ćete pritisnuti na neku od dostupnih akcija iznad.",
"labels": "Oznake",
"relations": "Odnosi",
"notes": "Beleške",
"other": "Ostalo"
},
"clone_to": {
"clone_notes_to": "Klonirajte beleške u...",
"help_on_links": "Pomoć na linkovima",
"notes_to_clone": "Beleške za kloniranje",
"target_parent_note": "Ciljna nadređena beleška",
"search_for_note_by_its_name": "potražite belešku po njenom imenu",
"cloned_note_prefix_title": "Klonirana beleška će biti prikazana u drvetu beleški sa datim prefiksom",
"prefix_optional": "Prefiks (opciono)",
"clone_to_selected_note": "Kloniranje u izabranu belešku <kbd>enter</kbd>",
"no_path_to_clone_to": "Nema putanje za kloniranje.",
"note_cloned": "Beleška \"{{clonedTitle}}\" je klonirana u \"{{targetTitle}}\""
},
"confirm": {
"confirmation": "Potvrda",
"cancel": "Otkaži",
"ok": "U redu",
"are_you_sure_remove_note": "Da li ste sigurni da želite da uklonite belešku \"{{title}}\" iz mape odnosa? ",
"if_you_dont_check": "Ako ne izaberete ovo, beleška će biti uklonjena samo sa mape odnosa.",
"also_delete_note": "Takođe obriši belešku"
},
"delete_notes": {
"delete_notes_preview": "Obriši pregled beleške",
"close": "Zatvori",
"delete_all_clones_description": "Obriši i sve klonove (može biti poništeno u skorašnjim izmenama)",
"erase_notes_description": "Normalno (blago) brisanje samo označava beleške kao obrisane i one mogu biti vraćene (u dijalogu skorašnjih izmena) u određenom vremenskom periodu. Biranje ove opcije će momentalno obrisati beleške i ove beleške neće biti moguće vratiti.",
"erase_notes_warning": "Trajno obriši beleške (ne može se opozvati), uključujući sve klonove. Ovo će prisiliti aplikaciju da se ponovo pokrene.",
"notes_to_be_deleted": "Sledeće beleške će biti obrisane ({{- noteCount}})",
"no_note_to_delete": "Nijedna beleška neće biti obrisana (samo klonovi).",
"broken_relations_to_be_deleted": "Sledeći odnosi će biti prekinuti i obrisani ({{- relationCount}})",
"cancel": "Otkaži",
"ok": "U redu",
"deleted_relation_text": "Beleška {{- note}} (za brisanje) je referencirana sa odnosom {{- relation}} koji potiče iz {{- source}}."
},
"export": {
"export_note_title": "Izvezi belešku",
"close": "Zatvori",
"export_type_subtree": "Ova beleška i svi njeni potomci",
"format_html": "HTML - preporučuje se jer čuva formatiranje",
"format_html_zip": "HTML u ZIP arhivi - ovo se preporučuje jer se na taj način čuva celokupno formatiranje.",
"format_markdown": "Markdown - ovo čuva većinu formatiranja.",
"format_opml": "OPML - format za razmenu okvira samo za tekst. Formatiranje, slike i datoteke nisu uključeni.",
"opml_version_1": "OPML v1.0 - samo običan tekst",
"opml_version_2": "OPML v2.0 - dozvoljava i HTML",
"export_type_single": "Samo ovu belešku bez njenih potomaka",
"export": "Izvoz",
"choose_export_type": "Molimo vas da prvo izaberete tip izvoza",
"export_status": "Status izvoza",
"export_in_progress": "Izvoz u toku: {{progressCount}}",
"export_finished_successfully": "Izvoz je uspešno završen.",
"format_pdf": "PDF - za namene štampanja ili deljenja."
},
"help": {
"noteNavigation": "Navigacija beleški",
"goUpDown": "<kbd>UP</kbd>, <kbd>DOWN</kbd> - kretanje gore/dole u listi sa beleškama",
"collapseExpand": "<kbd>LEFT</kbd>, <kbd>RIGHT</kbd> - sakupi/proširi čvor",
"notSet": "nije podešeno",
"goBackForwards": "idi u nazad/napred kroz istoriju",
"showJumpToNoteDialog": "prikaži <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Idi na\" dijalog</a>",
"scrollToActiveNote": "skroluj do aktivne beleške",
"jumpToParentNote": "idi do nadređene beleške",
"collapseWholeTree": "sakupi celo drvo beleški",
"collapseSubTree": "sakupi pod-drvo",
"tabShortcuts": "Prečice na karticama",
"newTabNoteLink": "na link beleške otvara belešku u novoj kartici",
"newTabWithActivationNoteLink": "na link beleške otvara i aktivira belešku u novoj kartici",
"onlyInDesktop": "Samo na dektop-u (Electron verzija)",
"openEmptyTab": "otvori praznu karticu",
"closeActiveTab": "zatvori aktivnu karticu",
"activateNextTab": "aktiviraj narednu karticu",
"activatePreviousTab": "aktiviraj prethodnu karticu",
"creatingNotes": "Pravljenje beleški",
"createNoteAfter": "napravi novu belešku nakon aktivne beleške",
"createNoteInto": "napravi novu pod-belešku u aktivnoj belešci",
"editBranchPrefix": "izmeni <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/tree-concepts.html#prefix\">prefiks</a> klona aktivne beleške",
"movingCloningNotes": "Premeštanje / kloniranje beleški",
"moveNoteUpDown": "pomeri belešku gore/dole u listi beleški",
"moveNoteUpHierarchy": "pomeri belešku na gore u hijerarhiji",
"multiSelectNote": "višestruki izbor beleški iznad/ispod",
"selectAllNotes": "izaberi sve beleške u trenutnom nivou",
"selectNote": "izaberi belešku",
"copyNotes": "kopiraj aktivnu belešku (ili trenutni izbor) u privremenu memoriju (koristi se za <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/cloning-notes.html#cloning-notes\">kloniranje</a>)",
"cutNotes": "iseci trenutnu belešku (ili trenutni izbor) u privremenu memoriju (koristi se za premeštanje beleški)",
"pasteNotes": "nalepi belešku/e kao podbelešku u aktivnoj belešci (koja se ili premešta ili klonira u zavisnosti od toga da li je beleška kopirana ili isečena u privremenu memoriju)",
"deleteNotes": "obriši belešku / podstablo",
"editingNotes": "Izmena beleški",
"editNoteTitle": "u ravni drveta će se prebaciti sa ravni drveta na naslov beleške. Ulaz sa naslova beleške će prebaciti fokus na uređivač teksta. <kbd>Ctrl+.</kbd> će se vratiti sa uređivača na ravan drveta.",
"createEditLink": "napravi / izmeni spoljašnji link",
"createInternalLink": "napravi unutrašnji link",
"followLink": "prati link ispod kursora",
"insertDateTime": "ubaci trenutan datum i vreme na poziciju kursora",
"jumpToTreePane": "idi na ravan stabla i pomeri se do aktivne beleške",
"markdownAutoformat": "Autoformatiranje kao u Markdown-u",
"headings": "<code>##</code>, <code>###</code>, <code>####</code> itd. praćeno razmakom za naslove",
"bulletList": "<code>*</code> ili <code>-</code> praćeno razmakom za listu sa tačkama",
"numberedList": "<code>1.</code> ili <code>1)</code> praćeno razmakom za numerisanu listu",
"blockQuote": "započnite liniju sa <code>></code> praćeno sa razmakom za blok citat",
"troubleshooting": "Rešavanje problema",
"reloadFrontend": "ponovo učitaj Trilium frontend",
"showDevTools": "prikaži alate za programere",
"showSQLConsole": "prikaži SQL konzolu",
"other": "Ostalo",
"quickSearch": "fokus na unos za brzu pretragu",
"inPageSearch": "pretraga unutar stranice"
},
"import": {
"importIntoNote": "Uvezi u belešku",
"chooseImportFile": "Izaberi datoteku za uvoz",
"importDescription": "Sadržaj izabranih datoteka će biti uvezen kao podbeleške u",
"options": "Opcije",
"safeImportTooltip": "Trilium <code>.zip</code> izvozne datoteke mogu da sadrže izvršne skripte koje mogu imati štetno ponašanje. Bezbedan uvoz će deaktivirati automatsko izvršavanje svih uvezenih skripti. Isključite \"Bezbedan uvoz\" samo ako uvezena arhiva treba da sadrži izvršne skripte i ako potpuno verujete sadržaju uvezene datoteke.",
"safeImport": "Bezbedan uvoz",
"explodeArchivesTooltip": "Ako je ovo označeno onda će Trilium pročitati <code>.zip</code>, <code>.enex</code> i <code>.opml</code> datoteke i napraviti beleške od datoteka unutar tih arhiva. Ako nije označeno, Trilium će same arhive priložiti belešci.",
"explodeArchives": "Pročitaj sadržaj <code>.zip</code>, <code>.enex</code> i <code>.opml</code> arhiva.",
"shrinkImagesTooltip": "<p>Ako označite ovu opciju, Trilium će pokušati da smanji uvezene slike skaliranjem i optimizacijom što će možda uticati na kvalitet slike. Ako nije označeno, slike će biti uvezene bez promena.</p><p>Ovo se ne primenjuje na <code>.zip</code> uvoze sa metapodacima jer se tada podrazumeva da su te datoteke već optimizovane.</p>",
"shrinkImages": "Smanji slike",
"textImportedAsText": "Uvezi HTML, Markdown i TXT kao tekstualne beleške ako je nejasno iz metapodataka",
"codeImportedAsCode": "Uvezi prepoznate datoteke sa kodom (poput <code>.json</code>) ako beleške sa kodom ako nije jasno iz metapodataka",
"replaceUnderscoresWithSpaces": "Zameni podvlake sa razmacima u nazivima uvezenih beleški",
"import": "Uvezi",
"failed": "Uvoz nije uspeo: {{message}}.",
"html_import_tags": {
"title": "HTML oznake za uvoz",
"description": "Podesite koje HTML oznake trebaju biti sačuvane kada se uvoze beleške. Oznake koje se ne nalaze na listi će biti uklonjene tokom uvoza. Pojedine oznake (poput 'script') se uvek uklanjaju zbog bezbednosti.",
"placeholder": "Unesite HTML oznake, po jednu u svaki red",
"reset_button": "Vrati na podrazumevanu listu"
},
"import-status": "Status uvoza",
"in-progress": "Uvoz u toku: {{progress}}",
"successful": "Uvoz je uspešno završen."
},
"include_note": {
"dialog_title": "Uključi belešku",
"label_note": "Beleška",
"placeholder_search": "pretraži belešku po njenom imenu",
"box_size_prompt": "Veličina kutije priložene beleške:",
"box_size_small": "mala (~ 10 redova)",
"box_size_medium": "srednja (~ 30 redova)",
"box_size_full": "puna (kutija prikazuje ceo tekst)",
"button_include": "Uključi belešku"
},
"info": {
"modalTitle": "Informativna poruka",
"closeButton": "Zatvori",
"okButton": "U redu"
},
"jump_to_note": {
"search_placeholder": "Pretraži belešku po njenom imenu ili unesi > za komande...",
"search_button": "Pretraga u punom tekstu <kbd>Ctrl+Enter</kbd>"
},
"markdown_import": {
"dialog_title": "Uvoz za Markdown",
"modal_body_text": "Zbog Sandbox-a pretraživača nije moguće direktno učitati privremenu memoriju iz JavaScript-a. Molimo vas da nalepite Markdown za uvoz u tekstualno polje ispod i kliknete na dugme za uvoz",
"import_button": "Uvoz",
"import_success": "Markdown sadržaj je učitan u dokument."
},
"move_to": {
"dialog_title": "Premesti beleške u ...",
"notes_to_move": "Beleške za premeštanje",
"target_parent_note": "Ciljana nadbeleška",
"search_placeholder": "potraži belešku po njenom imenu",
"move_button": "Pređi na izabranu belešku",
"error_no_path": "Nema putanje za premeštanje.",
"move_success_message": "Izabrane beleške su premeštene u "
},
"note_type_chooser": {
"change_path_prompt": "Promenite gde će se napraviti nova beleška:",
"search_placeholder": "pretraži putanju po njenom imenu (podrazumevano ako je prazno)",
"modal_title": "Izaberite tip beleške",
"modal_body": "Izaberite tip beleške / šablon za novu belešku:",
"templates": "Šabloni"
},
"password_not_set": {
"title": "Lozinka nije podešena",
"body1": "Zaštićene beleške su enkriptovane sa korisničkom lozinkom, ali lozinka još uvek nije podešena.",
"body2": "Za biste mogli da sačuvate beleške, kliknite <a class=\"open-password-options-button\" href=\"javascript:\">ovde</a> da otvorite dijalog sa Opcijama i podesite svoju lozinku."
},
"prompt": {
"title": "Upit",
"ok": "U redu <kbd>enter</kbd>",
"defaultTitle": "Upit"
},
"protected_session_password": {
"modal_title": "Zaštićena sesija",
"help_title": "Pomoć za Zaštićene beleške",
"close_label": "Zatvori",
"form_label": "Da biste nastavili sa traženom akcijom moraćete započeti zaštićenu sesiju tako što ćete uneti lozinku:",
"start_button": "Započni zaštićenu sesiju"
},
"recent_changes": {
"title": "Nedavne promene",
"erase_notes_button": "Obriši izabrane beleške odmah",
"deleted_notes_message": "Obrisane beleške su uklonjene.",
"no_changes_message": "Još uvek nema izmena...",
"undelete_link": "poništi brisanje",
"confirm_undelete": "Da li želite da poništite brisanje ove beleške i njenih podbeleški?"
},
"revisions": {
"note_revisions": "Revizije beleški",
"delete_all_revisions": "Obriši sve revizije ove beleške",
"delete_all_button": "Obriši sve revizije",
"help_title": "Pomoć za Revizije beleški",
"confirm_delete_all": "Da li želite da obrišete sve revizije ove beleške?",
"no_revisions": "Još uvek nema revizija za ovu belešku...",
"restore_button": "Vrati",
"confirm_restore": "Da li želite da vratite ovu reviziju? Ovo će prepisati trenutan naslov i sadržaj beleške sa ovom revizijom.",
"delete_button": "Obriši",
"confirm_delete": "Da li želite da obrišete ovu reviziju?",
"revisions_deleted": "Revizije beleške su obrisane.",
"revision_restored": "Revizija beleške je vraćena.",
"revision_deleted": "Revizija beleške je obrisana.",
"snapshot_interval": "Interval snimanja revizije beleške: {{seconds}}s.",
"maximum_revisions": "Ograničenje broja slika revizije beleške: {{number}}.",
"settings": "Podešavanja revizija beleški",
"download_button": "Preuzmi",
"mime": "MIME: ",
"file_size": "Veličina datoteke:",
"preview": "Pregled:",
"preview_not_available": "Pregled nije dostupan za ovaj tip beleške."
},
"sort_child_notes": {
"sort_children_by": "Sortiranje podbeleški po...",
"sorting_criteria": "Kriterijum za sortiranje",
"title": "naslov",
"date_created": "datum kreiranja",
"date_modified": "datum izmene",
"sorting_direction": "Smer sortiranja",
"ascending": "uzlazni",
"descending": "silazni",
"folders": "Fascikle",
"sort_folders_at_top": "sortiraj fascikle na vrh",
"natural_sort": "Prirodno sortiranje",
"sort_with_respect_to_different_character_sorting": "sortiranje sa poštovanjem različitih pravila sortiranja karaktera i kolacija u različitim jezicima ili regionima.",
"natural_sort_language": "Jezik za prirodno sortiranje",
"the_language_code_for_natural_sort": "Kod jezika za prirodno sortiranje, npr. \"zh-CN\" za Kineski.",
"sort": "Sortiraj"
},
"upload_attachments": {
"upload_attachments_to_note": "Otpremite priloge uz belešku",
"choose_files": "Izaberite datoteke",
"files_will_be_uploaded": "Datoteke će biti otpremljene kao prilozi u {{noteTitle}}",
"options": "Opcije",
"shrink_images": "Smanji slike",
"upload": "Otpremi",
"tooltip": "Ako je označeno, Trilium će pokušati da smanji otpremljene slike skaliranjem i optimizacijom što može uticati na kvalitet slike. Ako nije označeno, slike će biti otpremljene bez izmena."
},
"attribute_detail": {
"attr_detail_title": "Naslov detalja atributa",
"close_button_title": "Otkaži izmene i zatvori",
"attr_is_owned_by": "Atribut je u vlasništvu",
"attr_name_title": "Naziv atributa može biti sastavljen samo od alfanumeričkih znakova, dvotačke i donje crte",
"name": "Naziv",
"value": "Vrednost",
"target_note_title": "Relacija je imenovana veza između izvorne beleške i ciljne beleške.",
"target_note": "Ciljna beleška",
"promoted_title": "Promovisani atribut je istaknut na belešci.",
"promoted": "Promovisan",
"promoted_alias_title": "Naziv koji će biti prikazan u korisničkom interfejsu promovisanih atributa.",
"promoted_alias": "Pseudonim",
"multiplicity_title": "Multiplicitet definiše koliko atributa sa istim nazivom se može napraviti - najviše 1 ili više od 1.",
"multiplicity": "Multiplicitet",
"single_value": "Jednostruka vrednost",
"multi_value": "Višestruka vrednost",
"label_type_title": "Tip oznake će pomoći Triliumu da izabere odgovarajući interfejs za unos vrednosti oznake.",
"label_type": "Tip",
"text": "Tekst",
"number": "Broj",
"boolean": "Boolean",
"date": "Datum",
"date_time": "Datum i vreme",
"time": "Vreme",
"url": "URL",
"precision_title": "Broj cifara posle zareza treba biti dostupan u interfejsu za postavljanje vrednosti.",
"precision": "Preciznost",
"digits": "cifre",
"inverse_relation_title": "Opciono podešavanje za definisanje kojoj relaciji je ova suprotna. Primer: Otac - Sin su inverzne relacije jedna drugoj.",
"inverse_relation": "Inverzna relacija",
"inheritable_title": "Atributi koji mogu da se nasleđuju će biti nasleđeni od strane svih potomaka unutar ovog stabla.",
"inheritable": "Nasledno",
"save_and_close": "Sačuvaj i zatvori <kbd>Ctrl+Enter</kbd>",
"delete": "Obriši",
"related_notes_title": "Druge beleške sa ovom oznakom",
"more_notes": "Još beleški",
"label": "Detalji oznake",
"label_definition": "Detalji definicije oznake",
"relation": "Detalji relacije",
"relation_definition": "Detalji definicije relacije",
"disable_versioning": "onemogućava auto-verzionisanje. Korisno za npr. velike, ali nebitne beleške - poput velikih JS biblioteka koje se koriste za skripte",
"calendar_root": "obeležava belešku koju treba koristiti kao osnova za dnevne beleške. Samo jedna beleška treba da bude označena kao takva.",
"archived": "beleške sa ovom oznakom neće biti podrazumevano vidljive u rezultatima pretrage (kao ni u dijalozima za Idi na, Dodaj link, itd.).",
"exclude_from_export": "beleške (sa svojim podstablom) neće biti uključene u bilo koji izvoz beleški",
"run": "definiše u kojim događajima se skripta pokreće. Moguće vrednosti su:\n<ul>\n<li>frontendStartup - kada se pokrene Trilium frontend (ili se osveži), ali ne na mobilnom uređaju.</li>\n<li>mobileStartup - kada se pokrene Trilium frontend (ili se osveži), na mobilnom uređaju..</li>\n<li>backendStartup - kada se Trilium backend pokrene</li>\n<li>hourly - pokreće se svaki sat. Može se koristiti dodatna oznaka <code>runAtHour</code> da se označi u kom satu.</li>\n<li>daily - pokreće se jednom dnevno</li>\n</ul>",
"run_on_instance": "Definiše u kojoj instanci Trilium-a ovo treba da se pokreće. Podrazumevano podešavanje je na svim instancama.",
"run_at_hour": "U kom satu ovo treba da se pokreće. Treba se koristiti zajedno sa <code>#run=hourly</code>. Može biti definisano više puta za više pokretanja u toku dana.",
"disable_inclusion": "skripte sa ovom oznakom neće biti uključene u izvršavanju nadskripte.",
"sorted": "čuva podbeleške sortirane alfabetski po naslovu",
"sort_direction": "Uzlazno (podrazumevano) ili silazno",
"sort_folders_first": "Fascikle (beleške sa podbeleškama) treba da budu sortirane na vrhu",
"top": "zadrži datu belešku na vrhu njene nadbeleške (primenjuje se samo na sortiranim nadbeleškama)",
"hide_promoted_attributes": "Sakrij promovisane atribute na ovoj belešci",
"read_only": "uređivač je u režimu samo za čitanje. Radi samo za tekst i beleške sa kodom.",
"auto_read_only_disabled": "beleške sa tekstom/kodom se mogu automatski podesiti u režim za čitanje kada su prevelike. Ovo ponašanje možete onemogućiti pojedinačno za belešku dodavanjem ove oznake na belešku",
"app_css": "označava CSS beleške koje nisu učitane u Trilium aplikaciju i zbog toga se mogu koristiti za menjanje izgleda Triliuma.",
"app_theme": "označava CSS beleške koje su pune Trilium teme i stoga su dostupne u Trilium podešavanjima.",
"app_theme_base": "podesite na „sledeće“, „sledeće-svetlo“ ili „sledeće-tamno“ da biste koristili odgovarajuću TriliumNext temu (automatsku, svetlu ili tamnu) kao osnovu za prilagođenu temu, umesto podrazumevane teme.",
"css_class": "vrednost ove oznake se zatim dodaje kao CSS klasa čvoru koji predstavlja datu belešku u stablu. Ovo može biti korisno za napredno temiranje. Može se koristiti u šablonima beleški.",
"workspace": "označava ovu belešku kao radni prostor što omogućava lako podizanje",
"workspace_icon_class": "definiše CSS klasu ikone okvira koja će se koristiti u kartici kada se podigne na ovoj belešci",
"workspace_tab_background_color": "CSS boja korišćena u kartici beleške kada se prebaci na ovu belešku",
"workspace_calendar_root": "Definiše koren kalendara za svaki radni prostor",
"workspace_template": "Ova beleška će se pojaviti u izboru dostupnih šablona prilikom kreiranja nove beleške, ali samo kada se podigne u radni prostor koji sadrži ovaj šablon",
"search_home": "nove beleške o pretrazi biće kreirane kao podređeni delovi ove beleške",
"workspace_search_home": "nove beleške o pretrazi biće kreirane kao podređeni delovi ove beleške kada se podignu na nekog pretka ove beleške iz radnog prostora",
"inbox": "podrazumevana lokacija u prijemnom sandučetu za nove beleške - kada kreirate belešku pomoću dugmeta „nova beleška“ u bočnoj traci, beleške će biti kreirane kao podbeleške u belešci označenoj sa oznakom <code>#inbox</code>.",
"workspace_inbox": "podrazumevana lokacija prijemnog sandučeta za nove beleške kada se prebace na nekog pretka ove beleške iz radnog prostora",
"sql_console_home": "podrazmevana lokacija beleški SQL konzole",
"bookmark_folder": "beleška sa ovom oznakom će se pojaviti u obeleživačima kao fascikla (omogućavajući pristup njenim podređenim fasciklama)",
"share_hidden_from_tree": "ova beleška je skrivena u levom navigacionom stablu, ali je i dalje dostupna preko svoje URL adrese",
"share_external_link": "beleška će služiti kao veza ka eksternoj veb stranici u stablu deljenja",
"share_alias": "definišite alias pomoću kog će beleška biti dostupna na https://your_trilium_host/share/[your_alias]",
"share_omit_default_css": "CSS kod podrazumevane stranice za deljenje će biti izostavljen. Koristite ga kada pravite opsežne promene stila.",
"share_root": "obeležava belešku koja se prikazuje na /share korenu.",
"share_description": "definišite tekst koji će se dodati HTML meta oznaci za opis",
"share_raw": "beleška će biti prikazana u svom sirovom (raw) formatu, bez HTML omotača",
"share_disallow_robot_indexing": "zabraniće robotsko indeksiranje ove beleške putem zaglavlja <code>X-Robots-Tag: noindex</code>",
"share_credentials": "potrebni su kredencijali za pristup ovoj deljenoj belešci. Očekuje se da vrednost bude u formatu „korisničko ime:lozinka“. Ne zaboravite da ovo označite kao nasledno da bi se primenilo na podbeleške/slike.",
"share_index": "beleška sa ovom oznakom će izlistati sve korene deljenih beleški",
"display_relations": "imena relacija razdvojenih zarezima koja treba da budu prikazana. Sva ostala će biti skrivena.",
"hide_relations": "imena relacija razdvojenih zarezima koja treba da budu skrivena. Sva ostala će biti prikazana.",
"title_template": "podrazumevani naslov beleški kreiranih kao deca ove beleške. Vrednost se procenjuje kao JavaScript string \n i stoga se može obogatiti dinamičkim sadržajem putem ubrizganih promenljivih <code>now</code> and <code>parentNote</code>. Primeri:\n \n <ul>\n <li><code>${parentNote.getLabelValue('authorName')}'s literary works</code></li>\n <li><code>Log for ${now.format('YYYY-MM-DD HH:mm:ss')}</code></li>\n </ul>\n \n Pogledati <a href=\"https://triliumnext.github.io/Docs/Wiki/default-note-title.html\">wiki sa detaljima</a>, API dokumentacija za <a href=\"https://zadam.github.io/trilium/backend_api/Note.html\">parentNote</a> i <a href=\"https://day.js.org/docs/en/display/format\">now</a> za detalje.",
"template": "Ova beleška će biti prikazana u izboru dostupnih šablona prilikom pravljenja nove beleške",
"toc": "<code>#toc</code> ili <code>#toc=show</code> će pristiliti Sadržaj (Table of Contents) da bude prikazan, <code>#toc=hide</code> prisiliti njegovo sakrivanje. Ako oznaka ne postoji, ponašanje će biti usklađeno sa globalnim podešavanjem",
"color": "definiše boju beleške u stablu beleški, linkovima itd. Koristite bilo koju važeću CSS vrednost boje kao što je „crvena“ ili #a13d5f",
"keyboard_shortcut": "Definiše prečicu na tastaturi koja će odmah preći na ovu belešku. Primer: „ctrl+alt+e“. Potrebno je ponovno učitavanje frontenda da bi promena stupila na snagu.",
"keep_current_hoisting": "Otvaranje ove veze neće promeniti podizanje čak i ako beleška nije prikazana u trenutno podignutom podstablu.",
"execute_button": "Naslov dugmeta koje će izvršiti trenutnu belešku sa kodom",
"execute_description": "Duži opis trenutne beleške sa kodom prikazan je zajedno sa dugmetom za izvršavanje",
"exclude_from_note_map": "Beleške sa ovom oznakom biće skrivene sa mape beleški",
"new_notes_on_top": "Nove beleške će biti napravljene na vrhu matične beleške, a ne na dnu.",
"hide_highlight_widget": "Sakrij vidžet sa listom istaknutih",
"run_on_note_creation": "izvršava se kada se beleška napravi na serverskoj strani. Koristite ovu relaciju ako želite da pokrenete skriptu za sve beleške napravljene u okviru određenog podstabla. U tom slučaju, kreirajte je na korenu beleške podstabla i učinite je naslednom. Nova beleška napravljena unutar podstabla (bilo koje dubine) pokrenuće skriptu.",
"run_on_child_note_creation": "izvršava se kada se napravi nova beleška ispod beleške gde je ova relacija definisana",
"run_on_note_title_change": "izvršava se kada se promeni naslov beleške (uključuje i pravljenje beleške)",
"run_on_note_content_change": "izvršava se kada se promeni sadržaj beleške (uključuje i pravljenje beleške).",
"run_on_note_change": "izvršava se kada se promeni beleška (uključuje i pravljenje beleške). Ne uključuje promene sadržaja",
"icon_class": "vrednost ove oznake se dodaje kao CSS klasa ikoni na stablu što može pomoći u vizuelnom razlikovanju beleški u stablu. Primer može biti bx bx-home - ikone su preuzete iz boxicons. Može se koristiti u šablonima beleški.",
"page_size": "broj stavki po stranici u listi beleški",
"custom_request_handler": "pogledajte <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Prilagođeni obrađivač zahteva</a>",
"custom_resource_provider": "pogledajte <a href=\"javascript:\" data-help-page=\"custom-request-handler.html\">Prilagođeni obrađivač zahteva</a>",
"widget": "označava ovu belešku kao prilagođeni vidžet koji će biti dodat u stablo komponenti Trilijuma",
"run_on_note_deletion": "izvršava se kada se beleška briše",
"run_on_branch_creation": "izvršava se kada se pravi grana. Grana je veza između matične i podređene beleške i pravi se npr. prilikom kloniranja ili premeštanja beleške.",
"run_on_branch_change": "izvršava se kada se grana ažurira.",
"run_on_branch_deletion": "izvršava se kada se grana briše. Grana je veza između nadređene beleške i podređene beleške i briše se npr. prilikom premeštanja beleške (stara grana/veza se briše).",
"run_on_attribute_creation": "izvršava se kada se pravi novi atribut za belešku koji definiše ovu relaciju",
"run_on_attribute_change": " izvršava se kada se promeni atribut beleške koja definiše ovu relaciju. Ovo se pokreće i kada se atribut obriše",
"relation_template": "atributi beleške će biti nasleđeni čak i bez odnosa roditelj-dete, sadržaj i podstablo beleške će biti dodati instanci beleške ako je prazna. Pogledajte dokumentaciju za detalje.",
"inherit": "Atributi beleške će biti nasleđeni čak i bez odnosa roditelj-dete. Pogledajte relaciju šablona za sličan koncept. Pogledajte nasleđivanje atributa u dokumentaciji.",
"render_note": "Beleške tipa „render HTML note“ će biti prikazane korišćenjem beleške za kod (HTML ili skripte) i potrebno je pomoću ove relacije ukazati na to koja beleška treba da se prikaže",
"widget_relation": "meta ove relacije će biti izvršena i prikazana kao vidžet u bočnoj traci",
"share_css": "CSS napomena koja će biti ubrizgana na stranicu za deljenje. CSS napomena mora biti i u deljenom podstablu. Razmotrite i korišćenje „share_hidden_from_tree“ i „share_omit_default_css“.",
"share_js": "JavaScript beleška koja će biti ubrizgana na stranicu za deljenje. JS beleška takođe mora biti u deljenom podstablu. Razmislite o korišćenju „share_hidden_from_tree“.",
"share_template": "Ugrađena JavaScript beleška koja će se koristiti kao šablon za prikazivanje deljene beleške. U slučaju neuspeha vraća se na podrazumevani šablon. Razmislite o korišćenju „share_hidden_from_tree“.",
"share_favicon": "Favicon beleška koju treba postaviti na deljenu stranicu. Obično je potrebno da je podesite da deli koren i učinite je naslednom. Favicon beleška takođe mora biti u deljenom podstablu. Razmislite o korišćenju „share_hidden_from_tree“.",
"is_owned_by_note": "je u vlasništvu beleške",
"other_notes_with_name": "Ostale beleške sa {{attributeType}} nazivom „{{attributeName}}“",
"and_more": "... i još {{count}}.",
"print_landscape": "Prilikom izvoza u PDF, menja orijentaciju stranice u pejzažnu umesto uspravne.",
"print_page_size": "Prilikom izvoza u PDF, menja veličinu stranice. Podržane vrednosti: <code>A0</code>, <code>A1</code>, <code>A2</code>, <code>A3</code>, <code>A4</code>, <code>A5</code>, <code>A6</code>, <code>Legal</code>, <code>Letter</code>, <code>Tabloid</code>, <code>Ledger</code>.",
"color_type": "Boja"
},
"attribute_editor": {
"help_text_body1": "Da biste dodali oznaku, samo unesite npr. <code>#rock</code> ili ako želite da dodate i vrednost, onda npr. <code>#year = 2020</code>",
"help_text_body2": "Za relaciju, unesite <code>~author = @</code> što bi trebalo da otvori automatsko dovršavanje gde možete potražiti željenu belešku.",
"help_text_body3": "Alternativno, možete dodati oznaku i relaciju pomoću dugmeta <code>+</code> sa desne strane.",
"save_attributes": "Sačuvaj atribute <enter>",
"add_a_new_attribute": "Dodajte novi atribut",
"add_new_label": "Dodajte novu oznaku <kbd data-command=\"addNewLabel\"></kbd>",
"add_new_relation": "Dodajte novu relaciju <kbd data-command=\"addNewRelation\"></kbd>",
"add_new_label_definition": "Dodajte novu definiciju oznake",
"add_new_relation_definition": "Dodajte novu definiciju relacije",
"placeholder": "Ovde unesite oznake i relacije"
},
"abstract_bulk_action": {
"remove_this_search_action": "Ukloni ovu radnju pretrage"
},
"execute_script": {
"execute_script": "Izvrši skriptu",
"help_text": "Možete izvršiti jednostavne skripte na podudarnim beleškama.",
"example_1": "Na primer, da biste dodali string u naslov beleške, koristite ovu malu skriptu:",
"example_2": "Složeniji primer bi bio brisanje svih atributa podudarnih beleški:"
},
"add_label": {
"add_label": "Dodaj oznaku",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crta i dvotačka su dozvoljeni znakovi.",
"to_value": "za vrednost",
"new_value_placeholder": "nova vrednost",
"help_text": "Na svim podudarnim beleškama:",
"help_text_item1": "dodajte datu oznaku ako beleška još uvek nema jednu",
"help_text_item2": "ili izmenite vrednost postojeće oznake",
"help_text_note": "Takođe možete pozvati ovu metodu bez vrednosti, u tom slučaju će oznaka biti dodeljena belešci bez vrednosti."
},
"delete_label": {
"delete_label": "Obriši oznaku",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi."
},
"rename_label": {
"rename_label": "Preimenuj oznaku",
"rename_label_from": "Preimenuj oznaku iz",
"old_name_placeholder": "stari naziv",
"to": "U",
"new_name_placeholder": "novi naziv",
"name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi."
},
"update_label_value": {
"update_label_value": "Ažuriraj vrednost oznake",
"label_name_placeholder": "ime oznake",
"label_name_title": "Alfanumerički znakovi, donja crtica i dvotačka su dozvoljeni znakovi.",
"to_value": "u vrednost",
"new_value_placeholder": "nova vrednost",
"help_text": "Na svim podudarnim beleškama, promenite vrednost postojeće oznake.",
"help_text_note": "Takođe možete pozvati ovu metodu bez vrednosti, u tom slučaju će oznaka biti dodeljena belešci bez vrednosti."
},
"delete_note": {
"delete_note": "Obriši belešku",
"delete_matched_notes": "Obriši podudarne beleške",
"delete_matched_notes_description": "Ovo će obrisati podudarne beleške.",
"undelete_notes_instruction": "Nakon brisanja, moguće ga je poništiti iz dijaloga Nedavne izmene."
}
}

View File

@ -96,11 +96,5 @@
"are_you_sure_remove_note": "\"{{title}}\" notunu ilişki haritasından kaldırmak istediğinize emin misiniz?. ",
"also_delete_note": "Notu da sil",
"if_you_dont_check": "Bunu işaretlemezseniz, not yalnızca ilişki haritasından kaldırılacaktır."
},
"ai_llm": {
"n_notes_queued": "{{ count }} not dizinleme için sıraya alındı",
"n_notes_queued_plural": "{{ count }} adet not dizinleme için sıraya alındı",
"notes_indexed": "{{ count }} not dizinlendi",
"notes_indexed_plural": "{{ count }} adet not dizinlendi"
}
}

View File

@ -162,7 +162,8 @@
"inPageSearch": "頁面內搜尋",
"title": "列表",
"newTabNoteLink": "在新分頁開啟筆記連結",
"newTabWithActivationNoteLink": "在新分頁開啟並切換至筆記連結"
"newTabWithActivationNoteLink": "在新分頁開啟並切換至筆記連結",
"editShortcuts": "編輯鍵盤快捷鍵"
},
"import": {
"importIntoNote": "匯入至筆記",
@ -732,9 +733,8 @@
"zoom_out_title": "縮小"
},
"zpetne_odkazy": {
"backlink": "{{count}} 個反連結",
"backlinks": "{{count}} 個反連結",
"relation": "關聯"
"relation": "關聯",
"backlink_one": "{{count}} 個反連結"
},
"mobile_detail_menu": {
"insert_child_note": "插入子筆記",
@ -1516,7 +1516,8 @@
"refresh-saved-search-results": "重新整理儲存的搜尋結果",
"create-child-note": "建立子筆記",
"unhoist": "取消聚焦",
"toggle-sidebar": "切換側邊欄"
"toggle-sidebar": "切換側邊欄",
"dropping-not-allowed": "不允許移動筆記至此處。"
},
"title_bar_buttons": {
"window-on-top": "保持此視窗置頂"
@ -1619,7 +1620,8 @@
"duplicate-launcher": "複製啟動器 <kbd data-command=\"duplicateSubtree\">"
},
"editable-text": {
"auto-detect-language": "自動檢測"
"auto-detect-language": "自動檢測",
"keeps-crashing": "編輯元件持續發生崩潰。請嘗試重新啟動 Trilium。若問題仍存在請考慮提交錯誤報告。"
},
"highlighting": {
"description": "控制文字筆記程式碼區塊中的語法高亮,程式碼筆記不會受到影響。",
@ -1795,9 +1797,7 @@
"indexing_stopped": "已停止索引",
"indexing_in_progress": "正在進行索引…",
"last_indexed": "最後索引時間",
"n_notes_queued_0": "{{ count }} 條筆記已加入索引隊列",
"note_chat": "筆記聊天",
"notes_indexed_0": "已索引 {{ count }} 條筆記",
"sources": "來源",
"start_indexing": "開始索引",
"use_advanced_context": "使用進階上下文",
@ -2096,12 +2096,14 @@
"read-only-info": {
"read-only-note": "目前正在檢視唯讀筆記。",
"auto-read-only-note": "此筆記以唯讀模式顯示以加快載入速度。",
"auto-read-only-learn-more": "了解更多",
"edit-note": "編輯筆記"
},
"note-color": {
"clear-color": "清除筆記顏色",
"set-color": "設定筆記顏色",
"set-custom-color": "設定自訂筆記顏色"
},
"popup-editor": {
"maximize": "切換至完整編輯器"
}
}

View File

@ -839,9 +839,10 @@
"zoom_out_title": "Зменшити масштаб"
},
"zpetne_odkazy": {
"backlink": "{{count}} Зворотне посилання",
"backlinks": "{{count}} Зворотні посилання",
"relation": "зв'язок"
"relation": "зв'язок",
"backlink_one": "{{count}} Зворотне посилання",
"backlink_few": "{{count}} Зворотні посилання",
"backlink_many": "{{count}} Зворотні посилання"
},
"mobile_detail_menu": {
"insert_child_note": "Вставити дочірню нотатку",
@ -1350,13 +1351,7 @@
"indexing_stopped": "Індексацію зупинено",
"indexing_in_progress": "Триває індексація...",
"last_indexed": "Остання індексація",
"n_notes_queued_0": "{{ count }} нотатка в черзі на індексацію",
"n_notes_queued_1": "{{ count }} нотатки в черзі на індексацію",
"n_notes_queued_2": "{{ count }} нотаток в черзі на індексацію",
"note_chat": "Нотатка Чат",
"notes_indexed_0": "{{ count }} нотатка індексовано",
"notes_indexed_1": "{{ count }} нотатки індексовано",
"notes_indexed_2": "{{ count }} нотаток індексовано",
"sources": "Джерела",
"start_indexing": "Почати індексацію",
"use_advanced_context": "Використовувати розширений контекст",

View File

@ -18,6 +18,8 @@ import froca from "../services/froca";
import NoteLink from "./react/NoteLink";
import RawHtml from "./react/RawHtml";
import { ViewTypeOptions } from "./collections/interface";
import attributes from "../services/attributes";
import LoadResults from "../services/load_results";
export interface FloatingButtonContext {
parentComponent: Component;
@ -310,13 +312,18 @@ function Backlinks({ note, isDefaultViewMode }: FloatingButtonContext) {
let [ popupOpen, setPopupOpen ] = useState(false);
const backlinksContainerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
function refresh() {
if (!isDefaultViewMode) return;
server.get<BacklinkCountResponse>(`note-map/${note.noteId}/backlink-count`).then(resp => {
setBacklinkCount(resp.count);
});
}, [ note ]);
}
useEffect(() => refresh(), [ note ]);
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (needsRefresh(note, loadResults)) refresh();
});
// Determine the max height of the container.
const { windowHeight } = useWindowSize();
@ -341,18 +348,18 @@ function Backlinks({ note, isDefaultViewMode }: FloatingButtonContext) {
{popupOpen && (
<div ref={backlinksContainerRef} className="backlinks-items dropdown-menu" style={{ display: "block" }}>
<BacklinksList noteId={note.noteId} />
<BacklinksList note={note} />
</div>
)}
</div>
);
}
function BacklinksList({ noteId }: { noteId: string }) {
function BacklinksList({ note }: { note: FNote }) {
const [ backlinks, setBacklinks ] = useState<BacklinksResponse>([]);
useEffect(() => {
server.get<BacklinksResponse>(`note-map/${noteId}/backlinks`).then(async (backlinks) => {
function refresh() {
server.get<BacklinksResponse>(`note-map/${note.noteId}/backlinks`).then(async (backlinks) => {
// prefetch all
const noteIds = backlinks
.filter(bl => "noteId" in bl)
@ -360,7 +367,12 @@ function BacklinksList({ noteId }: { noteId: string }) {
await froca.getNotes(noteIds);
setBacklinks(backlinks);
});
}, [ noteId ]);
}
useEffect(() => refresh(), [ note ]);
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (needsRefresh(note, loadResults)) refresh();
});
return backlinks.map(backlink => (
<div>
@ -380,3 +392,9 @@ function BacklinksList({ noteId }: { noteId: string }) {
</div>
));
}
function needsRefresh(note: FNote, loadResults: LoadResults) {
return loadResults.getAttributeRows().some(attr =>
attr.type === "relation" &&
attributes.isAffecting(attr, note));
}

View File

@ -28,8 +28,9 @@ export default function NoteDetail() {
const { note, type, mime, noteContext, parentComponent } = useNoteInfo();
const { ntxId, viewScope } = noteContext ?? {};
const isFullHeight = checkFullHeight(noteContext, type);
const noteTypesToRender = useRef<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({});
const [ noteTypesToRender, setNoteTypesToRender ] = useState<{ [ key in ExtendedNoteType ]?: (props: TypeWidgetProps) => VNode }>({});
const [ activeNoteType, setActiveNoteType ] = useState<ExtendedNoteType>();
const widgetRequestId = useRef(0);
const props: TypeWidgetProps = {
note: note!,
@ -38,19 +39,28 @@ export default function NoteDetail() {
parentComponent,
noteContext
};
useEffect(() => {
if (!type) return;
const requestId = ++widgetRequestId.current;
if (!noteTypesToRender.current[type]) {
if (!noteTypesToRender[type]) {
getCorrespondingWidget(type).then((el) => {
if (!el) return;
noteTypesToRender.current[type] = el;
// Ignore stale requests
if (requestId !== widgetRequestId.current) return;
setNoteTypesToRender(prev => ({
...prev,
[type]: el
}));
setActiveNoteType(type);
});
} else {
setActiveNoteType(type);
}
}, [ note, viewScope, type ]);
}, [ note, viewScope, type, noteTypesToRender ]);
// Detect note type changes.
useTriliumEvent("entitiesReloaded", async ({ loadResults }) => {
@ -95,9 +105,11 @@ export default function NoteDetail() {
});
// Automatically focus the editor.
useTriliumEvent("activeNoteChanged", () => {
// Restore focus to the editor when switching tabs, but only if the note tree is not already focused.
if (!document.activeElement?.classList.contains("fancytree-title")) {
useTriliumEvent("activeNoteChanged", ({ ntxId: eventNtxId }) => {
if (eventNtxId != ntxId) return;
// Restore focus to the editor when switching tabs,
// but only if the note tree and the note panel (e.g., note title or note detail) are not focused.
if (!document.activeElement?.classList.contains("fancytree-title") && !parentComponent.$widget[0].closest(".note-split")?.contains(document.activeElement)) {
parentComponent.triggerCommand("focusOnDetail", { ntxId });
}
});
@ -192,7 +204,7 @@ export default function NoteDetail() {
ref={containerRef}
class={`note-detail ${isFullHeight ? "full-height" : ""}`}
>
{Object.entries(noteTypesToRender.current).map(([ itemType, Element ]) => {
{Object.entries(noteTypesToRender).map(([ itemType, Element ]) => {
return <NoteDetailWrapper
Element={Element}
key={itemType}

View File

@ -14,8 +14,10 @@ import ws from "../services/ws";
import { UpdateAttributeResponse } from "@triliumnext/commons";
import attributes from "../services/attributes";
import debounce from "../services/debounce";
import { randomString } from "../services/utils";
interface Cell {
uniqueId: string;
definitionAttr: FAttribute;
definition: DefinitionObject;
valueAttr: Attribute;
@ -44,6 +46,7 @@ export default function PromotedAttributes() {
<div className="promoted-attributes-widget">
{cells && cells.length > 0 && <div className="promoted-attributes-container">
{note && cells?.map(cell => <PromotedAttributeCell
key={cell.uniqueId}
cell={cell}
cells={cells} setCells={setCells}
shouldFocus={cell === cellToFocus} setCellToFocus={setCellToFocus}
@ -103,7 +106,8 @@ function usePromotedAttributeData(note: FNote | null | undefined, componentId: s
valueAttr.attributeId = "";
}
cells.push({ definitionAttr, definition, valueAttr, valueName });
const uniqueId = randomString(10);
cells.push({ definitionAttr, definition, valueAttr, valueName, uniqueId });
}
}
setCells(cells);

View File

@ -3,34 +3,33 @@ import { t } from "../services/i18n";
import { useIsNoteReadOnly, useNoteContext, useTriliumEvent } from "./react/hooks"
import Button from "./react/Button";
import InfoBar from "./react/InfoBar";
import HelpButton from "./react/HelpButton";
export default function ReadOnlyNoteInfoBar(props: {}) {
const {note, noteContext} = useNoteContext();
const {isReadOnly, enableEditing} = useIsNoteReadOnly(note, noteContext);
const { note, noteContext } = useNoteContext();
const { isReadOnly, enableEditing } = useIsNoteReadOnly(note, noteContext);
const isExplicitReadOnly = note?.isLabelTruthy("readOnly");
return <InfoBar className="read-only-note-info-bar-widget"
type={(isExplicitReadOnly ? "subtle" : "prominent")}
style={{display: (!isReadOnly) ? "none" : undefined}}>
<div class="read-only-note-info-bar-widget-content">
{(isExplicitReadOnly) ? (
<div>{t("read-only-info.read-only-note")}</div>
) : (
<div>
{t("read-only-info.auto-read-only-note")}
&nbsp;
<a class="tn-link"
href="https://docs.triliumnotes.org/user-guide/concepts/notes/read-only-notes#automatic-read-only-mode">
{t("read-only-info.auto-read-only-learn-more")}
</a>
</div>
)}
<Button text={t("read-only-info.edit-note")}
icon="bx-pencil" onClick={() => enableEditing()} />
return (
<InfoBar
className="read-only-note-info-bar-widget"
type={(isExplicitReadOnly ? "subtle" : "prominent")}
style={{display: (!isReadOnly) ? "none" : undefined}}
>
<div class="read-only-note-info-bar-widget-content">
{(isExplicitReadOnly) ? (
<div>{t("read-only-info.read-only-note")}</div>
) : (
<div>
{t("read-only-info.auto-read-only-note")}
{" "}
<HelpButton helpPage="CoFPLs3dRlXc" />
</div>
</InfoBar>
)}
}
<Button text={t("read-only-info.edit-note")}
icon="bx-pencil" onClick={() => enableEditing()} />
</div>
</InfoBar>
);
}

View File

@ -110,7 +110,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
private weekNotes: string[] = [];
constructor(title: string = "", icon: string = "") {
super(title, icon, DROPDOWN_TPL);
super(title, icon, DROPDOWN_TPL, "calendar-dropdown-menu");
}
doRender() {
@ -211,8 +211,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
const $target = $(e.target);
// Keep dropdown open when clicking on month select button or year selector area
if ($target.closest('.btn.dropdown-toggle.select-button').length ||
$target.closest('.calendar-year-selector').length) {
if ($target.closest('.btn.dropdown-toggle.select-button').length) {
e.stopPropagation();
return;
}

View File

@ -26,6 +26,7 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout:
const isVerticalLayout = !isHorizontalLayout;
const parentComponent = useContext(ParentComponent);
const { isUpdateAvailable, latestVersion } = useTriliumUpdateStatus();
const isMobileLocal = isMobile();
return (
<Dropdown
@ -38,6 +39,8 @@ export default function GlobalMenu({ isHorizontalLayout }: { isHorizontalLayout:
</div>}
</>}
noDropdownListStyle
onShown={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.add("show", "global-menu-cover") : undefined}
onHidden={isMobileLocal ? () => document.getElementById("context-menu-cover")?.classList.remove("show", "global-menu-cover") : undefined}
>
<MenuItem command="openNewWindow" icon="bx bx-window-open" text={t("global_menu.open_new_window")} />

View File

@ -7,9 +7,9 @@ const TPL = /*html*/`
<div class="dropdown right-dropdown-widget">
<button type="button" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false"
class="bx right-dropdown-button launcher-button"></button>
<div class="tooltip-trigger"></div>
class="bx right-dropdown-button launcher-button">
<div class="tooltip-trigger"></div>
</button>
<div class="dropdown-menu"></div>
</div>
@ -24,14 +24,16 @@ export default class RightDropdownButtonWidget extends BasicWidget {
protected dropdown!: Dropdown;
protected $tooltip!: JQuery<HTMLElement>;
protected tooltip!: Tooltip;
private dropdownClass?: string;
public $dropdownContent!: JQuery<HTMLElement>;
constructor(title: string, iconClass: string, dropdownTpl: string) {
constructor(title: string, iconClass: string, dropdownTpl: string, dropdownClass?: string) {
super();
this.iconClass = iconClass;
this.title = title;
this.dropdownTpl = dropdownTpl;
this.dropdownClass = dropdownClass;
this.settings = {
titlePlacement: "right"
@ -41,15 +43,17 @@ export default class RightDropdownButtonWidget extends BasicWidget {
doRender() {
this.$widget = $(TPL);
this.$dropdownMenu = this.$widget.find(".dropdown-menu");
if (this.dropdownClass) {
this.$dropdownMenu.addClass(this.dropdownClass);
}
this.dropdown = Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']")[0], {
popperConfig: {
placement: this.settings.titlePlacement,
}
});
this.$widget.attr("title", this.title);
this.tooltip = Tooltip.getOrCreateInstance(this.$widget[0], {
trigger: "hover",
this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title);
this.tooltip = new Tooltip(this.$tooltip[0], {
placement: handleRightToLeftPlacement(this.settings.titlePlacement),
fallbackPlacements: [ handleRightToLeftPlacement(this.settings.titlePlacement) ]
});
@ -57,7 +61,9 @@ export default class RightDropdownButtonWidget extends BasicWidget {
this.$widget
.find(".right-dropdown-button")
.addClass(this.iconClass)
.on("click", () => this.tooltip.hide());
.on("click", () => this.tooltip.hide())
.on("mouseenter", () => this.tooltip.show())
.on("mouseleave", () => this.tooltip.hide());
this.$widget.on("show.bs.dropdown", async () => {
await this.dropdownShown();

View File

@ -2,9 +2,9 @@ import FNote from "../../../entities/fnote";
import NoteColorPicker from "../../../menus/custom-items/NoteColorPicker";
import contextMenu, { ContextMenuEvent } from "../../../menus/context_menu";
import link_context_menu from "../../../menus/link_context_menu";
import attributes from "../../../services/attributes";
import branches from "../../../services/branches";
import dialog from "../../../services/dialog";
import { getArchiveMenuItem } from "../../../menus/context_menu_utils";
import { t } from "../../../services/i18n";
import Api from "./api";
@ -41,18 +41,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
x: event.pageX,
y: event.pageY,
items: [
...link_context_menu.getItems(),
{ kind: "separator" },
{
title: t("board_view.move-to"),
uiIcon: "bx bx-transfer",
items: api.columns.map(columnToMoveTo => ({
title: columnToMoveTo,
enabled: columnToMoveTo !== column,
handler: () => api.changeColumn(note.noteId, columnToMoveTo)
})),
},
getArchiveMenuItem(note),
...link_context_menu.getItems(event),
{ kind: "separator" },
{
title: t("board_view.insert-above"),
@ -65,6 +54,17 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
handler: () => api.insertRowAtPosition(column, branchId, "after")
},
{ kind: "separator" },
{
title: t("board_view.move-to"),
uiIcon: "bx bx-transfer",
items: api.columns.map(columnToMoveTo => ({
title: columnToMoveTo,
enabled: columnToMoveTo !== column,
handler: () => api.changeColumn(note.noteId, columnToMoveTo)
})),
},
{ kind: "separator" },
getArchiveMenuItem(note),
{
title: t("board_view.remove-from-board"),
uiIcon: "bx bx-task-x",
@ -81,24 +81,7 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
componentFn: () => NoteColorPicker({note})
}
],
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, note.noteId),
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, event, note.noteId),
});
}
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

@ -204,8 +204,19 @@ function AddNewColumn({ api, isInRelationMode }: { api: BoardApi, isInRelationMo
setIsCreatingNewColumn(true);
}, []);
const keydownCallback = useCallback((e: KeyboardEvent) => {
if (e.key === "Enter") {
setIsCreatingNewColumn(true);
}
}, []);
return (
<div className={`board-add-column ${isCreatingNewColumn ? "editing" : ""}`} onClick={addColumnCallback}>
<div
className={`board-add-column ${isCreatingNewColumn ? "editing" : ""}`}
onClick={addColumnCallback}
onKeyDown={keydownCallback}
tabIndex={300}
>
{!isCreatingNewColumn
? <>
<Icon icon="bx bx-plus" />{" "}

View File

@ -3,11 +3,10 @@ import FNote from "../../../entities/fnote";
import contextMenu, { ContextMenuEvent } from "../../../menus/context_menu";
import link_context_menu from "../../../menus/link_context_menu";
import branches from "../../../services/branches";
import froca from "../../../services/froca";
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
import { getArchiveMenuItem } from "../../../menus/context_menu_utils";
import { t } from "../../../services/i18n";
export function openCalendarContextMenu(e: ContextMenuEvent, noteId: string, parentNote: FNote) {
export function openCalendarContextMenu(e: ContextMenuEvent, note: FNote, parentNote: FNote) {
e.preventDefault();
e.stopPropagation();
@ -15,17 +14,15 @@ export function openCalendarContextMenu(e: ContextMenuEvent, noteId: string, par
x: e.pageX,
y: e.pageY,
items: [
...link_context_menu.getItems(),
...link_context_menu.getItems(e),
{ kind: "separator" },
getArchiveMenuItem(note),
{
title: t("calendar_view.delete_note"),
uiIcon: "bx bx-trash",
handler: async () => {
const noteToDelete = await froca.getNote(noteId);
if (!noteToDelete) return;
let branchIdToDelete: string | null = null;
for (const parentBranch of noteToDelete.getParentBranches()) {
for (const parentBranch of note.getParentBranches()) {
const parentNote = await parentBranch.getNote();
if (parentNote?.hasAncestor(parentNote.noteId)) {
branchIdToDelete = parentBranch.branchId;
@ -40,9 +37,9 @@ export function openCalendarContextMenu(e: ContextMenuEvent, noteId: string, par
{ kind: "separator" },
{
kind: "custom",
componentFn: () => NoteColorPicker({note: noteId})
componentFn: () => NoteColorPicker({note: note})
}
],
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, noteId),
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, e, note.noteId),
})
}

View File

@ -3,6 +3,7 @@ import froca from "../../../services/froca";
import { formatDateToLocalISO, getCustomisableLabel, getMonthsInDateRange, offsetDate } from "./utils";
import FNote from "../../../entities/fnote";
import server from "../../../services/server";
import clsx from "clsx";
interface Event {
startDate: string,
@ -80,7 +81,7 @@ export async function buildEventsForCalendar(note: FNote, e: EventSourceFuncArg)
export async function buildEvent(note: FNote, { startDate, endDate, startTime, endTime, isArchived }: Event) {
const customTitleAttributeName = note.getLabelValue("calendar:title");
const titles = await parseCustomTitle(customTitleAttributeName, note);
const color = note.getLabelValue("calendar:color") ?? note.getLabelValue("color");
const colorClass = note.getColorClass();
const events: EventInput[] = [];
const calendarDisplayedAttributes = note.getLabelValue("calendar:displayedAttributes")?.split(",");
@ -108,10 +109,9 @@ export async function buildEvent(note: FNote, { startDate, endDate, startTime, e
start: startDate,
url: `#${note.noteId}?popup`,
noteId: note.noteId,
color: color ?? undefined,
iconClass: note.getLabelValue("iconClass"),
promotedAttributes: displayedAttributesData,
className: isArchived ? "archived" : ""
className: clsx({archived: isArchived}, colorClass)
};
if (endDate) {
eventData.end = endDate;

View File

@ -1,4 +1,21 @@
:root {
/* Default values to be overridden by themes */
--calendar-coll-event-background-lightness: 95%;
--calendar-coll-event-background-saturation: 80%;
--calendar-coll-event-background-color: var(--accented-background-color);
--calendar-coll-event-text-color: var(--main-text-color);
--calendar-coll-event-hover-filter: none;
--callendar-coll-event-archived-sripe-color: #00000013;
--calendar-coll-today-background-color: var(--more-accented-background-color);
}
.calendar-view {
--fc-event-border-color: var(--calendar-coll-event-text-color);
--fc-event-bg-color: var(--calendar-coll-event-background-color);
--fc-event-text-color: var(--calendar-coll-event-text-color);
--fc-event-selected-overlay-color: transparent;
--fc-today-bg-color: var(--calendar-coll-today-background-color);
overflow: hidden;
position: relative;
outline: 0;
@ -7,8 +24,9 @@
padding: 10px;
}
.calendar-view a {
color: unset;
.calendar-view a,
:root .calendar-view a.fc-daygrid-event:hover {
color: var(--fc-event-text-color);
}
.search-result-widget-content .calendar-view {
@ -31,14 +49,6 @@
z-index: 50;
}
.calendar-container a.fc-event {
text-decoration: none;
}
.calendar-container a.fc-event.archived {
opacity: 0.5;
}
.calendar-container .fc-button {
padding: 0.2em 0.5em;
}
@ -75,4 +85,107 @@ body.desktop:not(.zen) .calendar-view .calendar-header {
.search-result-widget-content .calendar-view .calendar-header {
padding-inline-end: unset !important;
}
/* #endregion */
/* #region Events */
/*
* week, month, year views
*/
.calendar-container a.fc-event {
text-decoration: none;
}
.calendar-container a.fc-event.archived {
opacity: .65;
}
.calendar-container a.fc-event.archived::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: -1;
--c1: transparent;
--c2: var(--callendar-coll-event-archived-sripe-color);
background: repeating-linear-gradient(45deg, var(--c1), var(--c1) 8px,
var(--c2) 8px, var(--c2) 16px);
}
.calendar-view a.fc-timegrid-event,
.calendar-view a.fc-daygrid-event,
.calendar-view .fc-daygrid-dot-event .fc-event-title {
font-weight: 500;
}
.calendar-view a.fc-timegrid-event,
.calendar-view a.fc-daygrid-event {
--border-color: transparent;
border: 2px solid;
border-left-width: 4px;
border-color: var(--border-color) var(--border-color) var(--border-color)
var(--fc-event-text-color) !important;
background: var(--fc-event-bg-color) !important;
padding-left: 8px;
}
.calendar-view .fc-timegrid-event.with-hue,
.calendar-view .fc-daygrid-event.with-hue {
--fc-event-text-color: var(--custom-color);
--fc-event-bg-color: hsl(var(--custom-color-hue),
var(--calendar-coll-event-background-saturation),
var(--calendar-coll-event-background-lightness)) !important;
}
.calendar-view a.fc-timegrid-event:focus-visible,
.calendar-view a.fc-daygrid-event:focus-visible {
outline: none;
}
.calendar-view a.fc-timegrid-event.fc-event-selected,
.calendar-view a.fc-timegrid-event.fc-event:focus,
.calendar-view a.fc-daygrid-event.fc-event-selected,
.calendar-view a.fc-daygrid-event.fc-event:focus {
--border-color: var(--custom-color, var(--input-focus-outline-color));
}
.calendar-view a.fc-timegrid-event:hover,
.calendar-view a.fc-daygrid-event:hover {
filter: var(--calendar-coll-event-hover-filter);
border-color: var(--fc-event-text-color);
text-decoration: none;
color: currentColor;
opacity: 1;
}
.calendar-view .fc-daygrid-event-dot {
display: none;
}
.calendar-view .fc-event-time {
opacity: .75;
}
/*
* List view
*/
.fc-list-table tr.fc-event.archived {
opacity: .5;
}
.fc-list-table .fc-list-event-dot {
/* Apply note colors to the list item dots */
--fc-event-border-color: var(--custom-color);
}
/* #endregion */

View File

@ -77,6 +77,7 @@ export const LOCALE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, (() => Promise<{ de
"pt_br": () => import("@fullcalendar/core/locales/pt-br"),
uk: () => import("@fullcalendar/core/locales/uk"),
en: null,
"en-GB": () => import("@fullcalendar/core/locales/en-gb"),
"en_rtl": null,
ar: () => import("@fullcalendar/core/locales/ar")
};
@ -116,7 +117,10 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
if (loadResults.getNoteIds().some(noteId => noteIds.includes(noteId)) // note title change.
|| loadResults.getAttributeRows().some((a) => noteIds.includes(a.noteId ?? ""))) // subnote change.
{
calendarRef.current?.refetchEvents();
// Defer execution after the load results are processed so that the event builder has the updated data to work with.
setTimeout(() => {
calendarRef.current?.refetchEvents();
}, 0);
}
});
@ -306,9 +310,11 @@ function useEventDisplayCustomization(parentNote: FNote) {
$(mainContainer ?? e.el).append($(promotedAttributesHtml));
}
e.el.addEventListener("contextmenu", (contextMenuEvent) => {
const noteId = e.event.extendedProps.noteId;
openCalendarContextMenu(contextMenuEvent, noteId, parentNote);
e.el.addEventListener("contextmenu", async (contextMenuEvent) => {
const note = await froca.getNote(e.event.extendedProps.noteId);
if (!note) return;
openCalendarContextMenu(contextMenuEvent, note, parentNote);
});
}, []);
return { eventDidMount };

View File

@ -12,7 +12,7 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent, is
let items: MenuItem<keyof CommandMappings>[] = [
...buildGeoLocationItem(e),
{ kind: "separator" },
...linkContextMenu.getItems(),
...linkContextMenu.getItems(e),
];
if (isEditable) {
@ -32,14 +32,14 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent, is
x: e.originalEvent.pageX,
y: e.originalEvent.pageY,
items,
selectMenuItemHandler: ({ command }, e) => {
selectMenuItemHandler: ({ command }) => {
if (command === "deleteFromMap") {
appContext.triggerCommand(command, { noteId });
return;
}
// Pass the events to the link context menu
linkContextMenu.handleLinkContextMenuItem(command, noteId);
linkContextMenu.handleLinkContextMenuItem(command, e, noteId);
}
});
}

View File

@ -174,7 +174,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
contextMenu.show({
items: [
...link_context_menu.getItems(),
...link_context_menu.getItems(e),
{ kind: "separator" },
{
title: t("table_view.row-insert-above"),
@ -227,7 +227,7 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
componentFn: () => NoteColorPicker({note: rowData.noteId})
}
],
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, rowData.noteId),
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, e, rowData.noteId),
x: e.pageX,
y: e.pageY
});

View File

@ -29,7 +29,11 @@ export default class LeftPaneContainer extends FlexContainer<Component> {
if (visible) {
this.triggerEvent("focusTree", {});
} else {
this.triggerEvent("focusOnDetail", { ntxId: appContext.tabManager.getActiveContext()?.ntxId });
const ntxId = appContext.tabManager.getActiveContext()?.ntxId;
const noteContainer = document.querySelector(`.note-split[data-ntx-id="${ntxId}"]`);
if (!noteContainer?.contains(document.activeElement)) {
this.triggerEvent("focusOnDetail", { ntxId });
}
}
options.save("leftPaneVisible", this.currentLeftPaneVisible.toString());

View File

@ -1,12 +1,10 @@
import FlexContainer from "./flex_container.js";
import appContext, { type CommandData, type CommandListenerData, type EventData, type EventNames, type NoteSwitchedContext } from "../../components/app_context.js";
import type BasicWidget from "../basic_widget.js";
import type NoteContext from "../../components/note_context.js";
import Component from "../../components/component.js";
import splitService from "../../services/resizer.js";
interface NoteContextEvent {
noteContext: NoteContext;
}
import { isMobile } from "../../services/utils.js";
import NoteContext from "../../components/note_context.js";
interface SplitNoteWidget extends BasicWidget {
hasBeenAlreadyShown?: boolean;
@ -53,13 +51,14 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
this.child(widget);
if (noteContext.mainNtxId && noteContext.ntxId) {
if (noteContext.mainNtxId && noteContext.ntxId && !isMobile()) {
splitService.setupNoteSplitResizer([noteContext.mainNtxId,noteContext.ntxId]);
}
}
async openNewNoteSplitEvent({ ntxId, notePath, hoistedNoteId, viewScope }: EventData<"openNewNoteSplit">) {
const mainNtxId = appContext.tabManager.getActiveMainContext()?.ntxId;
const activeContext = appContext.tabManager.getActiveMainContext();
const mainNtxId = activeContext?.ntxId;
if (!mainNtxId) {
console.warn("Missing main note context ID");
return;
@ -73,22 +72,30 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
hoistedNoteId = hoistedNoteId || appContext.tabManager.getActiveContext()?.hoistedNoteId;
const noteContext = await appContext.tabManager.openEmptyTab(null, hoistedNoteId, mainNtxId);
if (!noteContext.ntxId) {
logError("Failed to create new note context!");
return;
const subContexts = activeContext.getSubContexts();
let noteContext: NoteContext | undefined = undefined;
if (isMobile() && subContexts.length > 1) {
noteContext = subContexts.find(s => s.ntxId !== ntxId);
}
if (!noteContext) {
noteContext = await appContext.tabManager.openEmptyTab(null, hoistedNoteId, mainNtxId);
// remove the original position of newly created note context
const ntxIds = appContext.tabManager.children.map((c) => c.ntxId).filter((id) => id !== noteContext?.ntxId) as string[];
// insert the note context after the originating note context
if (!noteContext.ntxId) {
logError("Failed to create new note context!");
return;
}
ntxIds.splice(ntxIds.indexOf(ntxId) + 1, 0, noteContext.ntxId);
this.triggerCommand("noteContextReorder", { ntxIdsInOrder: ntxIds });
// move the note context rendered widget after the originating widget
this.$widget.find(`[data-ntx-id="${noteContext.ntxId}"]`).insertAfter(this.$widget.find(`[data-ntx-id="${ntxId}"]`));
}
// remove the original position of newly created note context
const ntxIds = appContext.tabManager.children.map((c) => c.ntxId).filter((id) => id !== noteContext.ntxId) as string[];
// insert the note context after the originating note context
ntxIds.splice(ntxIds.indexOf(ntxId) + 1, 0, noteContext.ntxId);
this.triggerCommand("noteContextReorder", { ntxIdsInOrder: ntxIds });
// move the note context rendered widget after the originating widget
this.$widget.find(`[data-ntx-id="${noteContext.ntxId}"]`).insertAfter(this.$widget.find(`[data-ntx-id="${ntxId}"]`));
await appContext.tabManager.activateNoteContext(noteContext.ntxId);

View File

@ -5,14 +5,24 @@ body.popup-editor-open .ck-clipboard-drop-target-line { z-index: 1000; }
body.desktop .modal.popup-editor-dialog .modal-dialog {
max-width: 75vw;
}
.modal.popup-editor-dialog .modal-dialog {
border-bottom-left-radius: var(--bs-modal-border-radius);
border-bottom-right-radius: var(--bs-modal-border-radius);
}
body.desktop .modal.popup-editor-dialog .modal-dialog {
overflow: hidden;
}
body.mobile .modal.popup-editor-dialog .modal-dialog {
max-width: min(var(--preferred-max-content-width), 95vw);
max-height: var(--tn-modal-max-height);
height: 100%;
}
.modal.popup-editor-dialog .modal-content {
transition: background-color 250ms ease-in;
}
.modal.popup-editor-dialog .modal-header .modal-title {
font-size: 1.1em;
}
@ -23,8 +33,8 @@ body.desktop .modal.popup-editor-dialog .modal-dialog {
align-items: center;
}
.modal.popup-editor-dialog .modal-header .title-row > * {
margin: 5px;
.modal.popup-editor-dialog .modal-header .note-title-widget {
margin-top: 8px;
}
.modal.popup-editor-dialog .modal-body {
@ -52,13 +62,23 @@ body.desktop .modal.popup-editor-dialog .modal-dialog {
font-size: 1em;
}
.modal.popup-editor-dialog .classic-toolbar-outer-container.visible {
background-color: transparent;
}
.modal.popup-editor-dialog div.promoted-attributes-container {
margin-block: 0;
}
.modal.popup-editor-dialog .classic-toolbar-widget {
position: sticky;
margin-inline: 8px;
top: 0;
inset-inline-start: 0;
inset-inline-end: 0;
background: var(--modal-background-color);
z-index: 998;
align-items: flex-start;
}
.modal.popup-editor-dialog .note-detail.full-height {

View File

@ -1,7 +1,7 @@
import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
import Modal from "../react/Modal";
import "./PopupEditor.css";
import { useNoteContext, useTriliumEvent } from "../react/hooks";
import { useNoteContext, useNoteLabel, useTriliumEvent } from "../react/hooks";
import NoteTitleWidget from "../note_title";
import NoteIcon from "../note_icon";
import NoteContext from "../../components/note_context";
@ -18,6 +18,9 @@ import utils from "../../services/utils";
import tree from "../../services/tree";
import froca from "../../services/froca";
import ReadOnlyNoteInfoBar from "../ReadOnlyNoteInfoBar";
import MobileEditorToolbar from "../type_widgets/text/mobile_editor_toolbar";
import { t } from "../../services/i18n";
import appContext from "../../components/app_context";
export default function PopupEditor() {
const [ shown, setShown ] = useState(false);
@ -59,6 +62,16 @@ export default function PopupEditor() {
<DialogWrapper>
<Modal
title={<TitleRow />}
customTitleBarButtons={[{
iconClassName: "bx-expand-alt",
title: t("popup-editor.maximize"),
onClick: async () => {
if (!noteContext.noteId) return;
const { noteId, hoistedNoteId } = noteContext;
await appContext.tabManager.openInNewTab(noteId, hoistedNoteId, true);
setShown(false);
}
}]}
className="popup-editor-dialog"
size="lg"
show={shown}
@ -67,10 +80,15 @@ export default function PopupEditor() {
}}
onHidden={() => setShown(false)}
keepInDom // needed for faster loading
noFocus // automatic focus breaks block popup
>
<ReadOnlyNoteInfoBar />
<PromotedAttributes />
<StandaloneRibbonAdapter component={FormattingToolbar} />
{isMobile
? <MobileEditorToolbar inPopupEditor />
: <StandaloneRibbonAdapter component={FormattingToolbar} />}
<FloatingButtons items={items} />
<NoteDetail />
<NoteList media="screen" displayOnlyCollections />
@ -83,17 +101,10 @@ export default function PopupEditor() {
export function DialogWrapper({ children }: { children: ComponentChildren }) {
const { note } = useNoteContext();
const wrapperRef = useRef<HTMLDivElement>(null);
const [ hasTint, setHasTint ] = useState(false);
// Apply the tinted-dialog class only if the custom color CSS class specifies a hue
useEffect(() => {
if (!wrapperRef.current) return;
const customHue = getComputedStyle(wrapperRef.current).getPropertyValue("--custom-color-hue");
setHasTint(!!customHue);
}, [ note ]);
useNoteLabel(note, "color"); // to update color class
return (
<div ref={wrapperRef} class={`quick-edit-dialog-wrapper ${note?.getColorClass() ?? ""} ${hasTint ? "tinted-quick-edit-dialog" : ""}`}>
<div ref={wrapperRef} class={`quick-edit-dialog-wrapper ${note?.getColorClass() ?? ""}`}>
{children}
</div>
)

View File

@ -31,29 +31,29 @@ export default function AboutDialog() {
<tbody>
<tr>
<th>{t("about.homepage")}</th>
<td><a className="tn-link external" href="https://github.com/TriliumNext/Trilium" style={forceWordBreak}>https://github.com/TriliumNext/Trilium</a></td>
<td className="selectable-text"><a className="tn-link external" href="https://github.com/TriliumNext/Trilium" style={forceWordBreak}>https://github.com/TriliumNext/Trilium</a></td>
</tr>
<tr>
<th>{t("about.app_version")}</th>
<td className="app-version">{appInfo?.appVersion}</td>
<td className="app-version selectable-text">{appInfo?.appVersion}</td>
</tr>
<tr>
<th>{t("about.db_version")}</th>
<td className="db-version">{appInfo?.dbVersion}</td>
<td className="db-version selectable-text">{appInfo?.dbVersion}</td>
</tr>
<tr>
<th>{t("about.sync_version")}</th>
<td className="sync-version">{appInfo?.syncVersion}</td>
<td className="sync-version selectable-text">{appInfo?.syncVersion}</td>
</tr>
<tr>
<th>{t("about.build_date")}</th>
<td className="build-date">
<td className="build-date selectable-text">
{appInfo?.buildDate ? formatDateTime(appInfo.buildDate) : ""}
</td>
</tr>
<tr>
<th>{t("about.build_revision")}</th>
<td>
<td className="selectable-text">
{appInfo?.buildRevision && <a className="tn-link build-revision external" href={`https://github.com/TriliumNext/Trilium/commit/${appInfo.buildRevision}`} target="_blank" style={forceWordBreak}>{appInfo.buildRevision}</a>}
</td>
</tr>
@ -76,8 +76,8 @@ function DirectoryLink({ directory, style }: { directory: string, style?: CSSPro
openService.openDirectory(directory);
};
return <a className="tn-link" href="#" onClick={onClick} style={style}>{directory}</a>
return <a className="tn-link selectable-text" href="#" onClick={onClick} style={style}>{directory}</a>
} else {
return <span style={style}>{directory}</span>;
return <span className="selectable-text" style={style}>{directory}</span>;
}
}

View File

@ -1,7 +1,7 @@
import Modal from "../react/Modal.jsx";
import { t } from "../../services/i18n.js";
import { ComponentChildren } from "preact";
import { CommandNames } from "../../components/app_context.js";
import appContext, { CommandNames } from "../../components/app_context.js";
import RawHtml from "../react/RawHtml.jsx";
import { useEffect, useState } from "preact/hooks";
import keyboard_actions from "../../services/keyboard_actions.js";
@ -14,6 +14,7 @@ export default function HelpDialog() {
return (
<Modal
title={t("help.title")} className="help-dialog use-tn-links" minWidth="90%" size="lg" scrollable
customTitleBarButtons={[{title: t("help.editShortcuts"), iconClassName: "bxs-pencil", onClick: editShortcuts}]}
onHidden={() => setShown(false)}
show={shown}
>
@ -160,3 +161,7 @@ function Card({ title, children }: { title: string, children: ComponentChildren
</div>
)
}
function editShortcuts() {
appContext.tabManager.openContextWithNote("_optionsShortcuts", { activate: true });
}

View File

@ -34,15 +34,26 @@ export default function MarkdownImportDialog() {
}
});
function submit() {
setShown(false);
if (editorApiRef.current && text) {
convertMarkdownToHtml(text, editorApiRef.current);
}
}
return (
<Modal
className="markdown-import-dialog" title={t("markdown_import.dialog_title")} size="lg"
footer={<Button className="markdown-import-button" text={t("markdown_import.import_button")} onClick={() => setShown(false)} keyboardShortcut="Ctrl+Enter" />}
footer={
<Button
className="markdown-import-button"
text={t("markdown_import.import_button")}
keyboardShortcut="Ctrl+Enter"
onClick={submit}
/>
}
onShown={() => markdownImportTextArea.current?.focus()}
onHidden={async () => {
if (editorApiRef.current) {
await convertMarkdownToHtml(text, editorApiRef.current);
}
onHidden={() => {
setShown(false);
setText("");
}}
@ -55,7 +66,7 @@ export default function MarkdownImportDialog() {
onKeyDown={(e) => {
if (e.key === "Enter" && e.ctrlKey) {
e.preventDefault();
setShown(false);
submit();
}
}}></textarea>
</Modal>

View File

@ -0,0 +1,63 @@
body.mobile .revisions-dialog {
.modal-dialog {
height: 95vh;
}
.modal-header {
display: flex;
flex-wrap: wrap;
gap: 0.25em;
font-size: 0.9em;
}
.modal-title {
flex-grow: 1;
width: 100%;
}
.modal-body {
height: fit-content !important;
flex-direction: column;
padding: 0;
}
.modal-footer {
font-size: 0.9em;
}
.revision-list {
height: fit-content !important;
max-height: 20vh;
border-bottom: 1px solid var(--main-border-color) !important;
padding: 0 1em;
flex-shrink: 0;
}
.modal-body > .revision-content-wrapper {
flex-grow: 1;
max-width: unset !important;
height: 100%;
margin: 0;
display: block !important;
}
.modal-body > .revision-content-wrapper > div:first-of-type {
flex-direction: column;
}
.revision-title {
font-size: 1rem;
}
.revision-title-buttons {
text-align: center;
display: flex;
gap: 0.25em;
flex-wrap: wrap;
}
.revision-content {
padding: 0.5em;
height: fit-content;
}
}

View File

@ -20,6 +20,7 @@ import ActionButton from "../react/ActionButton";
import options from "../../services/options";
import { useTriliumEvent } from "../react/hooks";
import { diffWords } from "diff";
import "./revisions.css";
export default function RevisionsDialog() {
const [ note, setNote ] = useState<FNote>();
@ -137,7 +138,7 @@ export default function RevisionsDialog() {
function RevisionsList({ revisions, onSelect, currentRevision }: { revisions: RevisionItem[], onSelect: (val: string) => void, currentRevision?: RevisionItem }) {
return (
<FormList onSelect={onSelect} fullHeight>
<FormList onSelect={onSelect} fullHeight wrapperClassName="revision-list">
{revisions.map((item) =>
<FormListItem
value={item.revisionId}
@ -208,7 +209,7 @@ function RevisionPreview({noteContent, revisionItem, showDiff, setShown, onRevis
}
</div>)}
</div>
<div className="revision-content use-tn-links" style={{ overflow: "auto", wordBreak: "break-word" }}>
<div className="revision-content use-tn-links selectable-text" style={{ overflow: "auto", wordBreak: "break-word" }}>
<RevisionContent noteContent={noteContent} revisionItem={revisionItem} fullRevision={fullRevision} showDiff={showDiff}/>
</div>
</>

View File

@ -1,12 +1,13 @@
import { useContext } from "preact/hooks";
import appContext from "../../components/app_context";
import contextMenu from "../../menus/context_menu";
import appContext, { CommandMappings } from "../../components/app_context";
import contextMenu, { MenuItem } from "../../menus/context_menu";
import branches from "../../services/branches";
import { t } from "../../services/i18n";
import note_create from "../../services/note_create";
import tree from "../../services/tree";
import ActionButton from "../react/ActionButton";
import { ParentComponent } from "../react/react_utils";
import BasicWidget from "../basic_widget";
export default function MobileDetailMenu() {
const parentComponent = useContext(ParentComponent);
@ -16,17 +17,33 @@ export default function MobileDetailMenu() {
icon="bx bx-dots-vertical-rounded"
text=""
onClick={(e) => {
const note = appContext.tabManager.getActiveContextNote();
const ntxId = (parentComponent as BasicWidget | null)?.getClosestNtxId();
if (!ntxId) return;
contextMenu.show<"insertChildNote" | "delete" | "showRevisions">({
const noteContext = appContext.tabManager.getNoteContextById(ntxId);
const subContexts = noteContext.getMainContext().getSubContexts();
const isMainContext = noteContext?.isMainContext();
const note = noteContext.note;
const items: (MenuItem<keyof CommandMappings>)[] = [
{ title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" },
{ title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" },
{ kind: "separator" },
{ title: t("mobile_detail_menu.note_revisions"), command: "showRevisions", uiIcon: "bx bx-history" },
{ kind: "separator" },
subContexts.length < 2 && { title: t("create_pane_button.create_new_split"), command: "openNewNoteSplit", uiIcon: "bx bx-dock-right" },
!isMainContext && { title: t("close_pane_button.close_this_pane"), command: "closeThisNoteSplit", uiIcon: "bx bx-x" }
].filter(i => !!i) as MenuItem<keyof CommandMappings>[];
const lastItem = items.at(-1);
if (lastItem && "kind" in lastItem && lastItem.kind === "separator") {
items.pop();
}
contextMenu.show<keyof CommandMappings>({
x: e.pageX,
y: e.pageY,
items: [
{ title: t("mobile_detail_menu.insert_child_note"), command: "insertChildNote", uiIcon: "bx bx-plus", enabled: note?.type !== "search" },
{ title: t("mobile_detail_menu.delete_this_note"), command: "delete", uiIcon: "bx bx-trash", enabled: note?.noteId !== "root" },
{ kind: "separator" },
{ title: t("mobile_detail_menu.note_revisions"), command: "showRevisions", uiIcon: "bx bx-history" }
],
items,
selectMenuItemHandler: async ({ command }) => {
if (command === "insertChildNote") {
note_create.createNote(appContext.tabManager.getActiveContextNotePath() ?? undefined);
@ -46,7 +63,7 @@ export default function MobileDetailMenu() {
parentComponent.triggerCommand("setActiveScreen", { screen: "tree" });
}
} else if (command && parentComponent) {
parentComponent.triggerCommand(command);
parentComponent.triggerCommand(command, { ntxId });
}
},
forcePositionOnMobile: true

View File

@ -1,18 +1,19 @@
import { useContext } from "preact/hooks";
import ActionButton from "../react/ActionButton";
import { ParentComponent } from "../react/react_utils";
import { t } from "../../services/i18n";
import { useNoteContext } from "../react/hooks";
export default function ToggleSidebarButton() {
const parentComponent = useContext(ParentComponent);
const { noteContext, parentComponent } = useNoteContext();
return (
<ActionButton
icon="bx bx-sidebar"
text={t("note_tree.toggle-sidebar")}
onClick={() => parentComponent?.triggerCommand("setActiveScreen", {
screen: "tree"
})}
/>
<div style={{ contain: "none", minWidth: 8 }}>
{ noteContext?.isMainContext() && <ActionButton
icon="bx bx-sidebar"
text={t("note_tree.toggle-sidebar")}
onClick={() => parentComponent?.triggerCommand("setActiveScreen", {
screen: "tree"
})}
/>}
</div>
)
}

View File

@ -19,9 +19,11 @@ export interface DropdownProps extends Pick<HTMLProps<HTMLDivElement>, "id" | "c
disabled?: boolean;
text?: ComponentChildren;
forceShown?: boolean;
onShown?: () => void;
onHidden?: () => void;
}
export default function Dropdown({ id, className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle, noDropdownListStyle, forceShown }: DropdownProps) {
export default function Dropdown({ id, className, buttonClassName, isStatic, children, title, text, dropdownContainerStyle, dropdownContainerClassName, hideToggleArrow, iconAction, disabled, noSelectButtonStyle, noDropdownListStyle, forceShown, onShown: externalOnShown, onHidden: externalOnHidden }: DropdownProps) {
const dropdownRef = useRef<HTMLDivElement | null>(null);
const triggerRef = useRef<HTMLButtonElement | null>(null);
@ -40,10 +42,12 @@ export default function Dropdown({ id, className, buttonClassName, isStatic, chi
const onShown = useCallback(() => {
setShown(true);
externalOnShown?.();
}, [])
const onHidden = useCallback(() => {
setShown(false);
externalOnHidden?.();
}, []);
useEffect(() => {

View File

@ -6,15 +6,17 @@ import "./FormList.css";
import { CommandNames } from "../../components/app_context";
import { useStaticTooltip } from "./hooks";
import { handleRightToLeftPlacement, isMobile } from "../../services/utils";
import clsx from "clsx";
interface FormListOpts {
children: ComponentChildren;
onSelect?: (value: string) => void;
style?: CSSProperties;
wrapperClassName?: string;
fullHeight?: boolean;
}
export default function FormList({ children, onSelect, style, fullHeight }: FormListOpts) {
export default function FormList({ children, onSelect, style, fullHeight, wrapperClassName }: FormListOpts) {
const wrapperRef = useRef<HTMLDivElement | null>(null);
const triggerRef = useRef<HTMLButtonElement | null>(null);
@ -43,7 +45,7 @@ export default function FormList({ children, onSelect, style, fullHeight }: Form
}, [ fullHeight ]);
return (
<div className="dropdownWrapper" ref={wrapperRef} style={builtinStyles}>
<div className={clsx("dropdownWrapper", wrapperClassName)} ref={wrapperRef} style={builtinStyles}>
<div className="dropdown" style={builtinStyles}>
<button
ref={triggerRef}

View File

@ -1,3 +1,4 @@
import clsx from "clsx";
import { useEffect, useRef, useMemo } from "preact/hooks";
import { t } from "../../services/i18n";
import { ComponentChildren } from "preact";
@ -7,9 +8,16 @@ import { Modal as BootstrapModal } from "bootstrap";
import { memo } from "preact/compat";
import { useSyncedRef } from "./hooks";
interface CustomTitleBarButton {
title: string;
iconClassName: string;
onClick: () => void;
}
interface ModalProps {
className: string;
title: string | ComponentChildren;
customTitleBarButtons?: (CustomTitleBarButton | null)[];
size: "xl" | "lg" | "md" | "sm";
children: ComponentChildren;
/**
@ -66,9 +74,13 @@ interface ModalProps {
* If true, the modal will remain in the DOM even when not shown. This can be useful for certain CSS transitions or when you want to avoid re-mounting the modal content.
*/
keepInDom?: boolean;
/**
* If true, the modal will not focus itself after becoming visible.
*/
noFocus?: boolean;
}
export default function Modal({ children, className, size, title, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom }: ModalProps) {
export default function Modal({ children, className, size, title, customTitleBarButtons: titleBarButtons, header, footer, footerStyle, footerAlignment, onShown, onSubmit, helpPageId, minWidth, maxWidth, zIndex, scrollable, onHidden: onHidden, modalRef: externalModalRef, formRef, bodyStyle, show, stackable, keepInDom, noFocus }: ModalProps) {
const modalRef = useSyncedRef<HTMLDivElement>(externalModalRef);
const modalInstanceRef = useRef<BootstrapModal>();
const elementToFocus = useRef<Element | null>();
@ -100,13 +112,15 @@ export default function Modal({ children, className, size, title, header, footer
useEffect(() => {
if (show && modalRef.current) {
elementToFocus.current = document.activeElement;
openDialog($(modalRef.current), !stackable).then(($widget) => {
openDialog($(modalRef.current), !stackable, {
focus: !noFocus
}).then(($widget) => {
modalInstanceRef.current = BootstrapModal.getOrCreateInstance($widget[0]);
})
} else {
modalInstanceRef.current?.hide();
}
}, [ show, modalRef.current ]);
}, [ show, modalRef.current, noFocus ]);
// Memoize styles to prevent recreation on every render
const dialogStyle = useMemo<CSSProperties>(() => {
@ -142,7 +156,17 @@ export default function Modal({ children, className, size, title, header, footer
{helpPageId && (
<button className="help-button" type="button" data-in-app-help={helpPageId} title={t("modal.help_title")}>?</button>
)}
{titleBarButtons?.filter((b) => b !== null).map((titleBarButton) => (
<button type="button"
className={clsx("custom-title-bar-button bx", titleBarButton.iconClassName)}
title={titleBarButton.title}
onClick={titleBarButton.onClick}>
</button>
))}
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label={t("modal.close")}></button>
</div>
{onSubmit ? (

View File

@ -461,26 +461,29 @@ export function useNoteLabelInt(note: FNote | undefined | null, labelName: Filte
export function useNoteBlob(note: FNote | null | undefined, componentId?: string): FBlob | null | undefined {
const [ blob, setBlob ] = useState<FBlob | null>();
const requestIdRef = useRef(0);
function refresh() {
note?.getBlob().then(setBlob);
async function refresh() {
const requestId = ++requestIdRef.current;
const newBlob = await note?.getBlob();
// Only update if this is the latest request.
if (requestId === requestIdRef.current) {
setBlob(newBlob);
}
}
useEffect(refresh, [ note?.noteId ]);
useEffect(() => { refresh() }, [ note?.noteId ]);
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (!note) return;
// Check if the note was deleted.
if (loadResults.getEntityRow("notes", note.noteId)?.isDeleted) {
requestIdRef.current++; // invalidate pending results
setBlob(null);
return;
}
// Check if a revision occurred.
if (loadResults.hasRevisionForNote(note.noteId)) {
refresh();
}
if (loadResults.isNoteContentReloaded(note.noteId, componentId)) {
refresh();
}
@ -791,7 +794,7 @@ export function useKeyboardShortcuts(scope: "code-detail" | "text-detail", conta
* and provides a way to switch to editing mode.
*/
export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: NoteContext | undefined) {
const [isReadOnly, setIsReadOnly] = useState<boolean | undefined>(undefined);
const [ isReadOnly, setIsReadOnly ] = useState<boolean | undefined>(undefined);
const enableEditing = useCallback(() => {
if (noteContext?.viewScope) {
@ -806,7 +809,7 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N
setIsReadOnly(readOnly);
});
}
}, [note, noteContext]);
}, [ note, noteContext, noteContext?.viewScope ]);
useTriliumEvent("readOnlyTemporarilyDisabled", ({noteContext: eventNoteContext}) => {
if (noteContext?.ntxId === eventNoteContext.ntxId) {
@ -814,7 +817,7 @@ export function useIsNoteReadOnly(note: FNote | null | undefined, noteContext: N
}
});
return {isReadOnly, enableEditing};
return { isReadOnly, enableEditing };
}
async function isNoteReadOnly(note: FNote, noteContext: NoteContext) {

View File

@ -17,24 +17,24 @@ export default function FilePropertiesTab({ note }: { note?: FNote | null }) {
return (
<div className="file-properties-widget">
{note && (
<table class="file-table">
<table className="file-table">
<tbody>
<tr>
<th class="text-nowrap">{t("file_properties.note_id")}:</th>
<td class="file-note-id">{note.noteId}</td>
<th class="text-nowrap">{t("file_properties.original_file_name")}:</th>
<td class="file-filename">{originalFileName ?? "?"}</td>
<th className="text-nowrap">{t("file_properties.note_id")}:</th>
<td className="file-note-id selectable-text">{note.noteId}</td>
<th className="text-nowrap">{t("file_properties.original_file_name")}:</th>
<td className="file-filename selectable-text">{originalFileName ?? "?"}</td>
</tr>
<tr>
<th class="text-nowrap">{t("file_properties.file_type")}:</th>
<td class="file-filetype">{note.mime}</td>
<th class="text-nowrap">{t("file_properties.file_size")}:</th>
<td class="file-filesize">{formatSize(blob?.contentLength ?? 0)}</td>
<th className="text-nowrap">{t("file_properties.file_type")}:</th>
<td className="file-filetype selectable-text">{note.mime}</td>
<th className="text-nowrap">{t("file_properties.file_size")}:</th>
<td className="file-filesize selectable-text">{formatSize(blob?.contentLength ?? 0)}</td>
</tr>
<tr>
<td colSpan={4}>
<div class="file-buttons">
<div className="file-buttons">
<Button
icon="bx bx-download"
text={t("file_properties.download")}

View File

@ -23,17 +23,17 @@ export default function ImagePropertiesTab({ note, ntxId }: TabContext) {
<div style={{ display: "flex", justifyContent: "space-evenly", margin: "10px" }}>
<span>
<strong>{t("image_properties.original_file_name")}:</strong>{" "}
<span>{originalFileName ?? "?"}</span>
<span className="selectable-text">{originalFileName ?? "?"}</span>
</span>
<span>
<strong>{t("image_properties.file_type")}:</strong>{" "}
<span>{note.mime}</span>
<span className="selectable-text">{note.mime}</span>
</span>
<span>
<strong>{t("image_properties.file_size")}:</strong>{" "}
<span>{formatSize(blob?.contentLength)}</span>
<span className="selectable-text">{formatSize(blob?.contentLength)}</span>
</span>
</div>

View File

@ -37,7 +37,7 @@ export default function InheritedAttributesTab({ note, componentId }: TabContext
return (
<div className="inherited-attributes-widget">
<div className="inherited-attributes-container">
<div className="inherited-attributes-container selectable-text">
{inheritedAttributes?.length ? (
joinElements(inheritedAttributes.map(attribute => (
<InheritedAttribute

View File

@ -1,5 +1,5 @@
import { ConvertToAttachmentResponse } from "@triliumnext/commons";
import { FormDropdownDivider, FormListItem } from "../react/FormList";
import { FormDropdownDivider, FormListHeader, FormListItem } from "../react/FormList";
import { isElectron as getIsElectron, isMac as getIsMac } from "../../services/utils";
import { ParentComponent } from "../react/react_utils";
import { t } from "../../services/i18n"
@ -113,8 +113,7 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
function DevelopmentActions({ note }: { note: FNote }) {
return (
<>
<FormDropdownDivider />
<FormListItem disabled>Development-only Actions</FormListItem>
<FormListHeader text="Development-only Actions" />
<FormListItem
icon="bx bx-printer"
onClick={() => window.open(`/?print=#root/${note.noteId}`, "_blank")}

View File

@ -39,21 +39,21 @@ export default function NoteInfoTab({ note }: TabContext) {
<>
<div className="note-info-item">
<span>{t("note_info_widget.note_id")}:</span>
<span className="note-info-id">{note.noteId}</span>
<span className="note-info-id selectable-text">{note.noteId}</span>
</div>
<div className="note-info-item">
<span>{t("note_info_widget.created")}:</span>
<span>{formatDateTime(metadata?.dateCreated)}</span>
<span className="selectable-text">{formatDateTime(metadata?.dateCreated)}</span>
</div>
<div className="note-info-item">
<span>{t("note_info_widget.modified")}:</span>
<span>{formatDateTime(metadata?.dateModified)}</span>
<span className="selectable-text">{formatDateTime(metadata?.dateModified)}</span>
</div>
<div className="note-info-item">
<span>{t("note_info_widget.type")}:</span>
<span>
<span className="note-info-type">{note.type}</span>{' '}
{note.mime && <span className="note-info-mime">({note.mime})</span>}
{note.mime && <span className="note-info-mime selectable-text">({note.mime})</span>}
</span>
</div>
<div className="note-info-item">
@ -77,7 +77,7 @@ export default function NoteInfoTab({ note }: TabContext) {
/>
)}
<span className="note-sizes-wrapper">
<span className="note-sizes-wrapper selectable-text">
<span className="note-size">{formatSize(noteSizeResponse?.noteSize)}</span>
{" "}
{subtreeSizeResponse && subtreeSizeResponse.subTreeNoteCount > 1 &&

View File

@ -8,6 +8,7 @@ import NoteActions from "./NoteActions";
import { KeyboardActionNames } from "@triliumnext/commons";
import { RIBBON_TAB_DEFINITIONS } from "./RibbonDefinition";
import { TabConfiguration, TitleContext } from "./ribbon-interface";
import clsx from "clsx";
const TAB_CONFIGURATION = numberObjectsInPlace<TabConfiguration>(RIBBON_TAB_DEFINITIONS);
@ -63,62 +64,61 @@ export default function Ribbon() {
}, [ computedTabs, activeTabIndex ]));
return (
<div className="ribbon-container" style={{ contain: "none" }}>
{noteContext?.viewScope?.viewMode === "default" && (
<>
<div className="ribbon-top-row">
<div className="ribbon-tab-container">
{computedTabs && computedTabs.map(({ title, icon, index, toggleCommand, shouldShow }) => (
shouldShow && <RibbonTab
icon={icon}
title={typeof title === "string" ? title : title(titleContext)}
active={index === activeTabIndex}
toggleCommand={toggleCommand}
onClick={() => {
if (activeTabIndex !== index) {
setActiveTabIndex(index);
} else {
// Collapse
setActiveTabIndex(undefined);
}
}}
/>
))}
<div
className={clsx("ribbon-container", noteContext?.viewScope?.viewMode !== "default" && "hidden-ext")}
style={{ contain: "none" }}
>
<div className="ribbon-top-row">
<div className="ribbon-tab-container">
{computedTabs && computedTabs.map(({ title, icon, index, toggleCommand, shouldShow }) => (
shouldShow && <RibbonTab
icon={icon}
title={typeof title === "string" ? title : title(titleContext)}
active={index === activeTabIndex}
toggleCommand={toggleCommand}
onClick={() => {
if (activeTabIndex !== index) {
setActiveTabIndex(index);
} else {
// Collapse
setActiveTabIndex(undefined);
}
}}
/>
))}
</div>
<div className="ribbon-button-container">
{ note && <NoteActions note={note} noteContext={noteContext} /> }
</div>
</div>
<div className="ribbon-body-container">
{computedTabs && computedTabs.map(tab => {
const isActive = tab.index === activeTabIndex;
if (!isActive && !tab.stayInDom) {
return;
}
const TabContent = tab.content;
return (
<div className={`ribbon-body ${!isActive ? "hidden-ext" : ""}`}>
<TabContent
note={note}
hidden={!isActive}
ntxId={ntxId}
hoistedNoteId={hoistedNoteId}
notePath={notePath}
noteContext={noteContext}
componentId={componentId}
activate={useCallback(() => {
setActiveTabIndex(tab.index)
}, [setActiveTabIndex])}
/>
</div>
<div className="ribbon-button-container">
{ note && <NoteActions note={note} noteContext={noteContext} /> }
</div>
</div>
<div className="ribbon-body-container">
{computedTabs && computedTabs.map(tab => {
const isActive = tab.index === activeTabIndex;
if (!isActive && !tab.stayInDom) {
return;
}
const TabContent = tab.content;
return (
<div className={`ribbon-body ${!isActive ? "hidden-ext" : ""}`}>
<TabContent
note={note}
hidden={!isActive}
ntxId={ntxId}
hoistedNoteId={hoistedNoteId}
notePath={notePath}
noteContext={noteContext}
componentId={componentId}
activate={useCallback(() => {
setActiveTabIndex(tab.index)
}, [setActiveTabIndex])}
/>
</div>
);
})}
</div>
</>
)}
);
})}
</div>
</div>
)
}

View File

@ -26,7 +26,7 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [
&& !(await noteContext?.isReadOnly()),
toggleCommand: "toggleRibbonTabClassicEditor",
content: FormattingToolbar,
activate: true,
activate: ({ note }) => !options.is("editedNotesOpenInRibbon") || !note?.hasOwnedLabel("dateNote"),
stayInDom: true
},
{
@ -50,7 +50,7 @@ export const RIBBON_TAB_DEFINITIONS: TabConfiguration[] = [
icon: "bx bx-calendar-edit",
content: EditedNotesTab,
show: ({ note }) => note?.hasOwnedLabel("dateNote"),
activate: ({ note }) => (note?.getPromotedDefinitionAttributes().length === 0 || !options.is("promotedAttributesOpenInRibbon")) && options.is("editedNotesOpenInRibbon")
activate: () => options.is("editedNotesOpenInRibbon")
},
{
title: t("book_properties.book_properties"),

View File

@ -1,5 +1,6 @@
.note-detail-doc-content {
padding: 15px;
user-select: text;
}
.note-detail-doc-content pre {

View File

@ -1,3 +1,21 @@
.note-detail-empty {
container-type: size;
padding-top: 50px;
min-width: 350px;
}
.note-detail-empty > * {
margin-inline: auto;
max-width: 850px;
padding-inline: 50px;
}
@container (max-width: 600px) {
.note-detail-empty > * {
padding-inline: 20px;
}
}
.workspace-notes {
display: flex;
flex-direction: row;
@ -14,7 +32,8 @@
.workspace-notes .workspace-note:hover {
cursor: pointer;
border: 1px solid var(--main-border-color);
background-color: var(--icon-button-hover-background);
border-radius: 8px;
}
.note-detail-empty-results .aa-dropdown-menu {
@ -24,6 +43,11 @@
border-top: 0;
}
.empty-tab-search label {
margin-bottom: 8px;
color: var(--muted-text-color);
}
.empty-tab-search .note-autocomplete-input {
border-bottom-left-radius: 0;
}

View File

@ -10,16 +10,16 @@ import FNote from "../../entities/fnote";
import search from "../../services/search";
import { TypeWidgetProps } from "./type_widget";
export default function Empty({ }: TypeWidgetProps) {
export default function Empty({ ntxId }: TypeWidgetProps) {
return (
<>
<WorkspaceSwitcher />
<NoteSearch />
<NoteSearch ntxId={ntxId ?? null} />
</>
)
}
function NoteSearch() {
function NoteSearch({ ntxId }: { ntxId: string | null }) {
const resultsContainerRef = useRef<HTMLDivElement>(null);
const autocompleteRef = useRef<HTMLInputElement>(null);
@ -45,10 +45,9 @@ function NoteSearch() {
if (!suggestion?.notePath) {
return false;
}
const activeContext = appContext.tabManager.getActiveContext();
if (activeContext) {
activeContext.setNote(suggestion.notePath);
const activeNoteContext = appContext.tabManager.getNoteContextById(ntxId) ?? appContext.tabManager.getActiveContext();
if (activeNoteContext) {
activeNoteContext.setNote(suggestion.notePath);
}
}}
/>

View File

@ -28,6 +28,7 @@ const LOCALE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, Options["locale"] | null>
de: null,
en: "en",
en_rtl: "en",
"en-GB": "en",
es: "es",
fr: "fr",
it: "it",

View File

@ -0,0 +1,10 @@
.note-detail-note-map {
&>div {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
}

View File

@ -1,6 +1,7 @@
import { TypeWidgetProps } from "./type_widget";
import NoteMapEl from "../note_map/NoteMap";
import { useRef } from "preact/hooks";
import "./NoteMap.css";
export default function NoteMap({ note }: TypeWidgetProps) {
const containerRef = useRef<HTMLDivElement>(null);

View File

@ -22,6 +22,7 @@ describe("Canvas i18n", () => {
if (locale.contentOnly || locale.devOnly) continue;
const languageCode = LANGUAGE_MAPPINGS[locale.id];
if (!supportedLanguageCodes.has(languageCode)) {
console.log("Supported locales:", Array.from(supportedLanguageCodes.values()).join(", "));
expect.fail(`Unable to find locale for ${locale.id} -> ${languageCode}.`)
}
}

View File

@ -1,10 +1,12 @@
import { Language } from "@excalidraw/excalidraw/i18n";
import type { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
export const LANGUAGE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, string | null> = {
export const LANGUAGE_MAPPINGS: Record<DISPLAYABLE_LOCALE_IDS, Language["code"] | null> = {
ar: "ar-SA",
cn: "zh-CN",
de: "de-DE",
en: "en",
"en-GB": "en",
en_rtl: "en",
es: "es-ES",
fr: "fr-FR",

View File

@ -104,7 +104,7 @@ export function BackupList({ backups }: { backups: DatabaseBackup[] }) {
backups.map(({ mtime, filePath }) => (
<tr>
<td>{mtime ? formatDateTime(mtime) : "-"}</td>
<td>{filePath}</td>
<td className="selectable-text">{filePath}</td>
</tr>
))
) : (

View File

@ -226,7 +226,7 @@ function CodeBlockPreview({ theme, wordWrap }: { theme: string, wordWrap: boolea
return (
<div className="note-detail-readonly-text-content ck-content code-sample-wrapper">
<pre className="hljs" style={{ marginBottom: 0 }}>
<pre className="hljs selectable-text" style={{ marginBottom: 0 }}>
<code className="code-sample" style={codeStyle} dangerouslySetInnerHTML={getHtml(code)} />
</pre>
</div>

View File

@ -98,6 +98,14 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
editorApi: editorApiRef.current,
});
},
insertDateTimeToTextCommand() {
if (!editorApiRef.current) return;
const date = new Date();
const customDateTimeFormat = options.get("customDateTimeFormat");
const dateString = utils.formatDateTime(date, customDateTimeFormat);
addTextToEditor(dateString);
},
// Include note functionality note
addIncludeNoteToTextCommand() {
if (!editorApiRef.current) return;
@ -197,14 +205,6 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
});
}
useTriliumEvent("insertDateTimeToText", ({ ntxId: eventNtxId }) => {
if (eventNtxId !== ntxId) return;
const date = new Date();
const customDateTimeFormat = options.get("customDateTimeFormat");
const dateString = utils.formatDateTime(date, customDateTimeFormat);
addTextToEditor(dateString);
});
useTriliumEvent("addTextToActiveEditor", ({ text }) => {
if (!noteContext?.isActive()) return;
addTextToEditor(text);

View File

@ -41,7 +41,6 @@ export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetPro
// React to included note changes.
useTriliumEvent("refreshIncludedNote", ({ noteId }) => {
console.log("Refresh ", noteId);
if (!contentRef.current) return;
refreshIncludedNote(contentRef.current, noteId);
});
@ -56,7 +55,7 @@ export default function ReadOnlyText({ note, noteContext, ntxId }: TypeWidgetPro
<>
<RawHtmlBlock
containerRef={contentRef}
className={clsx("note-detail-readonly-text-content ck-content use-tn-links", codeBlockWordWrap && "word-wrap")}
className={clsx("note-detail-readonly-text-content ck-content use-tn-links selectable-text", codeBlockWordWrap && "word-wrap")}
tabindex={100}
dir={isRtl ? "rtl" : "ltr"}
html={blob?.content}

View File

@ -1,52 +1,54 @@
.classic-toolbar-outer-container {
contain: none !important;
}
.classic-toolbar-outer-container.visible {
height: 38px;
background-color: var(--main-background-color);
position: relative;
overflow: visible;
flex-shrink: 0;
}
#root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios {
position: absolute;
inset-inline-start: 0;
inset-inline-end: 0;
bottom: 0;
}
.classic-toolbar-widget {
position: absolute;
bottom: 0;
inset-inline-start: 0;
inset-inline-end: 0;
height: 38px;
overflow: scroll;
display: flex;
align-items: flex-end;
user-select: none;
scrollbar-width: 0 !important;
}
.classic-toolbar-widget::-webkit-scrollbar:horizontal {
height: 0 !important;
}
.classic-toolbar-widget.dropdown-active {
height: 50vh;
}
.classic-toolbar-widget .ck.ck-toolbar {
--ck-color-toolbar-background: transparent;
--ck-color-button-default-background: transparent;
--ck-color-button-default-disabled-background: transparent;
position: absolute;
background-color: transparent;
border: none;
}
.classic-toolbar-widget .ck.ck-button.ck-disabled {
opacity: 0.3;
body.mobile {
.classic-toolbar-outer-container {
contain: none !important;
}
.classic-toolbar-outer-container.visible {
height: 38px;
background-color: var(--main-background-color);
position: relative;
overflow: visible;
flex-shrink: 0;
}
#root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios {
position: absolute;
inset-inline-start: 0;
inset-inline-end: 0;
bottom: 0;
}
.classic-toolbar-widget {
position: absolute;
bottom: 0;
inset-inline-start: 0;
inset-inline-end: 0;
height: 38px;
overflow: scroll;
display: flex;
align-items: flex-end;
user-select: none;
scrollbar-width: 0 !important;
}
.classic-toolbar-widget::-webkit-scrollbar:horizontal {
height: 0 !important;
}
.classic-toolbar-widget.dropdown-active {
height: 50vh;
}
.classic-toolbar-widget .ck.ck-toolbar {
--ck-color-toolbar-background: transparent;
--ck-color-button-default-background: transparent;
--ck-color-button-default-disabled-background: transparent;
position: absolute;
background-color: transparent;
border: none;
}
.classic-toolbar-widget .ck.ck-button.ck-disabled {
opacity: 0.3;
}
}

View File

@ -4,19 +4,23 @@ import "./mobile_editor_toolbar.css";
import { isIOS } from "../../../services/utils";
import { CKTextEditor, ClassicEditor } from "@triliumnext/ckeditor5";
interface MobileEditorToolbarProps {
inPopupEditor?: boolean;
}
/**
* Handles the editing toolbar for CKEditor in mobile mode. The toolbar acts as a floating bar, with two different mechanism:
*
* - On iOS, because it does not respect the viewport meta value `interactive-widget=resizes-content`, we need to listen to window resizes and scroll and reposition the toolbar using absolute positioning.
* - On Android, the viewport change makes the keyboard resize the content area, all we have to do is to hide the tab bar and global menu (handled in the global style).
*/
export default function MobileEditorToolbar() {
export default function MobileEditorToolbar({ inPopupEditor }: MobileEditorToolbarProps) {
const containerRef = useRef<HTMLDivElement>(null);
const { note, noteContext, ntxId } = useNoteContext();
const [ shouldDisplay, setShouldDisplay ] = useState(false);
const [ dropdownActive, setDropdownActive ] = useState(false);
usePositioningOniOS(containerRef);
usePositioningOniOS(!inPopupEditor, containerRef);
useEffect(() => {
noteContext?.isReadOnly().then(isReadOnly => {
@ -29,7 +33,10 @@ export default function MobileEditorToolbar() {
if (eventNtxId !== ntxId || !containerRef.current) return;
const toolbar = editor.ui.view.toolbar?.element;
repositionDropdowns(editor);
if (!inPopupEditor) {
repositionDropdowns(editor);
}
if (toolbar) {
containerRef.current.replaceChildren(toolbar);
} else {
@ -60,7 +67,7 @@ export default function MobileEditorToolbar() {
)
}
function usePositioningOniOS(wrapperRef: MutableRef<HTMLDivElement | null>) {
function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivElement | null>) {
const adjustPosition = useCallback(() => {
if (!wrapperRef.current) return;
let bottom = window.innerHeight - (window.visualViewport?.height || 0);
@ -68,7 +75,7 @@ function usePositioningOniOS(wrapperRef: MutableRef<HTMLDivElement | null>) {
}, []);
useEffect(() => {
if (!isIOS()) return;
if (!isIOS() || !enabled) return;
window.visualViewport?.addEventListener("resize", adjustPosition);
window.addEventListener("scroll", adjustPosition);
@ -77,7 +84,7 @@ function usePositioningOniOS(wrapperRef: MutableRef<HTMLDivElement | null>) {
window.visualViewport?.removeEventListener("resize", adjustPosition);
window.removeEventListener("scroll", adjustPosition);
};
}, []);
}, [ enabled ]);
}
/**

View File

@ -55,6 +55,7 @@ export function buildClassicToolbar(multilineToolbar: boolean) {
...TEXT_FORMATTING_GROUP,
items: ["underline", "strikethrough", "|", "superscript", "subscript", "|", "kbd"]
},
"formatPainter",
"|",
"fontColor",
"fontBackgroundColor",
@ -104,6 +105,7 @@ export function buildFloatingToolbar() {
...TEXT_FORMATTING_GROUP,
items: [ "strikethrough", "|", "superscript", "subscript", "|", "kbd" ]
},
"formatPainter",
"|",
"fontColor",
"fontBackgroundColor",

View File

@ -19,3 +19,9 @@ export function onWheelHorizontalScroll(event: WheelEvent) {
event.stopImmediatePropagation();
(event.currentTarget as HTMLElement).scrollLeft += event.deltaY + event.deltaX;
}
export function getClosestNtxId(element: HTMLElement) {
const closestNtxEl = element.closest<HTMLElement>("[data-ntx-id]");
if (!closestNtxEl) return null;
return closestNtxEl.dataset.ntxId ?? null;
}

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