1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-24 20:19:10 +02:00

Compare commits

...

165 Commits

Author SHA1 Message Date
Laurent Cozic
a2380fb752 Android release v1.0.122 2018-05-09 13:18:39 +01:00
Laurent Cozic
f6a902809d Electron release v1.0.89 2018-05-09 13:17:08 +01:00
Laurent Cozic
33a853397d Electron release v1.0.88 2018-05-09 13:16:55 +01:00
Laurent Cozic
4f02481899 Electron release v1.0.87 2018-05-09 13:14:42 +01:00
Laurent Cozic
b18076565f Update translations 2018-05-09 13:14:17 +01:00
Laurent Cozic
853ddc5840 Update website 2018-05-09 13:11:03 +01:00
Laurent Cozic
7930ab66c6 Merge branch 'master' into subnotebooks 2018-05-09 13:10:20 +01:00
Laurent Cozic
c7716c0d59 All: Resolves #122: Sub-notebook support in desktop, mobile and cli app 2018-05-09 13:08:00 +01:00
Laurent Cozic
49cbb254d0 CLI: Fixed link handling 2018-05-09 12:50:50 +01:00
Laurent Cozic
cf9246796d CLI: Added support for sub-notebooks 2018-05-09 12:39:27 +01:00
Laurent Cozic
e1dee546dc Mobile: Added support for sub-notebooks 2018-05-09 12:39:17 +01:00
Laurent Cozic
da6fdad2de All: Handle saving collapsed states of sub-notebook 2018-05-09 10:49:31 +01:00
Laurent Cozic
567596643c Electron: Handle drag and dropping notebooks to change the parent 2018-05-09 09:53:47 +01:00
Laurent Cozic
cb617e1b14 All: Fixes #61: Handle path that ends with slash for file system sync. 2018-05-08 11:29:25 +01:00
Laurent Cozic
facf8afa8b Update translations 2018-05-08 11:12:36 +01:00
Laurent Cozic
f0dd61a711 Merge pull request #495 from fmrtn/master
Updated Spanish translation
2018-05-08 11:12:01 +01:00
Laurent Cozic
e958211a13 Merge pull request #496 from zuphilip/patch-1
Update address pronouns "du" in German translation
2018-05-08 11:11:45 +01:00
Philipp Zumstein
0ed170b5bc Update address pronouns "du" in German translation 2018-05-07 07:12:01 +02:00
Fernando
473d3453a2 Updated Spanish translation 2018-05-06 20:29:35 +02:00
Laurent Cozic
fa9d7b0408 Electron: Started UI and backend for sub-notebook support 2018-05-06 12:11:59 +01:00
Laurent Cozic
d4a28f48c9 Update website 2018-05-06 11:17:34 +01:00
Laurent Cozic
ead6fff861 Merge branch 'master' of github.com:laurent22/joplin 2018-05-06 11:16:52 +01:00
Laurent Cozic
c7d06b35cd Merge pull request #494 from stweil/typo
Fix some typos
2018-05-06 11:16:43 +01:00
Laurent Cozic
fa939e5c76 Merge branch 'master' of github.com:laurent22/joplin 2018-05-06 11:16:19 +01:00
Laurent Cozic
1bf2601f4f Merge pull request #492 from zuphilip/patch-1
Update de_DE.po
2018-05-06 11:15:59 +01:00
Stefan Weil
feb0c02c9a ReactNativeClient: Fix some typos (found by codespell)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-05-05 16:25:37 +02:00
Stefan Weil
40a34a7c05 Fix typos in documentation (found by codespell)
Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-05-05 16:23:48 +02:00
Stefan Weil
c62dcd96b0 CliClient: Fix some typos (found by codespell)
Remove also a "translation" which was none from locales/hr_HR.po.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
2018-05-05 16:22:14 +02:00
Philipp Zumstein
1364d6786d Update de_DE.po 2018-05-05 11:08:47 +02:00
Laurent Cozic
a6a351e68d Electron: Export/Import links to notes 2018-05-03 13:11:45 +01:00
Laurent Cozic
1db38a9699 Merge pull request #484 from fmrtn/master
Spanish translation updated
2018-05-03 12:08:57 +01:00
Fernando
c57db1834f Spanish translation updated 2018-05-03 13:07:36 +02:00
Laurent Cozic
3aeb49b469 Merge branch 'master' of github.com:laurent22/joplin 2018-05-03 11:31:17 +01:00
Laurent Cozic
80b467eead All: For now, disable attaching resources larger than 10MB due to #371 2018-05-03 11:31:07 +01:00
Laurent Cozic
61572f287a Update README.md
Added note about large resources
2018-05-03 11:06:12 +01:00
Laurent Cozic
0e545baf10 Update issue_template.md 2018-05-02 21:39:11 +01:00
Laurent Cozic
e65e647359 Update issue_template.md 2018-05-02 21:38:49 +01:00
Laurent Cozic
238268884e Update debugging.md 2018-05-02 20:16:08 +01:00
Laurent Cozic
4c210d0956 Electron: Fixes #480: Ignore invalid flag automatically passed by macOS 2018-05-02 15:51:33 +01:00
Laurent Cozic
5f32c6466a Update website 2018-05-02 15:33:18 +01:00
Laurent Cozic
71bd39a8a3 Update website 2018-05-02 15:31:17 +01:00
Laurent Cozic
ffb660f0f4 Move tool file 2018-05-02 15:28:13 +01:00
Laurent Cozic
dde23632c1 Move tool file 2018-05-02 15:27:12 +01:00
Laurent Cozic
9d26f13db0 Android release v1.0.120 2018-05-02 15:18:13 +01:00
Laurent Cozic
2a4c9c4427 Electron release v1.0.86 2018-05-02 15:16:02 +01:00
Laurent Cozic
3bfde26b74 Merge branch 'master' of github.com:laurent22/joplin 2018-05-02 15:13:28 +01:00
Laurent Cozic
a419bc7253 All: Resolves #134: Allow linking to a note from another note 2018-05-02 15:13:20 +01:00
Laurent Cozic
89e0dad88b Update README.md
32-bit is now supported
2018-05-02 13:16:04 +01:00
Laurent Cozic
ff1ee1249b Mobile: Resolves #61: Enable File System sync on mobile as the driver seems to be working now 2018-05-02 10:27:37 +01:00
Laurent Cozic
ba9cfd8041 Electron: Increased timeout for sync-after-save to 30 seconds 2018-05-02 08:34:54 +01:00
Laurent Cozic
80a51e02a4 Update readme downloads 2018-05-01 22:33:01 +01:00
Laurent Cozic
a2e2a9a2f5 Electron release v1.0.85 2018-05-01 21:16:24 +01:00
Laurent Cozic
49e4c37cac Electron: Check that the filename contains 'Setup' when auto-updating 2018-05-01 21:13:41 +01:00
Laurent Cozic
11d323d8b7 Electron: Fixes #479: Currently loaded note was cleared when creating new note 2018-05-01 21:13:17 +01:00
Laurent Cozic
784ba45f1f Electron release v1.0.84 2018-05-01 19:39:06 +01:00
Laurent Cozic
e534414874 All: Fixes #434: Handle Katex block mode 2018-05-01 19:34:42 +01:00
Laurent Cozic
01f4faf8f1 Mobile: Fixes #426: Fix missing menu icon on Android 4 2018-05-01 19:30:41 +01:00
Laurent Cozic
b33d30ca47 Merge branch 'master' of github.com:laurent22/joplin 2018-05-01 19:05:33 +01:00
Laurent Cozic
1ba3fae101 All: Resolves #470: Make it clear that spaces in URLs are invalid. 2018-05-01 19:05:14 +01:00
Laurent Cozic
9550347e04 Merge pull request #448 from solariz/master
Fix for Issue #430
2018-05-01 18:54:43 +01:00
Laurent Cozic
398946d39a Mobile: Fixes #393: Fixed moving new notes before they are saved 2018-05-01 18:53:45 +01:00
Laurent Cozic
05faf55e8d All: Fixes #363: Fixed indentation and rendering of lists 2018-05-01 16:45:17 +01:00
Laurent Cozic
4cf5525e20 Electron: Fixes #355: Set undo state properly when loading new note 2018-05-01 10:48:15 +01:00
Laurent Cozic
62e91c44d7 Electron: Fixes #346: Make sure links have an address when exporting to PDF 2018-05-01 10:14:48 +01:00
Laurent Cozic
e4ec4ae92b Mobile: Fix action button when note is being edited. 2018-05-01 10:09:36 +01:00
Laurent Cozic
c1f5dfd9cc Keep Blob tests to revisit in a few weeks 2018-04-30 21:21:17 +01:00
Laurent Cozic
0c0efeac1f Android release v1.0.119 2018-04-30 18:34:55 +01:00
Laurent Cozic
5e0f2642e3 Android release v1.0.118 2018-04-30 17:41:39 +01:00
Laurent Cozic
93966b0fa1 Mobile: Trying to upgrade to React Native 0.55 2018-04-30 17:38:19 +01:00
Laurent Cozic
e90abf3517 Updated translations 2018-04-28 11:44:07 +02:00
Laurent Cozic
d3fa0dce96 Updated translations 2018-04-28 11:40:55 +02:00
Laurent Cozic
58a7c2fa94 Doc: Added forum link to website 2018-04-28 11:40:27 +02:00
Laurent Cozic
962a8700c2 Added ptBR translation 2018-04-28 11:35:28 +02:00
Laurent Cozic
b5c704e2bb Doc: Updated website 2018-04-25 20:08:59 +02:00
Laurent Cozic
e7b52b19d7 Doc: Updated website 2018-04-25 20:04:25 +02:00
Laurent Cozic
903c2e6d92 Doc: Updated website 2018-04-25 19:25:54 +02:00
Laurent Cozic
abcb1ac760 Doc: Update website 2018-04-25 19:24:13 +02:00
Laurent Cozic
b6bf76cc4c Doc: Mentioned forums and other community-related links 2018-04-25 11:59:43 +02:00
Laurent Cozic
2bf87655da Electron: Various tweaks to get PortableApps format to work 2018-04-23 21:50:29 +02:00
Laurent Cozic
d4b19f19a1 Electron: Use built-in image resizing instead of Sharp 2018-04-22 21:10:43 +02:00
Laurent Cozic
d8ccc38d5b All: Better handling of resources that are incorrectly flagged as encrypted 2018-04-22 14:33:12 +02:00
Marco G
577bef5704 Fix for Issue #430 2018-04-21 10:25:13 +02:00
Laurent Cozic
4e3b8a06ea Merge branch 'master' of github.com:laurent22/joplin 2018-04-19 19:43:27 +02:00
Laurent Cozic
363632ffa7 Doc: Added Arch Linux package info 2018-04-19 19:42:44 +02:00
Laurent Cozic
994c99f47f Merge pull request #442 from solariz/master
Common EU Date format DD.MM.YYYY added, issue #405
2018-04-19 19:32:22 +02:00
Marco G
96571baadc Common EU Date format DD.MM.YYYY added, issue #405 2018-04-19 17:03:16 +02:00
Laurent Cozic
4ce2b2c948 Doc: Added link to AUR package 2018-04-19 11:14:43 +02:00
Laurent Cozic
5d69f7a0a7 Doc: Added link to AUR package 2018-04-19 11:13:33 +02:00
Laurent Cozic
bcb1f36ad8 Merge pull request #428 from Abijeet/master
Add the toggle sidebar option to the View app menu bar.
2018-04-17 11:17:24 +02:00
Abijeet
34c65a686c Add the toggle sidebar option to the View app menu bar.
Towards #183

Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-04-16 22:57:36 +05:30
Laurent Cozic
0b32741a12 Electron: Resolves #252: Allow enabling tray icon in Linux 2018-04-16 19:18:28 +02:00
Laurent Cozic
dbb321a3cc CLI: Resolves #411: Fixed documentation 2018-04-16 16:29:34 +02:00
Laurent Cozic
a6e4f47adf All: Resolves #389: Documented method being used to encrypt master keys 2018-04-16 16:16:31 +02:00
Laurent Cozic
fb6dee32ac All: Resolves #380: Fixed documentation inconsitencies for webdav url 2018-04-16 16:09:38 +02:00
Laurent Cozic
984dd6f2c0 Electron: Rotate sidebar icon when it is hidden 2018-04-16 15:32:33 +02:00
Laurent Cozic
02bde2c6e9 Merge pull request #424 from Abijeet/master
Adds support to toggle the sidebar.
2018-04-16 15:24:33 +02:00
Laurent Cozic
782d24cc04 Updated Spanish translation 2018-04-16 15:16:29 +02:00
Laurent Cozic
4d0af575e5 Mobile: Resolves #360: Don't crash if theme not set and improved logging. 2018-04-16 15:15:29 +02:00
Laurent Cozic
be8bda8e73 Added Joplin letter as SVG 2018-04-16 11:20:33 +02:00
Abijeet
1242de532e Adds support to toggle the sidebar.
Closes #183

Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-04-15 21:20:39 +05:30
Laurent Cozic
7d7ec7f15e Update translation 2018-04-11 21:39:37 +02:00
Laurent Cozic
ca112ec5d3 Merge branch 'master' of github.com:laurent22/joplin 2018-04-11 21:39:13 +02:00
Laurent Cozic
5deb8cf76d Update translation 2018-04-11 19:27:45 +02:00
Laurent Cozic
a2c9737c17 utf-8 2018-04-11 19:27:20 +02:00
Laurent Cozic
d3fca3d6cc Mobile: Fixes #358: Fix cursor color in dark mode 2018-04-11 19:25:07 +02:00
Laurent Cozic
d5574098f0 Resolves #392: Clarified deletion of resources 2018-04-09 21:00:47 +02:00
Laurent Cozic
f5a683f25c Update issue_template.md 2018-04-09 20:58:35 +02:00
Laurent Cozic
5f04adb392 Merge pull request #376 from mjjzf/master
Updated Danish translation
2018-04-05 22:41:21 +02:00
Laurent Cozic
edd0f7e255 Update issue_template.md 2018-04-04 21:50:45 +02:00
Laurent Cozic
67145d9104 Updated website 2018-04-04 21:48:42 +02:00
Laurent Cozic
003e2afff7 Update readme downloads 2018-04-04 21:44:25 +02:00
Laurent Cozic
6e9d70c5cb Electron release v1.0.83 2018-04-04 21:25:45 +02:00
Laurent Cozic
4821b4cdf2 Electron: Fixes #365: Cannot paste in Dropbox screen 2018-04-04 21:25:27 +02:00
Morten Juhl-Johansen Zölde-Fejer
734d4db431 Updated Danish translation
Translated new strings, minor corrections
2018-04-04 12:32:30 +02:00
Morten Juhl-Johansen Zölde-Fejer
317aaed0ac Updated Danish translation
New strings and minor corrections.
2018-04-04 11:52:26 +02:00
Laurent Cozic
9778098d6c Merge pull request #366 from bimlas/patch-1
Clarify Windows build dependencies
2018-04-02 21:17:10 +02:00
Bimba Laszlo
5b1755f988 Clarify Windows build dependencies 2018-04-02 19:14:04 +02:00
Laurent Cozic
2a772895dd ios v10.0.20 2018-03-31 20:24:32 +02:00
Laurent Cozic
5fbb01cf2f Electron release v1.0.82 2018-03-31 19:23:06 +01:00
Laurent Cozic
f9e0870b4e Android release v1.0.116 2018-03-31 19:21:07 +01:00
Laurent Cozic
a58f1e9b4b Update Galician translation 2018-03-31 19:19:11 +01:00
Laurent Cozic
6fc0d89b30 Update website 2018-03-29 20:55:15 +01:00
Laurent Cozic
2dcadab7d2 Update website 2018-03-29 20:50:18 +01:00
Laurent Cozic
bb3307e156 Update website 2018-03-29 20:48:22 +01:00
Laurent Cozic
ecd07f1209 Update website 2018-03-29 20:42:11 +01:00
Laurent Cozic
266cb1174f Update website 2018-03-29 20:36:34 +01:00
Laurent Cozic
bfb9b77b6e Update website 2018-03-29 20:25:37 +01:00
Laurent Cozic
01b1361dcb Update website 2018-03-29 20:21:14 +01:00
Laurent Cozic
3a921720d6 Update website 2018-03-29 20:17:11 +01:00
Laurent Cozic
cdfd3d9c31 Updated French translation and added Galician translation 2018-03-29 18:30:33 +01:00
Laurent Cozic
9961fb64bb Updated website 2018-03-29 00:52:27 +01:00
Laurent Cozic
3137c355cf Added stats and changelog document 2018-03-28 17:41:14 +00:00
Laurent Cozic
16abaf60d2 Update readme downloads 2018-03-28 09:14:24 +01:00
Laurent Cozic
9004b710ea CLI v1.0.106 2018-03-27 23:22:06 +01:00
Laurent Cozic
6ebac21c2b Electron release v1.0.81 2018-03-27 23:03:25 +01:00
Laurent Cozic
99f79faf83 Android release v1.0.115 2018-03-27 23:01:56 +01:00
Laurent Cozic
613fa20806 Merge branch 'dropbox' 2018-03-27 23:00:49 +01:00
Laurent Cozic
1b5f812278 Merge branch 'master' of github.com:laurent22/joplin 2018-03-27 23:00:32 +01:00
Laurent Cozic
3a9643c1ea Electron release v1.0.80 2018-03-27 22:57:23 +01:00
Laurent Cozic
aee7f5a8ac Android release v1.0.114 2018-03-27 22:55:46 +01:00
Laurent Cozic
d3cd378922 Android release v1.0.113 2018-03-27 17:57:34 +01:00
Laurent Cozic
4f5e7367d0 Minor tweals 2018-03-27 17:48:55 +01:00
Laurent Cozic
2280fb5c43 Styled Dropbox mobile GUI 2018-03-27 17:41:19 +00:00
Laurent Cozic
96fb7c2087 Getting Dropbox to work in mobile app 2018-03-27 00:55:44 +01:00
Laurent Cozic
6e994fd8b9 All: Dropbox: Handle various error conditions 2018-03-27 00:05:39 +01:00
Laurent Cozic
a7cde1e269 All: Resolves #329: Add link to E2EE doc 2018-03-26 17:55:09 +00:00
Laurent Cozic
f8310ba0d5 Mobile: Fixed tag box styling in dark theme 2018-03-26 17:52:49 +00:00
Laurent Cozic
b239c3faba Update README.md 2018-03-26 18:51:03 +01:00
Laurent Cozic
3c2281dbf9 Merge branch 'master' into dropbox 2018-03-26 18:37:04 +01:00
Laurent Cozic
ac07bf784d Adding Dropbox sync to Electron app 2018-03-26 18:33:55 +01:00
Laurent Cozic
067455542f Update README.md 2018-03-25 20:02:54 +01:00
Laurent Cozic
5bfeaa357b Updated translations and added Czech translation 2018-03-24 20:15:36 +00:00
Laurent Cozic
fe27a64331 Merge branch 'master' of github.com:laurent22/joplin 2018-03-24 20:14:04 +00:00
Laurent Cozic
ed638612aa Moved to https:// domain 2018-03-24 20:13:52 +00:00
Laurent Cozic
1d7ec83510 Merge pull request #328 from hydrandt/czech_translation
adding Czech translation
2018-03-24 20:12:44 +00:00
Laurent Cozic
75c710232d Update readme downloads 2018-03-24 20:08:23 +00:00
hydrandt
5af52afadb adding Czech translation 2018-03-25 04:01:51 +08:00
Laurent Cozic
0f4324c2f8 All: Added backend for Dropbox support 2018-03-24 19:35:10 +00:00
Laurent Cozic
b48e1dac94 Update README.md
Fixes #327
2018-03-24 16:50:10 +00:00
Laurent Cozic
f0ca8e1e31 Update debugging.md 2018-03-24 15:37:33 +00:00
Laurent Cozic
74b83eb71e All: Fixes #318: Display full links in editor 2018-03-24 15:16:58 +00:00
Laurent Cozic
28dce0fbb5 iOS 19 2018-03-23 19:19:15 +00:00
Laurent Cozic
c12d402c7e Merge branch 'master' of github.com:laurent22/joplin 2018-03-23 18:19:46 +00:00
Laurent Cozic
014f5b123c iOS 15 2018-03-23 18:19:38 +00:00
Laurent Cozic
58601dfc04 CLI v1.0.104 2018-03-23 18:06:06 +00:00
1009 changed files with 16839 additions and 3537 deletions

62
Assets/JoplinLetter.svg Normal file
View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="116.54575mm"
height="131.19589mm"
viewBox="0 0 116.54575 131.19589"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="JoplinLetter.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.49497475"
inkscape:cx="152.11122"
inkscape:cy="-26.090631"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-2.7903623,-2.175533)">
<path
style="fill:#000000;stroke-width:0.26458332"
d="m 43.790458,133.13317 c -8.32317,-1.11843 -12.937,-2.40956 -18.46857,-5.16822 -10.21924,-5.09644 -18.1023498,-13.95338 -21.1745998,-23.79038 -1.22214,-3.91319 -1.3607,-4.872332 -1.35685,-9.392712 0.003,-3.72804 0.0907,-4.66941 0.59927,-6.44569 1.0664,-3.7246 2.49409,-6.1704 5.19529,-8.90014 3.2574198,-3.29184 6.6565798,-4.77332 11.3929598,-4.96548 4.53189,-0.18388 7.54661,0.59927 10.40386,2.70266 1.82035,1.34007 3.67693,3.96421 4.71565,6.66525 0.65839,1.71204 0.70959,2.1839 0.90042,8.29756 0.19973,6.39855 0.36372,7.6318 1.39223,10.469902 1.40468,3.87611 3.78939,6.56189 7.33039,8.25588 3.20047,1.53108 5.63801,2.00183 9.60817,1.8556 2.58182,-0.0951 3.60332,-0.25442 5.15337,-0.80371 4.61358,-1.63493 8.46322,-5.31381 10.31326,-9.85579 1.91154,-4.693002 1.90785,-4.609372 1.90213,-43.127082 -0.005,-33.78395 -0.0106,-34.14337 -0.54484,-35.32188 -1.30698,-2.882895 -2.68223,-3.398165 -9.66971,-3.622945 l -5.12472,-0.16486 V 10.998334 2.175533 l 31.41927,0.06723 31.419272,0.06723 0.0697,8.755726 0.0697,8.755724 -5.09675,0.1793 c -2.82759,0.0995 -5.60596,0.33101 -6.24051,0.52006 -1.72896,0.5151 -2.82899,1.538795 -3.52569,3.281045 l -0.61059,1.5269 -0.16762,34.7927 c -0.16988,35.26321 -0.19381,36.08914 -1.18496,40.914372 -1.81292,8.82581 -8.301582,17.89221 -16.959672,23.69719 -6.95182,4.66099 -14.48972,7.21214 -24.82645,8.40235 -2.7431,0.31585 -14.57797,0.31433 -16.93333,-0.002 z"
id="path21"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -37,8 +37,6 @@ yarn dist
If there's an error `while loading shared libraries: libgconf-2.so.4: cannot open shared object file: No such file or directory`, run `sudo apt-get install libgconf-2-4`
For node-gyp to work, you might need to install the `windows-build-tools` using `npm install --global windows-build-tools`.
That will create the executable file in the `dist` directory.
From `/ElectronClient` you can also run `run.sh` to run the app for testing.
@@ -54,6 +52,10 @@ npm install
yarn dist
```
If node-gyp does not works (MSBUILD: error MSB3428: Could not load the Visual C++ component "VCBuild.exe"), you might need to install the `windows-build-tools` using `npm install --global windows-build-tools`.
If `yarn dist` fails, it may need administrative rights.
# Building the Mobile application
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "Building Projects with Native Code" tab.

View File

@@ -1,3 +1,7 @@
# User support
For general discussion about Joplin, user support, software development questions, and to discuss new features, please go to the [Joplin Forum](https://discourse.joplin.cozic.net/). It is possible to login with your GitHub account.
# Reporting a bug
Please check first that it [has not already been reported](https://github.com/laurent22/joplin/issues?utf8=%E2%9C%93&q=is%3Aissue). Also consider [enabling debug mode](https://github.com/laurent22/joplin/blob/master/readme/debugging.md) before reporting the issue so that you can provide as much details as possible to help fix it.
@@ -6,7 +10,7 @@ If possible, **please provide a screenshot**. A screenshot showing the problem i
# Feature requests
Again, please check that it has not already been requested. If it has, simply **up-vote the issue** - the ones with the most up-votes are likely to be implemented. Adding a "+1" comment does nothing.
Again, please check that it has not already been requested. If it has, simply **up-vote the issue** - the ones with the most up-votes are likely to be implemented. "+1" comments are not tracked.
# Adding new features

View File

@@ -18,4 +18,5 @@ tests/cli-integration/
tests/sync
out.txt
linkToLocal.sh
yarn-error.log
yarn-error.log
tests/support/dropbox-auth.txt

View File

@@ -1,5 +1,6 @@
const { Logger } = require('lib/logger.js');
const Folder = require('lib/models/Folder.js');
const BaseItem = require('lib/models/BaseItem.js');
const Tag = require('lib/models/Tag.js');
const BaseModel = require('lib/BaseModel.js');
const Note = require('lib/models/Note.js');
@@ -9,6 +10,8 @@ const { reducer, defaultState } = require('lib/reducer.js');
const { splitCommandString } = require('lib/string-utils.js');
const { reg } = require('lib/registry.js');
const { _ } = require('lib/locale.js');
const Entities = require('html-entities').AllHtmlEntities;
const htmlentities = (new Entities()).encode;
const chalk = require('chalk');
const tk = require('terminal-kit');
@@ -638,12 +641,27 @@ class AppGui {
return true;
}
if (link.type === 'resource') {
const resourceId = link.id;
let resource = await Resource.load(resourceId);
if (!resource) throw new Error('No resource with ID ' + resourceId); // Should be nearly impossible
if (resource.mime) response.setHeader('Content-Type', resource.mime);
response.write(await Resource.content(resource));
if (link.type === 'item') {
const itemId = link.id;
let item = await BaseItem.loadItemById(itemId);
if (!item) throw new Error('No item with ID ' + itemId); // Should be nearly impossible
if (item.type_ === BaseModel.TYPE_RESOURCE) {
if (item.mime) response.setHeader('Content-Type', item.mime);
response.write(await Resource.content(item));
} else if (item.type_ === BaseModel.TYPE_NOTE) {
const html = [`
<!DOCTYPE html>
<html class="client-nojs" lang="en" dir="ltr">
<head><meta charset="UTF-8"/></head><body>
`];
html.push('<pre>' + htmlentities(item.title) + '\n\n' + htmlentities(item.body) + '</pre>');
html.push('</body></html>');
response.write(html.join(''));
} else {
throw new Error('Unsupported item type: ' + item.type_);
}
return true;
}
@@ -659,7 +677,7 @@ class AppGui {
if (resourceIdRegex.test(url)) {
noteLinks[index] = {
type: 'resource',
type: 'item',
id: url.substr(2),
};
} else if (hasProtocol(url, ['http', 'https', 'file', 'ftp'])) {

View File

@@ -36,7 +36,7 @@ async function handleAutocompletionPromise(line) {
if (next[0] === '-') {
for (let i = 0; i<metadata.options.length; i++) {
const options = metadata.options[i][0].split(' ');
//if there are multiple options then they will be seperated by comma and
//if there are multiple options then they will be separated by comma and
//space. The comma should be removed
if (options[0][options[0].length - 1] === ',') {
options[0] = options[0].slice(0, -1);

View File

@@ -102,7 +102,7 @@ function getFooter() {
output.push('WEBSITE');
output.push('');
output.push(INDENT + 'http://joplin.cozic.net');
output.push(INDENT + 'https://joplin.cozic.net');
output.push('');

View File

@@ -37,7 +37,7 @@ class Command extends BaseCommand {
const stdoutWidth = app().commandStdoutMaxWidth();
if (args.command === 'shortcuts' || args.command === 'keymap') {
this.stdout(_('For information on how to customise the shortcuts please visit %s', 'http://joplin.cozic.net/terminal/#shortcuts'));
this.stdout(_('For information on how to customise the shortcuts please visit %s', 'https://joplin.cozic.net/terminal/#shortcuts'));
this.stdout('');
if (app().gui().isDummy()) {
@@ -72,11 +72,11 @@ class Command extends BaseCommand {
this.stdout('');
this.stdout(commandNames.join(', '));
this.stdout('');
this.stdout(_('In any command, a note or notebook can be refered to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.'));
this.stdout(_('In any command, a note or notebook can be referred to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.'));
this.stdout('');
this.stdout(_('To move from one pane to another, press Tab or Shift+Tab.'));
this.stdout(_('Use the arrows and page up/down to scroll the lists and text areas (including this console).'));
this.stdout(_('To maximise/minimise the console, press "TC".'));
this.stdout(_('To maximise/minimise the console, press "tc".'));
this.stdout(_('To enter command line mode, press ":"'));
this.stdout(_('To exit command line mode, press ESCAPE'));
this.stdout(_('For the list of keyboard shortcuts and config options, type `help keymap`'));

View File

@@ -29,7 +29,7 @@ class Command extends BaseCommand {
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, pattern);
if (!folder) throw new Error(_('Cannot find "%s".', pattern));
const ok = force ? true : await this.prompt(_('Delete notebook? All notes within this notebook will also be deleted.'), { booleanAnswerDefault: 'n' });
const ok = force ? true : await this.prompt(_('Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.'), { booleanAnswerDefault: 'n' });
if (!ok) return;
await Folder.delete(folder.id);

View File

@@ -78,10 +78,26 @@ class Command extends BaseCommand {
return false;
}
return true;
} else if (syncTargetMd.name === 'dropbox') { // Dropbox
const api = await syncTarget.api();
const loginUrl = api.loginUrl();
this.stdout(_('To allow Joplin to synchronise with Dropbox, please follow the steps below:'));
this.stdout(_('Step 1: Open this URL in your browser to authorise the application:'));
this.stdout(loginUrl);
const authCode = await this.prompt(_('Step 2: Enter the code provided by Dropbox:'), { type: 'string' });
if (!authCode) {
this.stdout(_('Authentication was not completed (did not receive an authentication token).'));
return false;
}
const response = await api.execAuthToken(authCode);
Setting.setValue('sync.' + this.syncTargetId_ + '.auth', response.access_token);
api.setAuthToken(response.access_token);
return true;
}
this.stdout(_('Not authentified with %s. Please provide any missing credentials.', syncTarget.label()));
this.stdout(_('Not authentified with %s. Please provide any missing credentials.', syncTargetMd.label));
return false;
}
@@ -100,6 +116,7 @@ class Command extends BaseCommand {
this.releaseLockFn_ = null;
// Lock is unique per profile/database
// TODO: use SQLite database to do lock?
const lockFilePath = require('os').tmpdir() + '/synclock_' + md5(escape(Setting.value('profileDir'))); // https://github.com/pvorb/node-md5/issues/41
if (!await fs.pathExists(lockFilePath)) await fs.writeFile(lockFilePath, 'synclock');
@@ -130,7 +147,7 @@ class Command extends BaseCommand {
const syncTarget = reg.syncTarget(this.syncTargetId_);
if (!syncTarget.isAuthenticated()) {
if (!await syncTarget.isAuthenticated()) {
app().gui().showConsole();
app().gui().maximizeConsole();
@@ -197,7 +214,7 @@ class Command extends BaseCommand {
const syncTarget = reg.syncTarget(syncTargetId);
if (syncTarget.isAuthenticated()) {
if (await syncTarget.isAuthenticated()) {
const sync = await syncTarget.synchronizer();
if (sync) await sync.cancel();
} else {

View File

@@ -18,19 +18,20 @@ class FolderListWidget extends ListWidget {
this.notesParentType_ = 'Folder';
this.updateIndexFromSelectedFolderId_ = false;
this.updateItems_ = false;
this.trimItemTitle = false;
this.itemRenderer = (item) => {
let output = [];
if (item === '-') {
output.push('-'.repeat(this.innerWidth));
} else if (item.type_ === Folder.modelType()) {
output.push(Folder.displayTitle(item));
output.push(' '.repeat(this.folderDepth(this.folders, item.id)) + Folder.displayTitle(item));
} else if (item.type_ === Tag.modelType()) {
output.push('[' + Folder.displayTitle(item) + ']');
} else if (item.type_ === BaseModel.TYPE_SEARCH) {
output.push(_('Search:'));
output.push(item.title);
}
}
// if (item && item.id) output.push(item.id.substr(0, 5));
@@ -38,6 +39,17 @@ class FolderListWidget extends ListWidget {
};
}
folderDepth(folders, folderId) {
let output = 0;
while (true) {
const folder = BaseModel.byId(folders, folderId);
if (!folder.parent_id) return output;
output++;
folderId = folder.parent_id;
}
throw new Error('unreachable');
}
get selectedFolderId() {
return this.selectedFolderId_;
}

1436
CliClient/locales/cs_CZ.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Joplin-CLI 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
"Last-Translator: Morten Juhl-Johansen Zölde-Fejér <mjjzf@syntaktisk."
"dk>Language-Team: \n"
"Language: da_DK\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -127,7 +127,7 @@ msgid ""
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
"`status` and `target-status`."
msgstr ""
"Udfører E2EEE konfiguration. Kommandoer er `enable`(aktiver), "
"Udfører E2EE konfiguration. Kommandoer er `enable`(aktiver), "
"`disable`(sluk), `decrypt`(dekrypter), `status` og `target-status` (modtager-"
"status)."
@@ -163,8 +163,8 @@ msgstr "Rediger note."
msgid ""
"No text editor is defined. Please set it using `config editor <editor-path>`"
msgstr ""
"Ingen tekst editor er valgt. Vælg en ved at indstille `config editor "
"<editor-path>`"
"Ingen teksteditor er valgt. Vælg en ved at indstille `config editor <editor-"
"path>`"
msgid "No active notebook."
msgstr "Ingen aktiv notesbog."
@@ -229,7 +229,7 @@ msgid "The possible commands are:"
msgstr "Mulige kommandoer er:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -247,7 +247,8 @@ msgstr ""
"Brug pilene og PageUp/PageDown for at rulle lister og tekst-områder (inkl. "
"denne konsol)"
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "For at maximere/ninimere konsollen, tryk \"TC\"."
msgid "To enter command line mode, press \":\""
@@ -366,7 +367,10 @@ msgstr "Sletter aktuelle notesbog."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Sletter notesbogen uden at bede om bekræftelse."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr "Slet notesbog? Alle noter i notesbogen bliver også slettet."
msgid "Deletes the notes matching <note-pattern>."
@@ -410,6 +414,18 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Godkendelse blev ikke fuldført (modtog ikke godkendelses token)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
"For at Joplin kan synkronisere med Dropbox, skal man igennem nedenstående "
"trin:"
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr "Trin 1: Åben denne URL i din browser for at autorisere applikationen:"
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr "Trin 2: Indtast koden, som er oplyst af Dropbox:"
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr "Ikke godkendt med %s. Indtast venligst manglende koder/info."
@@ -423,8 +439,8 @@ msgid ""
"taking place, you may delete the lock file at \"%s\" and resume the "
"operation."
msgstr ""
"Låse fil er allerede i brug. Hvis du ved at ingen synkronisering er i gang "
"kan du slette låse-filen \"%s\" og genoptage synkroniseringen."
"Låsefil er allerede i brug. Hvis du ved at ingen synkronisering er i gang "
"kan du slette låsefilen \"%s\" og genoptage synkroniseringen."
#, javascript-format
msgid "Synchronisation target: %s (%s)"
@@ -609,6 +625,9 @@ msgstr "Søg i alle noter"
msgid "View"
msgstr "Vis"
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr "Skift editor layout"
@@ -678,6 +697,9 @@ msgstr "Noter og indstillinger er gemt i: %s"
msgid "Save"
msgstr "Gem"
msgid "Submit"
msgstr "Gem"
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -749,6 +771,13 @@ msgstr ""
"app'en har ikke pt adgang til dem. Det er sandsynligt at de vil blive hentet "
"(på et eller andet tidspunkt) via synkroniseringen."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
"Se dokumentationen for nærmere oplysninger om End-To-End-kryptering (E2EE) "
"og vejledning om hvordan det skal opsættes_"
msgid "Status"
msgstr "Status"
@@ -784,12 +813,13 @@ msgstr "Omdøb notesbog:"
msgid "Set alarm:"
msgstr "Indstil alarm:"
msgid "Search"
msgstr "Søg"
msgid "Layout"
msgstr "Layout"
#, fuzzy
msgid "Search..."
msgstr "Søg"
msgid "Some items cannot be synchronised."
msgstr "Nogle emner kan ikke synkroniseres."
@@ -808,6 +838,10 @@ msgstr "Tilføj eller slet mærker"
msgid "Switch between note and to-do type"
msgstr "Skift mellem note- og opgave type"
#, fuzzy
msgid "Copy Markdown link"
msgstr "Markdown"
msgid "Delete"
msgstr "Slet"
@@ -865,6 +899,9 @@ msgstr "Ryd/slet"
msgid "OneDrive Login"
msgstr "OneDrive login"
msgid "Dropbox Login"
msgstr "Dropbox Login"
msgid "Options"
msgstr "Muligheder"
@@ -889,9 +926,6 @@ msgstr "Synkroniser"
msgid "Notebooks"
msgstr "Notesbøger"
msgid "Searches"
msgstr "Søgninger"
msgid "Please select where the sync status should be exported to"
msgstr "Vælg hvor sync status skal eksporteres til"
@@ -903,6 +937,9 @@ msgstr "Forbrug: %s"
msgid "Unknown flag: %s"
msgstr "Ukendt flag: %s"
msgid "Dropbox"
msgstr "Dropbox"
msgid "File system"
msgstr "Fil system"
@@ -1014,6 +1051,10 @@ msgstr "Krypteret emner kan ikke rettes"
msgid "Conflicts"
msgstr "Konflikter"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Kan ikke flytte note til \"%s\" notesbog"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "En notesbog bruger allerede dette navn: \"%s\""
@@ -1091,6 +1132,9 @@ msgstr "Ved oprettelse af ny note:"
msgid "Show tray icon"
msgstr "Vis ikon på bundbjælke"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr "Global zoom procent"
@@ -1291,14 +1335,18 @@ msgid "Cancel synchronisation"
msgstr "Afbryd synkronisering"
msgid "New tags:"
msgstr ""
msgstr "Nye tags:"
msgid "Type new tags or select from list"
msgstr ""
msgstr "Indtast nye tags eller vælg fra listen"
msgid "Joplin website"
msgstr "Joplin hjemmeside"
#, fuzzy
msgid "Login with Dropbox"
msgstr "Log på med OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr "Hoved nøgle %s"
@@ -1338,6 +1386,14 @@ msgstr "Gem ændringer"
msgid "Discard changes"
msgstr "Fortryd ændringer"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Ulovlig billedtype: %s"
@@ -1369,6 +1425,9 @@ msgstr "Slet notesbog"
msgid "Login with OneDrive"
msgstr "Log på med OneDrive"
msgid "Search"
msgstr "Søg"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1381,3 +1440,13 @@ msgstr "Du har ingen notesbøger. Opret en ved at klikke på (+) knappen."
msgid "Welcome"
msgstr "Velkommen"
#~ msgid ""
#~ "For more information about End-To-End Encryption (E2EE) and advices on "
#~ "how to enable it please check the documentation"
#~ msgstr ""
#~ "Se dokumentationen for nærmere oplysninger om End-To-End-kryptering "
#~ "(E2EE) og vejledning om hvordan det skal opsættes"
#~ msgid "Searches"
#~ msgstr "Søgninger"

View File

@@ -7,13 +7,13 @@ msgid ""
msgstr ""
"Project-Id-Version: Joplin-CLI 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: Tobias Grasse <mail@tobias-grasse.net>\n"
"Last-Translator: Philipp Zumstein <zuphilip@gmail.com>\n"
"Language-Team: \n"
"Language: de_DE\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.0.7\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
msgid "To delete a tag, untag the associated notes."
@@ -238,7 +238,7 @@ msgid "The possible commands are:"
msgstr "Mögliche Befehle lauten:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -259,8 +259,8 @@ msgstr ""
"Benutze die Pfeiltasten und Bild hoch/runter um durch Listen und Texte zu "
"scrollen (inklusive diesem Terminal)."
msgid "To maximise/minimise the console, press \"TC\"."
msgstr "Um das Terminal zu maximieren/minimieren, drücke \"TC\"."
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Um das Terminal zu maximieren/minimieren, drücke \"tc\"."
msgid "To enter command line mode, press \":\""
msgstr "Um den Kommandozeilen Modus aufzurufen, drücke \":\""
@@ -379,7 +379,10 @@ msgstr "Löscht das ausgewählte Notizbuch."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Löscht das Notizbuch, ohne nach einer Bestätigung zu fragen."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"Notizbuch wirklich löschen? Alle Notizen darin werden ebenfalls gelöscht."
@@ -429,6 +432,18 @@ msgstr ""
"Authentifizierung wurde nicht abgeschlossen (keinen Authentifizierung-Token "
"erhalten)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
"Um Joplin die Synchronisation mit Dropbox zu ermöglichen, folge bitte den "
"folgenden Schritten:"
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr "Schritt 1: URL im Browser öffnen um die Anwendung zu autorisieren:"
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr "Schritt 2: Den von Dropbox bereitgestellten Code eingeben:"
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -520,9 +535,8 @@ msgstr "Standard: %s"
msgid "Possible keys/values:"
msgstr "Mögliche Werte:"
#, fuzzy
msgid "Type `joplin help` for usage information."
msgstr "Zeigt die Nutzungsstatistik an."
msgstr "Gib `joplin help` ein um die Nutzungsstatistik anzuzeigen."
msgid "Fatal error:"
msgstr "Schwerwiegender Fehler:"
@@ -530,7 +544,7 @@ msgstr "Schwerwiegender Fehler:"
msgid ""
"The application has been authorised - you may now close this browser tab."
msgstr ""
"Das Programm wurde autorisiert - Du kannst diesen Browsertab nun schließen."
"Das Programm wurde autorisiert - du kannst diesen Browsertab nun schließen."
msgid "The application has been successfully authorised."
msgstr "Das Programm wurde erfolgreich autorisiert."
@@ -635,6 +649,9 @@ msgstr "Alle Notizen durchsuchen"
msgid "View"
msgstr "Ansicht"
msgid "Toggle sidebar"
msgstr "Seitenleiste ein/aus"
msgid "Toggle editor layout"
msgstr "Editor Layout umschalten"
@@ -704,6 +721,9 @@ msgstr "Notizen und Einstellungen werden gespeichert in: %s"
msgid "Save"
msgstr "Speichern"
msgid "Submit"
msgstr "Absenden"
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -774,6 +794,13 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr "Die Master-Keas dieser IDs werden für die Verschlüsselung einiger ..."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
"Weitere Informationen zur Ende-zu-Ende-Verschlüsselung (E2EE) und Hinweise "
"zur Aktivierung findest du in der Dokumentation (auf Englisch):"
msgid "Status"
msgstr "Status"
@@ -811,12 +838,12 @@ msgstr "Notizbuch umbenennen:"
msgid "Set alarm:"
msgstr "Alarm erstellen:"
msgid "Search"
msgstr "Suchen"
msgid "Layout"
msgstr "Layout"
msgid "Search..."
msgstr "Suchen..."
msgid "Some items cannot be synchronised."
msgstr "Manche Objekte können nicht synchronisiert werden."
@@ -835,6 +862,10 @@ msgstr "Markierungen hinzufügen oder entfernen"
msgid "Switch between note and to-do type"
msgstr "Zwischen Notiz und To-Do Typ wechseln"
#, fuzzy
msgid "Copy Markdown link"
msgstr "Markdown"
msgid "Delete"
msgstr "Löschen"
@@ -849,8 +880,8 @@ msgstr ""
msgid ""
"There is currently no notebook. Create one by clicking on \"New notebook\"."
msgstr ""
"Momentan existieren noch keine Notizbücher. Erstelle eines, indem du auf den "
"(+) Knopf drückst."
"Momentan existieren noch keine Notizbücher. Erstelle eines, indem du auf "
"\"Neues Notizbuch\" drückst."
msgid "Open..."
msgstr "Öffne..."
@@ -898,6 +929,9 @@ msgstr "Leeren"
msgid "OneDrive Login"
msgstr "OneDrive Login"
msgid "Dropbox Login"
msgstr "Dropbox Anmeldung"
msgid "Options"
msgstr "Optionen"
@@ -922,9 +956,6 @@ msgstr "Synchronisieren"
msgid "Notebooks"
msgstr "Notizbücher"
msgid "Searches"
msgstr "Suchen"
msgid "Please select where the sync status should be exported to"
msgstr ""
"Bitte wähle aus, wohin der Synchronisations Status exportiert werden soll"
@@ -937,6 +968,9 @@ msgstr "Nutzung: %s"
msgid "Unknown flag: %s"
msgstr "Unbekanntes Argument: %s"
msgid "Dropbox"
msgstr "Dropbox"
msgid "File system"
msgstr "Dateisystem"
@@ -1014,9 +1048,9 @@ msgstr "Remote Objekte gelöscht: %d."
msgid "Fetched items: %d/%d."
msgstr "Geladene Objekte: %d/%d."
#, fuzzy, javascript-format
#, javascript-format
msgid "State: %s."
msgstr "Status: \"%s\"."
msgstr "Status: %s."
msgid "Cancelling..."
msgstr "Abbrechen..."
@@ -1048,6 +1082,10 @@ msgstr "Verschlüsselte Objekte können nicht verändert werden"
msgid "Conflicts"
msgstr "Konflikte"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Kann Notiz nicht zu Notizbuch \"%s\" verschieben"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Ein Notizbuch mit diesem Titel existiert bereits : \"%s\""
@@ -1127,6 +1165,9 @@ msgstr "Wenn eine neue Notiz erstellt wird:"
msgid "Show tray icon"
msgstr "Zeige Tray Icon"
msgid "Note: Does not work in all desktop environments."
msgstr "Hinweis: Funktioniert nicht in allen Desktopumgebungen."
msgid "Global zoom percentage"
msgstr "Zoomstufe der Benutzeroberfläche"
@@ -1255,7 +1296,7 @@ msgid ""
"(which is displayed in brackets above)."
msgstr ""
"Diese Objekte verbleiben auf dem Gerät, werden aber nicht zum "
"Synchronisationsziel hochgeladen. Um diese Objekte zu finden, suchen Sie "
"Synchronisationsziel hochgeladen. Um diese Objekte zu finden, suchst du "
"entweder nach dem Titel oder der ID (die oben in Klammern angezeigt wird)."
msgid "Sync status (synced items / total items)"
@@ -1331,14 +1372,17 @@ msgid "Cancel synchronisation"
msgstr "Synchronisation abbrechen"
msgid "New tags:"
msgstr ""
msgstr "Neue Markierungen:"
msgid "Type new tags or select from list"
msgstr ""
msgstr "Neue Markierungen eingeben oder aus der Liste auswählen"
msgid "Joplin website"
msgstr "Website von Joplin"
msgid "Login with Dropbox"
msgstr "Mit Dropbox anmelden"
#, javascript-format
msgid "Master Key %s"
msgstr "Hauptschlüssel %s"
@@ -1378,6 +1422,14 @@ msgstr "Änderungen speichern"
msgid "Discard changes"
msgstr "Änderungen verwerfen"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Nicht unterstütztes Fotoformat: %s"
@@ -1409,6 +1461,9 @@ msgstr "Notizbuch löschen"
msgid "Login with OneDrive"
msgstr "Mit OneDrive anmelden"
msgid "Search"
msgstr "Suchen"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1425,6 +1480,9 @@ msgstr ""
msgid "Welcome"
msgstr "Willkommen"
#~ msgid "Searches"
#~ msgstr "Suchen"
#~ msgid ""
#~ "Release notes:\n"
#~ "\n"

View File

@@ -210,7 +210,7 @@ msgid "The possible commands are:"
msgstr ""
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -223,7 +223,7 @@ msgid ""
"(including this console)."
msgstr ""
msgid "To maximise/minimise the console, press \"TC\"."
msgid "To maximise/minimise the console, press \"tc\"."
msgstr ""
msgid "To enter command line mode, press \":\""
@@ -332,7 +332,9 @@ msgstr ""
msgid "Deletes the notebook without asking for confirmation."
msgstr ""
msgid "Delete notebook? All notes within this notebook will also be deleted."
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
msgid "Deletes the notes matching <note-pattern>."
@@ -372,6 +374,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr ""
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -546,6 +558,9 @@ msgstr ""
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -615,6 +630,9 @@ msgstr ""
msgid "Save"
msgstr ""
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -673,6 +691,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr ""
@@ -708,10 +731,10 @@ msgstr ""
msgid "Set alarm:"
msgstr ""
msgid "Search"
msgid "Layout"
msgstr ""
msgid "Layout"
msgid "Search..."
msgstr ""
msgid "Some items cannot be synchronised."
@@ -732,6 +755,9 @@ msgstr ""
msgid "Switch between note and to-do type"
msgstr ""
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr ""
@@ -789,6 +815,9 @@ msgstr ""
msgid "OneDrive Login"
msgstr ""
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr ""
@@ -813,9 +842,6 @@ msgstr ""
msgid "Notebooks"
msgstr ""
msgid "Searches"
msgstr ""
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -827,6 +853,9 @@ msgstr ""
msgid "Unknown flag: %s"
msgstr ""
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr ""
@@ -930,6 +959,9 @@ msgstr ""
msgid "Conflicts"
msgstr ""
msgid "Cannot move notebook to this location"
msgstr ""
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr ""
@@ -1005,6 +1037,9 @@ msgstr ""
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1202,6 +1237,9 @@ msgstr ""
msgid "Joplin website"
msgstr ""
msgid "Login with Dropbox"
msgstr ""
#, javascript-format
msgid "Master Key %s"
msgstr ""
@@ -1241,6 +1279,14 @@ msgstr ""
msgid "Discard changes"
msgstr ""
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr ""
@@ -1272,6 +1318,9 @@ msgstr ""
msgid "Login with OneDrive"
msgstr ""
msgid "Search"
msgstr ""
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."

View File

@@ -230,7 +230,7 @@ msgid "The possible commands are:"
msgstr "Los posibles comandos son:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -250,8 +250,8 @@ msgstr ""
"Para desplazar en las listas y areas de texto (incluyendo la consola) "
"utilice las flechas y re pág/av pág."
msgid "To maximise/minimise the console, press \"TC\"."
msgstr "Para maximizar/minimizar la consola, presione \"TC\"."
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Para maximizar/minimizar la consola, presione \"tc\"."
msgid "To enter command line mode, press \":\""
msgstr "Para entrar a modo línea de comando, presione \":\""
@@ -368,7 +368,10 @@ msgstr "Elimina la libreta dada."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Elimina una libreta sin pedir confirmación."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"¿Desea eliminar la libreta? Todas las notas dentro de esta libreta también "
"serán eliminadas."
@@ -416,6 +419,18 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Autenticación no completada (no se recibió token de autenticación)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
"Para permitir a Joplin sincronizar con Dropbox, por favor siga estos pasos:"
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
"Paso 1: Abra esta dirección en su navegador para autorizar a la aplicación:"
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr "Paso 2: Introduzca el código provisto por Dropbox:"
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr "No autenticado con %s. Por favor provea las credenciales."
@@ -620,6 +635,9 @@ msgstr "Buscar en todas las notas"
msgid "View"
msgstr "Ver"
msgid "Toggle sidebar"
msgstr "Cambia la barra lateral"
msgid "Toggle editor layout"
msgstr "Cambia el diseño del editor"
@@ -689,6 +707,9 @@ msgstr "Las notas y los ajustes se guardan en: %s"
msgid "Save"
msgstr "Guardar"
msgid "Submit"
msgstr "Aceptar"
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -760,6 +781,13 @@ msgstr ""
"elementos, pero la apliación no tiene acceso a ellas. Serán descargadas a "
"través de la sincronización."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
"Para más información acerca del cifrado extremo a extremo (E2EE) y "
"advertencias de como habilitarlo por favor revise la documentación:"
msgid "Status"
msgstr "Estado"
@@ -795,12 +823,12 @@ msgstr "Renombrar libreta:"
msgid "Set alarm:"
msgstr "Ajustar alarma:"
msgid "Search"
msgstr "Buscar"
msgid "Layout"
msgstr "Diseño"
msgid "Search..."
msgstr "Buscar..."
msgid "Some items cannot be synchronised."
msgstr "No se han podido sincronizar algunos de los elementos."
@@ -819,6 +847,9 @@ msgstr "Añadir o borrar etiquetas"
msgid "Switch between note and to-do type"
msgstr "Cambiar entre nota y lista de tareas"
msgid "Copy Markdown link"
msgstr "Copiar el enlace de Markdown"
msgid "Delete"
msgstr "Eliminar"
@@ -878,6 +909,9 @@ msgstr "Limpiar"
msgid "OneDrive Login"
msgstr "Inicio de sesión de OneDrive"
msgid "Dropbox Login"
msgstr "Inicio de sesión de Dropbox"
msgid "Options"
msgstr "Opciones"
@@ -902,9 +936,6 @@ msgstr "Sincronizar"
msgid "Notebooks"
msgstr "Libretas"
msgid "Searches"
msgstr "Búsquedas"
msgid "Please select where the sync status should be exported to"
msgstr "Seleccione a dónde se debería exportar el estado de sincronización"
@@ -916,6 +947,9 @@ msgstr "Uso: %s"
msgid "Unknown flag: %s"
msgstr "Etiqueta desconocida: %s"
msgid "Dropbox"
msgstr "Dropbox"
msgid "File system"
msgstr "Sistema de archivos"
@@ -993,7 +1027,7 @@ msgstr "Elementos remotos borrados: %d."
msgid "Fetched items: %d/%d."
msgstr "Elementos obtenidos: %d/%d."
#, fuzzy, javascript-format
#, javascript-format
msgid "State: %s."
msgstr "Estado: «%s»."
@@ -1027,6 +1061,10 @@ msgstr "Los elementos cifrados no pueden ser modificados"
msgid "Conflicts"
msgstr "Conflictos"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "No se ha podido mover la nota a la libreta «%s»"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Ya existe una libreta con este nombre: «%s»"
@@ -1105,6 +1143,9 @@ msgstr "Cuando se crear una nota nueva:"
msgid "Show tray icon"
msgstr "Mostrar icono en la bandeja"
msgid "Note: Does not work in all desktop environments."
msgstr "Nota: No funciona en todos los entornos de escritorio."
msgid "Global zoom percentage"
msgstr "Establecer el porcentaje de aumento de la aplicación"
@@ -1306,14 +1347,17 @@ msgid "Cancel synchronisation"
msgstr "Cancelar sincronización"
msgid "New tags:"
msgstr ""
msgstr "Nuevas etiquetas:"
msgid "Type new tags or select from list"
msgstr ""
msgstr "Escriba nuevas etiquetas o seleccionelas de la lista"
msgid "Joplin website"
msgstr "Sitio web de Joplin"
msgid "Login with Dropbox"
msgstr "Acceder con Dropbox"
#, javascript-format
msgid "Master Key %s"
msgstr "Clave maestra %s"
@@ -1353,6 +1397,15 @@ msgstr "Guardar cambios"
msgid "Discard changes"
msgstr "Descartar cambios"
#, javascript-format
msgid "No item with ID %s"
msgstr "No hay elementos con el ID %s"
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
"La aplicación móvil de Joplin no soporta actualmente este tipo de enlace: %s"
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Tipo de imagen no soportado: %s"
@@ -1384,6 +1437,9 @@ msgstr "Borrar libreta"
msgid "Login with OneDrive"
msgstr "Acceder con OneDrive"
msgid "Search"
msgstr "Buscar"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1398,6 +1454,16 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenido"
#~ msgid ""
#~ "For more information about End-To-End Encryption (E2EE) and advices on "
#~ "how to enable it please check the documentation"
#~ msgstr ""
#~ "Para más información acerca del cifrado extremo a extremo (E2EE) y "
#~ "advertencias de como habilitarlo por favor revise la documentación"
#~ msgid "Searches"
#~ msgstr "Búsquedas"
#~ msgid ""
#~ "Release notes:\n"
#~ "\n"

View File

@@ -227,7 +227,7 @@ msgid "The possible commands are:"
msgstr "Litezkeen komandoak hauek dira:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -246,7 +246,8 @@ msgstr ""
"Erabili geziak edo page up/down list eta testu guneen artean aldatzeko "
"(kontsola hau ere kontuan izanda)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Kontsola maximizatu edo minimizatzeko, saka \"TC\" ."
msgid "To enter command line mode, press \":\""
@@ -367,7 +368,10 @@ msgstr "Ezabatu emandako koadernoak."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Ezabatu koadernoak berrespenik gabe."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr "Koadernoa ezabatu? Dituen ohar guztiak ere ezabatuko dira."
msgid "Deletes the notes matching <note-pattern>."
@@ -414,6 +418,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Autentifikazioa ez da egin osorik (ez du token-ik hartu)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr "Ez da autentifikatu %s -rekin. Eman galdutako kredentzialak."
@@ -619,6 +633,9 @@ msgstr "Bilatu ohar guztietan"
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -691,6 +708,9 @@ msgstr "Oharrak eta ezarpenak hemen daude gordeta: %s"
msgid "Save"
msgstr "Gorde"
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -761,6 +781,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "Egoera"
@@ -798,12 +823,13 @@ msgstr "Berrizendatu koadernoa:"
msgid "Set alarm:"
msgstr "Ezarri alarma:"
msgid "Search"
msgstr "Bilatu"
msgid "Layout"
msgstr "Diseinua"
#, fuzzy
msgid "Search..."
msgstr "Bilatu"
msgid "Some items cannot be synchronised."
msgstr "Zenbait item ezin dira sinkronizatu."
@@ -822,6 +848,9 @@ msgstr "Gehitu edo ezabatu etiketak"
msgid "Switch between note and to-do type"
msgstr "Aldatu oharra eta zeregin eren artean."
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr "Ezabatu"
@@ -883,6 +912,9 @@ msgstr "Garbitu"
msgid "OneDrive Login"
msgstr "Logeatu OneDriven"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "Aukerak"
@@ -907,9 +939,6 @@ msgstr "Sinkronizatu"
msgid "Notebooks"
msgstr "Koadernoak"
msgid "Searches"
msgstr "Bilaketak"
#, fuzzy
msgid "Please select where the sync status should be exported to"
msgstr "Aukeratu nora esportatu sinkronizazioaren egoera, mesedez"
@@ -922,6 +951,9 @@ msgstr "Erabili: %s"
msgid "Unknown flag: %s"
msgstr "Marka ezezaguna: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "Fitxategi sistema"
@@ -1034,6 +1066,10 @@ msgstr "Zifratutako itemak ezin aldatu daitezke"
msgid "Conflicts"
msgstr "Gatazkak"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Ezin eraman daiteke oharra \"%s\" koadernora"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Dagoeneko bada koaderno bat izen horrekin: \"%s\""
@@ -1116,6 +1152,9 @@ msgstr "Ohar berria sortzen du."
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
#, fuzzy
msgid "Global zoom percentage"
msgstr "Ezarri aplikazioaren zoomaren ehunekoa"
@@ -1326,6 +1365,10 @@ msgstr ""
msgid "Joplin website"
msgstr ""
#, fuzzy
msgid "Login with Dropbox"
msgstr "Login with OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr "Pasahitz Nagusia %s"
@@ -1365,6 +1408,14 @@ msgstr "Gorde aldaketak"
msgid "Discard changes"
msgstr "Bertan behera utzi aldaketak"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Irudi formatua ez onartua: %s"
@@ -1396,6 +1447,9 @@ msgstr "Ezabatu koadernoa"
msgid "Login with OneDrive"
msgstr "Login with OneDrive"
msgid "Search"
msgstr "Bilatu"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1409,6 +1463,9 @@ msgstr "Oraindik ez duzu koadernorik. Sortu bat (+) botoian sakatuta."
msgid "Welcome"
msgstr "Ongi etorri!"
#~ msgid "Searches"
#~ msgstr "Bilaketak"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

View File

@@ -14,6 +14,8 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.3\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
msgid "To delete a tag, untag the associated notes."
msgstr "Pour supprimer une vignette, enlever là des notes associées."
@@ -229,7 +231,7 @@ msgid "The possible commands are:"
msgstr "Les commandes possibles sont :"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -248,8 +250,8 @@ msgstr ""
"Utilisez les touches fléchées et page précédente/suivante pour faire défiler "
"les listes et zones de texte (y compris cette console)."
msgid "To maximise/minimise the console, press \"TC\"."
msgstr "Pour maximiser ou minimiser la console, pressez \"TC\"."
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Pour maximiser ou minimiser la console, pressez \"tc\"."
msgid "To enter command line mode, press \":\""
msgstr "Pour démarrer le mode ligne de commande, pressez \":\""
@@ -365,10 +367,12 @@ msgstr "Supprimer le carnet."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Supprimer le carnet sans demander la confirmation."
msgid "Delete notebook? All notes within this notebook will also be deleted."
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"Effacer le carnet ? Toutes les notes dans ce carnet seront également "
"effacées."
"Effacer le carnet ? Toutes les notes et sous-carnets dans ce carnet seront "
"également effacés."
msgid "Deletes the notes matching <note-pattern>."
msgstr "Supprimer les notes correspondants à <note-pattern>."
@@ -413,6 +417,20 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Impossible d'autoriser le logiciel (jeton d'identification non-reçu)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
"Pour permettre à Joplin de synchroniser avec Dropbox, veuillez suivre les "
"étapes ci-dessous :"
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
"Étape 1: Veuillez ouvrir cette URL dans votre navigateur internet pour "
"autoriser le logiciel :"
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr "Étape 2 : Entrez le code fourni par Dropbox :"
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -617,6 +635,9 @@ msgstr "Chercher dans toutes les notes"
msgid "View"
msgstr "Affichage"
msgid "Toggle sidebar"
msgstr "Basculer barre latérale"
msgid "Toggle editor layout"
msgstr "Basculer l'agencement de l'éditeur"
@@ -687,6 +708,9 @@ msgstr "Les notes et paramètres se trouve dans : %s"
msgid "Save"
msgstr "Enregistrer"
msgid "Submit"
msgstr "Envoyer"
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -760,6 +784,13 @@ msgstr ""
"de vos objets, cependant le logiciel n'y a pour l'instant pas accès. Il est "
"probable qu'elle vont être prochainement disponible via la synchronisation."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
"Pour plus d'informations sur l'encryption de bout en bout, ainsi que des "
"conseils pour l'activer, veuillez consulter la documentation :"
msgid "Status"
msgstr "État"
@@ -797,12 +828,12 @@ msgstr "Renommer le carnet :"
msgid "Set alarm:"
msgstr "Régler alarme :"
msgid "Search"
msgstr "Chercher"
msgid "Layout"
msgstr "Disposition"
msgid "Search..."
msgstr "Chercher..."
msgid "Some items cannot be synchronised."
msgstr "Certains objets ne peuvent être synchronisés."
@@ -821,6 +852,9 @@ msgstr "Gérer les étiquettes"
msgid "Switch between note and to-do type"
msgstr "Alterner entre note et tâche"
msgid "Copy Markdown link"
msgstr "Copier lien Markdown"
msgid "Delete"
msgstr "Supprimer"
@@ -883,6 +917,9 @@ msgstr "Supprimer"
msgid "OneDrive Login"
msgstr "Connexion OneDrive"
msgid "Dropbox Login"
msgstr "Connection à Dropbox"
msgid "Options"
msgstr "Options"
@@ -907,9 +944,6 @@ msgstr "Synchroniser"
msgid "Notebooks"
msgstr "Carnets"
msgid "Searches"
msgstr "Recherches"
msgid "Please select where the sync status should be exported to"
msgstr ""
"Veuillez sélectionner un répertoire ou exporter l'état de la synchronisation"
@@ -922,6 +956,9 @@ msgstr "Utilisation : %s"
msgid "Unknown flag: %s"
msgstr "Paramètre inconnu : %s"
msgid "Dropbox"
msgstr "Dropbox"
msgid "File system"
msgstr "Système de fichier"
@@ -1033,6 +1070,9 @@ msgstr "Les objets cryptés ne peuvent être modifiés"
msgid "Conflicts"
msgstr "Conflits"
msgid "Cannot move notebook to this location"
msgstr "Impossible de déplacer le carnet vers le carnet \"%s\""
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Un carnet avec ce titre existe déjà : \"%s\""
@@ -1110,6 +1150,9 @@ msgstr "Lors de la création d'une note :"
msgid "Show tray icon"
msgstr "Afficher icône dans la zone de notifications"
msgid "Note: Does not work in all desktop environments."
msgstr "Note : Ne fonctionne pas dans tous les environnements de bureau."
msgid "Global zoom percentage"
msgstr "Niveau de zoom"
@@ -1321,6 +1364,9 @@ msgstr "Entrez de nouvelles étiquettes ou sélectionnez de la liste"
msgid "Joplin website"
msgstr "Site web de Joplin"
msgid "Login with Dropbox"
msgstr "Se connecter à Dropbox"
#, javascript-format
msgid "Master Key %s"
msgstr "Clef maître %s"
@@ -1360,6 +1406,15 @@ msgstr "Enregistrer les changements"
msgid "Discard changes"
msgstr "Ignorer les changements"
#, javascript-format
msgid "No item with ID %s"
msgstr "Aucun objet avec identifiant %s"
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
"L'application mobile Joplin ne gère pas pour l'instant ce type de lien : %s"
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Type d'image non géré : %s"
@@ -1391,6 +1446,9 @@ msgstr "Supprimer le carnet"
msgid "Login with OneDrive"
msgstr "Se connecter à OneDrive"
msgid "Search"
msgstr "Chercher"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1406,6 +1464,16 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenue"
#~ msgid ""
#~ "For more information about End-To-End Encryption (E2EE) and advices on "
#~ "how to enable it please check the documentation"
#~ msgstr ""
#~ "Pour plus d'informations sur l'encryption de bout en bout, ainsi que des "
#~ "conseils pour l'activer, veuillez consulter la documentation"
#~ msgid "Searches"
#~ msgstr "Recherches"
#~ msgid ""
#~ "Release notes:\n"
#~ "\n"
@@ -1593,12 +1661,6 @@ msgstr "Bienvenue"
#~ msgid "Done."
#~ msgstr "Terminé."
#~ msgid ""
#~ "Please open this URL in your browser to authenticate the application:"
#~ msgstr ""
#~ "Veuillez ouvrir cette URL dans votre navigateur internet pour autoriser "
#~ "le logiciel :"
#~ msgid "Note does not exist."
#~ msgstr "Cette note n'existe pas."

1441
CliClient/locales/gl_ES.po Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -229,15 +229,11 @@ msgstr ""
msgid "The possible commands are:"
msgstr "Moguće naredbe su:"
#, fuzzy
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
"In any command, a note or notebook can be refered to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgid "To move from one pane to another, press Tab or Shift+Tab."
msgstr "Za prijelaz iz jednog okna u drugo, pritisni Tab ili Shift+Tab."
@@ -250,7 +246,8 @@ msgstr ""
"Use the arrows and page up/down to scroll the lists and text areas "
"(including this console)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Za maksimiziranje/minimiziranje konzole, pritisni \"TC\"."
msgid "To enter command line mode, press \":\""
@@ -371,7 +368,10 @@ msgstr "Briše datu bilježnicu."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Briše bilježnicu bez traženja potvrde."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"Obrisati bilježnicu? Sve bilješke u toj bilježnici će također biti obrisane."
@@ -420,6 +420,16 @@ msgid ""
msgstr ""
"Ovjera nije dovršena (nije dobivena potvrda ovjere - authentication token)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -621,6 +631,9 @@ msgstr "Pretraži u svim bilješkama"
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -694,6 +707,9 @@ msgstr "Bilješke i postavke su pohranjene u: %s"
msgid "Save"
msgstr "Spremi"
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -752,6 +768,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "Status"
@@ -789,12 +810,13 @@ msgstr "Preimenuj bilježnicu:"
msgid "Set alarm:"
msgstr "Postavi upozorenje:"
msgid "Search"
msgstr "Traži"
msgid "Layout"
msgstr "Izgled"
#, fuzzy
msgid "Search..."
msgstr "Traži"
msgid "Some items cannot be synchronised."
msgstr "Neke stavke se ne mogu sinkronizirati."
@@ -814,6 +836,9 @@ msgstr "Dodaj ili makni oznake"
msgid "Switch between note and to-do type"
msgstr "Zamijeni bilješku i zadatak"
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr "Obriši"
@@ -874,6 +899,9 @@ msgstr "Očisti"
msgid "OneDrive Login"
msgstr "OneDrive Login"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "Opcije"
@@ -898,9 +926,6 @@ msgstr "Sinkroniziraj"
msgid "Notebooks"
msgstr "Bilježnice"
msgid "Searches"
msgstr "Pretraživanja"
msgid "Please select where the sync status should be exported to"
msgstr "Odaberi lokaciju za izvoz statusa sinkronizacije"
@@ -912,6 +937,9 @@ msgstr "Korištenje: %s"
msgid "Unknown flag: %s"
msgstr "Nepoznata zastavica: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "Datotečni sustav"
@@ -1022,6 +1050,10 @@ msgstr "Neke stavke se ne mogu sinkronizirati."
msgid "Conflicts"
msgstr "Sukobi"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Ne mogu premjestiti bilješku u bilježnicu %s"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Bilježnica s ovim naslovom već postoji: \"%s\""
@@ -1104,6 +1136,9 @@ msgstr "Stvara novu bilješku."
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1306,6 +1341,10 @@ msgstr ""
msgid "Joplin website"
msgstr ""
#, fuzzy
msgid "Login with Dropbox"
msgstr "Prijavi se u OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr ""
@@ -1346,6 +1385,14 @@ msgstr "Spremi promjene"
msgid "Discard changes"
msgstr "Odbaci promjene"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Nepodržana vrsta slike: %s"
@@ -1377,6 +1424,9 @@ msgstr "Obriši bilježnicu"
msgid "Login with OneDrive"
msgstr "Prijavi se u OneDrive"
msgid "Search"
msgstr "Traži"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1390,6 +1440,9 @@ msgstr "Trenutno nemaš nijednu bilježnicu. Stvori novu klikom na (+) gumb."
msgid "Welcome"
msgstr "Dobro došli"
#~ msgid "Searches"
#~ msgstr "Pretraživanja"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

View File

@@ -226,7 +226,7 @@ msgid "The possible commands are:"
msgstr "I possibili comandi sono:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -245,7 +245,8 @@ msgstr ""
"Usa le frecce e pagina su/giù per scorrere le liste e le aree di testo "
"(compresa questa console)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Per massimizzare/minimizzare la console, premi \"TC\"."
msgid "To enter command line mode, press \":\""
@@ -363,7 +364,9 @@ msgstr "Elimina il seguente blocco note."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Elimina il blocco note senza richiedere una conferma."
msgid "Delete notebook? All notes within this notebook will also be deleted."
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
msgid "Deletes the notes matching <note-pattern>."
@@ -407,6 +410,16 @@ msgstr ""
"Autenticazione non completata (non è stato ricevuto alcun token di "
"autenticazione)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -603,6 +616,9 @@ msgstr "Cerca in tutte le note"
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -676,6 +692,9 @@ msgstr ""
msgid "Save"
msgstr ""
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -736,6 +755,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "Stato"
@@ -771,12 +795,13 @@ msgstr "Rinomina il blocco note:"
msgid "Set alarm:"
msgstr "Imposta allarme:"
msgid "Search"
msgstr "Cerca"
msgid "Layout"
msgstr "Disposizione"
#, fuzzy
msgid "Search..."
msgstr "Cerca"
msgid "Some items cannot be synchronised."
msgstr "Alcuni elementi non possono essere sincronizzati."
@@ -796,6 +821,9 @@ msgstr "Aggiungi o rimuovi etichetta"
msgid "Switch between note and to-do type"
msgstr "Passa da un tipo di nota a un elenco di attività"
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr "Elimina"
@@ -857,6 +885,9 @@ msgstr "Pulisci"
msgid "OneDrive Login"
msgstr "Login OneDrive"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "Opzioni"
@@ -881,9 +912,6 @@ msgstr "Sincronizza"
msgid "Notebooks"
msgstr "Blocchi note"
msgid "Searches"
msgstr "Ricerche"
#, fuzzy
msgid "Please select where the sync status should be exported to"
msgstr "Per favore seleziona la nota o il blocco note da eliminare."
@@ -896,6 +924,9 @@ msgstr "Uso: %s"
msgid "Unknown flag: %s"
msgstr "Etichetta sconosciuta: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "File system"
@@ -1008,6 +1039,10 @@ msgstr "Alcuni elementi non possono essere sincronizzati."
msgid "Conflicts"
msgstr "Conflitti"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Non posso spostare la nota nel blocco note \"%s\""
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Esiste già un blocco note col titolo \"%s\""
@@ -1090,6 +1125,9 @@ msgstr "Crea una nuova nota."
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1292,6 +1330,10 @@ msgstr ""
msgid "Joplin website"
msgstr ""
#, fuzzy
msgid "Login with Dropbox"
msgstr "Accedi a OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr ""
@@ -1332,6 +1374,14 @@ msgstr "Salva i cambiamenti"
msgid "Discard changes"
msgstr "Ignora modifiche"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Tipo di immagine non supportata: %s"
@@ -1363,6 +1413,9 @@ msgstr "Cancella blocco note"
msgid "Login with OneDrive"
msgstr "Accedi a OneDrive"
msgid "Search"
msgstr "Cerca"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1378,6 +1431,9 @@ msgstr ""
msgid "Welcome"
msgstr "Benvenuto"
#~ msgid "Searches"
#~ msgstr "Ricerche"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

View File

@@ -224,7 +224,7 @@ msgid "The possible commands are:"
msgstr "有効なコマンドは:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -240,7 +240,8 @@ msgid ""
"(including this console)."
msgstr "リストや入力エリアの移動には矢印キーまたはPage Up/Downを使用します。"
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "コンソールの最大化・最小化には\"TC\"と入力してください。"
msgid "To enter command line mode, press \":\""
@@ -360,7 +361,10 @@ msgstr "指定されたノートブックを削除します。"
msgid "Deletes the notebook without asking for confirmation."
msgstr "ノートブックを確認なしで削除します。"
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr "ノートブックを削除しますか?中にあるノートはすべて消えてしまいます。"
msgid "Deletes the notes matching <note-pattern>."
@@ -404,6 +408,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "認証は完了していません(認証トークンが得られませんでした)"
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -604,6 +618,9 @@ msgstr "すべてのノートを検索"
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -676,6 +693,9 @@ msgstr "ノートと設定は、%sに保存されます。"
msgid "Save"
msgstr "保存"
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -738,6 +758,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "状態"
@@ -775,12 +800,13 @@ msgstr "ノートブックの名前を変更:"
msgid "Set alarm:"
msgstr "アラームをセット:"
msgid "Search"
msgstr "検索"
msgid "Layout"
msgstr "レイアウト"
#, fuzzy
msgid "Search..."
msgstr "検索"
msgid "Some items cannot be synchronised."
msgstr "いくつかの項目は同期されませんでした。"
@@ -800,6 +826,9 @@ msgstr "タグの追加・削除"
msgid "Switch between note and to-do type"
msgstr "ノートとToDoを切り替え"
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr "削除"
@@ -860,6 +889,9 @@ msgstr "クリア"
msgid "OneDrive Login"
msgstr "OneDriveログイン"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "オプション"
@@ -884,9 +916,6 @@ msgstr "同期"
msgid "Notebooks"
msgstr "ノートブック"
msgid "Searches"
msgstr "検索"
msgid "Please select where the sync status should be exported to"
msgstr "同期状況の出力先を選択してください"
@@ -898,6 +927,9 @@ msgstr "使用方法: %s"
msgid "Unknown flag: %s"
msgstr "不明なフラグ: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "ファイルシステム"
@@ -1010,6 +1042,10 @@ msgstr "いくつかの項目は同期されませんでした。"
msgid "Conflicts"
msgstr "衝突"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "ノートをノートブック \"%s\"に移動できませんでした。"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "\"%s\"という名前のノートブックはすでに存在しています。"
@@ -1094,6 +1130,9 @@ msgstr "あたらしいノートを作成します。"
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1296,6 +1335,10 @@ msgstr ""
msgid "Joplin website"
msgstr ""
#, fuzzy
msgid "Login with Dropbox"
msgstr "OneDriveログイン"
#, javascript-format
msgid "Master Key %s"
msgstr ""
@@ -1336,6 +1379,14 @@ msgstr "変更を保存"
msgid "Discard changes"
msgstr "変更を破棄"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "サポートされていないイメージ形式: %s."
@@ -1367,6 +1418,9 @@ msgstr "ノートブックを削除"
msgid "Login with OneDrive"
msgstr "OneDriveログイン"
msgid "Search"
msgstr "検索"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1382,6 +1436,9 @@ msgstr ""
msgid "Welcome"
msgstr "ようこそ"
#~ msgid "Searches"
#~ msgstr "検索"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

View File

@@ -210,7 +210,7 @@ msgid "The possible commands are:"
msgstr ""
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -223,7 +223,7 @@ msgid ""
"(including this console)."
msgstr ""
msgid "To maximise/minimise the console, press \"TC\"."
msgid "To maximise/minimise the console, press \"tc\"."
msgstr ""
msgid "To enter command line mode, press \":\""
@@ -332,7 +332,9 @@ msgstr ""
msgid "Deletes the notebook without asking for confirmation."
msgstr ""
msgid "Delete notebook? All notes within this notebook will also be deleted."
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
msgid "Deletes the notes matching <note-pattern>."
@@ -372,6 +374,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr ""
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -546,6 +558,9 @@ msgstr ""
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -615,6 +630,9 @@ msgstr ""
msgid "Save"
msgstr ""
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -673,6 +691,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr ""
@@ -708,10 +731,10 @@ msgstr ""
msgid "Set alarm:"
msgstr ""
msgid "Search"
msgid "Layout"
msgstr ""
msgid "Layout"
msgid "Search..."
msgstr ""
msgid "Some items cannot be synchronised."
@@ -732,6 +755,9 @@ msgstr ""
msgid "Switch between note and to-do type"
msgstr ""
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr ""
@@ -789,6 +815,9 @@ msgstr ""
msgid "OneDrive Login"
msgstr ""
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr ""
@@ -813,9 +842,6 @@ msgstr ""
msgid "Notebooks"
msgstr ""
msgid "Searches"
msgstr ""
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -827,6 +853,9 @@ msgstr ""
msgid "Unknown flag: %s"
msgstr ""
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr ""
@@ -930,6 +959,9 @@ msgstr ""
msgid "Conflicts"
msgstr ""
msgid "Cannot move notebook to this location"
msgstr ""
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr ""
@@ -1005,6 +1037,9 @@ msgstr ""
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1202,6 +1237,9 @@ msgstr ""
msgid "Joplin website"
msgstr ""
msgid "Login with Dropbox"
msgstr ""
#, javascript-format
msgid "Master Key %s"
msgstr ""
@@ -1241,6 +1279,14 @@ msgstr ""
msgid "Discard changes"
msgstr ""
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr ""
@@ -1272,6 +1318,9 @@ msgstr ""
msgid "Login with OneDrive"
msgstr ""
msgid "Search"
msgstr ""
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."

View File

@@ -230,7 +230,7 @@ msgid "The possible commands are:"
msgstr "Mogelijke commando's zijn:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -249,7 +249,8 @@ msgstr ""
"Gebruik de pijltjes en page up/down om door de lijsten en de tekstvelden te "
"scrollen (ook deze console)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Om de console te maximaliseren/minimaliseren, typ \"TC\"."
msgid "To enter command line mode, press \":\""
@@ -368,7 +369,10 @@ msgstr "Verwijdert het opgegeven notitieboek."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Verwijdert het notitieboek zonder te vragen om bevestiging."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"Notitieboek verwijderen? Alle notities in dit notitieboek zullen ook "
"verwijderd worden."
@@ -415,6 +419,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Authenticatie was niet voltooid (geen authenticatietoken ontvangen)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -621,6 +635,9 @@ msgstr "Zoek in alle notities"
msgid "View"
msgstr ""
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr ""
@@ -693,6 +710,9 @@ msgstr "Notities en instellingen zijn opgeslaan in %s"
msgid "Save"
msgstr "Sla op"
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -763,6 +783,11 @@ msgid ""
"they will eventually be downloaded via synchronisation."
msgstr ""
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "Status"
@@ -800,12 +825,13 @@ msgstr "Hernoem notitieboek:"
msgid "Set alarm:"
msgstr "Stel melding in:"
msgid "Search"
msgstr "Zoeken"
msgid "Layout"
msgstr "Layout"
#, fuzzy
msgid "Search..."
msgstr "Zoeken"
msgid "Some items cannot be synchronised."
msgstr "Sommige items kunnen niet gesynchroniseerd worden."
@@ -824,6 +850,9 @@ msgstr "Voeg tag toe of verwijder tag"
msgid "Switch between note and to-do type"
msgstr "Wissel tussen notitie en to-do type"
msgid "Copy Markdown link"
msgstr ""
msgid "Delete"
msgstr "Verwijderen"
@@ -886,6 +915,9 @@ msgstr "Vrijmaken"
msgid "OneDrive Login"
msgstr "OneDrive Login"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "Opties"
@@ -910,9 +942,6 @@ msgstr "Synchroniseer"
msgid "Notebooks"
msgstr "Notitieboeken"
msgid "Searches"
msgstr "Zoekopdrachten"
msgid "Please select where the sync status should be exported to"
msgstr "Selecteer waar de synchronisatie status naar geëxporteerd moet worden"
@@ -924,6 +953,9 @@ msgstr "Gebruik: %s"
msgid "Unknown flag: %s"
msgstr "Onbekende optie: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "Bestandssysteem"
@@ -1036,6 +1068,10 @@ msgstr "Versleutelde items kunnen niet aangepast worden"
msgid "Conflicts"
msgstr "Conflicten"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Kan notitie niet naar notitieboek \"%s\" verplaatsen."
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Er bestaat al een notitieboek met \"%s\" als titel"
@@ -1120,6 +1156,9 @@ msgstr "Maakt een nieuwe notitie aan."
msgid "Show tray icon"
msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr ""
@@ -1328,6 +1367,10 @@ msgstr ""
msgid "Joplin website"
msgstr ""
#, fuzzy
msgid "Login with Dropbox"
msgstr "Log in met OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr "Hoofdsleutel: %s"
@@ -1367,6 +1410,14 @@ msgstr "Sla wijzigingen op"
msgid "Discard changes"
msgstr "Verwijder wijzigingen"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Afbeeldingstype %s wordt niet ondersteund"
@@ -1398,6 +1449,9 @@ msgstr "Verwijder notitieboek"
msgid "Login with OneDrive"
msgstr "Log in met OneDrive"
msgid "Search"
msgstr "Zoeken"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1413,6 +1467,9 @@ msgstr ""
msgid "Welcome"
msgstr "Welkom"
#~ msgid "Searches"
#~ msgstr "Zoekopdrachten"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

View File

@@ -13,7 +13,7 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.0.6\n"
"X-Generator: Poedit 2.0.7\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
msgid "To delete a tag, untag the associated notes."
@@ -227,7 +227,7 @@ msgid "The possible commands are:"
msgstr "Os comandos possíveis são:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -246,7 +246,8 @@ msgstr ""
"Use as setas e a Page Up/Page Down para rolar as listas e áreas de texto "
"(incluindo este console)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Para maximizar / minimizar o console, pressione \"TC\"."
msgid "To enter command line mode, press \":\""
@@ -362,7 +363,10 @@ msgstr "Exclui o caderno informado."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Exclui o caderno sem pedir confirmação."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr ""
"Excluir o caderno? Todas as notas deste caderno notebook também serão "
"excluídas."
@@ -411,6 +415,18 @@ msgid ""
msgstr ""
"A autenticação não foi concluída (não recebeu um token de autenticação)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
"Para permitir o Joplin sincronizar com o Dropbox, por favor, execute os "
"seguintes passos:"
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr "Passo 1: Abra essa URL em seu navegador para autorizar:"
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr "Passo 2: Entre o código fornecido pelo Dropbox:"
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -567,9 +583,8 @@ msgstr "Exportando para \"%s\" com o formato \"%s\". Por favor, aguarde..."
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
msgstr "Importando de \"%s\" com o formato \"%s\". Por favor, aguarde..."
#, fuzzy
msgid "PDF File"
msgstr "Arquivo"
msgstr "Arquivo PDF"
msgid "File"
msgstr "Arquivo"
@@ -590,7 +605,7 @@ msgid "Export"
msgstr "Exportar"
msgid "Print"
msgstr ""
msgstr "Imprimir"
#, javascript-format
msgid "Hide %s"
@@ -617,6 +632,9 @@ msgstr "Pesquisar em todas as notas"
msgid "View"
msgstr "Visualizar"
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr "Alternar layout do editor"
@@ -686,6 +704,9 @@ msgstr "Notas e configurações estão armazenadas em: %s"
msgid "Save"
msgstr "Salvar"
msgid "Submit"
msgstr "Enviar"
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -757,6 +778,13 @@ msgstr ""
"itens, contudo a aplicação atualmente não tem acesso a elas. Provavelmente, "
"elas serão baixadas via sincronização."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
"Para mais informações sobre Encriptação ponto-a-ponto (E2EE) e recomendações "
"sobre como habilitar, favor verificar a documentação:"
msgid "Status"
msgstr "Status"
@@ -793,12 +821,12 @@ msgstr "Renomear caderno:"
msgid "Set alarm:"
msgstr "Definir alarme:"
msgid "Search"
msgstr "Procurar"
msgid "Layout"
msgstr "Layout"
msgid "Search..."
msgstr "Pesquisar..."
msgid "Some items cannot be synchronised."
msgstr "Alguns itens não podem ser sincronizados."
@@ -817,6 +845,10 @@ msgstr "Adicionar ou remover tags"
msgid "Switch between note and to-do type"
msgstr "Alternar entre os tipos Nota e Tarefa"
#, fuzzy
msgid "Copy Markdown link"
msgstr "Markdown"
msgid "Delete"
msgstr "Excluir"
@@ -876,6 +908,9 @@ msgstr "Limpar (clear)"
msgid "OneDrive Login"
msgstr "Login no OneDrive"
msgid "Dropbox Login"
msgstr "Login no Dropbox"
msgid "Options"
msgstr "Opções"
@@ -900,9 +935,6 @@ msgstr "Sincronizar"
msgid "Notebooks"
msgstr "Cadernos"
msgid "Searches"
msgstr "Pesquisas"
msgid "Please select where the sync status should be exported to"
msgstr ""
"Favor selecionar o local para onde o status de sincronia deveria ser "
@@ -916,6 +948,9 @@ msgstr "Uso: %s"
msgid "Unknown flag: %s"
msgstr "Flag desconhecido: %s"
msgid "Dropbox"
msgstr "Dropbox"
msgid "File system"
msgstr "Sistema de arquivos"
@@ -993,7 +1028,7 @@ msgstr "Itens remotos excluídos: %d."
msgid "Fetched items: %d/%d."
msgstr "Itens pesquisados: %d/%d."
#, fuzzy, javascript-format
#, javascript-format
msgid "State: %s."
msgstr "Estado: \"%s\"."
@@ -1004,15 +1039,15 @@ msgstr "Cancelando..."
msgid "Completed: %s"
msgstr "Completado: %s"
#, fuzzy, javascript-format
#, javascript-format
msgid "Last error: %s"
msgstr "Erro fatal:"
msgstr "Último erro: %s"
msgid "Idle"
msgstr ""
msgstr "Inativo"
msgid "In progress"
msgstr ""
msgstr "Em andamento"
#, javascript-format
msgid "Synchronisation is already in progress. State: %s"
@@ -1027,6 +1062,10 @@ msgstr "Itens encriptados não podem ser modificados"
msgid "Conflicts"
msgstr "Conflitos"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Não é possível mover a nota para o caderno \"%s\""
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Já existe caderno com este título: \"%s\""
@@ -1105,6 +1144,9 @@ msgstr "Quando criar uma nota nova:"
msgid "Show tray icon"
msgstr "Exibir tray icon"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr "Porcentagem global do zoom"
@@ -1306,14 +1348,17 @@ msgid "Cancel synchronisation"
msgstr "Cancelar sincronização"
msgid "New tags:"
msgstr ""
msgstr "Novas tags:"
msgid "Type new tags or select from list"
msgstr ""
msgstr "Digite novsa tags, ou selecione da lista"
msgid "Joplin website"
msgstr "Site do Joplin"
msgid "Login with Dropbox"
msgstr "Login com Dropbox"
#, javascript-format
msgid "Master Key %s"
msgstr "Chave Master %s"
@@ -1353,6 +1398,14 @@ msgstr "Gravar alterações"
msgid "Discard changes"
msgstr "Descartar alterações"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Tipo de imagem não suportada: %s"
@@ -1384,6 +1437,9 @@ msgstr "Excluir caderno"
msgid "Login with OneDrive"
msgstr "Login com OneDrive"
msgid "Search"
msgstr "Procurar"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1397,6 +1453,9 @@ msgstr "Você não possui cadernos. Crie um clicando no botão (+)."
msgid "Welcome"
msgstr "Bem-vindo"
#~ msgid "Searches"
#~ msgstr "Pesquisas"
#~ msgid ""
#~ "Release notes:\n"
#~ "\n"

View File

@@ -230,7 +230,7 @@ msgid "The possible commands are:"
msgstr "Доступные команды:"
msgid ""
"In any command, a note or notebook can be refered to by title or ID, or "
"In any command, a note or notebook can be referred to by title or ID, or "
"using the shortcuts `$n` or `$b` for, respectively, the currently selected "
"note or notebook. `$c` can be used to refer to the currently selected item."
msgstr ""
@@ -249,7 +249,8 @@ msgstr ""
"Используйте стрелки и клавиши перелистывания страницы вверх/вниз для "
"прокрутки списков и текстовых областей (включая эту консоль)."
msgid "To maximise/minimise the console, press \"TC\"."
#, fuzzy
msgid "To maximise/minimise the console, press \"tc\"."
msgstr "Чтобы развернуть/свернуть консоль, нажимайте «TC»."
msgid "To enter command line mode, press \":\""
@@ -368,7 +369,10 @@ msgstr "Удаляет заданный блокнот."
msgid "Deletes the notebook without asking for confirmation."
msgstr "Удаляет блокнот без запроса подтверждения."
msgid "Delete notebook? All notes within this notebook will also be deleted."
#, fuzzy
msgid ""
"Delete notebook? All notes and sub-notebooks within this notebook will also "
"be deleted."
msgstr "Удалить блокнот? Все заметки в этом блокноте также будут удалены."
msgid "Deletes the notes matching <note-pattern>."
@@ -414,6 +418,16 @@ msgid ""
"Authentication was not completed (did not receive an authentication token)."
msgstr "Аутентификация не была завершена (не получен токен аутентификации)."
msgid ""
"To allow Joplin to synchronise with Dropbox, please follow the steps below:"
msgstr ""
msgid "Step 1: Open this URL in your browser to authorise the application:"
msgstr ""
msgid "Step 2: Enter the code provided by Dropbox:"
msgstr ""
#, javascript-format
msgid "Not authentified with %s. Please provide any missing credentials."
msgstr ""
@@ -618,6 +632,9 @@ msgstr "Поиск во всех заметках"
msgid "View"
msgstr "Вид"
msgid "Toggle sidebar"
msgstr ""
msgid "Toggle editor layout"
msgstr "Переключить вид редактора"
@@ -687,6 +704,9 @@ msgstr "Заметки и настройки сохранены в: %s"
msgid "Save"
msgstr "Сохранить"
msgid "Submit"
msgstr ""
msgid ""
"Disabling encryption means *all* your notes and attachments are going to be "
"re-synchronised and sent unencrypted to the sync target. Do you wish to "
@@ -760,6 +780,11 @@ msgstr ""
"элементов, однако у приложения сейчас нет к ним доступа. Скорее всего, они "
"загрузятся при синхронизации."
msgid ""
"For more information about End-To-End Encryption (E2EE) and advices on how "
"to enable it please check the documentation:"
msgstr ""
msgid "Status"
msgstr "Статус"
@@ -795,12 +820,13 @@ msgstr "Переименовать блокнот:"
msgid "Set alarm:"
msgstr "Установить напоминание:"
msgid "Search"
msgstr "Поиск"
msgid "Layout"
msgstr "Вид"
#, fuzzy
msgid "Search..."
msgstr "Поиск"
msgid "Some items cannot be synchronised."
msgstr "Некоторые элементы не могут быть синхронизированы."
@@ -819,6 +845,10 @@ msgstr "Добавить или удалить теги"
msgid "Switch between note and to-do type"
msgstr "Переключить тип между заметкой и задачей"
#, fuzzy
msgid "Copy Markdown link"
msgstr "Markdown"
msgid "Delete"
msgstr "Удалить"
@@ -878,6 +908,9 @@ msgstr "Очистить"
msgid "OneDrive Login"
msgstr "Вход в OneDrive"
msgid "Dropbox Login"
msgstr ""
msgid "Options"
msgstr "Настройки"
@@ -902,9 +935,6 @@ msgstr "Синхронизировать"
msgid "Notebooks"
msgstr "Блокноты"
msgid "Searches"
msgstr "Запросы"
msgid "Please select where the sync status should be exported to"
msgstr "Выберите, куда должен быть экспортирован статус синхронизации"
@@ -916,6 +946,9 @@ msgstr "Использование: %s"
msgid "Unknown flag: %s"
msgstr "Неизвестный флаг: %s"
msgid "Dropbox"
msgstr ""
msgid "File system"
msgstr "Файловая система"
@@ -1027,6 +1060,10 @@ msgstr "Зашифрованные элементы не могут быть и
msgid "Conflicts"
msgstr "Конфликты"
#, fuzzy
msgid "Cannot move notebook to this location"
msgstr "Не удалось переместить заметку в блокнот «%s»"
#, javascript-format
msgid "A notebook with this title already exists: \"%s\""
msgstr "Блокнот с таким названием уже существует: «%s»"
@@ -1104,6 +1141,9 @@ msgstr "При создании новой заметки:"
msgid "Show tray icon"
msgstr "Показывать иконку в панели задач"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid "Global zoom percentage"
msgstr "Глобальный масштаб в процентах"
@@ -1313,6 +1353,10 @@ msgstr ""
msgid "Joplin website"
msgstr "Сайт Joplin"
#, fuzzy
msgid "Login with Dropbox"
msgstr "Войти в OneDrive"
#, javascript-format
msgid "Master Key %s"
msgstr "Мастер-ключ %s"
@@ -1352,6 +1396,14 @@ msgstr "Сохранить изменения"
msgid "Discard changes"
msgstr "Отменить изменения"
#, javascript-format
msgid "No item with ID %s"
msgstr ""
#, javascript-format
msgid "The Joplin mobile app does not currently support this type of link: %s"
msgstr ""
#, javascript-format
msgid "Unsupported image type: %s"
msgstr "Неподдерживаемый формат изображения: %s"
@@ -1383,6 +1435,9 @@ msgstr "Удалить блокнот"
msgid "Login with OneDrive"
msgstr "Войти в OneDrive"
msgid "Search"
msgstr "Поиск"
msgid ""
"Click on the (+) button to create a new note or notebook. Click on the side "
"menu to access your existing notebooks."
@@ -1396,6 +1451,9 @@ msgstr "У вас сейчас нет блокнота. Создайте его
msgid "Welcome"
msgstr "Добро пожаловать"
#~ msgid "Searches"
#~ msgstr "Запросы"
#, fuzzy
#~ msgid ""
#~ "Release notes:\n"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.0.103",
"version": "1.0.106",
"bin": {
"joplin": "./main.js"
},
@@ -58,9 +58,10 @@
"strip-ansi": "^4.0.0",
"tar": "^4.4.0",
"tcp-port-used": "^0.1.2",
"tkwidgets": "^0.5.25",
"tkwidgets": "^0.5.26",
"url-parse": "^1.2.0",
"uuid": "^3.0.1",
"valid-url": "^1.0.9",
"word-wrap": "^1.2.3",
"xml2js": "^0.4.19",
"yargs-parser": "^7.0.0"

View File

@@ -0,0 +1,55 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
async function allItems() {
let folders = await Folder.all();
let notes = await Note.all();
return folders.concat(notes);
}
describe('models_Folder', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should tell if a notebook can be nested under another one', asyncTest(async () => {
let f1 = await Folder.save({ title: "folder1" });
let f2 = await Folder.save({ title: "folder2", parent_id: f1.id });
let f3 = await Folder.save({ title: "folder3", parent_id: f2.id });
let f4 = await Folder.save({ title: "folder4" });
expect(await Folder.canNestUnder(f1.id, f2.id)).toBe(false);
expect(await Folder.canNestUnder(f2.id, f2.id)).toBe(false);
expect(await Folder.canNestUnder(f3.id, f1.id)).toBe(true);
expect(await Folder.canNestUnder(f4.id, f1.id)).toBe(true);
expect(await Folder.canNestUnder(f2.id, f3.id)).toBe(false);
expect(await Folder.canNestUnder(f3.id, f2.id)).toBe(true);
expect(await Folder.canNestUnder(f1.id, '')).toBe(true);
expect(await Folder.canNestUnder(f2.id, '')).toBe(true);
}));
it('should recursively delete notes and sub-notebooks', asyncTest(async () => {
let f1 = await Folder.save({ title: "folder1" });
let f2 = await Folder.save({ title: "folder2", parent_id: f1.id });
let n1 = await Note.save({ title: 'note1', parent_id: f2.id });
await Folder.delete(f1.id);
const all = await allItems();
expect(all.length).toBe(0);
}));
});

View File

@@ -0,0 +1,39 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
describe('models_Note', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should find resource and note IDs', asyncTest(async () => {
let folder1 = await Folder.save({ title: "folder1" });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma deuxième note', body: 'Lien vers première note : ' + Note.markdownTag(note1), parent_id: folder1.id });
let items = await Note.linkedItems(note2.body);
expect(items.length).toBe(1);
expect(items[0].id).toBe(note1.id);
await shim.attachFileToNote(note2, __dirname + '/../tests/support/photo.jpg');
note2 = await Note.load(note2.id);
items = await Note.linkedItems(note2.body);
expect(items.length).toBe(2);
expect(items[0].type_).toBe(BaseModel.TYPE_NOTE);
expect(items[1].type_).toBe(BaseModel.TYPE_RESOURCE);
}));
});

View File

@@ -180,7 +180,7 @@ describe('services_InteropService', function() {
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
note1 = await Note.load(note1.id);
let resourceIds = Note.linkedResourceIds(note1.body);
let resourceIds = await Note.linkedResourceIds(note1.body);
let resource1 = await Resource.load(resourceIds[0]);
await service.export({ path: filePath });
@@ -193,7 +193,7 @@ describe('services_InteropService', function() {
let note2 = (await Note.all())[0];
expect(note2.body).not.toBe(note1.body);
resourceIds = Note.linkedResourceIds(note2.body);
resourceIds = await Note.linkedResourceIds(note2.body);
expect(resourceIds.length).toBe(1);
let resource2 = await Resource.load(resourceIds[0]);
expect(resource2.id).not.toBe(resource1.id);
@@ -249,4 +249,28 @@ describe('services_InteropService', function() {
expect(folder2.title).toBe('folder1');
}));
it('should export and import links to notes', asyncTest(async () => {
const service = new InteropService();
const filePath = exportDir() + '/test.jex';
let folder1 = await Folder.save({ title: "folder1" });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
let note2 = await Note.save({ title: 'ma deuxième note', body: 'Lien vers première note : ' + Note.markdownTag(note1), parent_id: folder1.id });
await service.export({ path: filePath, sourceFolderIds: [folder1.id] });
await Note.delete(note1.id);
await Note.delete(note2.id);
await Folder.delete(folder1.id);
await service.import({ path: filePath });
expect(await Note.count()).toBe(2);
expect(await Folder.count()).toBe(1);
let note1_2 = await Note.loadByTitle('ma note');
let note2_2 = await Note.loadByTitle('ma deuxième note');
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
}));
});

View File

@@ -339,22 +339,17 @@ describe('Synchronizer', function() {
it('should delete local folder', asyncTest(async () => {
let folder1 = await Folder.save({ title: "folder1" });
let folder2 = await Folder.save({ title: "folder2" });
await synchronizer().start();
let context1 = await synchronizer().start();
await switchClient(2);
await synchronizer().start();
await sleep(0.1);
let context2 = await synchronizer().start();
await Folder.delete(folder2.id);
await synchronizer().start();
await synchronizer().start({ context: context2 });
await switchClient(1);
await synchronizer().start();
await synchronizer().start({ context: context1 });
let items = await allItems();
await localItemsSameAsRemote(items, expect);
}));
@@ -377,7 +372,7 @@ describe('Synchronizer', function() {
expect(items.length).toBe(1);
expect(items[0].title).toBe('note1');
expect(items[0].is_conflict).toBe(1);
}));
}));
it('should resolve conflict if note has been deleted remotely and locally', asyncTest(async () => {
let folder = await Folder.save({ title: "folder" });
@@ -438,7 +433,7 @@ describe('Synchronizer', function() {
expect(items1.length).toBe(0);
expect(items1.length).toBe(items2.length);
}));
}));
it('should handle conflict when remote note is deleted then local note is modified', asyncTest(async () => {
let folder1 = await Folder.save({ title: "folder1" });
@@ -547,11 +542,11 @@ describe('Synchronizer', function() {
let n1 = await Note.save({ title: "mynote" });
let n2 = await Note.save({ title: "mynote2" });
let tag = await Tag.save({ title: 'mytag' });
await synchronizer().start();
let context1 = await synchronizer().start();
await switchClient(2);
await synchronizer().start();
let context2 = await synchronizer().start();
if (withEncryption) {
const masterKey_2 = await MasterKey.load(masterKey.id);
await encryptionService().loadMasterKey(masterKey_2, '123456', true);
@@ -565,21 +560,21 @@ describe('Synchronizer', function() {
await Tag.addNote(remoteTag.id, n2.id);
let noteIds = await Tag.noteIds(tag.id);
expect(noteIds.length).toBe(2);
await synchronizer().start();
context2 = await synchronizer().start({ context: context2 });
await switchClient(1);
await synchronizer().start();
context1 = await synchronizer().start({ context: context1 });
let remoteNoteIds = await Tag.noteIds(tag.id);
expect(remoteNoteIds.length).toBe(2);
await Tag.removeNote(tag.id, n1.id);
remoteNoteIds = await Tag.noteIds(tag.id);
expect(remoteNoteIds.length).toBe(1);
await synchronizer().start();
context1 = await synchronizer().start({ context: context1 });
await switchClient(2);
await synchronizer().start();
context2 = await synchronizer().start({ context: context2 });
noteIds = await Tag.noteIds(tag.id);
expect(noteIds.length).toBe(1);
expect(remoteNoteIds[0]).toBe(noteIds[0]);

View File

@@ -16,6 +16,7 @@ const { FileApi } = require('lib/file-api.js');
const { FileApiDriverMemory } = require('lib/file-api-driver-memory.js');
const { FileApiDriverLocal } = require('lib/file-api-driver-local.js');
const { FileApiDriverWebDav } = require('lib/file-api-driver-webdav.js');
const { FileApiDriverDropbox } = require('lib/file-api-driver-dropbox.js');
const BaseService = require('lib/services/BaseService.js');
const { FsDriverNode } = require('lib/fs-driver-node.js');
const { time } = require('lib/time-utils.js');
@@ -25,9 +26,11 @@ const SyncTargetMemory = require('lib/SyncTargetMemory.js');
const SyncTargetFilesystem = require('lib/SyncTargetFilesystem.js');
const SyncTargetOneDrive = require('lib/SyncTargetOneDrive.js');
const SyncTargetNextcloud = require('lib/SyncTargetNextcloud.js');
const SyncTargetDropbox = require('lib/SyncTargetDropbox.js');
const EncryptionService = require('lib/services/EncryptionService.js');
const DecryptionWorker = require('lib/services/DecryptionWorker.js');
const WebDavApi = require('lib/WebDavApi');
const DropboxApi = require('lib/DropboxApi');
let databases_ = [];
let synchronizers_ = [];
@@ -51,10 +54,12 @@ SyncTargetRegistry.addClass(SyncTargetMemory);
SyncTargetRegistry.addClass(SyncTargetFilesystem);
SyncTargetRegistry.addClass(SyncTargetOneDrive);
SyncTargetRegistry.addClass(SyncTargetNextcloud);
SyncTargetRegistry.addClass(SyncTargetDropbox);
// const syncTargetId_ = SyncTargetRegistry.nameToId("nextcloud");
const syncTargetId_ = SyncTargetRegistry.nameToId("memory");
//const syncTargetId_ = SyncTargetRegistry.nameToId('filesystem');
// const syncTargetId_ = SyncTargetRegistry.nameToId('dropbox');
const syncDir = __dirname + '/../tests/sync';
const sleepTime = syncTargetId_ == SyncTargetRegistry.nameToId('filesystem') ? 1001 : 100;//400;
@@ -247,25 +252,15 @@ function fileApi() {
const api = new WebDavApi(options);
fileApi_ = new FileApi('', new FileApiDriverWebDav(api));
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('dropbox')) {
const api = new DropboxApi();
const authTokenPath = __dirname + '/support/dropbox-auth.txt';
const authToken = fs.readFileSync(authTokenPath, 'utf8');
if (!authToken) throw new Error('Dropbox auth token missing in ' + authTokenPath);
api.setAuthToken(authToken);
fileApi_ = new FileApi('', new FileApiDriverDropbox(api));
}
// } else if (syncTargetId == Setting.SYNC_TARGET_ONEDRIVE) {
// let auth = require('./onedrive-auth.json');
// if (!auth) {
// const oneDriveApiUtils = new OneDriveApiNodeUtils(oneDriveApi);
// auth = await oneDriveApiUtils.oauthDance();
// fs.writeFileSync('./onedrive-auth.json', JSON.stringify(auth));
// process.exit(1);
// } else {
// auth = JSON.parse(auth);
// }
// // const oneDriveApiUtils = new OneDriveApiNodeUtils(reg.oneDriveApi());
// // const auth = await oneDriveApiUtils.oauthDance(this);
// // Setting.setValue('sync.3.auth', auth ? JSON.stringify(auth) : null);
// // if (!auth) return;
// }
fileApi_.setLogger(logger);
fileApi_.setSyncTargetId(syncTargetId_);
fileApi_.requestRepeatCount_ = 0;
@@ -306,8 +301,9 @@ function asyncTest(callback) {
await callback();
} catch (error) {
console.error(error);
} finally {
done();
}
done();
}
}

View File

@@ -9,9 +9,10 @@ const fs = require('fs-extra');
class ElectronAppWrapper {
constructor(electronApp, env) {
constructor(electronApp, env, profilePath) {
this.electronApp_ = electronApp;
this.env_ = env;
this.profilePath_ = profilePath;
this.win_ = null;
this.willQuitApp_ = false;
this.tray_ = null;
@@ -37,12 +38,16 @@ class ElectronAppWrapper {
createWindow() {
const windowStateKeeper = require('electron-window-state');
// Load the previous state with fallback to defaults
const windowState = windowStateKeeper({
const stateOptions = {
defaultWidth: 800,
defaultHeight: 600,
file: 'window-state-' + this.env_ + '.json',
});
}
if (this.profilePath_) stateOptions.path = this.profilePath_;
// Load the previous state with fallback to defaults
const windowState = windowStateKeeper(stateOptions);
const windowOptions = {
x: windowState.x,

View File

@@ -38,6 +38,7 @@ const appDefaultState = Object.assign({}, defaultState, {
fileToImport: null,
windowCommand: null,
noteVisiblePanes: ['editor', 'viewer'],
sidebarVisibility: true,
windowContentSize: bridge().windowContentSize(),
});
@@ -85,7 +86,7 @@ class Application extends BaseApplication {
action = newAction;
}
if (!goingBack) newNavHistory.push(currentRoute);
newState.navHistory = newNavHistory
newState.route = action;
@@ -123,11 +124,22 @@ class Application extends BaseApplication {
break;
case 'NOTE_VISIBLE_PANES_SET':
newState = Object.assign({}, state);
newState.noteVisiblePanes = action.panes;
break;
case 'SIDEBAR_VISIBILITY_TOGGLE':
newState = Object.assign({}, state);
newState.sidebarVisibility = !state.sidebarVisibility;
break;
case 'SIDEBAR_VISIBILITY_SET':
newState = Object.assign({}, state);
newState.sidebarVisibility = action.visibility;
break;
}
} catch (error) {
error.message = 'In reducer: ' + error.message + ' Action: ' + JSON.stringify(action);
@@ -152,7 +164,7 @@ class Application extends BaseApplication {
}
if (["NOTE_UPDATE_ONE", "NOTE_DELETE", "FOLDER_UPDATE_ONE", "FOLDER_DELETE"].indexOf(action.type) >= 0) {
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(5, { syncSteps: ["update_remote", "delete_remote"] });
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(30, { syncSteps: ["update_remote", "delete_remote"] });
}
if (['EVENT_NOTE_ALARM_FIELD_CHANGE', 'NOTE_DELETE'].indexOf(action.type) >= 0) {
@@ -170,6 +182,10 @@ class Application extends BaseApplication {
Setting.setValue('noteVisiblePanes', newState.noteVisiblePanes);
}
if (['SIDEBAR_VISIBILITY_TOGGLE', 'SIDEBAR_VISIBILITY_SET'].indexOf(action.type) >= 0) {
Setting.setValue('sidebarVisibility', newState.sidebarVisibility);
}
return result;
}
@@ -195,7 +211,7 @@ class Application extends BaseApplication {
Setting.setValue('notes.sortOrder.field', field);
this.refreshMenu();
}
});
});
}
const importItems = [];
@@ -273,7 +289,7 @@ class Application extends BaseApplication {
this.dispatch({
type: 'WINDOW_COMMAND',
name: 'exportPdf',
});
});
}
});
@@ -349,17 +365,17 @@ class Application extends BaseApplication {
label: _('Edit'),
submenu: [{
label: _('Copy'),
screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
//screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
role: 'copy',
accelerator: 'CommandOrControl+C',
}, {
label: _('Cut'),
screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
//screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
role: 'cut',
accelerator: 'CommandOrControl+X',
}, {
label: _('Paste'),
screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
//screens: ['Main', 'OneDriveLogin', 'Config', 'EncryptionConfig'],
role: 'paste',
accelerator: 'CommandOrControl+V',
}, {
@@ -379,6 +395,16 @@ class Application extends BaseApplication {
}, {
label: _('View'),
submenu: [{
label: _('Toggle sidebar'),
screens: ['Main'],
accelerator: 'F10',
click: () => {
this.dispatch({
type: 'WINDOW_COMMAND',
name: 'toggleSidebar',
});
}
}, {
label: _('Toggle editor layout'),
screens: ['Main'],
accelerator: 'CommandOrControl+L',
@@ -448,10 +474,10 @@ class Application extends BaseApplication {
submenu: [{
label: _('Website and documentation'),
accelerator: 'F1',
click () { bridge().openExternal('http://joplin.cozic.net') }
click () { bridge().openExternal('https://joplin.cozic.net') }
}, {
label: _('Make a donation'),
click () { bridge().openExternal('http://joplin.cozic.net/donate') }
click () { bridge().openExternal('https://joplin.cozic.net/donate') }
}, {
label: _('Check for updates...'),
click: () => {
@@ -510,11 +536,6 @@ class Application extends BaseApplication {
}
updateTray() {
// Tray icon (called AppIndicator) doesn't work in Ubuntu
// http://www.webupd8.org/2017/04/fix-appindicator-not-working-for.html
// Might be fixed in Electron 18.x but no non-beta release yet.
if (!shim.isWindows() && !shim.isMac()) return;
const app = bridge().electronApp();
if (app.trayShown() === Setting.value('showTrayIcon')) return;
@@ -547,6 +568,12 @@ class Application extends BaseApplication {
}
async start(argv) {
const electronIsDev = require('electron-is-dev');
// If running inside a package, the command line, instead of being "node.exe <path> <flags>" is "joplin.exe <flags>" so
// insert an extra argument so that they can be processed in a consistent way everywhere.
if (!electronIsDev) argv.splice(1, 0, '.');
argv = await super.start(argv);
AlarmService.setDriver(new AlarmServiceDriverNode({ appName: packageInfo.build.appId }));
@@ -588,6 +615,11 @@ class Application extends BaseApplication {
id: Setting.value('activeFolderId'),
});
this.store().dispatch({
type: 'FOLDER_SET_COLLAPSED_ALL',
ids: Setting.value('collapsedFolderIds'),
});
// Note: Auto-update currently doesn't work in Linux: it downloads the update
// but then doesn't install it on exit.
if (shim.isWindows() || shim.isMac()) {
@@ -596,7 +628,7 @@ class Application extends BaseApplication {
bridge().checkForUpdates(true, bridge().window(), this.checkForUpdateLoggerPath());
}
}
// Initial check on startup
setTimeout(() => { runAutoUpdateCheck() }, 5000);
// Then every x hours
@@ -633,4 +665,4 @@ function app() {
return application_;
}
module.exports = { app };
module.exports = { app };

View File

@@ -43,7 +43,7 @@ async function fetchLatestRelease() {
for (let i = 0; i < json.assets.length; i++) {
const asset = json.assets[i];
let found = false;
if (platform === 'win32' && asset.name.indexOf('.exe') >= 0) {
if (platform === 'win32' && asset.name.indexOf('.exe') >= 0 && asset.name.indexOf('Setup') >= 0) {
found = true;
} else if (platform === 'darwin' && asset.name.indexOf('.dmg') >= 0) {
found = true;

View File

@@ -0,0 +1,62 @@
const React = require('react');
const { connect } = require('react-redux');
const { reg } = require('lib/registry.js');
const { bridge } = require('electron').remote.require('./bridge');
const { Header } = require('./Header.min.js');
const { themeStyle } = require('../theme.js');
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
const { _ } = require('lib/locale.js');
const Shared = require('lib/components/shared/dropbox-login-shared');
class DropboxLoginScreenComponent extends React.Component {
constructor() {
super();
this.shared_ = new Shared(
this,
(msg) => bridge().showInfoMessageBox(msg),
(msg) => bridge().showErrorMessageBox(msg)
);
}
componentWillMount() {
this.shared_.refreshUrl();
}
render() {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const headerStyle = {
width: style.width,
};
const inputStyle = Object.assign({}, theme.inputStyle, { width: 500 });
return (
<div>
<Header style={headerStyle} />
<div style={{padding: theme.margin}}>
<p style={theme.textStyle}>{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}</p>
<p style={theme.textStyle}>{_('Step 1: Open this URL in your browser to authorise the application:')}</p>
<a style={theme.textStyle} href="#" onClick={this.shared_.loginUrl_click}>{this.state.loginUrl}</a>
<p style={theme.textStyle}>{_('Step 2: Enter the code provided by Dropbox:')}</p>
<p><input type="text" value={this.state.authCode} onChange={this.shared_.authCodeInput_change} style={inputStyle}/></p>
<button disabled={this.state.checkingAuthToken} onClick={this.shared_.submit_click}>{_('Submit')}</button>
</div>
</div>
);
}
}
const mapStateToProps = (state) => {
return {
theme: state.settings.theme,
};
};
const DropboxLoginScreen = connect(mapStateToProps)(DropboxLoginScreenComponent);
module.exports = { DropboxLoginScreen };

View File

@@ -182,17 +182,11 @@ class EncryptionConfigScreenComponent extends React.Component {
<div>
<Header style={headerStyle} />
<div style={containerStyle}>
{/*<div style={{backgroundColor: theme.warningBackgroundColor, paddingLeft: 10, paddingRight: 10, paddingTop: 2, paddingBottom: 2 }}>
{<div style={{backgroundColor: theme.warningBackgroundColor, paddingLeft: 10, paddingRight: 10, paddingTop: 2, paddingBottom: 2 }}>
<p style={theme.textStyle}>
Important: This is a <b>beta</b> feature. It has been extensively tested and is already in use by some users, but it is possible that some bugs remain.
<span>{_('For more information about End-To-End Encryption (E2EE) and advices on how to enable it please check the documentation:')}</span> <a onClick={() => {bridge().openExternal('https://joplin.cozic.net/e2ee')}} href="#">https://joplin.cozic.net/e2ee</a>
</p>
<p style={theme.textStyle}>
If you wish to you use it, it is recommended that you keep a backup of your data. The simplest way is to regularly backup <b>{pathUtils.toSystemSlashes(Setting.value('profileDir'), process.platform)}</b>
</p>
<p style={theme.textStyle}>
For more information about End-To-End Encryption (E2EE) and how it is going to work, please check the documentation: <a onClick={() => {bridge().openExternal('http://joplin.cozic.net/help/e2ee.html')}} href="#">http://joplin.cozic.net/help/e2ee.html</a>
</p>
</div>*/}
</div>}
<h1 style={theme.h1Style}>{_('Status')}</h1>
<p style={theme.textStyle}>{_('Encryption is:')} <strong>{this.props.encryptionEnabled ? _('Enabled') : _('Disabled')}</strong></p>
{decryptedItemsInfo}

View File

@@ -72,9 +72,10 @@ class HeaderComponent extends React.Component {
if (options.iconName) {
const iconStyle = {
fontSize: Math.round(style.fontSize * 1.4),
color: style.color
color: style.color,
};
if (options.title) iconStyle.marginRight = 5;
if (options.iconRotation) iconStyle.transform = 'rotate(' + options.iconRotation + 'deg)';
icon = <i style={iconStyle} className={"fa " + options.iconName}></i>
}

View File

@@ -25,7 +25,7 @@ class MainScreenComponent extends React.Component {
modalLayer: {
visible: false,
message: '',
},
}
});
}
@@ -41,6 +41,12 @@ class MainScreenComponent extends React.Component {
});
}
toggleSidebar() {
this.props.dispatch({
type: 'SIDEBAR_VISIBILITY_TOGGLE',
});
}
async doCommand(command) {
if (!command) return;
@@ -83,7 +89,7 @@ class MainScreenComponent extends React.Component {
if (answer) {
let folder = null;
try {
folder = await Folder.save({ title: answer }, { userSideValidation: true });
folder = await Folder.save({ title: answer }, { userSideValidation: true });
} catch (error) {
bridge().showErrorMessageBox(error.message);
}
@@ -160,9 +166,11 @@ class MainScreenComponent extends React.Component {
id: this.searchId_,
});
}
} else if (command.name === 'toggleVisiblePanes') {
this.toggleVisiblePanes();
} else if (command.name === 'toggleSidebar') {
this.toggleSidebar();
} else if (command.name === 'showModalMessage') {
this.setState({ modalLayer: { visible: true, message: command.message } });
} else if (command.name === 'hideModalMessage') {
@@ -203,7 +211,7 @@ class MainScreenComponent extends React.Component {
this.setState({ promptOptions: null });
}
},
});
});
} else {
commandProcessed = false;
}
@@ -216,8 +224,8 @@ class MainScreenComponent extends React.Component {
}
}
styles(themeId, width, height, messageBoxVisible) {
const styleKey = themeId + '_' + width + '_' + height + '_' + messageBoxVisible;
styles(themeId, width, height, messageBoxVisible, isSidebarVisible) {
const styleKey = themeId + '_' + width + '_' + height + '_' + messageBoxVisible + '_' + (+isSidebarVisible);
if (styleKey === this.styleKey_) return this.styles_;
const theme = themeStyle(themeId);
@@ -246,7 +254,12 @@ class MainScreenComponent extends React.Component {
height: rowHeight,
display: 'inline-block',
verticalAlign: 'top',
};
};
if (isSidebarVisible === false) {
this.styles_.sideBar.width = 0;
this.styles_.sideBar.display = 'none';
}
this.styles_.noteList = {
width: Math.floor(layoutUtils.size(width * .2, 150, 300)),
@@ -287,20 +300,28 @@ class MainScreenComponent extends React.Component {
const folders = this.props.folders;
const notes = this.props.notes;
const messageBoxVisible = this.props.hasDisabledSyncItems || this.props.showMissingMasterKeyMessage;
const styles = this.styles(this.props.theme, style.width, style.height, messageBoxVisible);
const sidebarVisibility = this.props.sidebarVisibility;
const styles = this.styles(this.props.theme, style.width, style.height, messageBoxVisible, sidebarVisibility);
const theme = themeStyle(this.props.theme);
const selectedFolderId = this.props.selectedFolderId;
const onConflictFolder = this.props.selectedFolderId === Folder.conflictFolderId();
const headerItems = [];
headerItems.push({
title: _('Toggle sidebar'),
iconName: 'fa-bars',
iconRotation: this.props.sidebarVisibility ? 0 : 90,
onClick: () => { this.doCommand({ name: 'toggleSidebar'}) }
});
headerItems.push({
title: _('New note'),
iconName: 'fa-file-o',
enabled: !!folders.length && !onConflictFolder,
onClick: () => { this.doCommand({ name: 'newNote' }) },
});
headerItems.push({
title: _('New to-do'),
iconName: 'fa-check-square-o',
@@ -400,14 +421,16 @@ const mapStateToProps = (state) => {
theme: state.settings.theme,
windowCommand: state.windowCommand,
noteVisiblePanes: state.noteVisiblePanes,
sidebarVisibility: state.sidebarVisibility,
folders: state.folders,
notes: state.notes,
hasDisabledSyncItems: state.hasDisabledSyncItems,
showMissingMasterKeyMessage: state.notLoadedMasterKeys.length && state.masterKeys.length,
selectedFolderId: state.selectedFolderId,
sidebarVisibility: state.sidebarVisibility,
};
};
const MainScreen = connect(mapStateToProps)(MainScreenComponent);
module.exports = { MainScreen };
module.exports = { MainScreen };

View File

@@ -96,6 +96,16 @@ class NoteListComponent extends React.Component {
}
}}));
menu.append(new MenuItem({label: _('Copy Markdown link'), click: async () => {
const { clipboard } = require('electron');
const links = [];
for (let i = 0; i < noteIds.length; i++) {
const note = await Note.load(noteIds[i]);
links.push(Note.markdownTag(note));
}
clipboard.writeText(links.join(' '));
}}));
const exportMenu = new Menu();
const ioService = new InteropService();

View File

@@ -1,5 +1,6 @@
const React = require('react');
const Note = require('lib/models/Note.js');
const BaseItem = require('lib/models/BaseItem.js');
const BaseModel = require('lib/BaseModel.js');
const Search = require('lib/models/Search.js');
const { time } = require('lib/time-utils.js');
@@ -76,7 +77,6 @@ class NoteTextComponent extends React.Component {
mdToHtml() {
if (this.mdToHtml_) return this.mdToHtml_;
this.mdToHtml_ = new MdToHtml({
supportsResourceLinks: true,
resourceBaseUrl: 'file://' + Setting.value('resourceDir') + '/',
});
return this.mdToHtml_;
@@ -210,10 +210,22 @@ class NoteTextComponent extends React.Component {
}
if (this.editor_) {
const session = this.editor_.editor.getSession();
const undoManager = session.getUndoManager();
undoManager.reset();
session.setUndoManager(undoManager);
// Calling setValue here does two things:
// 1. It sets the initial value as recorded by the undo manager. If we were to set it instead to "" and wait for the render
// phase to set the value, the initial value would still be "", which means pressing "undo" on a note that has just loaded
// would clear it.
// 2. It resets the undo manager - fixes https://github.com/laurent22/joplin/issues/355
// Note: calling undoManager.reset() doesn't work
try {
this.editor_.editor.getSession().setValue(note ? note.body : '');
} catch (error) {
if (error.message === "Cannot read property 'match' of undefined") {
// The internals of Ace Editor throws an exception when creating a new note,
// but that can be ignored.
} else {
console.error(error);
}
}
this.editor_.editor.clearSelection();
this.editor_.editor.moveCursorTo(0,0);
}
@@ -322,11 +334,29 @@ class NoteTextComponent extends React.Component {
menu.popup(bridge().window());
} else if (msg.indexOf('joplin://') === 0) {
const resourceId = msg.substr('joplin://'.length);
Resource.load(resourceId).then((resource) => {
const filePath = Resource.fullPath(resource);
const itemId = msg.substr('joplin://'.length);
const item = await BaseItem.loadItemById(itemId);
if (!item) throw new Error('No item with ID ' + itemId);
if (item.type_ === BaseModel.TYPE_RESOURCE) {
const filePath = Resource.fullPath(item);
bridge().openItem(filePath);
});
} else if (item.type_ === BaseModel.TYPE_NOTE) {
this.props.dispatch({
type: "FOLDER_SELECT",
id: item.parent_id,
});
setTimeout(() => {
this.props.dispatch({
type: 'NOTE_SELECT',
id: item.id,
});
}, 10);
} else {
throw new Error('Unsupported item type: ' + item.type_);
}
} else {
bridge().showErrorMessageBox(_('Unsupported link or message: %s', msg));
}
@@ -370,7 +400,7 @@ class NoteTextComponent extends React.Component {
webviewReady: true,
});
if (Setting.value('env') === 'dev') this.webview_.openDevTools();
// if (Setting.value('env') === 'dev') this.webview_.openDevTools();
}
webview_ref(element) {
@@ -500,6 +530,7 @@ class NoteTextComponent extends React.Component {
});
} catch (error) {
reg.logger().error(error);
bridge().showErrorMessageBox(error.message);
}
}
}

View File

@@ -8,6 +8,7 @@ const Setting = require('lib/models/Setting.js');
const { MainScreen } = require('./MainScreen.min.js');
const { OneDriveLoginScreen } = require('./OneDriveLoginScreen.min.js');
const { DropboxLoginScreen } = require('./DropboxLoginScreen.min.js');
const { StatusScreen } = require('./StatusScreen.min.js');
const { ImportScreen } = require('./ImportScreen.min.js');
const { ConfigScreen } = require('./ConfigScreen.min.js');
@@ -46,6 +47,11 @@ async function initialize(dispatch) {
type: 'NOTE_VISIBLE_PANES_SET',
panes: Setting.value('noteVisiblePanes'),
});
store.dispatch({
type: 'SIDEBAR_VISIBILITY_SET',
visibility: Setting.value('sidebarVisibility')
});
}
class RootComponent extends React.Component {
@@ -75,6 +81,7 @@ class RootComponent extends React.Component {
const screens = {
Main: { screen: MainScreen },
OneDriveLogin: { screen: OneDriveLoginScreen, title: () => _('OneDrive Login') },
DropboxLogin: { screen: DropboxLoginScreen, title: () => _('Dropbox Login') },
Import: { screen: ImportScreen, title: () => _('Import') },
Config: { screen: ConfigScreen, title: () => _('Options') },
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },

View File

@@ -14,6 +14,57 @@ const MenuItem = bridge().MenuItem;
const InteropServiceHelper = require("../InteropServiceHelper.js");
class SideBarComponent extends React.Component {
constructor() {
super();
this.onFolderDragStart_ = (event) => {
const folderId = event.currentTarget.getAttribute('folderid');
if (!folderId) return;
event.dataTransfer.setDragImage(new Image(), 1, 1);
event.dataTransfer.clearData();
event.dataTransfer.setData('text/x-jop-folder-ids', JSON.stringify([folderId]));
};
this.onFolderDragOver_ = (event) => {
if (event.dataTransfer.types.indexOf("text/x-jop-note-ids") >= 0) event.preventDefault();
if (event.dataTransfer.types.indexOf("text/x-jop-folder-ids") >= 0) event.preventDefault();
};
this.onFolderDrop_ = async (event) => {
const folderId = event.currentTarget.getAttribute('folderid');
const dt = event.dataTransfer;
if (!dt) return;
if (dt.types.indexOf("text/x-jop-note-ids") >= 0) {
event.preventDefault();
const noteIds = JSON.parse(dt.getData("text/x-jop-note-ids"));
for (let i = 0; i < noteIds.length; i++) {
await Note.moveToFolder(noteIds[i], folderId);
}
} else if (dt.types.indexOf("text/x-jop-folder-ids") >= 0) {
event.preventDefault();
const folderIds = JSON.parse(dt.getData("text/x-jop-folder-ids"));
for (let i = 0; i < folderIds.length; i++) {
await Folder.moveToFolder(folderIds[i], folderId);
}
}
};
this.onFolderToggleClick_ = async (event) => {
const folderId = event.currentTarget.getAttribute('folderid');
this.props.dispatch({
type: 'FOLDER_TOGGLE',
id: folderId,
});
};
}
style() {
const theme = themeStyle(this.props.theme);
@@ -23,23 +74,39 @@ class SideBarComponent extends React.Component {
root: {
backgroundColor: theme.backgroundColor2,
},
listItem: {
listItemContainer: {
boxSizing: "border-box",
height: itemHeight,
// paddingLeft: 14,
display: "flex",
alignItems: "stretch",
},
listItem: {
fontFamily: theme.fontFamily,
fontSize: theme.fontSize,
textDecoration: "none",
boxSizing: "border-box",
color: theme.color2,
paddingLeft: 14,
display: "flex",
alignItems: "center",
cursor: "default",
opacity: 0.8,
whiteSpace: "nowrap",
display: "flex",
flex: 1,
alignItems: 'center',
},
listItemSelected: {
backgroundColor: theme.selectedColor2,
},
listItemExpandIcon: {
color: theme.color2,
cursor: "default",
opacity: 0.8,
// fontFamily: theme.fontFamily,
fontSize: theme.fontSize,
textDecoration: "none",
paddingRight: 5,
display: "flex",
alignItems: 'center',
},
conflictFolder: {
color: theme.colorError2,
fontWeight: "bold",
@@ -101,7 +168,7 @@ class SideBarComponent extends React.Component {
let deleteMessage = "";
if (itemType === BaseModel.TYPE_FOLDER) {
deleteMessage = _("Delete notebook? All notes within this notebook will also be deleted.");
deleteMessage = _("Delete notebook? All notes and sub-notebooks within this notebook will also be deleted.");
} else if (itemType === BaseModel.TYPE_TAG) {
deleteMessage = _("Remove this tag from all the notes?");
} else if (itemType === BaseModel.TYPE_SEARCH) {
@@ -150,6 +217,19 @@ class SideBarComponent extends React.Component {
})
);
// menu.append(
// new MenuItem({
// label: _("Move"),
// click: async () => {
// this.props.dispatch({
// type: "WINDOW_COMMAND",
// name: "renameFolder",
// id: itemId,
// });
// },
// })
// );
menu.append(new MenuItem({ type: "separator" }));
const InteropService = require("lib/services/InteropService.js");
@@ -194,48 +274,46 @@ class SideBarComponent extends React.Component {
await shared.synchronize_press(this);
}
folderItem(folder, selected) {
folderItem(folder, selected, hasChildren, depth) {
let style = Object.assign({}, this.style().listItem);
if (selected) style = Object.assign(style, this.style().listItemSelected);
if (folder.id === Folder.conflictFolderId()) style = Object.assign(style, this.style().conflictFolder);
const onDragOver = (event, folder) => {
if (event.dataTransfer.types.indexOf("text/x-jop-note-ids") >= 0) event.preventDefault();
};
const onDrop = async (event, folder) => {
if (event.dataTransfer.types.indexOf("text/x-jop-note-ids") < 0) return;
event.preventDefault();
const noteIds = JSON.parse(event.dataTransfer.getData("text/x-jop-note-ids"));
for (let i = 0; i < noteIds.length; i++) {
await Note.moveToFolder(noteIds[i], folder.id);
}
};
const itemTitle = Folder.displayTitle(folder);
let containerStyle = Object.assign({}, this.style().listItemContainer);
// containerStyle.paddingLeft = containerStyle.paddingLeft + depth * 10;
if (selected) containerStyle = Object.assign(containerStyle, this.style().listItemSelected);
let expandLinkStyle = Object.assign({}, this.style().listItemExpandIcon);
let expandIconStyle = {
visibility: hasChildren ? 'visible' : 'hidden',
paddingLeft: 8 + depth * 10,
}
const iconName = this.props.collapsedFolderIds.indexOf(folder.id) >= 0 ? 'fa-plus-square' : 'fa-minus-square';
const expandIcon = <i style={expandIconStyle} className={"fa " + iconName}></i>
const expandLink = hasChildren ? <a style={expandLinkStyle} href="#" folderid={folder.id} onClick={this.onFolderToggleClick_}>{expandIcon}</a> : <span style={expandLinkStyle}>{expandIcon}</span>
return (
<a
className="list-item"
onDragOver={event => {
onDragOver(event, folder);
}}
onDrop={event => {
onDrop(event, folder);
}}
href="#"
data-id={folder.id}
data-type={BaseModel.TYPE_FOLDER}
onContextMenu={event => this.itemContextMenu(event)}
key={folder.id}
style={style}
onClick={() => {
this.folderItem_click(folder);
}}
>
{itemTitle}
</a>
<div className="list-item-container" style={containerStyle} key={folder.id} onDragStart={this.onFolderDragStart_} onDragOver={this.onFolderDragOver_} onDrop={this.onFolderDrop_} draggable={true} folderid={folder.id}>
{ expandLink }
<a
className="list-item"
href="#"
data-id={folder.id}
data-type={BaseModel.TYPE_FOLDER}
onContextMenu={event => this.itemContextMenu(event)}
style={style}
folderid={folder.id}
onClick={() => {
this.folderItem_click(folder);
}}
onDoubleClick={this.onFolderToggleClick_}
>
{itemTitle}
</a>
</div>
);
}
@@ -285,11 +363,11 @@ class SideBarComponent extends React.Component {
return <div style={{ height: 2, backgroundColor: "blue" }} key={key} />;
}
makeHeader(key, label, iconName) {
makeHeader(key, label, iconName, extraProps = {}) {
const style = this.style().header;
const icon = <i style={{ fontSize: style.fontSize * 1.2, marginRight: 5 }} className={"fa " + iconName} />;
return (
<div style={style} key={key}>
<div style={style} key={key} {...extraProps}>
{icon}
{label}
</div>
@@ -326,7 +404,10 @@ class SideBarComponent extends React.Component {
let items = [];
items.push(this.makeHeader("folderHeader", _("Notebooks"), "fa-folder-o"));
items.push(this.makeHeader("folderHeader", _("Notebooks"), "fa-folder-o", {
onDrop: this.onFolderDrop_,
folderid: '',
}));
if (this.props.folders.length) {
const folderItems = shared.renderFolders(this.props, this.folderItem.bind(this));
@@ -345,18 +426,6 @@ class SideBarComponent extends React.Component {
);
}
// if (this.props.searches.length) {
// items.push(this.makeHeader("searchHeader", _("Searches"), "fa-search"));
// const searchItems = shared.renderSearches(this.props, this.searchItem.bind(this));
// items.push(
// <div className="searches" key="search_items">
// {searchItems}
// </div>
// );
// }
let lines = Synchronizer.reportToLines(this.props.syncReport);
const syncReportText = [];
for (let i = 0; i < lines.length; i++) {
@@ -396,6 +465,7 @@ const mapStateToProps = state => {
notesParentType: state.notesParentType,
locale: state.settings.locale,
theme: state.settings.theme,
collapsedFolderIds: state.collapsedFolderIds,
};
};

View File

@@ -124,17 +124,17 @@
loadAndApplyHljs();
// Remove the bullet from "ul" for checkbox lists and extra padding
const checkboxes = document.getElementsByClassName('checkbox');
for (let i = 0; i < checkboxes.length; i++) {
const cb = checkboxes[i];
const ul = cb.parentElement.parentElement;
if (!ul) {
console.warn('Unexpected layout for checkbox');
continue;
}
ul.style.listStyleType = 'none';
ul.style.paddingLeft = 0;
}
// const checkboxes = document.getElementsByClassName('checkbox');
// for (let i = 0; i < checkboxes.length; i++) {
// const cb = checkboxes[i];
// const ul = cb.parentElement.parentElement;
// if (!ul) {
// console.warn('Unexpected layout for checkbox');
// continue;
// }
// ul.style.listStyleType = 'none';
// ul.style.paddingLeft = 0;
// }
let previousContentHeight = contentElement.scrollHeight;
let startTime = Date.now();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,12 @@
var locales = {};
locales['en_GB'] = require('./en_GB.json');
locales['cs_CZ'] = require('./cs_CZ.json');
locales['da_DK'] = require('./da_DK.json');
locales['de_DE'] = require('./de_DE.json');
locales['es_ES'] = require('./es_ES.json');
locales['eu'] = require('./eu.json');
locales['fr_FR'] = require('./fr_FR.json');
locales['gl_ES'] = require('./gl_ES.json');
locales['hr_HR'] = require('./hr_HR.json');
locales['it_IT'] = require('./it_IT.json');
locales['ja_JP'] = require('./ja_JP.json');

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -24,11 +24,22 @@ function envFromArgs(args) {
return 'prod';
}
// Likewise, we want to know if a profile is specified early, in particular
// to save the window state data.
function profileFromArgs(args) {
if (!args) return null;
const profileIndex = args.indexOf('--profile');
if (profileIndex <= 0 || profileIndex >= args.length - 1) return null;
const profileValue = args[profileIndex + 1];
return profileValue ? profileValue : null;
}
Logger.fsDriver_ = new FsDriverNode();
const env = envFromArgs(process.argv);
const profilePath = profileFromArgs(process.argv);
const wrapper = new ElectronAppWrapper(electronApp, env);
const wrapper = new ElectronAppWrapper(electronApp, env, profilePath);
initBridge(wrapper);

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.0.79",
"version": "1.0.89",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {
@@ -26,7 +26,23 @@
"build/icons/*"
],
"win": {
"icon": "../../Assets/Joplin.ico"
"icon": "../../Assets/Joplin.ico",
"target": [
{
"target": "nsis",
"arch": [
"x64",
"ia32"
]
},
{
"target": "portable",
"arch": [
"x64",
"ia32"
]
}
]
},
"nsis": {
"oneClick": false,
@@ -48,7 +64,7 @@
"babel-cli": "^6.26.0",
"babel-preset-react": "^6.24.1",
"electron": "^1.7.11",
"electron-builder": "^20.5.1"
"electron-builder": "^20.10.0"
},
"optionalDependencies": {
"7zip-bin-mac": "^1.0.1",
@@ -61,6 +77,7 @@
"base-64": "^0.1.0",
"compare-versions": "^3.1.0",
"electron-context-menu": "^0.9.1",
"electron-is-dev": "^0.3.0",
"electron-window-state": "^4.1.1",
"follow-redirects": "^1.2.5",
"form-data": "^2.3.1",
@@ -87,7 +104,6 @@
"react-dom": "^16.0.0",
"react-redux": "^5.0.6",
"redux": "^3.7.2",
"sharp": "^0.17.3",
"smalltalk": "^2.5.1",
"sprintf-js": "^1.1.1",
"sqlite3": "^3.1.13",
@@ -97,6 +113,7 @@
"tcp-port-used": "^0.1.2",
"url-parse": "^1.2.0",
"uuid": "^3.1.0",
"valid-url": "^1.0.9",
"xml2js": "^0.4.19"
}
}

View File

@@ -34,17 +34,15 @@ table td, table th {
background-color: rgba(0,160,255,0.1) !important;
}
.side-bar .list-item:hover,
/*.side-bar .list-item:hover,
.side-bar .synchronize-button:hover {
/*background-color: #453E53;*/
background-color: #01427B;
}
.side-bar .list-item:active,
.side-bar .synchronize-button:active {
/*background-color: #564B6C;*/
background-color: #0465BB;
}
}*/
.editor-toolbar .button:not(.disabled):hover,
.header .button:not(.disabled):hover {

View File

@@ -62,6 +62,7 @@ globalStyle.icon = {
globalStyle.lineInput = {
color: globalStyle.color,
backgroundColor: globalStyle.backgroundColor,
fontFamily: globalStyle.fontFamily,
};
globalStyle.textStyle = {

185
README.md
View File

@@ -1,16 +1,16 @@
# Joplin
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [![Donate with Bitcoin](https://en.cryptobadges.io/badge/micro/1AnbeRd5NZT1ssG93jXzaDoHwzgjQAHX3R)](https://en.cryptobadges.io/donate/1AnbeRd5NZT1ssG93jXzaDoHwzgjQAHX3R) [![Travis Build Status](https://travis-ci.org/laurent22/joplin.svg?branch=master)](https://travis-ci.org/laurent22/joplin) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/laurent22/joplin?branch=master&passingText=master%20-%20OK&svg=true)](https://ci.appveyor.com/project/laurent22/joplin)
[![Donate](https://joplin.cozic.net/images/badges/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [![Donate with Bitcoin](https://joplin.cozic.net/images/badges/Donate-Bitcoin.svg)](https://joplin.cozic.net/donate/#bitcoin) [![Travis Build Status](https://travis-ci.org/laurent22/joplin.svg?branch=master)](https://travis-ci.org/laurent22/joplin) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/laurent22/joplin?branch=master&passingText=master%20-%20OK&svg=true)](https://ci.appveyor.com/project/laurent22/joplin)
Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in [Markdown format](#markdown).
Notes exported from Evernote via .enex files [can be imported](#importing) into Joplin, including the formatted content (which is converted to Markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). Plain Markdown files can also be imported.
The notes can be [synchronised](#synchronisation) with various cloud services including [Nextcloud](https://nextcloud.com/), the file system (for example with a network directory) or with Microsoft OneDrive. When synchronising the notes, notebooks, tags and other metadata are saved to plain text files which can be easily inspected, backed up and moved around.
The notes can be [synchronised](#synchronisation) with various cloud services including [Nextcloud](https://nextcloud.com/), Dropbox, OneDrive or the file system (for example with a network directory). When synchronising the notes, notebooks, tags and other metadata are saved to plain text files which can be easily inspected, backed up and moved around.
The UI of the terminal client is built on top of the great [terminal-kit](https://github.com/cronvel/terminal-kit) library, the desktop client using [Electron](https://electronjs.org/), and the Android client front end is done using [React Native](https://facebook.github.io/react-native/).
<div class="top-screenshot"><img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/AllClients.jpg" style="max-width: 100%; max-height: 35em;"></div>
<div class="top-screenshot"><img src="https://joplin.cozic.net/images/AllClients.jpg" style="max-width: 100%; max-height: 35em;"></div>
# Installation
@@ -18,43 +18,60 @@ Three types of applications are available: for the **desktop** (Windows, macOS a
## Desktop applications
Operating System | Download
-----------------|--------
Windows | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.78/Joplin-Setup-1.0.78.exe'><img alt='Get it on Windows' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeWindows.png'/></a>
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.78/Joplin-1.0.78.dmg'><img alt='Get it on macOS' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeMacOS.png'/></a>
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.78/Joplin-1.0.78-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeLinux.png'/></a>
Operating System | Download | Alternative
-----------------|--------|-------------------
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.85/Joplin-Setup-1.0.85.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> |
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.85/Joplin-1.0.85.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a> |
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.85/Joplin-1.0.85-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package [is also available](#terminal-application).
## Mobile applications
Operating System | Download | Alt. Download
-----------------|----------|----------------
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.112/joplin-v1.0.112.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/BadgeIOS.png'/></a> | -
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.122/joplin-v1.0.122.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplin.cozic.net/images/BadgeIOS.png'/></a> | -
## Terminal application
On macOS:
brew install joplin
On Linux or Windows (via [WSL](https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)):
**Important:** First, [install Node 8+](https://nodejs.org/en/download/package-manager/). Node 8 is LTS but not yet available everywhere so you might need to manually install it.
NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin
sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin
By default, the application binary will be installed under `~/.joplin-bin`. You may change this directory if needed. Alternatively, if your npm permissions are setup as described [here](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-2-change-npms-default-directory-to-another-directory) (Option 2) then simply running `npm -g install joplin` would work.
Operating system | Method
-----------------|----------------
macOS | `brew install joplin`
Linux or Windows (via [WSL](https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)) | **Important:** First, [install Node 8+](https://nodejs.org/en/download/package-manager/). Node 8 is LTS but not yet available everywhere so you might need to manually install it.<br/><br/>`NPM_CONFIG_PREFIX=~/.joplin-bin npm install -g joplin`<br/>`sudo ln -s ~/.joplin-bin/bin/joplin /usr/bin/joplin`<br><br>By default, the application binary will be installed under `~/.joplin-bin`. You may change this directory if needed. Alternatively, if your npm permissions are setup as described [here](https://docs.npmjs.com/getting-started/fixing-npm-permissions#option-2-change-npms-default-directory-to-another-directory) (Option 2) then simply running `npm -g install joplin` would work.
Arch Linux | An Arch Linux package is available [here](https://aur.archlinux.org/packages/joplin/). To install it, use an AUR wrapper such as yay: `yay -S joplin`. Both the CLI tool (type `joplin`) and desktop app (type `joplin-desktop`) are packaged. For support, please go to the [GitHub repo](https://github.com/masterkorp/joplin-pkgbuild).
To start it, type `joplin`.
For usage information, please refer to the full [Joplin Terminal Application Documentation](http://joplin.cozic.net/terminal).
For usage information, please refer to the full [Joplin Terminal Application Documentation](https://joplin.cozic.net/terminal).
<!-- TOC -->
# Table of contents
- Applications
- [Desktop application](https://github.com/laurent22/joplin/blob/master/readme/desktop.md)
- [Mobile applications](https://github.com/laurent22/joplin/blob/master/readme/mobile.md)
- [Terminal application](https://github.com/laurent22/joplin/blob/master/readme/terminal.md)
- Support
- [Joplin Forum](https://discourse.joplin.cozic.net)
- [How to enable end-to-end encryption](https://github.com/laurent22/joplin/blob/master/readme/e2ee.md)
- [End-to-end encryption spec](https://github.com/laurent22/joplin/blob/master/readme/spec.md)
- [How to enable debug mode](https://github.com/laurent22/joplin/blob/master/readme/debugging.md)
- [FAQ](https://github.com/laurent22/joplin/blob/master/readme/faq.md)
- About
- [Changelog](https://github.com/laurent22/joplin/blob/master/readme/changelog.md)
- [Stats](https://github.com/laurent22/joplin/blob/master/readme/stats.md)
- [Donate](https://github.com/laurent22/joplin/blob/master/readme/donate.md)
<!-- TOC -->
# Features
- Desktop, mobile and terminal applications.
- End To End Encryption (E2EE)
- Synchronisation with various services, including NextCloud, WebDAV and OneDrive. Dropbox is planned.
- Synchronisation with various services, including NextCloud, Dropbox, WebDAV and OneDrive.
- Import Enex files (Evernote export format) and Markdown files.
- Export JEX files (Joplin Export format) and raw files.
- Support notes, to-dos, tags and notebooks.
@@ -81,7 +98,7 @@ To import Evernote data, first export your Evernote notebooks to ENEX files as d
On the **desktop application**, open File > Import > ENEX and select your file. The notes will be imported into a new separate notebook. If needed they can then be moved to a different notebook, or the notebook can be renamed, etc.
On the **terminal application**, in [command-line mode](/terminal#command-line-mode), type `import /path/to/file.enex`. This will import the notes into a new notebook named after the filename.
On the **terminal application**, in [command-line mode](https://joplin.cozic.net/terminal#command-line-mode), type `import /path/to/file.enex`. This will import the notes into a new notebook named after the filename.
## Importing from Markdown files
@@ -89,7 +106,7 @@ Joplin can import notes from plain Markdown file. You can either import a comple
On the **desktop application**, open File > Import > MD and select your Markdown file or directory.
On the **terminal application**, in [command-line mode](/terminal#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
On the **terminal application**, in [command-line mode](https://joplin.cozic.net/terminal#command-line-mode), type `import --format md /path/to/file.md` or `import --format md /path/to/directory/`.
## Importing from other applications
@@ -97,6 +114,7 @@ In general the way to import notes from any application into Joplin is to conver
* Standard Notes: Please see [this tutorial](https://programadorwebvalencia.com/migrate-notes-from-standard-notes-to-joplin/)
* Tomboy Notes: Export the notes to ENEX files [as described here](https://askubuntu.com/questions/243691/how-can-i-export-my-tomboy-notes-into-evernote/608551) for example, and import these ENEX files into Joplin.
* OneNote: First [import the notes from OneNote into Evernote](https://discussion.evernote.com/topic/107736-is-there-a-way-to-import-from-onenote-into-evernote-on-the-mac/). Then export the ENEX file from Evernote and import it into Joplin.
# Exporting
@@ -104,25 +122,35 @@ Joplin can export to the JEX format (Joplin Export file), which is a tar file th
# Synchronisation
One of the goals of Joplin was to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as Nextcloud or OneDrive, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another or to even sync to multiple services at once. Each note, notebook, tags, as well as the relation between items is transmitted as plain text files during synchronisation, which means the data can also be moved to a different application, can be easily backed up, inspected, etc.
One of the goals of Joplin was to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as Nextcloud or Dropbox, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another or to even sync to multiple services at once. Each note, notebook, tags, as well as the relation between items is transmitted as plain text files during synchronisation, which means the data can also be moved to a different application, can be easily backed up, inspected, etc.
Currently, synchronisation is possible with Nextcloud and OneDrive (by default) or the local filesystem. A Dropbox one will also be available once [this React Native bug](https://github.com/facebook/react-native/issues/14445) is fixed. To setup synchronisation please follow the instructions below. After that, the application will synchronise in the background whenever it is running, or you can click on "Synchronise" to start a synchronisation manually.
Currently, synchronisation is possible with Nextcloud, Dropbox (by default) or the local filesystem. To setup synchronisation please follow the instructions below. After that, the application will synchronise in the background whenever it is running, or you can click on "Synchronise" to start a synchronisation manually.
## Nextcloud synchronisation
<img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/nextcloud-logo-background.png" width="100" align="left"> <a href="https://nextcloud.com/">Nextcloud</a> is a self-hosted, private cloud solution. It can store documents, images and videos but also calendars, passwords and countless other things and can sync them to your laptop or phone. As you can host your own Nextcloud server, you own both the data on your device and infrastructure used for synchronisation. As such it is a good fit for Joplin. The platform is also well supported and with a strong community, so it is likely to be around for a while - since it's open source anyway, it is not a service that can be closed, it can exist on a server for as long as one chooses.
<img src="https://joplin.cozic.net/images/nextcloud-logo-background.png" width="100" align="left"> <a href="https://nextcloud.com/">Nextcloud</a> is a self-hosted, private cloud solution. It can store documents, images and videos but also calendars, passwords and countless other things and can sync them to your laptop or phone. As you can host your own Nextcloud server, you own both the data on your device and infrastructure used for synchronisation. As such it is a good fit for Joplin. The platform is also well supported and with a strong community, so it is likely to be around for a while - since it's open source anyway, it is not a service that can be closed, it can exist on a server for as long as one chooses.
On the **desktop application** or **mobile application**, go to the config screen and select Nextcloud as the synchronisation target. Then input the WebDAV URL (to get it, click on Settings in the bottom left corner of the page, in Nextcloud), this is normally `https://example.com/nextcloud/remote.php/webdav/Joplin` (**make sure to create the "Joplin" directory in Nextcloud**), and set the username and password. If it does not work, please [see this explanation](https://github.com/laurent22/joplin/issues/61#issuecomment-373282608) for more details.
On the **terminal application**, you will need to set the `sync.target` config variable and all the `sync.5.path`, `sync.5.username` and `sync.5.password` config variables to, respectively the Nextcloud WebDAV URL, your username and your password. This can be done from the command line mode using:
:config sync.5.path https://example.com/nextcloud/remote.php/dav/files/USERNAME/Joplin
:config sync.5.username YOUR_USERNAME
:config sync.5.password YOUR_PASSWORD
:config sync.5.path https://example.com/nextcloud/remote.php/webdav/Joplin
:config sync.5.username YOUR_USERNAME
:config sync.5.password YOUR_PASSWORD
:config sync.target 5
If synchronisation does not work, please consult the logs in the app profile directory - it is often due to a misconfigured URL or password. The log should indicate what the exact issue is.
## Dropbox synchronisation
When syncing with Dropbox, Joplin creates a sub-directory in Dropbox, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.
On the **desktop application** or **mobile application**, select "Dropbox" as the synchronisation target in the config screen (it is selected by default). Then, to initiate the synchronisation process, click on the "Synchronise" button in the sidebar and follow the instructions.
On the **terminal application**, to initiate the synchronisation process, type `:sync`. You will be asked to follow a link to authorise the application. It is possible to also synchronise outside of the user interface by typing `joplin sync` from the terminal. This can be used to setup a cron script to synchronise at regular interval. For example, this would do it every 30 minutes:
*/30 * * * * /path/to/joplin sync
## WebDAV synchronisation
Select the "WebDAV" synchronisation target and follow the same instructions as for Nextcloud above.
@@ -141,22 +169,24 @@ WebDAV-compatible services that are known to work with Joplin.
When syncing with OneDrive, Joplin creates a sub-directory in OneDrive, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.
On the **desktop application** or **mobile application**, select "OneDrive" as the synchronisation target in the config screen (it is selected by default). Then, to initiate the synchronisation process, click on the "Synchronise" button in the sidebar. You will be asked to login to OneDrive to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive).
On the **desktop application** or **mobile application**, select "OneDrive" as the synchronisation target in the config screen. Then, to initiate the synchronisation process, click on the "Synchronise" button in the sidebar and follow the instructions.
On the **terminal application**, to initiate the synchronisation process, type `:sync`. You will be asked to follow a link to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive). It is possible to also synchronise outside of the user interface by typing `joplin sync` from the terminal. This can be used to setup a cron script to synchronise at regular interval. For example, this would do it every 30 minutes:
*/30 * * * * /path/to/joplin sync
On the **terminal application**, to initiate the synchronisation process, type `:sync`. You will be asked to follow a link to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive).
# Encryption
Joplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the notes, notebooks, tags or resources can read them. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](http://joplin.cozic.net/help/e2ee) for more information about this feature and how to enable it.
Joplin supports end-to-end encryption (E2EE) on all the applications. E2EE is a system where only the owner of the notes, notebooks, tags or resources can read them. It prevents potential eavesdroppers - including telecom providers, internet providers, and even the developers of Joplin from being able to access the data. Please see the [End-To-End Encryption Tutorial](https://joplin.cozic.net/e2ee) for more information about this feature and how to enable it.
For a more technical description, mostly relevant for development or to review the method being used, please see the [Encryption specification](http://joplin.cozic.net/help/spec).
For a more technical description, mostly relevant for development or to review the method being used, please see the [Encryption specification](https://joplin.cozic.net/spec).
# Attachments / Resources
Any kind of file can be attached to a note. In Markdown, links to these files are represented as a simple ID to the resource. In the note viewer, these files, if they are images, will be displayed or, if they are other files (PDF, text files, etc.) they will be displayed as links. Clicking on this link will open the file in the default application.
Resources that are not attached to any note will be automatically deleted after a day or two.
**Important:** Resources larger than 10 MB are not currently supported on mobile. They will crash the application when synchronising so it is recommended not to attach such resources at the moment. The issue is being looked at.
# Notifications
On the desktop and mobile apps, an alarm can be associated with any to-do. It will be triggered at the given time by displaying a notification. How the notification will be displayed depends on the operating system since each has a different way to handle this. Please see below for the requirements for the desktop applications:
@@ -171,37 +201,55 @@ On mobile, the alarms will be displayed using the built-in notification system.
If for any reason the notifications do not work, please [open an issue](https://github.com/laurent22/joplin/issues).
# Sub-notebooks
Sub-notebooks allow organising multiple notebooks into a tree of notebooks. For example it can be used to regroup all the notebooks related to work, to family or to a particular project under a parent notebook.
![](https://joplin.cozic.net/images/SubNotebooks.png)
- On the **desktop application**, to create a subnotebook, drag and drop it onto another notebook. To move it back to the root, drag and drop it on the "Notebooks" header. Currently only the desktop app can be used to organise the notebooks.
- The **mobile application** supports displaying and collapsing/expanding the tree of notebooks, however it does not currently support moving the subnotebooks to different notebooks.
- The **terminal app** supports displaying the tree of subnotebooks but it does not support collapsing/expanding them or moving the subnotebooks around.
# Markdown
Joplin uses and renders [Github-flavoured Markdown](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet) with a few variations and additions. In particular:
## Links to other notes
You can create a link to a note by specifying its ID in the URL. For example:
[Link to my note](:/0b0d62d15e60409dac34f354b6e9e839)
Since getting the ID of a note is not straightforward, each app provides a way to create such link. In the **desktop app**, right click on a note an select "Copy Markdown link". In the **mobile app**, open a note and, in the top right menu, select "Copy Markdown link". You can then paste this link anywhere in another note.
## Math notation
Math expressions can be added using the [Katex notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `$EXPRESSION$`, eg. `$\sqrt{3x-1}+(1+x)^2$`. To create an expression block, wrap it as follow:
$$
EXPRESSION
$$
$$
EXPRESSION
$$
For example:
$$
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
$$
$$
f(x) = \int_{-\infty}^\infty
\hat f(\xi)\,e^{2 \pi i \xi x}
\,d\xi
$$
Here is an example with the Markdown and rendered result side by side:
<img src="https://raw.githubusercontent.com/laurent22/joplin/master/docs/images/Katex.png" style="max-width: 100%; max-height: 35em;">
<img src="https://joplin.cozic.net/images/Katex.png" style="max-width: 100%; max-height: 35em;">
## Checkboxes
Checkboxes can be added like so:
- [ ] Milk
- [ ] Rice
- [ ] Eggs
- [ ] Milk
- [ ] Rice
- [ ] Eggs
The checkboxes can then be ticked in the mobile and desktop applications.
@@ -209,7 +257,13 @@ The checkboxes can then be ticked in the mobile and desktop applications.
Donations to Joplin support the development of the project. Developing quality applications mostly takes time, but there are also some expenses, such as digital certificates to sign the applications, app store fees, hosting, etc. Most of all, your donation will make it possible to keep up the current development standard.
Please see the [donation page](http://joplin.cozic.net/donate/) for information on how to support the development of Joplin.
Please see the [donation page](https://joplin.cozic.net/donate/) for information on how to support the development of Joplin.
# Community
- For general discussion about Joplin, user support, software development questions, and to discuss new features, go to the [Joplin Forum](https://discourse.joplin.cozic.net/). It is possible to login with your GitHub account.
- For bug reports and feature requests, go to the [GitHub Issue Tracker](https://github.com/laurent22/joplin/issues).
- The latest news are often posted [on this Twitter account](https://twitter.com/laurent2233).
# Contributing
@@ -233,23 +287,26 @@ Current translations:
<!-- LOCALE-TABLE-AUTO-GENERATED -->
&nbsp; | Language | Po File | Last translator | Percent done
---|---|---|---|---
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 79%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/hr.png) | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić <trbuhom@net.hr> | 64%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/dk.png) | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | | 99%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/de.png) | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Tobias Grasse <mail@tobias-grasse.net> | 98%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/gb.png) | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/es.png) | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín <f@mrtn.es> | 99%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/fr.png) | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/it.png) | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 66%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/be.png) | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 79%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos <rnbastos@gmail.com> | 97%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/ru.png) | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov <artyom.karlov@gmail.com> | 99%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | RCJacH <RCJacH@outlook.com> | 66%
![](https://raw.githubusercontent.com/stevenrskelton/flag-icon/master/png/16/country-4x3/jp.png) | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | | 64%
![](https://joplin.cozic.net/images/flags/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 75%
![](https://joplin.cozic.net/images/flags/country-4x3/hr.png) | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić <trbuhom@net.hr> | 61%
![](https://joplin.cozic.net/images/flags/country-4x3/cz.png) | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt <lukas@aiya.cz> | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/dk.png) | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér <mjjzf@syntaktisk. | 97%
![](https://joplin.cozic.net/images/flags/country-4x3/de.png) | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Philipp Zumstein <zuphilip@gmail.com> | 98%
![](https://joplin.cozic.net/images/flags/country-4x3/gb.png) | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
![](https://joplin.cozic.net/images/flags/country-4x3/es.png) | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín <f@mrtn.es> | 99%
![](https://joplin.cozic.net/images/flags/country-4x3/fr.png) | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 98%
![](https://joplin.cozic.net/images/flags/country-4x3/es.png) | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans <marcoslansgarza@gmail.com> | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/it.png) | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 63%
![](https://joplin.cozic.net/images/flags/country-4x3/be.png) | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 76%
![](https://joplin.cozic.net/images/flags/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos <rnbastos@gmail.com> | 97%
![](https://joplin.cozic.net/images/flags/country-4x3/ru.png) | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov <artyom.karlov@gmail.com> | 94%
![](https://joplin.cozic.net/images/flags/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 91%
![](https://joplin.cozic.net/images/flags/country-4x3/jp.png) | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | | 61%
<!-- LOCALE-TABLE-AUTO-GENERATED -->
# Known bugs
- Resources larger than 10 MB are not currently supported on mobile. They will crash the application so it is recommended not to attach such resources at the moment. The issue is being looked at.
- Non-alphabetical characters such as Chinese or Arabic might create glitches in the terminal on Windows. This is a limitation of the current Windows console.
- It is only possible to upload files of up to 4MB to OneDrive due to a limitation of [the API](https://docs.microsoft.com/en-gb/onedrive/developer/rest-api/api/driveitem_put_content) being currently used. There is currently no plan to support OneDrive "large file" API.

View File

@@ -90,8 +90,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion 16
targetSdkVersion 22
versionCode 2097290
versionName "1.0.112"
versionCode 2097300
versionName "1.0.122"
ndk {
abiFilters "armeabi-v7a", "x86"
}

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0.13</string>
<string>10.0.20</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>13</string>
<string>20</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
@@ -67,6 +67,13 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>

View File

@@ -19,6 +19,7 @@ const BaseSyncTarget = require('lib/BaseSyncTarget.js');
const { fileExtension } = require('lib/path-utils.js');
const { shim } = require('lib/shim.js');
const { _, setLocale, defaultLocale, closestSupportedLocale } = require('lib/locale.js');
const reduxSharedMiddleware = require('lib/components/shared/reduxSharedMiddleware');
const os = require('os');
const fs = require('fs-extra');
const JoplinError = require('lib/JoplinError');
@@ -29,6 +30,7 @@ const SyncTargetOneDrive = require('lib/SyncTargetOneDrive.js');
const SyncTargetOneDriveDev = require('lib/SyncTargetOneDriveDev.js');
const SyncTargetNextcloud = require('lib/SyncTargetNextcloud.js');
const SyncTargetWebDAV = require('lib/SyncTargetWebDAV.js');
const SyncTargetDropbox = require('lib/SyncTargetDropbox.js');
const EncryptionService = require('lib/services/EncryptionService');
const DecryptionWorker = require('lib/services/DecryptionWorker');
const BaseService = require('lib/services/BaseService');
@@ -38,6 +40,7 @@ SyncTargetRegistry.addClass(SyncTargetOneDrive);
SyncTargetRegistry.addClass(SyncTargetOneDriveDev);
SyncTargetRegistry.addClass(SyncTargetNextcloud);
SyncTargetRegistry.addClass(SyncTargetWebDAV);
SyncTargetRegistry.addClass(SyncTargetDropbox);
class BaseApplication {
@@ -141,6 +144,14 @@ class BaseApplication {
continue;
}
if (arg.indexOf('-psn') === 0) {
// Some weird flag passed by macOS - can be ignored.
// https://github.com/laurent22/joplin/issues/480
// https://stackoverflow.com/questions/10242115
argv.splice(0, 1);
continue;
}
if (arg.length && arg[0] == '-') {
throw new JoplinError(_('Unknown flag: %s', arg), 'flagError');
} else {
@@ -260,6 +271,8 @@ class BaseApplication {
const newState = store.getState();
let refreshNotes = false;
reduxSharedMiddleware(store, next, action);
if (action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) {
Setting.setValue('activeFolderId', newState.selectedFolderId);
this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null;
@@ -366,11 +379,11 @@ class BaseApplication {
let initArgs = startFlags.matched;
if (argv.length) this.showPromptString_ = false;
if (process.argv[1].indexOf('joplindev') >= 0) {
if (!initArgs.profileDir) initArgs.profileDir = '/mnt/d/Temp/TestNotes2';
initArgs.logLevel = Logger.LEVEL_DEBUG;
initArgs.env = 'dev';
}
// if (process.argv[1].indexOf('joplindev') >= 0) {
// if (!initArgs.profileDir) initArgs.profileDir = '/mnt/d/Temp/TestNotes2';
// initArgs.logLevel = Logger.LEVEL_DEBUG;
// initArgs.env = 'dev';
// }
let appName = initArgs.env == 'dev' ? 'joplindev' : 'joplin';
if (Setting.value('appId').indexOf('-desktop') >= 0) appName += '-desktop';
@@ -421,8 +434,14 @@ class BaseApplication {
if (Setting.value('firstStart')) {
const locale = shim.detectAndSetLocale(Setting);
reg.logger().info('First start: detected locale as ' + locale);
if (Setting.value('env') === 'dev') Setting.setValue('sync.target', SyncTargetRegistry.nameToId('onedrive_dev'));
Setting.setValue('firstStart', 0)
if (Setting.value('env') === 'dev') {
Setting.setValue('showTrayIcon', 0);
Setting.setValue('autoUpdateEnabled', 0);
Setting.setValue('sync.interval', 3600);
}
Setting.setValue('firstStart', 0);
} else {
setLocale(Setting.value('locale'));
}

View File

@@ -44,6 +44,15 @@ class BaseModel {
return null;
}
// Prefer the use of this function to compare IDs as it handles the case where
// one ID is null and the other is "", in which case they are actually considered to be the same.
static idsEqual(id1, id2) {
if (!id1 && !id2) return true;
if (!id1 && !!id2) return false;
if (!!id1 && !id2) return false;
return id1 === id2;
}
static modelTypeToName(type) {
for (let i = 0; i < BaseModel.typeEnum_.length; i++) {
const e = BaseModel.typeEnum_[i];

View File

@@ -30,7 +30,7 @@ class BaseSyncTarget {
return this.db_;
}
isAuthenticated() {
async isAuthenticated() {
return false;
}
@@ -66,6 +66,10 @@ class BaseSyncTarget {
return this.fileApi_;
}
fileApiSync() {
return this.fileApi_;
}
// Usually each sync target should create and setup its own file API via initFileApi()
// but for testing purposes it might be convenient to provide it here so that multiple
// clients can share and sync to the same file api (see test-utils.js)
@@ -109,7 +113,7 @@ class BaseSyncTarget {
async syncStarted() {
if (!this.synchronizer_) return false;
if (!this.isAuthenticated()) return false;
if (!await this.isAuthenticated()) return false;
const sync = await this.synchronizer();
return sync.state() != 'idle';
}

View File

@@ -0,0 +1,214 @@
const { Logger } = require('lib/logger.js');
const { shim } = require('lib/shim.js');
const JoplinError = require('lib/JoplinError');
const URL = require('url-parse');
const { time } = require('lib/time-utils');
const EventDispatcher = require('lib/EventDispatcher');
class DropboxApi {
constructor(options) {
this.logger_ = new Logger();
this.options_ = options;
this.authToken_ = null;
this.dispatcher_ = new EventDispatcher();
}
clientId() {
return this.options_.id;
}
clientSecret() {
return this.options_.secret;
}
setLogger(l) {
this.logger_ = l;
}
logger() {
return this.logger_;
}
authToken() {
return this.authToken_; // Without the "Bearer " prefix
}
on(eventName, callback) {
return this.dispatcher_.on(eventName, callback);
}
setAuthToken(v) {
this.authToken_ = v;
this.dispatcher_.dispatch('authRefreshed', this.authToken());
}
loginUrl() {
return 'https://www.dropbox.com/oauth2/authorize?response_type=code&client_id=' + this.clientId();
}
baseUrl(endPointFormat) {
if (['content', 'api'].indexOf(endPointFormat) < 0) throw new Error('Invalid end point format: ' + endPointFormat);
return 'https://' + endPointFormat + '.dropboxapi.com/2';
}
requestToCurl_(url, options) {
let output = [];
output.push('curl');
if (options.method) output.push('-X ' + options.method);
if (options.headers) {
for (let n in options.headers) {
if (!options.headers.hasOwnProperty(n)) continue;
output.push('-H ' + "'" + n + ': ' + options.headers[n] + "'");
}
}
if (options.body) output.push('--data ' + '"' + options.body + '"');
output.push(url);
return output.join(' ');
}
async execAuthToken(authCode) {
const postData = {
code: authCode,
grant_type: 'authorization_code',
client_id: this.clientId(),
client_secret: this.clientSecret(),
};
var formBody = [];
for (var property in postData) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(postData[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
const response = await shim.fetch('https://api.dropboxapi.com/oauth2/token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
body: formBody
});
const responseText = await response.text();
if (!response.ok) throw new Error(responseText);
return JSON.parse(responseText);
}
isTokenError(status, responseText) {
if (status === 401) return true;
if (responseText.indexOf('OAuth 2 access token is malformed') >= 0) return true;
return false;
}
async exec(method, path = '', body = null, headers = null, options = null) {
if (headers === null) headers = {};
if (options === null) options = {};
if (!options.target) options.target = 'string';
const authToken = this.authToken();
if (authToken) headers['Authorization'] = 'Bearer ' + authToken;
const endPointFormat = ['files/upload', 'files/download'].indexOf(path) >= 0 ? 'content' : 'api';
if (endPointFormat === 'api') {
headers['Content-Type'] = 'application/json';
if (body && typeof body === 'object') body = JSON.stringify(body);
} else {
headers['Content-Type'] = 'application/octet-stream';
}
const fetchOptions = {};
fetchOptions.headers = headers;
fetchOptions.method = method;
if (options.path) fetchOptions.path = options.path;
if (body) fetchOptions.body = body;
const url = path.indexOf('https://') === 0 ? path : this.baseUrl(endPointFormat) + '/' + path;
let tryCount = 0;
while (true) {
try {
let response = null;
// console.info(this.requestToCurl_(url, fetchOptions));
// console.info(method + ' ' + url);
if (options.source == 'file' && (method == 'POST' || method == 'PUT')) {
response = await shim.uploadBlob(url, fetchOptions);
} else if (options.target == 'string') {
response = await shim.fetch(url, fetchOptions);
} else { // file
response = await shim.fetchBlob(url, fetchOptions);
}
const responseText = await response.text();
// console.info('Response: ' + responseText);
let responseJson_ = null;
const loadResponseJson = () => {
if (!responseText) return null;
if (responseJson_) return responseJson_;
try {
responseJson_ = JSON.parse(responseText);
} catch (error) {
return { error: responseText };
}
return responseJson_;
}
// Creates an error object with as much data as possible as it will appear in the log, which will make debugging easier
const newError = (message) => {
const json = loadResponseJson();
let code = '';
if (json && json.error_summary) {
code = json.error_summary;
}
// Gives a shorter response for error messages. Useful for cases where a full HTML page is accidentally loaded instead of
// JSON. That way the error message will still show there's a problem but without filling up the log or screen.
const shortResponseText = (responseText + '').substr(0, 1024);
const error = new JoplinError(method + ' ' + path + ': ' + message + ' (' + response.status + '): ' + shortResponseText, code);
error.httpStatus = response.status;
return error;
}
if (!response.ok) {
const json = loadResponseJson();
if (this.isTokenError(response.status, responseText)) {
this.setAuthToken(null);
}
// When using fetchBlob we only get a string (not xml or json) back
if (options.target === 'file') throw newError('fetchBlob error');
throw newError('Error');
}
if (options.responseFormat === 'text') return responseText;
return loadResponseJson();
} catch (error) {
tryCount++;
if (error.code.indexOf('too_many_write_operations') >= 0) {
this.logger().warn('too_many_write_operations ' + tryCount);
if (tryCount >= 3) {
throw error;
}
await time.sleep(tryCount * 2);
} else {
throw error;
}
}
}
}
}
module.exports = DropboxApi;

View File

@@ -32,4 +32,4 @@ class EventDispatcher {
}
module.exports = { EventDispatcher };
module.exports = EventDispatcher;

View File

@@ -14,7 +14,6 @@ class MdToHtml {
constructor(options = null) {
if (!options) options = {};
this.supportsResourceLinks_ = !!options.supportsResourceLinks;
this.loadedResources_ = {};
this.cachedContent_ = null;
this.cachedContentKey_ = null;
@@ -132,35 +131,27 @@ class MdToHtml {
const isResourceUrl = Resource.isResourceUrl(href);
const title = isResourceUrl ? this.getAttr_(attrs, 'title') : href;
if (isResourceUrl && !this.supportsResourceLinks_) {
// In mobile, links to local resources, such as PDF, etc. currently aren't supported.
// Ideally they should be opened in the user's browser.
return '<span style="opacity: 0.5">(Resource not yet supported: '; //+ htmlentities(text) + ']';
let resourceIdAttr = "";
let icon = "";
let hrefAttr = '#';
if (isResourceUrl) {
const resourceId = Resource.pathToId(href);
href = "joplin://" + resourceId;
resourceIdAttr = "data-resource-id='" + resourceId + "'";
icon = '<span class="resource-icon"></span>';
} else {
let resourceIdAttr = "";
let icon = "";
if (isResourceUrl) {
const resourceId = Resource.pathToId(href);
href = "joplin://" + resourceId;
resourceIdAttr = "data-resource-id='" + resourceId + "'";
icon = '<span class="resource-icon"></span>';
}
const js = options.postMessageSyntax + "(" + JSON.stringify(href) + "); return false;";
let output = "<a " + resourceIdAttr + " title='" + htmlentities(title) + "' href='#' onclick='" + js + "'>" + icon;
return output;
// If the link is a plain URL (as opposed to a resource link), set the href to the actual
// link. This allows the link to be exported too when exporting to PDF.
hrefAttr = href;
}
const js = options.postMessageSyntax + "(" + JSON.stringify(href) + "); return false;";
let output = "<a " + resourceIdAttr + " title='" + htmlentities(title) + "' href='" + hrefAttr + "' onclick='" + js + "'>" + icon;
return output;
}
renderCloseLink_(attrs, options) {
const href = this.getAttr_(attrs, 'href');
const isResourceUrl = Resource.isResourceUrl(href);
if (isResourceUrl && !this.supportsResourceLinks_) {
return ')</span>';
} else {
return '</a>';
}
return '</a>';
}
rendererPlugin_(language) {
@@ -220,12 +211,7 @@ class MdToHtml {
if (isCodeBlock) rendererPlugin = this.rendererPlugin_(codeBlockLanguage);
if (previousToken && previousToken.tag === 'li' && tag === 'p') {
// Markdown-it render list items as <li><p>Text<p></li> which makes it
// complicated to style and layout the HTML, so we remove this extra
// <p> here and below in closeTag.
openTag = null;
} else if (isInlineCode) {
if (isInlineCode) {
openTag = null;
} else if (tag && t.type.indexOf('html_inline') >= 0) {
openTag = null;
@@ -334,8 +320,12 @@ class MdToHtml {
if (closeTag) {
if (closeTag === 'a') {
const currentAnchorAttrs = anchorAttrs.pop();
const previousContent = output.length ? output[output.length - 1].trim() : '';
const anchorHref = this.getAttr_(currentAnchorAttrs, 'href', '').trim();
// NOTE: Disabled for now due to this:
// https://github.com/laurent22/joplin/issues/318#issuecomment-375854848
// const previousContent = output.length ? output[output.length - 1].trim() : '';
// const anchorHref = this.getAttr_(currentAnchorAttrs, 'href', '').trim();
// Optimisation: If the content of the anchor is the same as the URL, we replace the content
// by (Link). This is to shorten the text, which is important especially when the note comes
@@ -349,10 +339,11 @@ class MdToHtml {
// worse that this in notes that come from web-clipped content.
// With this change, the links will still be preserved but displayed like
// (link) (link) (link) (link) (link)
if (this.urldecode_(previousContent) === htmlentities(this.urldecode_(anchorHref))) {
output.pop();
output.push(_('(Link)'));
}
// if (this.urldecode_(previousContent) === htmlentities(this.urldecode_(anchorHref))) {
// output.pop();
// output.push(_('(Link)'));
// }
output.push(this.renderCloseLink_(currentAnchorAttrs, options));
} else {
@@ -415,8 +406,8 @@ class MdToHtml {
if (HORRIBLE_HACK) {
let counter = -1;
while (body.indexOf('- [ ]') >= 0 || body.indexOf('- [X]') >= 0) {
body = body.replace(/- \[(X| )\]/, function(v, p1) {
while (body.indexOf('- [ ]') >= 0 || body.indexOf('- [X]') >= 0 || body.indexOf('- [x]') >= 0) {
body = body.replace(/- \[(X| |x)\]/, function(v, p1) {
let s = p1 == ' ' ? 'NOTICK' : 'TICK';
counter++;
return '- mJOPmCHECKBOXm' + s + 'm' + counter + 'm';
@@ -485,6 +476,9 @@ class MdToHtml {
ul {
padding-left: 1.3em;
}
li p {
margin-bottom: 0;
}
.resource-icon {
display: inline-block;
position: relative;
@@ -572,10 +566,10 @@ class MdToHtml {
toggleTickAt(body, index) {
let counter = -1;
while (body.indexOf('- [ ]') >= 0 || body.indexOf('- [X]') >= 0) {
while (body.indexOf('- [ ]') >= 0 || body.indexOf('- [X]') >= 0 || body.indexOf('- [x]') >= 0) {
counter++;
body = body.replace(/- \[(X| )\]/, function(v, p1) {
body = body.replace(/- \[(X| |x)\]/, function(v, p1) {
let s = p1 == ' ' ? 'NOTICK' : 'TICK';
if (index == counter) {
s = s == 'NOTICK' ? 'TICK' : 'NOTICK';

View File

@@ -11,7 +11,9 @@ class MdToHtml_Katex {
processContent(renderedTokens, content, tagType) {
try {
let renderered = katex.renderToString(content);
let renderered = katex.renderToString(content, {
displayMode: tagType === 'block',
});
if (tagType === 'block') renderered = '<p>' + renderered + '</p>';

View File

@@ -0,0 +1,73 @@
const BaseSyncTarget = require('lib/BaseSyncTarget.js');
const { _ } = require('lib/locale.js');
const DropboxApi = require('lib/DropboxApi');
const Setting = require('lib/models/Setting.js');
const { parameters } = require('lib/parameters.js');
const { FileApi } = require('lib/file-api.js');
const { Synchronizer } = require('lib/synchronizer.js');
const { FileApiDriverDropbox } = require('lib/file-api-driver-dropbox.js');
class SyncTargetDropbox extends BaseSyncTarget {
static id() {
return 7;
}
constructor(db, options = null) {
super(db, options);
this.api_ = null;
}
static targetName() {
return 'dropbox';
}
static label() {
return _('Dropbox');
}
authRouteName() {
return 'DropboxLogin';
}
async isAuthenticated() {
const f = await this.fileApi();
return !!f.driver().api().authToken();
}
async api() {
const fileApi = await this.fileApi();
return fileApi.driver().api();
}
async initFileApi() {
const params = parameters().dropbox;
const api = new DropboxApi({
id: params.id,
secret: params.secret,
});
api.on('authRefreshed', (auth) => {
this.logger().info('Saving updated OneDrive auth.');
Setting.setValue('sync.' + SyncTargetDropbox.id() + '.auth', auth ? auth : null);
});
const authToken = Setting.value('sync.' + SyncTargetDropbox.id() + '.auth');
api.setAuthToken(authToken);
const appDir = '';
const fileApi = new FileApi(appDir, new FileApiDriverDropbox(api));
fileApi.setSyncTargetId(SyncTargetDropbox.id());
fileApi.setLogger(this.logger());
return fileApi;
}
async initSynchronizer() {
if (!(await this.isAuthenticated())) throw new Error('User is not authentified');
return new Synchronizer(this.db(), await this.fileApi(), Setting.value('appType'));
}
}
module.exports = SyncTargetDropbox;

View File

@@ -19,7 +19,7 @@ class SyncTargetFilesystem extends BaseSyncTarget {
return _('File system');
}
isAuthenticated() {
async isAuthenticated() {
return true;
}

View File

@@ -19,7 +19,7 @@ class SyncTargetMemory extends BaseSyncTarget {
return 'Memory';
}
isAuthenticated() {
async isAuthenticated() {
return true;
}

View File

@@ -28,7 +28,7 @@ class SyncTargetNextcloud extends BaseSyncTarget {
return _('Nextcloud');
}
isAuthenticated() {
async isAuthenticated() {
return true;
}

View File

@@ -26,7 +26,7 @@ class SyncTargetOneDrive extends BaseSyncTarget {
return _('OneDrive');
}
isAuthenticated() {
async isAuthenticated() {
return this.api().auth();
}
@@ -80,7 +80,7 @@ class SyncTargetOneDrive extends BaseSyncTarget {
}
async initSynchronizer() {
if (!this.isAuthenticated()) throw new Error('User is not authentified');
if (!await this.isAuthenticated()) throw new Error('User is not authentified');
return new Synchronizer(this.db(), await this.fileApi(), Setting.value('appType'));
}

View File

@@ -24,7 +24,7 @@ class SyncTargetWebDAV extends BaseSyncTarget {
return _('WebDAV');
}
isAuthenticated() {
async isAuthenticated() {
return true;
}

View File

@@ -10,7 +10,7 @@ class Dropdown extends React.Component {
this.headerRef_ = null;
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({
headerSize: { x: 0, y: 0, width: 0, height: 0 },
listVisible: false,

View File

@@ -34,7 +34,7 @@ class ItemList extends React.Component {
});
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({
topItemIndex: 0,
bottomItemIndex: 0,
@@ -45,7 +45,7 @@ class ItemList extends React.Component {
this.updateStateItemIndexes();
}
componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.itemHeight) {
this.setState({
itemHeight: newProps.itemHeight,

View File

@@ -35,16 +35,17 @@ class ModalDialog extends React.Component {
modalContentWrapper2: {
flex:1,
},
title: {
title: Object.assign({}, theme.normalText, {
borderBottomWidth: 1,
borderBottomColor: theme.dividerColor,
paddingBottom: 10,
fontWeight: 'bold',
},
}),
buttonRow: {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: theme.dividerColor,
paddingTop: 10,
},
};

View File

@@ -26,7 +26,7 @@ class ActionButtonComponent extends React.Component {
};
}
componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
if ('buttonIndex' in newProps) {
this.setState({ buttonIndex: newProps.buttonIndex });
}

View File

@@ -16,7 +16,7 @@ class AppNavComponent extends Component {
}
}
componentWillMount() {
UNSAFE_componentWillMount() {
if (Platform.OS === 'ios') {
this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this.keyboardDidShow.bind(this));
this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this.keyboardDidHide.bind(this));

View File

@@ -19,11 +19,11 @@ class Checkbox extends Component {
}
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({ checked: this.props.checked });
}
componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
if ('checked' in newProps) {
this.setState({ checked: newProps.checked });
}

View File

@@ -1,4 +1,5 @@
const Setting = require('lib/models/Setting.js');
const { Platform } = require('react-native');
const globalStyle = {
fontSize: 16,
@@ -14,6 +15,8 @@ const globalStyle = {
dividerColor: "#dddddd",
selectedColor: '#e5e5e5',
disabledOpacity: 0.2,
colorUrl: '#000CFF',
textSelectionColor: "#0096FF",
raisedBackgroundColor: "#0080EF",
raisedColor: "#003363",
@@ -36,36 +39,83 @@ globalStyle.marginTop = globalStyle.margin;
globalStyle.marginBottom = globalStyle.margin;
globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em';
globalStyle.icon = {
color: globalStyle.color,
fontSize: 30,
};
// globalStyle.icon = {
// color: globalStyle.color,
// fontSize: 30,
// };
globalStyle.lineInput = {
color: globalStyle.color,
backgroundColor: globalStyle.backgroundColor,
};
// globalStyle.lineInput = {
// color: globalStyle.color,
// backgroundColor: globalStyle.backgroundColor,
// };
globalStyle.buttonRow = {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: globalStyle.dividerColor,
paddingTop: 10,
};
// globalStyle.buttonRow = {
// flexDirection: 'row',
// borderTopWidth: 1,
// borderTopColor: globalStyle.dividerColor,
// paddingTop: 10,
// };
// globalStyle.normalText = {
// color: globalStyle.color,
// fontSize: globalStyle.fontSize,
// };
let themeCache_ = {};
function addExtraStyles(style) {
style.icon = {
color: style.color,
fontSize: 30,
};
style.lineInput = {
color: style.color,
backgroundColor: style.backgroundColor,
};
if (Platform.OS === 'ios') {
style.lineInput.borderBottomWidth = 1;
style.lineInput.borderBottomColor = style.dividerColor;
}
style.buttonRow = {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: style.dividerColor,
paddingTop: 10,
};
style.normalText = {
color: style.color,
fontSize: style.fontSize,
};
style.urlText = {
color: style.colorUrl,
fontSize: style.fontSize,
};
return style;
}
function themeStyle(theme) {
if (!theme) {
console.warn('Theme not set!! Defaulting to Light theme');
theme = Setting.THEME_LIGHT;
}
if (themeCache_[theme]) return themeCache_[theme];
let output = Object.assign({}, globalStyle);
if (theme == Setting.THEME_LIGHT) return output;
if (theme == Setting.THEME_LIGHT) return addExtraStyles(output);
output.backgroundColor = '#1D2024';
output.color = '#dddddd';
output.colorFaded = '#777777';
output.dividerColor = '#555555';
output.selectedColor = '#333333';
output.textSelectionColor = '#00AEFF';
output.raisedBackgroundColor = "#0F2051";
output.raisedColor = "#788BC3";
@@ -76,7 +126,7 @@ function themeStyle(theme) {
output.htmlLinkColor = 'rgb(166,166,255)';
themeCache_[theme] = output;
return themeCache_[theme];
return addExtraStyles(themeCache_[theme]);
}
module.exports = { globalStyle, themeStyle };

View File

@@ -1,5 +1,5 @@
const React = require('react'); const Component = React.Component;
const { Platform, WebView, View, Linking } = require('react-native');
const { Platform, WebView, View } = require('react-native');
const { globalStyle } = require('lib/components/global-style.js');
const Resource = require('lib/models/Resource.js');
const Setting = require('lib/models/Setting.js');
@@ -18,8 +18,8 @@ class NoteBodyViewer extends Component {
this.isMounted_ = false;
}
componentWillMount() {
this.mdToHtml_ = new MdToHtml({ supportsResourceLinks: false });
UNSAFE_componentWillMount() {
this.mdToHtml_ = new MdToHtml();
this.isMounted_ = true;
}
@@ -115,7 +115,7 @@ class NoteBodyViewer extends Component {
//msg = msg.split(':');
//this.bodyScrollTop_ = Number(msg[1]);
} else {
Linking.openURL(msg);
this.props.onJoplinLinkClick(msg);
}
}}
/>

View File

@@ -68,12 +68,12 @@ class NoteListComponent extends Component {
return output;
}
componentWillMount() {
UNSAFE_componentWillMount() {
const newDataSource = this.state.dataSource.cloneWithRows(this.filterNotes(this.props.items));
this.setState({ dataSource: newDataSource });
}
componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
// https://stackoverflow.com/questions/38186114/react-native-redux-and-listview
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.filterNotes(newProps.items)),

View File

@@ -99,7 +99,8 @@ class ScreenHeaderComponent extends Component {
height: 18,
},
contextMenuTrigger: {
fontSize: 25,
fontSize: 30,
paddingLeft: 10,
paddingRight: theme.marginRight,
color: theme.raisedColor,
fontWeight: 'bold',
@@ -445,7 +446,7 @@ class ScreenHeaderComponent extends Component {
const menuComp = !showContextMenuButton ? null : (
<Menu onSelect={(value) => this.menu_select(value)} style={this.styles().contextMenu}>
<MenuTrigger style={{ paddingTop: PADDING_V, paddingBottom: PADDING_V }}>
<Text style={this.styles().contextMenuTrigger}> &#8942;</Text>
<Icon name='md-more' style={this.styles().contextMenuTrigger} />
</MenuTrigger>
<MenuOptions>
<ScrollView style={{ maxHeight: windowHeight }}>

View File

@@ -65,7 +65,7 @@ class NoteTagsDialogComponent extends React.Component {
return (
<TouchableOpacity key={tag.id} onPress={() => this.tag_press(tag.id)} style={this.styles().tag}>
<View style={this.styles().tagIconText}>
<Icon name={iconName} style={this.styles().tagCheckbox}/><Text>{tag.title}</Text>
<Icon name={iconName} style={this.styles().tagCheckbox}/><Text style={this.styles().tagText}>{tag.title}</Text>
</View>
</TouchableOpacity>
);
@@ -96,7 +96,7 @@ class NoteTagsDialogComponent extends React.Component {
}
}
componentWillMount() {
UNSAFE_componentWillMount() {
const noteId = this.props.noteId;
this.setState({ noteId: noteId });
this.loadNoteTags(noteId);
@@ -114,7 +114,6 @@ class NoteTagsDialogComponent extends React.Component {
tagListData.sort((a, b) => {
return naturalCompare.caseInsensitive(a.title, b.title);
//return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : +1;
});
this.setState({ tagListData: tagListData });
@@ -137,9 +136,11 @@ class NoteTagsDialogComponent extends React.Component {
flexDirection: 'row',
alignItems: 'center',
},
tagText: Object.assign({}, theme.normalText),
tagCheckbox: {
marginRight: 5,
marginRight: 8,
fontSize: 20,
color: theme.color,
},
newTagBox: {
flexDirection:'row',
@@ -149,6 +150,8 @@ class NoteTagsDialogComponent extends React.Component {
borderBottomWidth: 1,
borderBottomColor: theme.dividerColor
},
newTagBoxLabel: Object.assign({}, theme.normalText, { marginRight: 8 }),
newTagBoxInput: Object.assign({}, theme.lineInput, { flex: 1 }),
};
this.styles_[themeId] = StyleSheet.create(styles);
@@ -161,7 +164,7 @@ class NoteTagsDialogComponent extends React.Component {
const dialogContent = (
<View style={{flex:1}}>
<View style={this.styles().newTagBox}>
<Text>{_('New tags:')}</Text><TextInput value={this.state.newTags} onChangeText={value => { this.setState({ newTags: value }) }} style={{flex:1}}/>
<Text style={this.styles().newTagBoxLabel}>{_('New tags:')}</Text><TextInput selectionColor={theme.textSelectionColor} value={this.state.newTags} onChangeText={value => { this.setState({ newTags: value }) }} style={this.styles().newTagBoxInput}/>
</View>
<FlatList
data={this.state.tagListData}

View File

@@ -31,7 +31,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
};
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({ settings: this.props.settings });
}
@@ -165,7 +165,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
return (
<View key={key} style={this.styles().settingContainer}>
<Text key="label" style={this.styles().settingText}>{md.label()}</Text>
<TextInput autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
<TextInput selectionColor={theme.textSelectionColor} autoCapitalize="none" key="control" style={this.styles().settingControl} value={value} onChangeText={(value) => updateSettingValue(key, value)} secureTextEntry={!!md.secure} />
</View>
);
} else {
@@ -203,7 +203,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
settingComps.push(
<View key="donate_link" style={this.styles().settingContainer}>
<TouchableOpacity onPress={() => { Linking.openURL('http://joplin.cozic.net/donate/') }}>
<TouchableOpacity onPress={() => { Linking.openURL('https://joplin.cozic.net/donate/') }}>
<Text key="label" style={this.styles().linkText}>{_('Make a donation')}</Text>
</TouchableOpacity>
</View>
@@ -211,7 +211,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
settingComps.push(
<View key="website_link" style={this.styles().settingContainer}>
<TouchableOpacity onPress={() => { Linking.openURL('http://joplin.cozic.net/') }}>
<TouchableOpacity onPress={() => { Linking.openURL('https://joplin.cozic.net/') }}>
<Text key="label" style={this.styles().linkText}>{_('Joplin website')}</Text>
</TouchableOpacity>
</View>
@@ -219,7 +219,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
settingComps.push(
<View key="privacy_link" style={this.styles().settingContainer}>
<TouchableOpacity onPress={() => { Linking.openURL('http://joplin.cozic.net/privacy/') }}>
<TouchableOpacity onPress={() => { Linking.openURL('https://joplin.cozic.net/privacy/') }}>
<Text key="label" style={this.styles().linkText}>Privacy Policy</Text>
</TouchableOpacity>
</View>

View File

@@ -0,0 +1,83 @@
const React = require('react'); const Component = React.Component;
const { View, Button, Text, TextInput, TouchableOpacity, StyleSheet } = require('react-native');
const { connect } = require('react-redux');
const { ScreenHeader } = require('lib/components/screen-header.js');
const { _ } = require('lib/locale.js');
const { BaseScreenComponent } = require('lib/components/base-screen.js');
const DialogBox = require('react-native-dialogbox').default;
const { dialogs } = require('lib/dialogs.js');
const Shared = require('lib/components/shared/dropbox-login-shared');
const { themeStyle } = require('lib/components/global-style.js');
class DropboxLoginScreenComponent extends BaseScreenComponent {
constructor() {
super();
this.styles_ = {};
this.shared_ = new Shared(
this,
(msg) => dialogs.info(this, msg),
(msg) => dialogs.error(this, msg)
);
}
UNSAFE_componentWillMount() {
this.shared_.refreshUrl();
}
styles() {
const themeId = this.props.theme;
const theme = themeStyle(themeId);
if (this.styles_[themeId]) return this.styles_[themeId];
this.styles_ = {};
let styles = {
container: {
padding: theme.margin,
},
stepText: Object.assign({}, theme.normalText, { marginBottom: theme.margin }),
urlText: Object.assign({}, theme.urlText, { marginBottom: theme.margin }),
}
this.styles_[themeId] = StyleSheet.create(styles);
return this.styles_[themeId];
}
render() {
const theme = themeStyle(this.props.theme);
return (
<View style={this.styles().screen}>
<ScreenHeader title={_('Login with Dropbox')}/>
<View style={this.styles().container}>
<Text style={this.styles().stepText}>{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}</Text>
<Text style={this.styles().stepText}>{_('Step 1: Open this URL in your browser to authorise the application:')}</Text>
<View>
<TouchableOpacity onPress={this.shared_.loginUrl_click}>
<Text style={this.styles().urlText}>{this.state.loginUrl}</Text>
</TouchableOpacity>
</View>
<Text style={this.styles().stepText}>{_('Step 2: Enter the code provided by Dropbox:')}</Text>
<TextInput selectionColor={theme.textSelectionColor} value={this.state.authCode} onChangeText={this.shared_.authCodeInput_change} style={theme.lineInput}/>
<Button disabled={this.state.checkingAuthToken} title={_("Submit")} onPress={this.shared_.submit_click}></Button>
</View>
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
</View>
);
}
}
const DropboxLoginScreen = connect((state) => {
return {
theme: state.settings.theme,
};
})(DropboxLoginScreenComponent)
module.exports = { DropboxLoginScreen };

View File

@@ -48,11 +48,11 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
return shared.refreshStats(this);
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.initState(this.props);
}
componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
this.initState(nextProps);
}
@@ -122,7 +122,7 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
<Text style={this.styles().normalText}>{_('Created: %s', time.formatMsToLocal(mk.created_time))}</Text>
<View style={{flexDirection: 'row', alignItems: 'center'}}>
<Text style={{flex:0, fontSize: theme.fontSize, marginRight: 10, color: theme.color}}>{_('Password:')}</Text>
<TextInput secureTextEntry={true} value={password} onChangeText={(text) => onPasswordChange(text)} style={inputStyle}></TextInput>
<TextInput selectionColor={theme.textSelectionColor} secureTextEntry={true} value={password} onChangeText={(text) => onPasswordChange(text)} style={inputStyle}></TextInput>
<Text style={{fontSize: theme.fontSize, marginRight: 10, color: theme.color}}>{passwordOk}</Text>
<Button title={_('Save')} onPress={() => onSaveClick()}></Button>
</View>
@@ -147,7 +147,7 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
return (
<View style={{flex:1, borderColor: theme.dividerColor, borderWidth: 1, padding: 10, marginTop: 10, marginBottom: 10}}>
<Text style={{fontSize: theme.fontSize, color: theme.color}}>{_('Enabling encryption means *all* your notes and attachments are going to be re-synchronised and sent encrypted to the sync target. Do not lose the password as, for security purposes, this will be the *only* way to decrypt the data! To enable encryption, please enter your password below.')}</Text>
<TextInput style={{margin: 10, color: theme.color, borderWidth: 1, borderColor: theme.dividerColor }} secureTextEntry={true} value={this.state.passwordPromptAnswer} onChangeText={(text) => { this.setState({ passwordPromptAnswer: text }) }}></TextInput>
<TextInput selectionColor={theme.textSelectionColor} style={{margin: 10, color: theme.color, borderWidth: 1, borderColor: theme.dividerColor }} secureTextEntry={true} value={this.state.passwordPromptAnswer} onChangeText={(text) => { this.setState({ passwordPromptAnswer: text }) }}></TextInput>
<View style={{flexDirection: 'row'}}>
<View style={{flex:1 , marginRight:10}} >
<Button title={_('Enable')} onPress={() => { onEnableClick() }}></Button>
@@ -222,12 +222,10 @@ class EncryptionConfigScreenComponent extends BaseScreenComponent {
<ScreenHeader title={_('Encryption Config')}/>
<ScrollView style={this.styles().container}>
{/*<View style={{backgroundColor: theme.warningBackgroundColor, padding: 5}}>
<Text>Important: This is a *beta* feature. It has been extensively tested and is already in use by some users, but it is possible that some bugs remain.</Text>
<Text>If you wish to you use it, it is recommended that you keep a backup of your data. The simplest way is to regularly backup your notes from the desktop or terminal application.</Text>
<Text>For more information about End-To-End Encryption (E2EE) and how it is going to work, please check the documentation:</Text>
<TouchableOpacity onPress={() => { Linking.openURL('http://joplin.cozic.net/help/e2ee.html') }}><Text>http://joplin.cozic.net/help/e2ee.html</Text></TouchableOpacity>
</View>*/}
{<View style={{backgroundColor: theme.warningBackgroundColor, paddingTop: 5, paddingBottom: 5, paddingLeft: 10, paddingRight: 10 }}>
<Text>{_('For more information about End-To-End Encryption (E2EE) and advices on how to enable it please check the documentation:')}</Text>
<TouchableOpacity onPress={() => { Linking.openURL('https://joplin.cozic.net/e2ee') }}><Text>https://joplin.cozic.net/e2ee</Text></TouchableOpacity>
</View>}
<Text style={this.styles().titleText}>{_('Status')}</Text>
<Text style={this.styles().normalText}>{_('Encryption is: %s', this.props.encryptionEnabled ? _('Enabled') : _('Disabled'))}</Text>

View File

@@ -43,7 +43,7 @@ class FolderScreenComponent extends BaseScreenComponent {
return this.styles_[this.props.theme];
}
componentWillMount() {
UNSAFE_componentWillMount() {
if (!this.props.folderId) {
const folder = Folder.new();
this.setState({
@@ -103,6 +103,7 @@ class FolderScreenComponent extends BaseScreenComponent {
render() {
let saveButtonDisabled = !this.isModified();
const theme = themeStyle(this.props.theme);
return (
<View style={this.rootStyle(this.props.theme).root}>
@@ -112,7 +113,7 @@ class FolderScreenComponent extends BaseScreenComponent {
saveButtonDisabled={saveButtonDisabled}
onSaveButtonPress={() => this.saveFolderButton_press()}
/>
<TextInput style={this.styles().textInput} autoFocus={true} value={this.state.folder.title} onChangeText={(text) => this.title_changeText(text)} />
<TextInput selectionColor={theme.textSelectionColor} style={this.styles().textInput} autoFocus={true} value={this.state.folder.title} onChangeText={(text) => this.title_changeText(text)} />
<dialogs.DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
</View>
);

View File

@@ -61,7 +61,7 @@ class LogScreenComponent extends BaseScreenComponent {
return this.styles_[this.props.theme];
}
componentWillMount() {
UNSAFE_componentWillMount() {
this.resfreshLogEntries();
}

View File

@@ -1,9 +1,10 @@
const React = require('react'); const Component = React.Component;
const { Platform, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image } = require('react-native');
const { Platform, Clipboard, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image } = require('react-native');
const { connect } = require('react-redux');
const { uuid } = require('lib/uuid.js');
const RNFS = require('react-native-fs');
const Note = require('lib/models/Note.js');
const BaseItem = require('lib/models/BaseItem.js');
const Setting = require('lib/models/Setting.js');
const Resource = require('lib/models/Resource.js');
const Folder = require('lib/models/Folder.js');
@@ -22,8 +23,8 @@ const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
const { shim } = require('lib/shim.js');
const { BaseScreenComponent } = require('lib/components/base-screen.js');
const { dialogs } = require('lib/dialogs.js');
const { globalStyle, themeStyle } = require('lib/components/global-style.js');
const { dialogs } = require('lib/dialogs.js');
const DialogBox = require('react-native-dialogbox').default;
const { NoteBodyViewer } = require('lib/components/note-body-viewer.js');
const RNFetchBlob = require('react-native-fetch-blob').default;
@@ -107,6 +108,39 @@ class NoteScreenComponent extends BaseScreenComponent {
this.noteTagDialog_closeRequested = () => {
this.setState({ noteTagDialogShown: false });
}
this.onJoplinLinkClick_ = async (msg) => {
try {
if (msg.indexOf('joplin://') === 0) {
const itemId = msg.substr('joplin://'.length);
const item = await BaseItem.loadItemById(itemId);
if (!item) throw new Error(_('No item with ID %s', itemId));
if (item.type_ === BaseModel.TYPE_NOTE) {
// Easier to just go back, then go to the note since
// the Note screen doesn't handle reloading a different note
this.props.dispatch({
type: 'NAV_BACK',
});
setTimeout(() => {
this.props.dispatch({
type: 'NAV_GO',
routeName: 'Note',
noteId: item.id,
});
}, 5);
} else {
throw new Error(_('The Joplin mobile app does not currently support this type of link: %s', BaseModel.modelTypeToName(item.type_)));
}
} else {
Linking.openURL(msg);
}
} catch (error) {
dialogs.error(this, error.message);
}
}
}
styles() {
@@ -160,7 +194,7 @@ class NoteScreenComponent extends BaseScreenComponent {
return shared.isModified(this);
}
async componentWillMount() {
async UNSAFE_componentWillMount() {
BackButtonService.addHandler(this.backHandler);
NavService.addHandler(this.navHandler);
@@ -186,8 +220,8 @@ class NoteScreenComponent extends BaseScreenComponent {
shared.noteComponent_change(this, 'body', text);
}
async saveNoteButton_press() {
await shared.saveNoteButton_press(this);
async saveNoteButton_press(folderId = null) {
await shared.saveNoteButton_press(this, folderId);
Keyboard.dismiss();
}
@@ -330,10 +364,16 @@ class NoteScreenComponent extends BaseScreenComponent {
return;
} else {
await RNFetchBlob.fs.cp(localFilePath, targetPath);
const stat = await shim.fsDriver().stat(targetPath);
if (stat.size >= 10000000) {
await shim.fsDriver().remove(targetPath);
throw new Error('Resources larger than 10 MB are not currently supported as they may crash the mobile applications. The issue is being investigated and will be fixed at a later time.');
}
}
}
} catch (error) {
reg.logger().warn('Could not attach file:', error);
await dialogs.error(this, error.message);
return;
}
@@ -402,6 +442,11 @@ class NoteScreenComponent extends BaseScreenComponent {
}
}
copyMarkdownLink_onPress() {
const note = this.state.note;
Clipboard.setString(Note.markdownTag(note));
}
menuOptions() {
const note = this.state.note;
const isTodo = note && !!note.is_todo;
@@ -425,6 +470,7 @@ class NoteScreenComponent extends BaseScreenComponent {
if (isSaved) output.push({ title: _('Tags'), onPress: () => { this.tags_onPress(); } });
output.push({ title: isTodo ? _('Convert to note') : _('Convert to todo'), onPress: () => { this.toggleIsTodo_onPress(); } });
if (isSaved) output.push({ title: _('Copy Markdown link'), onPress: () => { this.copyMarkdownLink_onPress(); } });
output.push({ isDivider: true });
if (this.props.showAdvancedOptions) output.push({ title: this.state.showNoteMetadata ? _('Hide metadata') : _('Show metadata'), onPress: () => { this.showMetadata_onPress(); } });
output.push({ title: _('View on map'), onPress: () => { this.showOnMap_onPress(); } });
@@ -466,7 +512,7 @@ class NoteScreenComponent extends BaseScreenComponent {
this.saveOneProperty('body', newBody);
};
bodyComponent = <NoteBodyViewer style={this.styles().noteBodyViewer} webViewStyle={theme} note={note} onCheckboxChange={(newBody) => { onCheckboxChange(newBody) }}/>
bodyComponent = <NoteBodyViewer onJoplinLinkClick={this.onJoplinLinkClick_} style={this.styles().noteBodyViewer} webViewStyle={theme} note={note} onCheckboxChange={(newBody) => { onCheckboxChange(newBody) }}/>
} else {
const focusBody = !isNew && !!note.title;
@@ -481,6 +527,7 @@ class NoteScreenComponent extends BaseScreenComponent {
value={note.body}
onChangeText={(text) => this.body_changeText(text)}
blurOnSubmit={false}
selectionColor={theme.textSelectionColor}
/>
);
}
@@ -496,7 +543,7 @@ class NoteScreenComponent extends BaseScreenComponent {
},
});
if (this.state.mode == 'edit') return <ActionButton style={{display:'none'}}/>;
if (this.state.mode == 'edit') return null;//<ActionButton style={{display:'none'}}/>;
return <ActionButton multiStates={true} buttons={buttons} buttonIndex={0} />
}
@@ -545,6 +592,7 @@ class NoteScreenComponent extends BaseScreenComponent {
style={titleTextInputStyle}
value={note.title}
onChangeText={(text) => this.title_changeText(text)}
selectionColor={theme.textSelectionColor}
/>
</View>
);
@@ -558,7 +606,12 @@ class NoteScreenComponent extends BaseScreenComponent {
enabled: true,
selectedFolderId: folder ? folder.id : null,
onValueChange: async (itemValue, itemIndex) => {
if (note.id) await Note.moveToFolder(note.id, itemValue);
if (!note.id) {
await this.saveNoteButton_press(itemValue);
} else {
await Note.moveToFolder(note.id, itemValue);
}
note.parent_id = itemValue;
const folder = await Folder.load(note.parent_id);

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