You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-24 20:19:10 +02:00
Compare commits
172 Commits
android-v1
...
android-v1
Author | SHA1 | Date | |
---|---|---|---|
|
5e0f2642e3 | ||
|
93966b0fa1 | ||
|
e90abf3517 | ||
|
d3fa0dce96 | ||
|
58a7c2fa94 | ||
|
962a8700c2 | ||
|
b5c704e2bb | ||
|
e7b52b19d7 | ||
|
903c2e6d92 | ||
|
abcb1ac760 | ||
|
b6bf76cc4c | ||
|
2bf87655da | ||
|
d4b19f19a1 | ||
|
d8ccc38d5b | ||
|
4e3b8a06ea | ||
|
363632ffa7 | ||
|
994c99f47f | ||
|
96571baadc | ||
|
4ce2b2c948 | ||
|
5d69f7a0a7 | ||
|
bcb1f36ad8 | ||
|
34c65a686c | ||
|
0b32741a12 | ||
|
dbb321a3cc | ||
|
a6e4f47adf | ||
|
fb6dee32ac | ||
|
984dd6f2c0 | ||
|
02bde2c6e9 | ||
|
782d24cc04 | ||
|
4d0af575e5 | ||
|
be8bda8e73 | ||
|
1242de532e | ||
|
7d7ec7f15e | ||
|
ca112ec5d3 | ||
|
5deb8cf76d | ||
|
a2c9737c17 | ||
|
d3fca3d6cc | ||
|
d5574098f0 | ||
|
f5a683f25c | ||
|
5f04adb392 | ||
|
edd0f7e255 | ||
|
67145d9104 | ||
|
003e2afff7 | ||
|
6e9d70c5cb | ||
|
4821b4cdf2 | ||
|
734d4db431 | ||
|
317aaed0ac | ||
|
9778098d6c | ||
|
5b1755f988 | ||
|
2a772895dd | ||
|
5fbb01cf2f | ||
|
f9e0870b4e | ||
|
a58f1e9b4b | ||
|
6fc0d89b30 | ||
|
2dcadab7d2 | ||
|
bb3307e156 | ||
|
ecd07f1209 | ||
|
266cb1174f | ||
|
bfb9b77b6e | ||
|
01b1361dcb | ||
|
3a921720d6 | ||
|
cdfd3d9c31 | ||
|
9961fb64bb | ||
|
3137c355cf | ||
|
16abaf60d2 | ||
|
9004b710ea | ||
|
6ebac21c2b | ||
|
99f79faf83 | ||
|
613fa20806 | ||
|
1b5f812278 | ||
|
3a9643c1ea | ||
|
aee7f5a8ac | ||
|
d3cd378922 | ||
|
4f5e7367d0 | ||
|
2280fb5c43 | ||
|
96fb7c2087 | ||
|
6e994fd8b9 | ||
|
a7cde1e269 | ||
|
f8310ba0d5 | ||
|
b239c3faba | ||
|
3c2281dbf9 | ||
|
ac07bf784d | ||
|
067455542f | ||
|
5bfeaa357b | ||
|
fe27a64331 | ||
|
ed638612aa | ||
|
1d7ec83510 | ||
|
75c710232d | ||
|
5af52afadb | ||
|
0f4324c2f8 | ||
|
b48e1dac94 | ||
|
f0ca8e1e31 | ||
|
74b83eb71e | ||
|
28dce0fbb5 | ||
|
c12d402c7e | ||
|
014f5b123c | ||
|
58601dfc04 | ||
|
9fe7f0adae | ||
|
ea1374371f | ||
|
bce4294529 | ||
|
de409b632a | ||
|
a677b2e844 | ||
|
c63bb19cb6 | ||
|
72fd77812e | ||
|
40f3e72bd1 | ||
|
d6d86f2aff | ||
|
c71809438b | ||
|
3e6e1a0a36 | ||
|
f590ce4a34 | ||
|
67608e29c8 | ||
|
d5c2982093 | ||
|
90fad2a3ab | ||
|
bc7c82e3da | ||
|
cb824f7dd7 | ||
|
32c47a96f1 | ||
|
4e3f8893f7 | ||
|
ca3946689a | ||
|
e2ad2dfcaa | ||
|
d6f7893c56 | ||
|
8c65a7cc31 | ||
|
aabb9be7de | ||
|
544f93bf22 | ||
|
f81dbf4a4c | ||
|
fbec8263a3 | ||
|
68d77a69e6 | ||
|
f2ef2446c6 | ||
|
875cb5387a | ||
|
ae9ecdad40 | ||
|
86a0e34975 | ||
|
1141074745 | ||
|
efc46d9989 | ||
|
2b45f745b6 | ||
|
37fb81e9b2 | ||
|
255a4fac93 | ||
|
3e3fb88de8 | ||
|
e4cf03ae46 | ||
|
554a3eb10d | ||
|
61881b528a | ||
|
c2507cbc4e | ||
|
ed0f6d165c | ||
|
8e22d38eb3 | ||
|
2599c425c3 | ||
|
0e15821a81 | ||
|
c1bb51c12b | ||
|
1532b6d159 | ||
|
945018b698 | ||
|
df7b981e5e | ||
|
4fe495675b | ||
|
7828eef2ad | ||
|
694f81b75f | ||
|
8364b6e08d | ||
|
3f4328ce9d | ||
|
9e0bf1acb2 | ||
|
c9e130a771 | ||
|
26331f61e1 | ||
|
694672859a | ||
|
858ead40b9 | ||
|
b07fe5cc34 | ||
|
0317171097 | ||
|
9741a3a53d | ||
|
7937fab5ff | ||
|
f595be07d4 | ||
|
eef106c99b | ||
|
dbe1833f92 | ||
|
520dc0ae21 | ||
|
c9be287f4a | ||
|
0faaf660b4 | ||
|
dfbe37fdaf | ||
|
37e7ea0b52 | ||
|
44bf518244 | ||
|
63cb9b4968 | ||
|
a6cecc103c |
@@ -3,6 +3,14 @@ if: tag IS present
|
||||
|
||||
rvm: 2.3.3
|
||||
|
||||
# It's important to only build production branches otherwise Electron Builder
|
||||
# might take assets from dev branches and overwrite those of production.
|
||||
# https://docs.travis-ci.com/user/customizing-the-build/#Building-Specific-Branches
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
|
62
Assets/JoplinLetter.svg
Normal file
62
Assets/JoplinLetter.svg
Normal 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 |
6
BUILD.md
6
BUILD.md
@@ -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.
|
||||
|
@@ -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,14 +10,10 @@ 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
|
||||
|
||||
If you want to add a new feature, consider asking about it before implementing it to make sure it is within the scope of the project. Of course you are free to create the pull request directly but it is not guaranteed it is going to be accepted.
|
||||
If you want to add a new feature, consider asking about it before implementing it or checking existing discussions to make sure it is within the scope of the project. Of course you are free to create the pull request directly but it is not guaranteed it is going to be accepted.
|
||||
|
||||
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/master/BUILD.md) for more details.
|
||||
|
||||
# Coding style
|
||||
|
||||
See the [prettier config](https://github.com/laurent22/joplin/blob/master/prettier.config.js).
|
||||
|
3
CliClient/.gitignore
vendored
3
CliClient/.gitignore
vendored
@@ -18,4 +18,5 @@ tests/cli-integration/
|
||||
tests/sync
|
||||
out.txt
|
||||
linkToLocal.sh
|
||||
yarn-error.log
|
||||
yarn-error.log
|
||||
tests/support/dropbox-auth.txt
|
@@ -496,7 +496,7 @@ class AppGui {
|
||||
cmd = cmd.trim();
|
||||
if (!cmd.length) return;
|
||||
|
||||
this.logger().info('Got command: ' + cmd);
|
||||
// this.logger().debug('Got command: ' + cmd);
|
||||
|
||||
try {
|
||||
let note = this.widget('noteList').currentItem;
|
||||
@@ -757,7 +757,7 @@ class AppGui {
|
||||
if (statusBar.promptActive) processShortcutKeys = false;
|
||||
|
||||
if (processShortcutKeys) {
|
||||
this.logger().info('Shortcut:', shortcutKey, keymapItem);
|
||||
this.logger().debug('Shortcut:', shortcutKey, keymapItem);
|
||||
|
||||
this.currentShortcutKeys_ = [];
|
||||
|
||||
|
@@ -5,6 +5,7 @@ const { JoplinDatabase } = require('lib/joplin-database.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const { FoldersScreenUtils } = require('lib/folders-screen-utils.js');
|
||||
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
@@ -292,7 +293,7 @@ class Application extends BaseApplication {
|
||||
|
||||
async execCommand(argv) {
|
||||
if (!argv.length) return this.execCommand(['help']);
|
||||
reg.logger().info('execCommand()', argv);
|
||||
// reg.logger().debug('execCommand()', argv);
|
||||
const commandName = argv[0];
|
||||
this.activeCommand_ = this.findCommandByName(commandName);
|
||||
|
||||
@@ -412,6 +413,8 @@ class Application extends BaseApplication {
|
||||
|
||||
const tags = await Tag.allWithNotes();
|
||||
|
||||
ResourceService.runInBackground();
|
||||
|
||||
this.dispatch({
|
||||
type: 'TAG_UPDATE_ALL',
|
||||
items: tags,
|
||||
|
@@ -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('');
|
||||
|
||||
|
@@ -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()) {
|
||||
@@ -76,7 +76,7 @@ class Command extends BaseCommand {
|
||||
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`'));
|
||||
|
@@ -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 {
|
||||
|
1417
CliClient/locales/cs_CZ.po
Normal file
1417
CliClient/locales/cs_CZ.po
Normal file
File diff suppressed because it is too large
Load Diff
1433
CliClient/locales/da_DK.po
Normal file
1433
CliClient/locales/da_DK.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Tobias Strobel <git@strobeltobias.de>\n"
|
||||
"Last-Translator: Tobias Grasse <mail@tobias-grasse.net>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: de_DE\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@@ -18,7 +18,8 @@ msgstr ""
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr ""
|
||||
"Hebe die Markierungen zugehöriger Notizen auf, um eine Markierung zu löschen."
|
||||
"Um eine Markierung zu löschen, entferne diese bei allen damit verbundenen "
|
||||
"Notizen."
|
||||
|
||||
msgid "Please select the note or notebook to be deleted first."
|
||||
msgstr ""
|
||||
@@ -26,19 +27,18 @@ msgstr ""
|
||||
"soll."
|
||||
|
||||
msgid "Press Ctrl+D or type \"exit\" to exit the application"
|
||||
msgstr "Drücke Strg+D oder tippe \"exit\", um das Programm zu verlassen"
|
||||
msgstr "Drücke Strg+D oder tippe \"exit\" um das Programm zu verlassen"
|
||||
|
||||
#, javascript-format
|
||||
msgid "More than one item match \"%s\". Please narrow down your query."
|
||||
msgstr ""
|
||||
"Mehr als eine Notiz stimmt mit \"%s\" überein. Bitte schränke deine Suche "
|
||||
"ein."
|
||||
"Mehr als eine Notiz stimmt mit \"%s\" überein. Bitte die Suche einschränken."
|
||||
|
||||
msgid "No notebook selected."
|
||||
msgstr "Kein Notizbuch ausgewählt."
|
||||
|
||||
msgid "No notebook has been specified."
|
||||
msgstr "Kein Notizbuch wurde angegeben."
|
||||
msgstr "Es wurde kein Notizbuch festgelegt."
|
||||
|
||||
msgid "Y"
|
||||
msgstr "J"
|
||||
@@ -68,7 +68,7 @@ msgstr "Kann verschlüsseltes Objekt nicht ändern"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Missing required argument: %s"
|
||||
msgstr "Fehlendes benötigtes Argument: %s"
|
||||
msgstr "Fehlendes erforderliches Argument: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s: %s"
|
||||
@@ -104,8 +104,7 @@ msgstr ""
|
||||
"gegeben sind, wird eine Liste der momentanen Konfiguration angezeigt."
|
||||
|
||||
msgid "Also displays unset and hidden config variables."
|
||||
msgstr ""
|
||||
"Zeigt auch nicht angegebene oder versteckte Konfigurationsvariablen an."
|
||||
msgstr "Zeigt auch nicht gesetzte und versteckte Konfigurationsvariablen an."
|
||||
|
||||
#, javascript-format
|
||||
msgid "%s = %s (%s)"
|
||||
@@ -119,12 +118,12 @@ msgid ""
|
||||
"Duplicates the notes matching <note> to [notebook]. If no notebook is "
|
||||
"specified the note is duplicated in the current notebook."
|
||||
msgstr ""
|
||||
"Dupliziert die Notizen die mit <note> übereinstimmen zu [Notizbuch]. Wenn "
|
||||
"kein Notizbuch angegeben ist, wird die Notiz in das momentane Notizbuch "
|
||||
"Dupliziert die Notizen die mit <note> übereinstimmen in [Notizbuch]. Wenn "
|
||||
"kein Notizbuch angegeben ist, wird die Notiz in das aktuelle Notizbuch "
|
||||
"kopiert."
|
||||
|
||||
msgid "Marks a to-do as done."
|
||||
msgstr "Markiert ein To-Do als abgeschlossen."
|
||||
msgstr "Markiert ein To-Do als erledigt."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Note is not a to-do: \"%s\""
|
||||
@@ -134,7 +133,7 @@ msgid ""
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
|
||||
"`status` and `target-status`."
|
||||
msgstr ""
|
||||
"Verwaltet die E2EE-Konfiguration. Die Befehle sind `enable`, `disable`, "
|
||||
"Verwaltet die E2EE-Konfiguration. Die Befehle lauten `enable`, `disable`, "
|
||||
"`decrypt`, `status` und `target-status`."
|
||||
|
||||
msgid "Enter master password:"
|
||||
@@ -147,8 +146,8 @@ msgid ""
|
||||
"Starting decryption... Please wait as it may take several minutes depending "
|
||||
"on how much there is to decrypt."
|
||||
msgstr ""
|
||||
"Entschlüsselung starten.... Warte bitte, da es einige Minuten dauern kann, "
|
||||
"je nachdem, wie viel es zu entschlüsseln gibt."
|
||||
"Starte Entschlüsselung.... Bitte warten, da dies je nach Anzahl der "
|
||||
"betreffenden Objekte einige Minuten dauern kann."
|
||||
|
||||
msgid "Completed decryption."
|
||||
msgstr "Entschlüsselung abgeschlossen."
|
||||
@@ -161,7 +160,7 @@ msgstr "Deaktiviert"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Encryption is: %s"
|
||||
msgstr "Die Verschlüsselung ist: %s"
|
||||
msgstr "Verschlüsselung ist: %s"
|
||||
|
||||
msgid "Edit note."
|
||||
msgstr "Notiz bearbeiten."
|
||||
@@ -169,8 +168,8 @@ msgstr "Notiz bearbeiten."
|
||||
msgid ""
|
||||
"No text editor is defined. Please set it using `config editor <editor-path>`"
|
||||
msgstr ""
|
||||
"Kein Textverarbeitungsprogramm angegeben. Bitte lege eines mit `config "
|
||||
"editor <Pfad-Zum-Textverarbeitungsprogramm>` fest"
|
||||
"Kein Texteditor definiert. Bitte lege einen mit `config editor <Pfad-Zum-"
|
||||
"Texteditor>` fest"
|
||||
|
||||
msgid "No active notebook."
|
||||
msgstr "Kein aktives Notizbuch."
|
||||
@@ -192,20 +191,19 @@ msgid "Note has been saved."
|
||||
msgstr "Die Notiz wurde gespeichert."
|
||||
|
||||
msgid "Exits the application."
|
||||
msgstr "Schließt das Programm."
|
||||
msgstr "Beendet das Programm."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Exports Joplin data to the given path. By default, it will export the "
|
||||
"complete database including notebooks, notes, tags and resources."
|
||||
msgstr ""
|
||||
"Exportiert Joplins Dateien zu dem angegebenen Pfad. Standardmäßig wird die "
|
||||
"Exportiert Joplin Dateien in den angegebenen Pfad. Standardmäßig wird die "
|
||||
"komplette Datenbank inklusive Notizbüchern, Notizen, Markierungen und "
|
||||
"Anhängen exportiert."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Destination format: %s"
|
||||
msgstr "Datumsformat"
|
||||
msgstr "Zielformat: %s"
|
||||
|
||||
msgid "Exports only the given note."
|
||||
msgstr "Exportiert nur die angegebene Notiz."
|
||||
@@ -222,6 +220,8 @@ msgstr "Zeigt die Nutzungsstatistik an."
|
||||
#, javascript-format
|
||||
msgid "For information on how to customise the shortcuts please visit %s"
|
||||
msgstr ""
|
||||
"Für weitere Informationen über die Anpassung von Tastenkürzel besuche bitte "
|
||||
"%s"
|
||||
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr "Tastenkürzel sind im CLI Modus nicht verfügbar."
|
||||
@@ -230,11 +230,12 @@ msgid ""
|
||||
"Type `help [command]` for more information about a command; or type `help "
|
||||
"all` for the complete usage information."
|
||||
msgstr ""
|
||||
"Tippe `help [Befehl]` für weitere Informationen über einen Befehl; oder "
|
||||
"tippe `help all` für die vollständigen Informationen zur Befehlsverwendung."
|
||||
"Tippe `help [Befehl]` um weitere Informationen über einen Befehl zu erhalten "
|
||||
"oder tippe `help all` für die vollständigen Informationen zur "
|
||||
"Befehlsverwendung."
|
||||
|
||||
msgid "The possible commands are:"
|
||||
msgstr "Mögliche Befehle sind:"
|
||||
msgstr "Mögliche Befehle lauten:"
|
||||
|
||||
msgid ""
|
||||
"In any command, a note or notebook can be refered to by title or ID, or "
|
||||
@@ -243,13 +244,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"In jedem Befehl können Notizen oder Notizbücher durch ihren Titel oder ihre "
|
||||
"ID spezifiziert werden, oder durch die Abkürzung `$n` oder `$b` um entweder "
|
||||
"das momentan ausgewählte Notizbuch oder die momentan ausgewählte Notiz zu "
|
||||
"wählen. `$c` kann benutzt werden, um auf die momentane Auswahl zu verweisen."
|
||||
"das momentan ausgewählte Notizbuch oder die momentan ausgewählte Notiz "
|
||||
"auszuwählen. `$c` kann benutzt werden, um auf die momentane Auswahl zu "
|
||||
"verweisen."
|
||||
|
||||
msgid "To move from one pane to another, press Tab or Shift+Tab."
|
||||
msgstr ""
|
||||
"Um ein von einem Fenster zu einem anderen zu wechseln, drücke Tab oder Shift"
|
||||
"+Tab."
|
||||
"Um von einem Fenster zu einem anderen zu wechseln, drücke Tab oder Shift+Tab."
|
||||
|
||||
msgid ""
|
||||
"Use the arrows and page up/down to scroll the lists and text areas "
|
||||
@@ -258,7 +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\"."
|
||||
#, fuzzy
|
||||
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 \":\""
|
||||
@@ -267,19 +269,18 @@ msgstr "Um den Kommandozeilen Modus aufzurufen, drücke \":\""
|
||||
msgid "To exit command line mode, press ESCAPE"
|
||||
msgstr "Um den Kommandozeilen Modus zu beenden, drücke ESCAPE"
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`"
|
||||
msgstr ""
|
||||
"Um die komplette Liste von verfügbaren Tastenkürzeln anzuzeigen, tippe `help "
|
||||
"shortcuts` ein"
|
||||
"Um die komplette Liste aller verfügbaren Tastenkürzeln anzuzeigen, tippe "
|
||||
"`help keymap` ein"
|
||||
|
||||
msgid "Imports data into Joplin."
|
||||
msgstr ""
|
||||
msgstr "Importiert Daten in Joplin."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Source format: %s"
|
||||
msgstr "Ungültiger Befehl: %s"
|
||||
msgstr "Quellformat: %s"
|
||||
|
||||
msgid "Do not ask for confirmation."
|
||||
msgstr "Nicht nach einer Bestätigung fragen."
|
||||
@@ -429,6 +430,16 @@ msgstr ""
|
||||
"Authentifizierung wurde nicht abgeschlossen (keinen Authentifizierung-Token "
|
||||
"erhalten)."
|
||||
|
||||
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 ""
|
||||
@@ -458,7 +469,7 @@ msgid "Starting synchronisation..."
|
||||
msgstr "Starte Synchronisation..."
|
||||
|
||||
msgid "Cancelling... Please wait."
|
||||
msgstr "Abbrechen... Bitte warten."
|
||||
msgstr "Abbrechen… Bitte warten."
|
||||
|
||||
msgid ""
|
||||
"<tag-command> can be \"add\", \"remove\" or \"list\" to assign or remove "
|
||||
@@ -580,17 +591,17 @@ msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Datei"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
msgstr "Exportiere „%s“ ins „%s“ Format. Bitte warten..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
msgstr "Importiere „%s“ ins „%s“ Format. Bitte warten…"
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "PDF-Datei"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Datei"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Neue Notiz"
|
||||
@@ -604,13 +615,15 @@ msgstr "Neues Notizbuch"
|
||||
msgid "Import"
|
||||
msgstr "Importieren"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Export"
|
||||
msgstr "Importieren"
|
||||
msgstr "Exportieren"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Drucken"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
msgstr "%s ausblenden"
|
||||
|
||||
msgid "Quit"
|
||||
msgstr "Verlassen"
|
||||
@@ -631,10 +644,13 @@ msgid "Search in all the notes"
|
||||
msgstr "Alle Notizen durchsuchen"
|
||||
|
||||
msgid "View"
|
||||
msgstr "Ansicht"
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
msgstr "Editor Layout umschalten"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Werkzeuge"
|
||||
@@ -643,7 +659,7 @@ msgid "Synchronisation status"
|
||||
msgstr "Status der Synchronisation"
|
||||
|
||||
msgid "Encryption options"
|
||||
msgstr "Verschlüsselungsoptionen"
|
||||
msgstr "Verschlüsselung"
|
||||
|
||||
msgid "General Options"
|
||||
msgstr "Allgemeine Einstellungen"
|
||||
@@ -654,12 +670,11 @@ msgstr "Hilfe"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Webseite und Dokumentation"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Make a donation"
|
||||
msgstr "Webseite und Dokumentation"
|
||||
msgstr "Spenden"
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr ""
|
||||
msgstr "Überprüfe auf Updates..."
|
||||
|
||||
msgid "About Joplin"
|
||||
msgstr "Über Joplin"
|
||||
@@ -668,12 +683,12 @@ msgstr "Über Joplin"
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr "%s %s (%s, %s)"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
msgstr "Auf %s: %s"
|
||||
msgstr "Öffne %s"
|
||||
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
msgstr "Verlassen"
|
||||
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
@@ -681,37 +696,31 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Notizen löschen?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "Die aktuelle Version ist up-to-date."
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
msgstr "Es ist ein Update verfügbar! Soll dies jetzt heruntergeladen werden?"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Ja"
|
||||
|
||||
#, fuzzy
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
msgstr "Nein"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Synchronisation abbrechen"
|
||||
msgstr "Überprüfen der Synchronisationseinstellungen"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr "Notizen und Einstellungen gespeichert in: %s"
|
||||
msgstr "Notizen und Einstellungen werden gespeichert in: %s"
|
||||
|
||||
msgid "Save"
|
||||
msgstr "Speichern"
|
||||
|
||||
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 "
|
||||
@@ -773,14 +782,18 @@ msgstr ""
|
||||
"verwendet werden, abhängig davon, wie die jeweiligen Notizen oder "
|
||||
"Notizbücher ursprünglich verschlüsselt wurden."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Missing Master Keys"
|
||||
msgstr "Hauptschlüssel"
|
||||
msgstr "Fehlender Master-Key"
|
||||
|
||||
msgid ""
|
||||
"The master keys with these IDs are used to encrypt some of your items, "
|
||||
"however the application does not currently have access to them. It is likely "
|
||||
"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 ""
|
||||
|
||||
msgid "Status"
|
||||
@@ -796,7 +809,7 @@ msgstr "Zurück"
|
||||
msgid ""
|
||||
"New notebook \"%s\" will be created and file \"%s\" will be imported into it"
|
||||
msgstr ""
|
||||
"Neues Notizbuch \"%s\" wird erstellt und die Datei \"%s\" wird hinein "
|
||||
"Neues Notizbuch \"%s\" wird erstellt und die Datei \"%s\" wird dort hinein "
|
||||
"importiert"
|
||||
|
||||
msgid "Please create a notebook first."
|
||||
@@ -815,17 +828,18 @@ msgid "Separate each tag by a comma."
|
||||
msgstr "Trenne jede Markierung mit einem Komma."
|
||||
|
||||
msgid "Rename notebook:"
|
||||
msgstr "Benne Notizbuch um:"
|
||||
msgstr "Notizbuch umbenennen:"
|
||||
|
||||
msgid "Set alarm:"
|
||||
msgstr "Alarm erstellen:"
|
||||
|
||||
msgid "Search"
|
||||
msgstr "Suchen"
|
||||
|
||||
msgid "Layout"
|
||||
msgstr "Layout"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Search..."
|
||||
msgstr "Suchen"
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr "Manche Objekte können nicht synchronisiert werden."
|
||||
|
||||
@@ -862,11 +876,10 @@ msgstr ""
|
||||
"(+) Knopf drückst."
|
||||
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
msgstr "Öffne..."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Save as..."
|
||||
msgstr "Änderungen speichern"
|
||||
msgstr "Sichern unter..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
@@ -886,18 +899,18 @@ msgid ""
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the "
|
||||
"note."
|
||||
msgstr ""
|
||||
"Diese Notiz hat keinen Inhalt. Klicke auf „%s“ um den Editor zu aktivieren "
|
||||
"und die Notiz zu bearbeiten."
|
||||
|
||||
#, fuzzy
|
||||
msgid "to-do"
|
||||
msgstr "Neues To-Do"
|
||||
msgstr "To-Do"
|
||||
|
||||
#, fuzzy
|
||||
msgid "note"
|
||||
msgstr "Neue Notiz"
|
||||
msgstr "Notiz"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Creating new %s..."
|
||||
msgstr "Importiere Notizen..."
|
||||
msgstr "Erstelle neue %s..."
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr "Aktualisieren"
|
||||
@@ -908,6 +921,9 @@ msgstr "Leeren"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "OneDrive Login"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Optionen"
|
||||
|
||||
@@ -932,9 +948,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"
|
||||
@@ -947,12 +960,14 @@ msgstr "Nutzung: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Unbekanntes Argument: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Dateisystem"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Nextcloud"
|
||||
msgstr "Nextcloud (Beta)"
|
||||
msgstr "Nextcloud"
|
||||
|
||||
msgid "OneDrive"
|
||||
msgstr "OneDrive"
|
||||
@@ -960,9 +975,8 @@ msgstr "OneDrive"
|
||||
msgid "OneDrive Dev (For testing only)"
|
||||
msgstr "OneDrive Dev (Nur für Tests)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV"
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unknown log level: %s"
|
||||
@@ -1026,8 +1040,8 @@ msgstr "Remote Objekte gelöscht: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Geladene Objekte: %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Status: \"%s\"."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1037,6 +1051,16 @@ msgstr "Abbrechen..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Abgeschlossen: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Letzte Fehlermeldung: %s"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr "wartend"
|
||||
|
||||
msgid "In progress"
|
||||
msgstr "In Bearbeitung"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Synchronisation ist bereits im Gange. Status: %s"
|
||||
@@ -1045,7 +1069,7 @@ msgid "Encrypted"
|
||||
msgstr "Verschlüsselt"
|
||||
|
||||
msgid "Encrypted items cannot be modified"
|
||||
msgstr "Verschlüsselte Objekte können nicht verändert werden."
|
||||
msgstr "Verschlüsselte Objekte können nicht verändert werden"
|
||||
|
||||
msgid "Conflicts"
|
||||
msgstr "Konflikte"
|
||||
@@ -1102,49 +1126,48 @@ msgstr "Hell"
|
||||
msgid "Dark"
|
||||
msgstr "Dunkel"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Zeige unvollständige To-Dos oben in der Liste"
|
||||
msgstr "Zeige unvollständige To-Dos an oberster Stelle"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
msgstr "Sortiere Notizen nach"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Reverse sort order"
|
||||
msgstr "Dreht die Sortierreihenfolge um."
|
||||
msgstr "Sortierreihenfolge umdrehen"
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr "Momentanen Standort zusammen mit Notizen speichern"
|
||||
|
||||
#, fuzzy
|
||||
msgid "When creating a new to-do:"
|
||||
msgstr "Erstellt ein neues To-Do."
|
||||
msgstr "Wenn eine neue To-Do erstellt wird:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus title"
|
||||
msgstr "Notiz Titel:"
|
||||
msgstr "Fokussiere Titel"
|
||||
|
||||
msgid "Focus body"
|
||||
msgstr ""
|
||||
msgstr "Fokussiere Inhalt"
|
||||
|
||||
#, fuzzy
|
||||
msgid "When creating a new note:"
|
||||
msgstr "Erstellt eine neue Notiz."
|
||||
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 ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Global zoom percentage"
|
||||
msgstr "Einstellen des Anwendungszooms"
|
||||
msgstr "Zoomstufe der Benutzeroberfläche"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr ""
|
||||
msgstr "Editor Schriftenfamilie"
|
||||
|
||||
msgid ""
|
||||
"The font name will not be checked. If incorrect or empty, it will default to "
|
||||
"a generic monospace font."
|
||||
msgstr ""
|
||||
"Der Name der Schrift wird nicht überprüft. Ist dieser inkorrekt oder leer "
|
||||
"wird eine generische Monospace Schrift verwendet."
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr "Die Applikation automatisch aktualisieren"
|
||||
@@ -1197,57 +1220,56 @@ msgstr "Nextcloud Benutzername"
|
||||
msgid "Nextcloud password"
|
||||
msgstr "Nextcloud Passwort"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV URL"
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
msgstr "WebDAV URL"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV username"
|
||||
msgstr "Nextcloud Benutzername"
|
||||
msgstr "WebDAV Benutzername"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV password"
|
||||
msgstr "Setze ein Passwort"
|
||||
msgstr "WebDAV Passwort"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Ungültiger Optionswert: \"%s\". Mögliche Werte sind: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Export File"
|
||||
msgstr "Evernote Export Dateien"
|
||||
msgstr "Joplin Export Datei"
|
||||
|
||||
msgid "Markdown"
|
||||
msgstr ""
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr ""
|
||||
msgstr "Joplin Export Verzeichnis"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Evernote Export Dateien"
|
||||
msgstr "Evernote Export Datei"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Verzeichnis"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
msgstr "Das Modul „%s“ für das Format „%s“ kann nicht geladen werden"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Please specify import format for %s"
|
||||
msgstr ""
|
||||
msgstr "Bitte das Exportformat für %s angeben"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This item is currently encrypted: %s \"%s\". Please wait for all items to be "
|
||||
"decrypted and try again."
|
||||
msgstr ""
|
||||
"Dieses Objekt ist zur Zeit verschlüsselt: %s „%s“. Bitte warten bis alle "
|
||||
"Objekte entschlüsselt wurden und versuche es dann erneut."
|
||||
|
||||
msgid "There is no data to export."
|
||||
msgstr ""
|
||||
msgstr "Keine Daten für den Export vorhanden."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr ""
|
||||
"Bitte wähle aus, wohin der Synchronisations Status exportiert werden soll"
|
||||
"Bitte wähle aus, wohin der Synchronisations-Status exportiert werden soll."
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr "Objekte können nicht synchronisiert werden"
|
||||
@@ -1337,9 +1359,19 @@ msgstr "Bestätigen"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Synchronisation abbrechen"
|
||||
|
||||
msgid "Joplin website"
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr "Website von Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Mit OneDrive anmelden"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr "Hauptschlüssel %s"
|
||||
@@ -1365,10 +1397,10 @@ msgid "Edit notebook"
|
||||
msgstr "Notizbuch bearbeiten"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
msgstr "Zeige Alles"
|
||||
|
||||
msgid "Errors only"
|
||||
msgstr ""
|
||||
msgstr "Nur Fehler"
|
||||
|
||||
msgid "This note has been modified:"
|
||||
msgstr "Diese Notiz wurde verändert:"
|
||||
@@ -1410,6 +1442,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."
|
||||
@@ -1426,6 +1461,18 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Willkommen"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "Suchen"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr ""
|
||||
#~ "Versionshinweise:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importiert eine Evernote Notizbuch-Datei (.enex Datei)."
|
||||
|
||||
|
@@ -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 \":\""
|
||||
@@ -372,6 +372,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 ""
|
||||
@@ -493,16 +503,16 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "New note"
|
||||
msgstr ""
|
||||
|
||||
@@ -518,6 +528,9 @@ msgstr ""
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -543,6 +556,9 @@ msgstr ""
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -590,11 +606,7 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
@@ -606,9 +618,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
@@ -619,6 +628,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 "
|
||||
@@ -677,6 +689,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 ""
|
||||
|
||||
@@ -712,10 +729,10 @@ msgstr ""
|
||||
msgid "Set alarm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgid "Layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Layout"
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
@@ -793,6 +810,9 @@ msgstr ""
|
||||
msgid "OneDrive Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
@@ -817,9 +837,6 @@ msgstr ""
|
||||
msgid "Notebooks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Searches"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr ""
|
||||
|
||||
@@ -831,6 +848,9 @@ msgstr ""
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr ""
|
||||
|
||||
@@ -901,7 +921,7 @@ msgid "Fetched items: %d/%d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "State: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -911,6 +931,16 @@ msgstr ""
|
||||
msgid "Completed: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr ""
|
||||
@@ -999,6 +1029,9 @@ msgstr ""
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr ""
|
||||
|
||||
@@ -1081,6 +1114,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1184,9 +1220,18 @@ msgstr ""
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr ""
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
@@ -1257,6 +1302,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."
|
||||
|
@@ -16,8 +16,6 @@ msgstr ""
|
||||
"X-Generator: Poedit 1.8.11\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr "Desmarque las notas asociadas para eliminar una etiqueta."
|
||||
@@ -252,8 +250,9 @@ 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\"."
|
||||
#, fuzzy
|
||||
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 \":\""
|
||||
@@ -418,6 +417,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."
|
||||
@@ -569,16 +580,16 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exportando el formato de \"%s\" a \"%s\". Por favor espere..."
|
||||
|
||||
msgid "File"
|
||||
msgstr "Archivo"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Directorio"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importando el formato de \"%s\" a \"%s\". Por favor espere..."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "Archivo PDF"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Archivo"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nueva nota"
|
||||
|
||||
@@ -594,6 +605,9 @@ msgstr "Importar"
|
||||
msgid "Export"
|
||||
msgstr "Exportar"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr "Oculta %s"
|
||||
@@ -619,6 +633,9 @@ msgstr "Buscar en todas las notas"
|
||||
msgid "View"
|
||||
msgstr "Ver"
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr "Cambia el diseño del editor"
|
||||
|
||||
@@ -666,15 +683,8 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"Notas de la versión:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "La versión actual está actualizada."
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr "Hay disponible una actualización. ¿Quiere descargarla ahora?"
|
||||
@@ -685,9 +695,6 @@ msgstr "Sí"
|
||||
msgid "No"
|
||||
msgstr "No"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "La versión actual está actualizada."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Comprobar sincronización"
|
||||
|
||||
@@ -698,6 +705,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 "
|
||||
@@ -769,6 +779,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"
|
||||
|
||||
@@ -804,12 +821,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."
|
||||
|
||||
@@ -887,6 +904,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"
|
||||
|
||||
@@ -911,9 +931,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"
|
||||
|
||||
@@ -925,6 +942,9 @@ msgstr "Uso: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Etiqueta desconocida: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr "Dropbox"
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Sistema de archivos"
|
||||
|
||||
@@ -1003,7 +1023,7 @@ msgid "Fetched items: %d/%d."
|
||||
msgstr "Elementos obtenidos: %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "State: %s."
|
||||
msgstr "Estado: «%s»."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1013,6 +1033,16 @@ msgstr "Cancelando..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Completado: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Último error: %s"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr "Espera"
|
||||
|
||||
msgid "In progress"
|
||||
msgstr "En progreso"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "La sincronización ya está en progreso. Estado: %s"
|
||||
@@ -1104,6 +1134,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 ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr "Establecer el porcentaje de aumento de la aplicación"
|
||||
|
||||
@@ -1193,6 +1226,9 @@ msgstr "Directorio para exportar de Joplin"
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Archivo exportado de Evernote"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Directorio"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr "No se puede cargar el módulo \"%s\" para el formato \"%s\""
|
||||
@@ -1301,9 +1337,18 @@ msgstr "Confirmar"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Cancelar sincronización"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr "Nuevas etiquetas:"
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
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"
|
||||
@@ -1374,6 +1419,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."
|
||||
@@ -1388,6 +1436,25 @@ 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"
|
||||
#~ "%s"
|
||||
#~ msgstr ""
|
||||
#~ "Notas de la versión:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importar una libreta de Evernote (archivo .enex)."
|
||||
|
||||
|
@@ -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 \":\""
|
||||
@@ -414,6 +415,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."
|
||||
@@ -564,16 +575,17 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Fitxategia"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "PDF File"
|
||||
msgstr "Fitxategia"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Fitxategia"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Ohar berria"
|
||||
|
||||
@@ -590,6 +602,9 @@ msgstr "Inportatu"
|
||||
msgid "Export"
|
||||
msgstr "Inportatu"
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -615,6 +630,9 @@ msgstr "Bilatu ohar guztietan"
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -663,12 +681,8 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Utzi"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Oharrak ezabatu?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -680,9 +694,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr "E"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Sinkronizazioa utzi"
|
||||
@@ -694,6 +705,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 "
|
||||
@@ -764,6 +778,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"
|
||||
|
||||
@@ -801,12 +820,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."
|
||||
|
||||
@@ -886,6 +906,9 @@ msgstr "Garbitu"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "Logeatu OneDriven"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Aukerak"
|
||||
|
||||
@@ -910,9 +933,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"
|
||||
@@ -925,6 +945,9 @@ msgstr "Erabili: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Marka ezezaguna: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Fitxategi sistema"
|
||||
|
||||
@@ -1003,8 +1026,8 @@ msgstr "Urruneko itemak ezabatuta: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Itemak eskuratuta: %d%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Egoera: \"%s\"."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1014,6 +1037,16 @@ msgstr "Bertan behera uzten..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Osatuta: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Aio! Agur! :_( "
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Sinkronizazioa hasita dago. Egoera: %s"
|
||||
@@ -1109,6 +1142,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"
|
||||
@@ -1201,6 +1237,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Evernotetik esportatutako fitxategiak"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1307,9 +1346,19 @@ msgstr "Baieztatu"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Sinkronizazioa utzi"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Login with OneDrive"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr "Pasahitz Nagusia %s"
|
||||
@@ -1380,6 +1429,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."
|
||||
@@ -1393,6 +1445,16 @@ msgstr "Oraindik ez duzu koadernorik. Sortu bat (+) botoian sakatuta."
|
||||
msgid "Welcome"
|
||||
msgstr "Ongi etorri!"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "Bilaketak"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "Oharrak ezabatu?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Inportatu Evernote koaderno fitxategia (.enex fitxategia)."
|
||||
|
||||
|
@@ -248,8 +248,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 \":\""
|
||||
@@ -413,6 +413,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 ""
|
||||
@@ -564,16 +578,16 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Exporter vers \"%s\" au format \"%s\". Veuillez patienter..."
|
||||
|
||||
msgid "File"
|
||||
msgstr "Fichier"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Dossier"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr "Importer depuis \"%s\" au format \"%s\". Veuillez patienter..."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "Fichier PDF"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Fichier"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nouvelle note"
|
||||
|
||||
@@ -589,6 +603,9 @@ msgstr "Importer"
|
||||
msgid "Export"
|
||||
msgstr "Exporter"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Imprimer"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr "Cacher %s"
|
||||
@@ -614,6 +631,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"
|
||||
|
||||
@@ -661,15 +681,8 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"Notes de version :\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "La version actuelle est à jour."
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -681,9 +694,6 @@ msgstr "Oui"
|
||||
msgid "No"
|
||||
msgstr "Non"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "La version actuelle est à jour."
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Vérifier config synchronisation"
|
||||
|
||||
@@ -694,6 +704,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 "
|
||||
@@ -767,6 +780,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"
|
||||
|
||||
@@ -804,12 +824,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."
|
||||
|
||||
@@ -890,6 +910,9 @@ msgstr "Supprimer"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "Connexion OneDrive"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr "Connection à Dropbox"
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Options"
|
||||
|
||||
@@ -914,9 +937,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"
|
||||
@@ -929,6 +949,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"
|
||||
|
||||
@@ -1007,8 +1030,8 @@ msgid "Fetched items: %d/%d."
|
||||
msgstr "Téléchargés : %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgstr "État : \"%s\"."
|
||||
msgid "State: %s."
|
||||
msgstr "État : %s."
|
||||
|
||||
msgid "Cancelling..."
|
||||
msgstr "Annulation..."
|
||||
@@ -1017,6 +1040,16 @@ msgstr "Annulation..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Terminé : %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Dernière erreur : %s"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr "Arrêté"
|
||||
|
||||
msgid "In progress"
|
||||
msgstr "En cours"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "La synchronisation est déjà en cours. État : %s"
|
||||
@@ -1087,7 +1120,7 @@ msgid "Sort notes by"
|
||||
msgstr "Trier les notes par"
|
||||
|
||||
msgid "Reverse sort order"
|
||||
msgstr "Inverser l'ordre."
|
||||
msgstr "Inverser l'ordre"
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr "Enregistrer l'emplacement avec les notes"
|
||||
@@ -1107,6 +1140,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"
|
||||
|
||||
@@ -1196,6 +1232,9 @@ msgstr "Dossier d'export Joplin"
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Fichiers d'export Evernote"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Dossier"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr "Impossible de charger module \"%s\" pour le format \"%s\""
|
||||
@@ -1306,9 +1345,18 @@ msgstr "Confirmer"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Annuler synchronisation"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr "Nouvelles étiquettes :"
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
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"
|
||||
@@ -1379,6 +1427,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."
|
||||
@@ -1394,6 +1445,25 @@ 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"
|
||||
#~ "%s"
|
||||
#~ msgstr ""
|
||||
#~ "Notes de version :\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importer un carnet Evernote (fichier .enex)."
|
||||
|
||||
@@ -1572,12 +1642,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."
|
||||
|
||||
|
1422
CliClient/locales/gl_ES.po
Normal file
1422
CliClient/locales/gl_ES.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -250,7 +250,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 \":\""
|
||||
@@ -420,6 +421,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 ""
|
||||
@@ -566,16 +577,17 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Datoteka"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "PDF File"
|
||||
msgstr "Datoteka"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Datoteka"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nova bilješka"
|
||||
|
||||
@@ -592,6 +604,9 @@ msgstr "Uvoz"
|
||||
msgid "Export"
|
||||
msgstr "Uvoz"
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -617,6 +632,9 @@ msgstr "Pretraži u svim bilješkama"
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -666,12 +684,8 @@ msgstr "U redu"
|
||||
msgid "Cancel"
|
||||
msgstr "Odustani"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Obriši bilješke?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -683,9 +697,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Prekini sinkronizaciju"
|
||||
@@ -697,6 +708,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 "
|
||||
@@ -755,6 +769,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"
|
||||
|
||||
@@ -792,12 +811,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."
|
||||
|
||||
@@ -877,6 +897,9 @@ msgstr "Očisti"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "OneDrive Login"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Opcije"
|
||||
|
||||
@@ -901,9 +924,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"
|
||||
|
||||
@@ -915,6 +935,9 @@ msgstr "Korištenje: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Nepoznata zastavica: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Datotečni sustav"
|
||||
|
||||
@@ -990,8 +1013,8 @@ msgstr "Obrisane udaljene stavke: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Stvorene lokalne stavke: %d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Stanje: \"%s\"."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1001,6 +1024,16 @@ msgstr "Prekidam..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Dovršeno: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Fatalna greška:"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Sinkronizacija je već u toku. Stanje: %s"
|
||||
@@ -1097,6 +1130,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 ""
|
||||
|
||||
@@ -1183,6 +1219,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Evernote izvozne datoteke"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1287,9 +1326,19 @@ msgstr "Potvrdi"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Prekini sinkronizaciju"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Prijavi se u OneDrive"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
@@ -1361,6 +1410,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."
|
||||
@@ -1374,6 +1426,16 @@ 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"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "Obriši bilješke?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Uvozi Evernote bilježnicu (.enex datoteku)."
|
||||
|
||||
|
@@ -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 \":\""
|
||||
@@ -407,6 +408,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 ""
|
||||
@@ -548,16 +559,17 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "File"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "PDF File"
|
||||
msgstr "File"
|
||||
|
||||
msgid "File"
|
||||
msgstr "File"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nuova nota"
|
||||
|
||||
@@ -574,6 +586,9 @@ msgstr "Importa"
|
||||
msgid "Export"
|
||||
msgstr "Importa"
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -599,6 +614,9 @@ msgstr "Cerca in tutte le note"
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -648,12 +666,8 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancella"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Eliminare le note?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -665,9 +679,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Cancella la sincronizzazione"
|
||||
@@ -679,6 +690,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 "
|
||||
@@ -739,6 +753,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"
|
||||
|
||||
@@ -774,12 +793,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."
|
||||
|
||||
@@ -860,6 +880,9 @@ msgstr "Pulisci"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "Login OneDrive"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Opzioni"
|
||||
|
||||
@@ -884,9 +907,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."
|
||||
@@ -899,6 +919,9 @@ msgstr "Uso: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Etichetta sconosciuta: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "File system"
|
||||
|
||||
@@ -976,8 +999,8 @@ msgstr "Elementi remoti eliminati: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Elementi locali creati: %d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Stato: \"%s\"."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -987,6 +1010,16 @@ msgstr "Cancellazione..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Completata: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Errore fatale:"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "La sincronizzazione è già in corso. Stato: %s"
|
||||
@@ -1083,6 +1116,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 ""
|
||||
|
||||
@@ -1169,6 +1205,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Esposta i files di Evernote"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1273,9 +1312,19 @@ msgstr "Conferma"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Cancella la sincronizzazione"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Accedi a OneDrive"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
@@ -1347,6 +1396,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."
|
||||
@@ -1362,6 +1414,16 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Benvenuto"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "Ricerche"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "Eliminare le note?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importa un file blocco note di Evernote (.enex file)."
|
||||
|
||||
|
@@ -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 \":\""
|
||||
@@ -404,6 +405,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 ""
|
||||
@@ -549,16 +560,17 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "ファイル"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "PDF File"
|
||||
msgstr "ファイル"
|
||||
|
||||
msgid "File"
|
||||
msgstr "ファイル"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "新しいノート"
|
||||
|
||||
@@ -575,6 +587,9 @@ msgstr "インポート"
|
||||
msgid "Export"
|
||||
msgstr "インポート"
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -600,6 +615,9 @@ msgstr "すべてのノートを検索"
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -649,12 +667,8 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "ノートを削除しますか?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -665,9 +679,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "同期の中止"
|
||||
@@ -679,6 +690,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 "
|
||||
@@ -741,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 "状態"
|
||||
|
||||
@@ -778,12 +797,13 @@ msgstr "ノートブックの名前を変更:"
|
||||
msgid "Set alarm:"
|
||||
msgstr "アラームをセット:"
|
||||
|
||||
msgid "Search"
|
||||
msgstr "検索"
|
||||
|
||||
msgid "Layout"
|
||||
msgstr "レイアウト"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Search..."
|
||||
msgstr "検索"
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr "いくつかの項目は同期されませんでした。"
|
||||
|
||||
@@ -863,6 +883,9 @@ msgstr "クリア"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "OneDriveログイン"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "オプション"
|
||||
|
||||
@@ -887,9 +910,6 @@ msgstr "同期"
|
||||
msgid "Notebooks"
|
||||
msgstr "ノートブック"
|
||||
|
||||
msgid "Searches"
|
||||
msgstr "検索"
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr "同期状況の出力先を選択してください"
|
||||
|
||||
@@ -901,6 +921,9 @@ msgstr "使用方法: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "不明なフラグ: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "ファイルシステム"
|
||||
|
||||
@@ -978,8 +1001,8 @@ msgstr "リモートアイテムの削除: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "ローカルアイテムの作成: %d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "状態: \"%s\"。"
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -989,6 +1012,16 @@ msgstr "中止中..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "完了: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "致命的なエラー: "
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "同期作業はすでに実行中です。状態: %s"
|
||||
@@ -1087,6 +1120,9 @@ msgstr "あたらしいノートを作成します。"
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr ""
|
||||
|
||||
@@ -1173,6 +1209,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Evernote Exportファイル"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1277,9 +1316,19 @@ msgstr "確認"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "同期の中止"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "OneDriveログイン"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
@@ -1351,6 +1400,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."
|
||||
@@ -1366,6 +1418,16 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "ようこそ"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "検索"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "ノートを削除しますか?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Evernoteノートブックファイル(.enex)のインポート"
|
||||
|
||||
|
@@ -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 \":\""
|
||||
@@ -372,6 +372,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 ""
|
||||
@@ -493,16 +503,16 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
msgid "New note"
|
||||
msgstr ""
|
||||
|
||||
@@ -518,6 +528,9 @@ msgstr ""
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -543,6 +556,9 @@ msgstr ""
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -590,11 +606,7 @@ msgstr ""
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
@@ -606,9 +618,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr ""
|
||||
|
||||
@@ -619,6 +628,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 "
|
||||
@@ -677,6 +689,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 ""
|
||||
|
||||
@@ -712,10 +729,10 @@ msgstr ""
|
||||
msgid "Set alarm:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Search"
|
||||
msgid "Layout"
|
||||
msgstr ""
|
||||
|
||||
msgid "Layout"
|
||||
msgid "Search..."
|
||||
msgstr ""
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
@@ -793,6 +810,9 @@ msgstr ""
|
||||
msgid "OneDrive Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr ""
|
||||
|
||||
@@ -817,9 +837,6 @@ msgstr ""
|
||||
msgid "Notebooks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Searches"
|
||||
msgstr ""
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr ""
|
||||
|
||||
@@ -831,6 +848,9 @@ msgstr ""
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr ""
|
||||
|
||||
@@ -901,7 +921,7 @@ msgid "Fetched items: %d/%d."
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "State: %s."
|
||||
msgstr ""
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -911,6 +931,16 @@ msgstr ""
|
||||
msgid "Completed: %s"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr ""
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr ""
|
||||
@@ -999,6 +1029,9 @@ msgstr ""
|
||||
msgid "Show tray icon"
|
||||
msgstr ""
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
msgid "Global zoom percentage"
|
||||
msgstr ""
|
||||
|
||||
@@ -1081,6 +1114,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr ""
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1184,9 +1220,18 @@ msgstr ""
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr ""
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
@@ -1257,6 +1302,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."
|
||||
|
@@ -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 \":\""
|
||||
@@ -415,6 +416,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 ""
|
||||
@@ -566,16 +577,17 @@ msgstr ""
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Bestand"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "PDF File"
|
||||
msgstr "Bestand"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Bestand"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nieuwe notitie"
|
||||
|
||||
@@ -592,6 +604,9 @@ msgstr "Importeer"
|
||||
msgid "Export"
|
||||
msgstr "Importeer"
|
||||
|
||||
msgid "Print"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
@@ -617,6 +632,9 @@ msgstr "Zoek in alle notities"
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
|
||||
@@ -665,12 +683,8 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Annuleer"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Notities verwijderen?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
@@ -682,9 +696,6 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Annuleer synchronisatie"
|
||||
@@ -696,6 +707,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 "
|
||||
@@ -766,6 +780,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"
|
||||
|
||||
@@ -803,12 +822,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."
|
||||
|
||||
@@ -889,6 +909,9 @@ msgstr "Vrijmaken"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "OneDrive Login"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Opties"
|
||||
|
||||
@@ -913,9 +936,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"
|
||||
|
||||
@@ -927,6 +947,9 @@ msgstr "Gebruik: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Onbekende optie: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Bestandssysteem"
|
||||
|
||||
@@ -1005,8 +1028,8 @@ msgstr "Verwijderde remote items: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Opgehaalde items: %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Status: \"%s\""
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1016,6 +1039,16 @@ msgstr "Annuleren..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Voltooid: %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Fatale fout:"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr ""
|
||||
|
||||
msgid "In progress"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Synchronisatie is reeds bezig. Status: %s"
|
||||
@@ -1113,6 +1146,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 ""
|
||||
|
||||
@@ -1201,6 +1237,9 @@ msgstr ""
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Exporteer Evernote bestanden"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
@@ -1309,9 +1348,19 @@ msgstr "Bevestig"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Annuleer synchronisatie"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Log in met OneDrive"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr "Hoofdsleutel: %s"
|
||||
@@ -1382,6 +1431,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."
|
||||
@@ -1397,6 +1449,16 @@ msgstr ""
|
||||
msgid "Welcome"
|
||||
msgstr "Welkom"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "Zoekopdrachten"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "Notities verwijderen?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importeer een Evernote notitieboek (.enex bestand)."
|
||||
|
||||
|
@@ -7,13 +7,13 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Joplin-CLI 1.0.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: \n"
|
||||
"Last-Translator: Renato Nunes Bastos <rnbastos@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: pt_BR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.5\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."
|
||||
@@ -50,16 +50,16 @@ msgstr "s"
|
||||
msgid "Cancelling background synchronisation... Please wait."
|
||||
msgstr "Cancelando sincronização em segundo plano... Por favor, aguarde."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "No such command: %s"
|
||||
msgstr "Comando inválido: \"%s\""
|
||||
msgstr "Não existe o comando: \"%s\""
|
||||
|
||||
#, javascript-format
|
||||
msgid "The command \"%s\" is only available in GUI mode"
|
||||
msgstr "O comando \"%s\" está disponível somente em modo gráfico"
|
||||
|
||||
msgid "Cannot change encrypted item"
|
||||
msgstr ""
|
||||
msgstr "Não pode mudar um item encriptado"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Missing required argument: %s"
|
||||
@@ -127,22 +127,25 @@ msgid ""
|
||||
"Manages E2EE configuration. Commands are `enable`, `disable`, `decrypt`, "
|
||||
"`status` and `target-status`."
|
||||
msgstr ""
|
||||
"Gerencia a configuração E2EE. Os comandos são `enable`, `disable`, "
|
||||
"`decrypt`, `status` e `target-status`."
|
||||
|
||||
msgid "Enter master password:"
|
||||
msgstr ""
|
||||
msgstr "Entre a senha master:"
|
||||
|
||||
msgid "Operation cancelled"
|
||||
msgstr ""
|
||||
msgstr "Operação cancelada"
|
||||
|
||||
msgid ""
|
||||
"Starting decryption... Please wait as it may take several minutes depending "
|
||||
"on how much there is to decrypt."
|
||||
msgstr ""
|
||||
"Iniciando decriptação... Por favor aguarde, pois isso pode demorar vários "
|
||||
"minutos, dependendo de quanto há para decriptar."
|
||||
|
||||
msgid "Completed decryption."
|
||||
msgstr ""
|
||||
msgstr "Decriptação completada."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enabled"
|
||||
msgstr "Desabilitado"
|
||||
|
||||
@@ -151,7 +154,7 @@ msgstr "Desabilitado"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Encryption is: %s"
|
||||
msgstr ""
|
||||
msgstr "Encriptação está: %s"
|
||||
|
||||
msgid "Edit note."
|
||||
msgstr "Editar nota."
|
||||
@@ -174,7 +177,7 @@ msgstr "Começando a editar a nota. Feche o editor para voltar ao prompt."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Error opening note in editor: %s"
|
||||
msgstr ""
|
||||
msgstr "Erro ao abir a nota no editor: %s"
|
||||
|
||||
msgid "Note has been saved."
|
||||
msgstr "Nota gravada."
|
||||
@@ -182,7 +185,6 @@ msgstr "Nota gravada."
|
||||
msgid "Exits the application."
|
||||
msgstr "Sai da aplicação."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Exports Joplin data to the given path. By default, it will export the "
|
||||
"complete database including notebooks, notes, tags and resources."
|
||||
@@ -191,9 +193,9 @@ msgstr ""
|
||||
"exportará o banco de dados completo, incluindo cadernos, notas, tags e "
|
||||
"recursos."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Destination format: %s"
|
||||
msgstr "Formato de data"
|
||||
msgstr "Formato do destino: %s"
|
||||
|
||||
msgid "Exports only the given note."
|
||||
msgstr "Exporta apenas a nota fornecida."
|
||||
@@ -209,16 +211,17 @@ msgstr "Exibe informações de uso."
|
||||
|
||||
#, javascript-format
|
||||
msgid "For information on how to customise the shortcuts please visit %s"
|
||||
msgstr ""
|
||||
msgstr "Para informações sobre como customizar os atalhos, por favor visite %s"
|
||||
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr "Os atalhos não estão disponíveis no modo CLI."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Type `help [command]` for more information about a command; or type `help "
|
||||
"all` for the complete usage information."
|
||||
msgstr "Digite `help [comando]` para obter mais informações sobre um comando."
|
||||
msgstr ""
|
||||
"Digite `help [comando]` para obter mais informações sobre um comando; ou "
|
||||
"digite `help all` para informações completas de uso."
|
||||
|
||||
msgid "The possible commands are:"
|
||||
msgstr "Os comandos possíveis são:"
|
||||
@@ -243,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 \":\""
|
||||
@@ -252,19 +256,17 @@ msgstr "Para entrar no modo de linha de comando, pressione \":\""
|
||||
msgid "To exit command line mode, press ESCAPE"
|
||||
msgstr "Para sair do modo de linha de comando, pressione o ESC"
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`"
|
||||
msgstr ""
|
||||
"Para a lista completa de atalhos de teclado disponíveis, digite `help "
|
||||
"shortcuts`"
|
||||
"Para a lista completa de atalhos de teclado disponíveis, digite `help keymap`"
|
||||
|
||||
msgid "Imports data into Joplin."
|
||||
msgstr ""
|
||||
msgstr "Importa dados para o Joplin."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Source format: %s"
|
||||
msgstr "Comando inválido: \"%s\""
|
||||
msgstr "Formato da origem: \"%s\""
|
||||
|
||||
msgid "Do not ask for confirmation."
|
||||
msgstr "Não pedir confirmação."
|
||||
@@ -363,6 +365,8 @@ msgstr "Exclui o caderno sem pedir confirmação."
|
||||
|
||||
msgid "Delete notebook? All notes within this notebook will also be deleted."
|
||||
msgstr ""
|
||||
"Excluir o caderno? Todas as notas deste caderno notebook também serão "
|
||||
"excluídas."
|
||||
|
||||
msgid "Deletes the notes matching <note-pattern>."
|
||||
msgstr "Exclui as notas correspondentes ao padrão <note-pattern>."
|
||||
@@ -380,13 +384,17 @@ msgstr "Apagar nota?"
|
||||
msgid "Searches for the given <pattern> in all the notes."
|
||||
msgstr "Procura o padrão <pattern>em todas as notas."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"Sets the property <name> of the given <note> to the given [value]. Possible "
|
||||
"properties are:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Define a propriedade <name> da <note> para o dado [valor]."
|
||||
msgstr ""
|
||||
"Define a propriedade <name> da <note> para o valor [value]. As propriedades "
|
||||
"possíveis são:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
|
||||
msgid "Displays summary about the notes and notebooks."
|
||||
msgstr "Exibe sumário sobre as notas e cadernos."
|
||||
@@ -404,9 +412,23 @@ 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 ""
|
||||
"Não autenticado com %s. Por favor, complete as credenciais que estiverem "
|
||||
"faltando."
|
||||
|
||||
msgid "Synchronisation is already in progress."
|
||||
msgstr "A sincronização já está em andamento."
|
||||
@@ -493,9 +515,8 @@ msgstr "Padrão: %s"
|
||||
msgid "Possible keys/values:"
|
||||
msgstr "Possíveis chaves/valores:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Type `joplin help` for usage information."
|
||||
msgstr "Exibe informações de uso."
|
||||
msgstr "Digite 'joplin help' para informações de uso."
|
||||
|
||||
msgid "Fatal error:"
|
||||
msgstr "Erro fatal:"
|
||||
@@ -532,6 +553,13 @@ msgid ""
|
||||
"\n"
|
||||
"For example, to create a notebook press `mb`; to create a note press `mn`."
|
||||
msgstr ""
|
||||
"Bem-vindo ao Joplin!\n"
|
||||
"\n"
|
||||
"Digite `:help shortcuts` para obter a lista de atalhos de teclado, ou apenas "
|
||||
"`:help` para informações de utilização.\n"
|
||||
"\n"
|
||||
"Por exemplo, para criar um caderno digite `mb`; para criar uma nota, digite "
|
||||
"`mn`."
|
||||
|
||||
msgid ""
|
||||
"One or more items are currently encrypted and you may need to supply a "
|
||||
@@ -539,20 +567,24 @@ msgid ""
|
||||
"supplied the password, the encrypted items are being decrypted in the "
|
||||
"background and will be available soon."
|
||||
msgstr ""
|
||||
"Um ou mais itens estão criptografados, e você pode precisar de informar uma "
|
||||
"senha master. Para fazer isso, por favor digite `e2ee decrypt`. Se você já "
|
||||
"forneceu a senha, os itens criptografados estão sendo decriptados em "
|
||||
"background e logo estarão disponíveis."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Arquivo"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
msgstr "Exportando para \"%s\" com o formato \"%s\". Por favor, aguarde..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
msgstr "Importando de \"%s\" com o formato \"%s\". Por favor, aguarde..."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "Arquivo PDF"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Arquivo"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Nova nota"
|
||||
@@ -566,13 +598,15 @@ msgstr "Novo caderno"
|
||||
msgid "Import"
|
||||
msgstr "Importar"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Export"
|
||||
msgstr "Importar"
|
||||
msgstr "Exportar"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Imprimir"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
msgstr "Ocultar %s"
|
||||
|
||||
msgid "Quit"
|
||||
msgstr "Sair"
|
||||
@@ -593,24 +627,25 @@ msgid "Search in all the notes"
|
||||
msgstr "Pesquisar em todas as notas"
|
||||
|
||||
msgid "View"
|
||||
msgstr "Visualizar"
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
msgstr "Alternar layout do editor"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Ferramentas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation status"
|
||||
msgstr "Alvo de sincronização"
|
||||
msgstr "Status de sincronização"
|
||||
|
||||
msgid "Encryption options"
|
||||
msgstr ""
|
||||
msgstr "Opções de Encriptação"
|
||||
|
||||
#, fuzzy
|
||||
msgid "General Options"
|
||||
msgstr "Opções"
|
||||
msgstr "Opções Gerais"
|
||||
|
||||
msgid "Help"
|
||||
msgstr "Ajuda"
|
||||
@@ -618,12 +653,11 @@ msgstr "Ajuda"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Website e documentação"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Make a donation"
|
||||
msgstr "Website e documentação"
|
||||
msgstr "Fazer uma doação"
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr ""
|
||||
msgstr "Verificar atualizações..."
|
||||
|
||||
msgid "About Joplin"
|
||||
msgstr "Sobre o Joplin"
|
||||
@@ -632,12 +666,12 @@ msgstr "Sobre o Joplin"
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr "%s %s (%s, %s)"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
msgstr "Em %s: %s"
|
||||
msgstr "Abrir %s"
|
||||
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
msgstr "Sair"
|
||||
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
@@ -645,42 +679,38 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Excluir notas?"
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "A versão atual está atualizada."
|
||||
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr ""
|
||||
msgstr "Uma atualização está disponível, você quer baixar agora?"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "Sim"
|
||||
|
||||
#, fuzzy
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
msgstr "Não"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Cancelar sincronização"
|
||||
msgstr "Verificar a configuração da sincronização"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
msgstr ""
|
||||
msgstr "Notas e configurações estão armazenadas em: %s"
|
||||
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
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 "
|
||||
"continue?"
|
||||
msgstr ""
|
||||
"Desabilitar a encriptação significa que *todas* as suas notas e anexos serão "
|
||||
"re-sincronizados e enviados sem encriptação. Você quer continuar?"
|
||||
|
||||
msgid ""
|
||||
"Enabling encryption means *all* your notes and attachments are going to be "
|
||||
@@ -688,59 +718,75 @@ msgid ""
|
||||
"password as, for security purposes, this will be the *only* way to decrypt "
|
||||
"the data! To enable encryption, please enter your password below."
|
||||
msgstr ""
|
||||
"Habilitar a encriptação significa que *todas* as suas notas e anexos serão "
|
||||
"re-sincronizados e re-enviados com encriptação. Não perca sua senha, pois, "
|
||||
"por medidas de segurança, esse será o *único* modo de decriptar seus dados! "
|
||||
"Para habilitar a encriptação, por favor entre sua senha abaixo."
|
||||
|
||||
msgid "Disable encryption"
|
||||
msgstr ""
|
||||
msgstr "Desabilitar encriptação"
|
||||
|
||||
msgid "Enable encryption"
|
||||
msgstr ""
|
||||
msgstr "Habilitar encriptação"
|
||||
|
||||
msgid "Master Keys"
|
||||
msgstr ""
|
||||
msgstr "Chaves mestras"
|
||||
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Ativar"
|
||||
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
msgstr "ID"
|
||||
|
||||
msgid "Source"
|
||||
msgstr ""
|
||||
msgstr "Origem"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Created"
|
||||
msgstr "Criado: %d."
|
||||
msgstr "Criado"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Updated"
|
||||
msgstr "Atualizado: %d."
|
||||
msgstr "Atualizado"
|
||||
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
msgstr "Senha"
|
||||
|
||||
msgid "Password OK"
|
||||
msgstr ""
|
||||
msgstr "Senha OK"
|
||||
|
||||
msgid ""
|
||||
"Note: Only one master key is going to be used for encryption (the one marked "
|
||||
"as \"active\"). Any of the keys might be used for decryption, depending on "
|
||||
"how the notes or notebooks were originally encrypted."
|
||||
msgstr ""
|
||||
"Noto: Apenas uma chave máster será usada para encriptação (a que estiver "
|
||||
"marcada como \"ativa\"). Qualquer uma das chaves pode ser usada para "
|
||||
"decriptação, dependendo de como as notas ou os cadernos foram encriptados "
|
||||
"originalmente."
|
||||
|
||||
msgid "Missing Master Keys"
|
||||
msgstr ""
|
||||
msgstr "Chaves Master faltando"
|
||||
|
||||
msgid ""
|
||||
"The master keys with these IDs are used to encrypt some of your items, "
|
||||
"however the application does not currently have access to them. It is likely "
|
||||
"they will eventually be downloaded via synchronisation."
|
||||
msgstr ""
|
||||
"As chaves master com essas IDs são usadas para encriptar alguns de seus "
|
||||
"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"
|
||||
|
||||
msgid "Encryption is:"
|
||||
msgstr ""
|
||||
msgstr "Encriptação está:"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Voltar"
|
||||
@@ -772,25 +818,23 @@ msgstr "Renomear caderno:"
|
||||
msgid "Set alarm:"
|
||||
msgstr "Definir alarme:"
|
||||
|
||||
msgid "Search"
|
||||
msgstr "Procurar"
|
||||
|
||||
msgid "Layout"
|
||||
msgstr "Layout"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Search..."
|
||||
msgstr "Pesquisar..."
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr "Não é possível inicializar o sincronizador."
|
||||
msgstr "Alguns itens não podem ser sincronizados."
|
||||
|
||||
msgid "View them now"
|
||||
msgstr ""
|
||||
msgstr "Visualizar agora"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Some items cannot be decrypted."
|
||||
msgstr "Não é possível inicializar o sincronizador."
|
||||
msgstr "Alguns itens não podem ser decriptados."
|
||||
|
||||
msgid "Set the password"
|
||||
msgstr ""
|
||||
msgstr "Configurar a senha"
|
||||
|
||||
msgid "Add or remove tags"
|
||||
msgstr "Adicionar ou remover tags"
|
||||
@@ -807,17 +851,15 @@ msgstr "Excluir notas?"
|
||||
msgid "No notes in here. Create one by clicking on \"New note\"."
|
||||
msgstr "Não há notas aqui. Crie uma, clicando em \"Nova nota\"."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"There is currently no notebook. Create one by clicking on \"New notebook\"."
|
||||
msgstr "Atualmente, não há notas. Crie uma, clicando no botão (+)."
|
||||
msgstr "Atualmente, não há cadernos. Crie um, clicando em \"Novo caderno\"."
|
||||
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
msgstr "Abrir..."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Save as..."
|
||||
msgstr "Gravar alterações"
|
||||
msgstr "Salvar como..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
@@ -837,18 +879,18 @@ msgid ""
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the "
|
||||
"note."
|
||||
msgstr ""
|
||||
"Esta nota não possui conteúdo. Clique em \"%s\" para alternar para o editor, "
|
||||
"e edite a nota."
|
||||
|
||||
#, fuzzy
|
||||
msgid "to-do"
|
||||
msgstr "Nova tarefa"
|
||||
msgstr "tarefa"
|
||||
|
||||
#, fuzzy
|
||||
msgid "note"
|
||||
msgstr "Nova nota"
|
||||
msgstr "nota"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Creating new %s..."
|
||||
msgstr "Importando notas ..."
|
||||
msgstr "Criando novo %s..."
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr "Atualizar"
|
||||
@@ -859,15 +901,17 @@ msgstr "Limpar (clear)"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "Login no OneDrive"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr "Login no Dropbox"
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Opções"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Synchronisation Status"
|
||||
msgstr "Alvo de sincronização"
|
||||
msgstr "Status de sincronização"
|
||||
|
||||
msgid "Encryption Options"
|
||||
msgstr ""
|
||||
msgstr "Opções de Encriptação"
|
||||
|
||||
msgid "Remove this tag from all the notes?"
|
||||
msgstr "Remover esta tag de todas as notas?"
|
||||
@@ -884,12 +928,10 @@ msgstr "Sincronizar"
|
||||
msgid "Notebooks"
|
||||
msgstr "Cadernos"
|
||||
|
||||
msgid "Searches"
|
||||
msgstr "Pesquisas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr "Por favor, primeiro, selecione a nota ou caderno a excluir."
|
||||
msgstr ""
|
||||
"Favor selecionar o local para onde o status de sincronia deveria ser "
|
||||
"exportado"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Usage: %s"
|
||||
@@ -899,11 +941,14 @@ msgstr "Uso: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Flag desconhecido: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr "Dropbox"
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Sistema de arquivos"
|
||||
|
||||
msgid "Nextcloud"
|
||||
msgstr ""
|
||||
msgstr "Nextcloud"
|
||||
|
||||
msgid "OneDrive"
|
||||
msgstr "OneDrive"
|
||||
@@ -912,7 +957,7 @@ msgid "OneDrive Dev (For testing only)"
|
||||
msgstr "OneDrive Dev (apenas para testes)"
|
||||
|
||||
msgid "WebDAV"
|
||||
msgstr ""
|
||||
msgstr "WebDAV"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unknown log level: %s"
|
||||
@@ -972,12 +1017,12 @@ msgstr "Itens locais excluídos: %d."
|
||||
msgid "Deleted remote items: %d."
|
||||
msgstr "Itens remotos excluídos: %d."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Itens locais criados: %d."
|
||||
msgstr "Itens pesquisados: %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
msgid "State: %s."
|
||||
msgstr "Estado: \"%s\"."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -987,16 +1032,25 @@ msgstr "Cancelando..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Completado: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Último erro: %s"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr "Inativo"
|
||||
|
||||
msgid "In progress"
|
||||
msgstr "Em andamento"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Sincronização já em andamento. Estado: %s"
|
||||
|
||||
msgid "Encrypted"
|
||||
msgstr ""
|
||||
msgstr "Encriptado"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Encrypted items cannot be modified"
|
||||
msgstr "Não é possível inicializar o sincronizador."
|
||||
msgstr "Itens encriptados não podem ser modificados"
|
||||
|
||||
msgid "Conflicts"
|
||||
msgstr "Conflitos"
|
||||
@@ -1018,7 +1072,7 @@ msgstr "Esta nota não possui informações de geolocalização."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot copy note to \"%s\" notebook"
|
||||
msgstr "Não é possível copiar a nota para o caderno \"%s\" "
|
||||
msgstr "Não é possível copiar a nota para o caderno \"%s\""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot move note to \"%s\" notebook"
|
||||
@@ -1052,48 +1106,48 @@ msgstr "Light"
|
||||
msgid "Dark"
|
||||
msgstr "Dark"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Mostrar tarefas incompletas no topo das listas"
|
||||
msgstr "Mostrar tarefas incompletas no topo"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
msgstr "Ordenar notas por"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Reverse sort order"
|
||||
msgstr "Inverte a ordem de classificação."
|
||||
msgstr "Inverter ordem de classificação."
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr "Salvar geolocalização com notas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "When creating a new to-do:"
|
||||
msgstr "Cria uma nova tarefa."
|
||||
msgstr "Quando criar uma nova tarefa:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Focus title"
|
||||
msgstr "Título da nota:"
|
||||
msgstr "Foco no título"
|
||||
|
||||
msgid "Focus body"
|
||||
msgstr ""
|
||||
msgstr "Focar no corpo"
|
||||
|
||||
#, fuzzy
|
||||
msgid "When creating a new note:"
|
||||
msgstr "Cria uma nova nota."
|
||||
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 ""
|
||||
msgstr "Porcentagem global do zoom"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr ""
|
||||
msgstr "Família de fontes do editor"
|
||||
|
||||
msgid ""
|
||||
"The font name will not be checked. If incorrect or empty, it will default to "
|
||||
"a generic monospace font."
|
||||
msgstr ""
|
||||
"O nomes da fonte não será verificado. Se estiver incorreto ou vazio, será "
|
||||
"usado por default uma fonte genérica monospace."
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr "Atualizar automaticamente o aplicativo"
|
||||
@@ -1123,9 +1177,11 @@ msgid ""
|
||||
"The target to synchonise to. Each sync target may have additional parameters "
|
||||
"which are named as `sync.NUM.NAME` (all documented below)."
|
||||
msgstr ""
|
||||
"O alvo para onde sincronizar. Cada alvo pode ter parâmetros adicionais que "
|
||||
"são nomeados como `sync.NUM.NAME` (todos documentados abaixo)."
|
||||
|
||||
msgid "Directory to synchronise with (absolute path)"
|
||||
msgstr ""
|
||||
msgstr "Diretório para sincronizar (caminho absoluto)"
|
||||
|
||||
msgid ""
|
||||
"The path to synchronise with when file system synchronisation is enabled. "
|
||||
@@ -1135,74 +1191,80 @@ msgstr ""
|
||||
"está habilitada. Veja `sync.target`."
|
||||
|
||||
msgid "Nextcloud WebDAV URL"
|
||||
msgstr ""
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
|
||||
msgid "Nextcloud username"
|
||||
msgstr ""
|
||||
msgstr "Usuário da Nextcloud"
|
||||
|
||||
msgid "Nextcloud password"
|
||||
msgstr ""
|
||||
msgstr "Senha da Nextcloud"
|
||||
|
||||
msgid "WebDAV URL"
|
||||
msgstr ""
|
||||
msgstr "WebDAV URL"
|
||||
|
||||
msgid "WebDAV username"
|
||||
msgstr ""
|
||||
msgstr "Usuário do WebDAV"
|
||||
|
||||
msgid "WebDAV password"
|
||||
msgstr ""
|
||||
msgstr "Senha do WebDAV"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Valor da opção inválida: \"%s\". Os valores possíveis são: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Export File"
|
||||
msgstr "Arquivos de Exportação do Evernote"
|
||||
msgstr "Arquivo de Exportação do Joplin"
|
||||
|
||||
msgid "Markdown"
|
||||
msgstr ""
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr ""
|
||||
msgstr "Diretório de Exportação do Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Arquivos de Exportação do Evernote"
|
||||
msgstr "Arquivo de Exportação do Evernote"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "DIretório"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
msgstr "Não é possível carregar o módulo \"%s\" para o formato \"%s\""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Please specify import format for %s"
|
||||
msgstr ""
|
||||
msgstr "Favor especificar o formato de importação para %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This item is currently encrypted: %s \"%s\". Please wait for all items to be "
|
||||
"decrypted and try again."
|
||||
msgstr ""
|
||||
"Este item atualmente está encriptado: %s \"%s\". Favor aguardar que todos os "
|
||||
"itens sejam decriptados e tente novamente."
|
||||
|
||||
msgid "There is no data to export."
|
||||
msgstr ""
|
||||
msgstr "Não há dados a exportar."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr "Por favor, primeiro, selecione a nota ou caderno a excluir."
|
||||
msgstr ""
|
||||
"Por favor, especifique o caderno para onde as notas deveriam ser importadas."
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr ""
|
||||
msgstr "Os itens não podem ser sincronizados"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "%s (%s): %s"
|
||||
msgstr "%s %s (%s)"
|
||||
msgstr "%s (%s): %s"
|
||||
|
||||
msgid ""
|
||||
"These items will remain on the device but will not be uploaded to the sync "
|
||||
"target. In order to find these items, either search for the title or the ID "
|
||||
"(which is displayed in brackets above)."
|
||||
msgstr ""
|
||||
"Estes itens continuarão no dispositivo mas não serão enviados ao alvo de "
|
||||
"sincronização. Para encontrar esses itens, ou pesquise pelo título ou pelo "
|
||||
"ID (que é exibido nos colchetes acima)"
|
||||
|
||||
msgid "Sync status (synced items / total items)"
|
||||
msgstr "Status de sincronização (sincronizados / totais)"
|
||||
@@ -1250,7 +1312,7 @@ msgid "Export Debug Report"
|
||||
msgstr "Exportar Relatório de Debug"
|
||||
|
||||
msgid "Encryption Config"
|
||||
msgstr ""
|
||||
msgstr "Configuração de Encriptação"
|
||||
|
||||
msgid "Configuration"
|
||||
msgstr "Configuração"
|
||||
@@ -1263,7 +1325,7 @@ msgid "Move %d notes to notebook \"%s\"?"
|
||||
msgstr "Mover %d notas para o caderno \"%s\"?"
|
||||
|
||||
msgid "Press to set the decryption password."
|
||||
msgstr ""
|
||||
msgstr "Pressione para configurar a senha de decriptação."
|
||||
|
||||
msgid "Select date"
|
||||
msgstr "Selecionar data"
|
||||
@@ -1274,26 +1336,34 @@ msgstr "Confirmar"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Cancelar sincronização"
|
||||
|
||||
msgid "New tags:"
|
||||
msgstr "Novas tags:"
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr "Digite novsa tags, ou selecione da lista"
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr ""
|
||||
msgstr "Site do Joplin"
|
||||
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Login com Dropbox"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr ""
|
||||
msgstr "Chave Master %s"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Created: %s"
|
||||
msgstr "Criado: %d."
|
||||
msgstr "Criado: %s"
|
||||
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
msgstr "Senha:"
|
||||
|
||||
msgid "Password cannot be empty"
|
||||
msgstr ""
|
||||
msgstr "Senha não pode ser vazia"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Enable"
|
||||
msgstr "Desabilitado"
|
||||
msgstr "Habilitar"
|
||||
|
||||
#, javascript-format
|
||||
msgid "The notebook could not be saved: %s"
|
||||
@@ -1303,10 +1373,10 @@ msgid "Edit notebook"
|
||||
msgstr "Editar caderno"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
msgstr "Exibir tudo"
|
||||
|
||||
msgid "Errors only"
|
||||
msgstr ""
|
||||
msgstr "Somente erros"
|
||||
|
||||
msgid "This note has been modified:"
|
||||
msgstr "Esta nota foi modificada:"
|
||||
@@ -1348,6 +1418,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."
|
||||
@@ -1361,6 +1434,18 @@ 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"
|
||||
#~ "%s"
|
||||
#~ msgstr ""
|
||||
#~ "Notas da versão:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Importa um arquivo de caderno do Evernote (arquivo .enex)."
|
||||
|
||||
|
@@ -189,17 +189,16 @@ msgstr "Заметка сохранена."
|
||||
msgid "Exits the application."
|
||||
msgstr "Выход из приложения."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Exports Joplin data to the given path. By default, it will export the "
|
||||
"complete database including notebooks, notes, tags and resources."
|
||||
msgstr ""
|
||||
"Экспортирует данные Joplin в заданный каталог. По умолчанию экспортируется "
|
||||
"Экспортирует данные Joplin по заданному пути. По умолчанию экспортируется "
|
||||
"полная база данных, включая блокноты, заметки, теги и ресурсы."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Destination format: %s"
|
||||
msgstr "Формат даты"
|
||||
msgstr "Целевой формат: %s"
|
||||
|
||||
msgid "Exports only the given note."
|
||||
msgstr "Экспортирует только заданную заметку."
|
||||
@@ -215,7 +214,7 @@ msgstr "Выводит информацию об использовании."
|
||||
|
||||
#, javascript-format
|
||||
msgid "For information on how to customise the shortcuts please visit %s"
|
||||
msgstr ""
|
||||
msgstr "Информацию по настройке сочетаний можно получить, посетив %s"
|
||||
|
||||
msgid "Shortcuts are not available in CLI mode."
|
||||
msgstr "Ярлыки недоступны в режиме командной строки."
|
||||
@@ -250,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 \":\""
|
||||
@@ -259,19 +259,18 @@ msgstr "Чтобы войти в режим командной строки, н
|
||||
msgid "To exit command line mode, press ESCAPE"
|
||||
msgstr "Чтобы выйти из режима командной строки, нажмите ESCAPE"
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"For the list of keyboard shortcuts and config options, type `help keymap`"
|
||||
msgstr ""
|
||||
"Для просмотра списка доступных клавиатурных сочетаний введите `help "
|
||||
"shortcuts`"
|
||||
"Для просмотра списка клавиатурных сочетаний и настроек конфигурации введите "
|
||||
"`help keymap`"
|
||||
|
||||
msgid "Imports data into Joplin."
|
||||
msgstr ""
|
||||
msgstr "Импортирует данные в Joplin."
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Source format: %s"
|
||||
msgstr "Нет такой команды: %s"
|
||||
msgstr "Исходный формат: %s"
|
||||
|
||||
msgid "Do not ask for confirmation."
|
||||
msgstr "Не запрашивать подтверждение."
|
||||
@@ -416,6 +415,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 ""
|
||||
@@ -507,9 +516,8 @@ msgstr "По умолчанию: %s"
|
||||
msgid "Possible keys/values:"
|
||||
msgstr "Возможные ключи/значения:"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Type `joplin help` for usage information."
|
||||
msgstr "Выводит информацию об использовании."
|
||||
msgstr "Введите `joplin help` для получения информации об использовании."
|
||||
|
||||
msgid "Fatal error:"
|
||||
msgstr "Фатальная ошибка:"
|
||||
@@ -566,17 +574,17 @@ msgstr ""
|
||||
|
||||
#, javascript-format
|
||||
msgid "Exporting to \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
|
||||
msgid "File"
|
||||
msgstr "Файл"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr ""
|
||||
msgstr "Экспорт в «%s» в формате «%s». Пожалуйста, ожидайте..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Importing from \"%s\" as \"%s\" format. Please wait..."
|
||||
msgstr ""
|
||||
msgstr "Импорт из «%s» в формате «%s». Пожалуйста, ожидайте..."
|
||||
|
||||
msgid "PDF File"
|
||||
msgstr "PDF-файл"
|
||||
|
||||
msgid "File"
|
||||
msgstr "Файл"
|
||||
|
||||
msgid "New note"
|
||||
msgstr "Новая заметка"
|
||||
@@ -590,13 +598,15 @@ msgstr "Новый блокнот"
|
||||
msgid "Import"
|
||||
msgstr "Импорт"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Export"
|
||||
msgstr "Импорт"
|
||||
msgstr "Экспорт"
|
||||
|
||||
msgid "Print"
|
||||
msgstr "Печать"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Hide %s"
|
||||
msgstr ""
|
||||
msgstr "Скрыть %s"
|
||||
|
||||
msgid "Quit"
|
||||
msgstr "Выход"
|
||||
@@ -617,10 +627,13 @@ msgid "Search in all the notes"
|
||||
msgstr "Поиск во всех заметках"
|
||||
|
||||
msgid "View"
|
||||
msgstr "Вид"
|
||||
|
||||
msgid "Toggle sidebar"
|
||||
msgstr ""
|
||||
|
||||
msgid "Toggle editor layout"
|
||||
msgstr ""
|
||||
msgstr "Переключить вид редактора"
|
||||
|
||||
msgid "Tools"
|
||||
msgstr "Инструменты"
|
||||
@@ -640,9 +653,8 @@ msgstr "Помощь"
|
||||
msgid "Website and documentation"
|
||||
msgstr "Сайт и документация"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Make a donation"
|
||||
msgstr "Сайт и документация"
|
||||
msgstr "Сделать пожертвование"
|
||||
|
||||
msgid "Check for updates..."
|
||||
msgstr "Проверить обновления..."
|
||||
@@ -654,12 +666,12 @@ msgstr "О Joplin"
|
||||
msgid "%s %s (%s, %s)"
|
||||
msgstr "%s %s (%s, %s)"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Open %s"
|
||||
msgstr "В %s: %s"
|
||||
msgstr "Открыть %s"
|
||||
|
||||
msgid "Exit"
|
||||
msgstr ""
|
||||
msgstr "Выход"
|
||||
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
@@ -667,30 +679,20 @@ msgstr "OK"
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
msgid ""
|
||||
"Release notes:\n"
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr "Удалить заметки?"
|
||||
|
||||
#, fuzzy
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr "Доступно обновление. Обновить сейчас?"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "No"
|
||||
msgstr "N"
|
||||
|
||||
msgid "Current version is up-to-date."
|
||||
msgstr "Вы используете самую свежую версию."
|
||||
|
||||
#, fuzzy
|
||||
msgid "An update is available, do you want to download it now?"
|
||||
msgstr "Доступно обновление. Желаете скачать его сейчас?"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "Да"
|
||||
|
||||
msgid "No"
|
||||
msgstr "Нет"
|
||||
|
||||
msgid "Check synchronisation configuration"
|
||||
msgstr "Отменить синхронизацию"
|
||||
msgstr "Проверить настройки синхронизации"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Notes and settings are stored in: %s"
|
||||
@@ -699,6 +701,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,15 +765,22 @@ msgstr ""
|
||||
"ключей, в зависимости от того, как изначально были зашифрованы заметки или "
|
||||
"блокноты."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Missing Master Keys"
|
||||
msgstr "Мастер-ключи"
|
||||
msgstr "Недостающие мастер-ключи"
|
||||
|
||||
msgid ""
|
||||
"The master keys with these IDs are used to encrypt some of your items, "
|
||||
"however the application does not currently have access to them. It is likely "
|
||||
"they will eventually be downloaded via synchronisation."
|
||||
msgstr ""
|
||||
"Мастер-ключи с такими ID используются для шифрования некоторых из ваших "
|
||||
"элементов, однако у приложения сейчас нет к ним доступа. Скорее всего, они "
|
||||
"загрузятся при синхронизации."
|
||||
|
||||
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 "Статус"
|
||||
@@ -805,12 +817,13 @@ msgstr "Переименовать блокнот:"
|
||||
msgid "Set alarm:"
|
||||
msgstr "Установить напоминание:"
|
||||
|
||||
msgid "Search"
|
||||
msgstr "Поиск"
|
||||
|
||||
msgid "Layout"
|
||||
msgstr "Вид"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Search..."
|
||||
msgstr "Поиск"
|
||||
|
||||
msgid "Some items cannot be synchronised."
|
||||
msgstr "Некоторые элементы не могут быть синхронизированы."
|
||||
|
||||
@@ -843,11 +856,10 @@ msgid ""
|
||||
msgstr "Сейчас здесь нет блокнотов. Создайте новый нажав «Новый блокнот»."
|
||||
|
||||
msgid "Open..."
|
||||
msgstr ""
|
||||
msgstr "Открыть..."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Save as..."
|
||||
msgstr "Сохранить изменения"
|
||||
msgstr "Сохранить как..."
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unsupported link or message: %s"
|
||||
@@ -867,18 +879,18 @@ msgid ""
|
||||
"This note has no content. Click on \"%s\" to toggle the editor and edit the "
|
||||
"note."
|
||||
msgstr ""
|
||||
"Заметка пуста. Нажмите на «%s», чтобы переключиться в редактор и "
|
||||
"отредактировать её."
|
||||
|
||||
#, fuzzy
|
||||
msgid "to-do"
|
||||
msgstr "Новая задача"
|
||||
msgstr "задача"
|
||||
|
||||
#, fuzzy
|
||||
msgid "note"
|
||||
msgstr "Новая заметка"
|
||||
msgstr "заметка"
|
||||
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Creating new %s..."
|
||||
msgstr "Импорт заметок..."
|
||||
msgstr "Создание новой %s..."
|
||||
|
||||
msgid "Refresh"
|
||||
msgstr "Обновить"
|
||||
@@ -889,6 +901,9 @@ msgstr "Очистить"
|
||||
msgid "OneDrive Login"
|
||||
msgstr "Вход в OneDrive"
|
||||
|
||||
msgid "Dropbox Login"
|
||||
msgstr ""
|
||||
|
||||
msgid "Options"
|
||||
msgstr "Настройки"
|
||||
|
||||
@@ -913,9 +928,6 @@ msgstr "Синхронизировать"
|
||||
msgid "Notebooks"
|
||||
msgstr "Блокноты"
|
||||
|
||||
msgid "Searches"
|
||||
msgstr "Запросы"
|
||||
|
||||
msgid "Please select where the sync status should be exported to"
|
||||
msgstr "Выберите, куда должен быть экспортирован статус синхронизации"
|
||||
|
||||
@@ -927,12 +939,14 @@ msgstr "Использование: %s"
|
||||
msgid "Unknown flag: %s"
|
||||
msgstr "Неизвестный флаг: %s"
|
||||
|
||||
msgid "Dropbox"
|
||||
msgstr ""
|
||||
|
||||
msgid "File system"
|
||||
msgstr "Файловая система"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Nextcloud"
|
||||
msgstr "Nextcloud (Beta)"
|
||||
msgstr "Nextcloud"
|
||||
|
||||
msgid "OneDrive"
|
||||
msgstr "OneDrive"
|
||||
@@ -940,9 +954,8 @@ msgstr "OneDrive"
|
||||
msgid "OneDrive Dev (For testing only)"
|
||||
msgstr "OneDrive Dev (только для тестирования)"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV"
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
msgstr "WebDAV"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Unknown log level: %s"
|
||||
@@ -1006,8 +1019,8 @@ msgstr "Удалено удалённых элементов: %d."
|
||||
msgid "Fetched items: %d/%d."
|
||||
msgstr "Получено элементов: %d/%d."
|
||||
|
||||
#, javascript-format
|
||||
msgid "State: \"%s\"."
|
||||
#, fuzzy, javascript-format
|
||||
msgid "State: %s."
|
||||
msgstr "Статус: «%s»."
|
||||
|
||||
msgid "Cancelling..."
|
||||
@@ -1017,6 +1030,16 @@ msgstr "Отмена..."
|
||||
msgid "Completed: %s"
|
||||
msgstr "Завершено: %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Last error: %s"
|
||||
msgstr "Последняя ошибка: %s"
|
||||
|
||||
msgid "Idle"
|
||||
msgstr "Простой"
|
||||
|
||||
msgid "In progress"
|
||||
msgstr "Выполнение"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Synchronisation is already in progress. State: %s"
|
||||
msgstr "Синхронизация уже выполняется. Статус: %s"
|
||||
@@ -1080,16 +1103,14 @@ msgstr "Светлая"
|
||||
msgid "Dark"
|
||||
msgstr "Тёмная"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Показывать незавершённые задачи вверху списков"
|
||||
msgstr "Незавершённые задачи сверху"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
msgstr "Сортировать заметки по"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Reverse sort order"
|
||||
msgstr "Обращает порядок сортировки."
|
||||
msgstr "Обратный порядок сортировки"
|
||||
|
||||
msgid "Save geo-location with notes"
|
||||
msgstr "Сохранять информацию о геолокации в заметках"
|
||||
@@ -1107,19 +1128,23 @@ msgid "When creating a new note:"
|
||||
msgstr "При создании новой заметки:"
|
||||
|
||||
msgid "Show tray icon"
|
||||
msgstr "Показывать иконку в панели задач"
|
||||
|
||||
msgid "Note: Does not work in all desktop environments."
|
||||
msgstr ""
|
||||
|
||||
#, fuzzy
|
||||
msgid "Global zoom percentage"
|
||||
msgstr "Масштаб приложения в процентах"
|
||||
msgstr "Глобальный масштаб в процентах"
|
||||
|
||||
msgid "Editor font family"
|
||||
msgstr ""
|
||||
msgstr "Семейство шрифтов редактора"
|
||||
|
||||
msgid ""
|
||||
"The font name will not be checked. If incorrect or empty, it will default to "
|
||||
"a generic monospace font."
|
||||
msgstr ""
|
||||
"Название шрифта не проверяется. Если оно указано некорректно или не задано, "
|
||||
"будет использоваться стандартный моноширинный шрифт."
|
||||
|
||||
msgid "Automatically update the application"
|
||||
msgstr "Автоматически обновлять приложение"
|
||||
@@ -1171,56 +1196,56 @@ msgstr "Имя пользователя Nextcloud"
|
||||
msgid "Nextcloud password"
|
||||
msgstr "Пароль Nextcloud"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV URL"
|
||||
msgstr "Nextcloud WebDAV URL"
|
||||
msgstr "URL WebDAV"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV username"
|
||||
msgstr "Имя пользователя Nextcloud"
|
||||
msgstr "Имя пользователя WebDAV"
|
||||
|
||||
#, fuzzy
|
||||
msgid "WebDAV password"
|
||||
msgstr "Установить пароль"
|
||||
msgstr "Пароль WebDAV"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Invalid option value: \"%s\". Possible values are: %s."
|
||||
msgstr "Неверное значение параметра: «%s». Доступные значения: %s."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Joplin Export File"
|
||||
msgstr "Файлы экспорта Evernote"
|
||||
msgstr "Файл экспорта Joplin"
|
||||
|
||||
msgid "Markdown"
|
||||
msgstr ""
|
||||
msgstr "Markdown"
|
||||
|
||||
msgid "Joplin Export Directory"
|
||||
msgstr ""
|
||||
msgstr "Папка экспорта Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Evernote Export File"
|
||||
msgstr "Файлы экспорта Evernote"
|
||||
msgstr "Файл экспорта Evernote"
|
||||
|
||||
msgid "Directory"
|
||||
msgstr "Директория"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\""
|
||||
msgstr ""
|
||||
msgstr "Не удалось загрузить модуль «%s» для формата «%s»"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Please specify import format for %s"
|
||||
msgstr ""
|
||||
msgstr "Пожалуйста, укажите формат импорта для %s"
|
||||
|
||||
#, javascript-format
|
||||
msgid ""
|
||||
"This item is currently encrypted: %s \"%s\". Please wait for all items to be "
|
||||
"decrypted and try again."
|
||||
msgstr ""
|
||||
"Этот элемент сейчас зашифрован: %s «%s». Пожалуйста, дождитесь расшифровки "
|
||||
"всех элементов и попробуйте снова."
|
||||
|
||||
msgid "There is no data to export."
|
||||
msgstr ""
|
||||
msgstr "Нет данных для экспорта."
|
||||
|
||||
#, fuzzy
|
||||
msgid "Please specify the notebook where the notes should be imported to."
|
||||
msgstr "Выберите, куда должен быть экспортирован статус синхронизации"
|
||||
msgstr ""
|
||||
"Пожалуйста, укажите блокнот, в который должны быть импортированы заметки."
|
||||
|
||||
msgid "Items that cannot be synchronised"
|
||||
msgstr "Элементы, которые не могут быть синхронизированы"
|
||||
@@ -1308,9 +1333,19 @@ msgstr "Подтвердить"
|
||||
msgid "Cancel synchronisation"
|
||||
msgstr "Отменить синхронизацию"
|
||||
|
||||
msgid "Joplin website"
|
||||
msgid "New tags:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Type new tags or select from list"
|
||||
msgstr ""
|
||||
|
||||
msgid "Joplin website"
|
||||
msgstr "Сайт Joplin"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Login with Dropbox"
|
||||
msgstr "Войти в OneDrive"
|
||||
|
||||
#, javascript-format
|
||||
msgid "Master Key %s"
|
||||
msgstr "Мастер-ключ %s"
|
||||
@@ -1336,11 +1371,10 @@ msgid "Edit notebook"
|
||||
msgstr "Редактировать блокнот"
|
||||
|
||||
msgid "Show all"
|
||||
msgstr ""
|
||||
msgstr "Показать всё"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Errors only"
|
||||
msgstr "Ошибка"
|
||||
msgstr "Только ошибки"
|
||||
|
||||
msgid "This note has been modified:"
|
||||
msgstr "Эта заметка была изменена:"
|
||||
@@ -1382,6 +1416,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."
|
||||
@@ -1395,6 +1432,16 @@ msgstr "У вас сейчас нет блокнота. Создайте его
|
||||
msgid "Welcome"
|
||||
msgstr "Добро пожаловать"
|
||||
|
||||
#~ msgid "Searches"
|
||||
#~ msgstr "Запросы"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Release notes:\n"
|
||||
#~ "\n"
|
||||
#~ "%s"
|
||||
#~ msgstr "Удалить заметки?"
|
||||
|
||||
#~ msgid "Imports an Evernote notebook file (.enex file)."
|
||||
#~ msgstr "Импортирует файл блокнотов Evernote (.enex-файл)."
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
7
CliClient/package-lock.json
generated
7
CliClient/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.0.100",
|
||||
"version": "1.0.106",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -983,11 +983,6 @@
|
||||
"wrappy": "1.0.2"
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"parse-data-uri": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz",
|
||||
|
@@ -19,7 +19,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.0.100",
|
||||
"version": "1.0.106",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
|
99
CliClient/tests/services_ResourceService.js
Normal file
99
CliClient/tests/services_ResourceService.js
Normal file
@@ -0,0 +1,99 @@
|
||||
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 InteropService = require('lib/services/InteropService.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const NoteResource = require('lib/models/NoteResource.js');
|
||||
const ResourceService = require('lib/services/ResourceService.js');
|
||||
const fs = require('fs-extra');
|
||||
const ArrayUtils = require('lib/ArrayUtils');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const { shim } = require('lib/shim.js');
|
||||
|
||||
process.on('unhandledRejection', (reason, p) => {
|
||||
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
|
||||
});
|
||||
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
|
||||
|
||||
function exportDir() {
|
||||
return __dirname + '/export';
|
||||
}
|
||||
|
||||
function fieldsEqual(model1, model2, fieldNames) {
|
||||
for (let i = 0; i < fieldNames.length; i++) {
|
||||
const f = fieldNames[i];
|
||||
expect(model1[f]).toBe(model2[f], 'For key ' + f);
|
||||
}
|
||||
}
|
||||
|
||||
describe('services_ResourceService', function() {
|
||||
|
||||
beforeEach(async (done) => {
|
||||
await setupDatabaseAndSynchronizer(1);
|
||||
await switchClient(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should delete orphaned resources', asyncTest(async () => {
|
||||
const service = new ResourceService();
|
||||
|
||||
let folder1 = await Folder.save({ title: "folder1" });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
note1 = await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
|
||||
let resource1 = (await Resource.all())[0];
|
||||
const resourcePath = Resource.fullPath(resource1);
|
||||
|
||||
await service.indexNoteResources();
|
||||
await service.deleteOrphanResources(0);
|
||||
|
||||
expect(!!(await Resource.load(resource1.id))).toBe(true);
|
||||
|
||||
await Note.delete(note1.id);
|
||||
await service.deleteOrphanResources(0);
|
||||
|
||||
expect(!!(await Resource.load(resource1.id))).toBe(true);
|
||||
|
||||
await service.indexNoteResources();
|
||||
await service.deleteOrphanResources(1000 * 60);
|
||||
|
||||
expect(!!(await Resource.load(resource1.id))).toBe(true);
|
||||
|
||||
await service.deleteOrphanResources(0);
|
||||
|
||||
expect(!!(await Resource.load(resource1.id))).toBe(false);
|
||||
expect(await shim.fsDriver().exists(resourcePath)).toBe(false);
|
||||
expect(!(await NoteResource.all()).length).toBe(true);
|
||||
}));
|
||||
|
||||
it('should not delete resource if still associated with at least one note', asyncTest(async () => {
|
||||
const service = new ResourceService();
|
||||
|
||||
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', parent_id: folder1.id });
|
||||
note1 = await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
|
||||
let resource1 = (await Resource.all())[0];
|
||||
const resourcePath = Resource.fullPath(resource1);
|
||||
|
||||
await service.indexNoteResources();
|
||||
|
||||
await Note.delete(note1.id);
|
||||
|
||||
await service.indexNoteResources();
|
||||
|
||||
await Note.save({ id: note2.id, body: Resource.markdownTag(resource1) });
|
||||
|
||||
await service.indexNoteResources();
|
||||
|
||||
await service.deleteOrphanResources(0);
|
||||
|
||||
expect(!!(await Resource.load(resource1.id))).toBe(true);
|
||||
}));
|
||||
|
||||
});
|
@@ -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]);
|
||||
@@ -883,6 +878,37 @@ describe('Synchronizer', function() {
|
||||
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
|
||||
}));
|
||||
|
||||
it('should delete resources', asyncTest(async () => {
|
||||
while (insideBeforeEach) await time.msleep(500);
|
||||
|
||||
let folder1 = await Folder.save({ title: "folder1" });
|
||||
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
|
||||
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
|
||||
let resource1 = (await Resource.all())[0];
|
||||
let resourcePath1 = Resource.fullPath(resource1);
|
||||
await synchronizer().start();
|
||||
|
||||
await switchClient(2);
|
||||
|
||||
await synchronizer().start();
|
||||
let allResources = await Resource.all();
|
||||
expect(allResources.length).toBe(1);
|
||||
let all = await fileApi().list();
|
||||
expect(all.items.length).toBe(3);
|
||||
await Resource.delete(resource1.id);
|
||||
await synchronizer().start();
|
||||
all = await fileApi().list();
|
||||
expect(all.items.length).toBe(2);
|
||||
|
||||
await switchClient(1);
|
||||
|
||||
expect(await shim.fsDriver().exists(resourcePath1)).toBe(true);
|
||||
await synchronizer().start();
|
||||
allResources = await Resource.all();
|
||||
expect(allResources.length).toBe(0);
|
||||
expect(await shim.fsDriver().exists(resourcePath1)).toBe(false);
|
||||
}));
|
||||
|
||||
it('should encryt resources', asyncTest(async () => {
|
||||
Setting.setValue('encryption.enabled', true);
|
||||
const masterKey = await loadEncryptionMasterKey();
|
||||
|
@@ -16,6 +16,8 @@ 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');
|
||||
const { shimInit } = require('lib/shim-init-node.js');
|
||||
@@ -24,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_ = [];
|
||||
@@ -50,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;
|
||||
@@ -63,7 +69,7 @@ console.info('Testing with sync target: ' + SyncTargetRegistry.idToName(syncTarg
|
||||
const logger = new Logger();
|
||||
logger.addTarget('console');
|
||||
logger.addTarget('file', { path: logDir + '/log.txt' });
|
||||
logger.setLevel(Logger.LEVEL_WARN); // Set to INFO to display sync process in console
|
||||
logger.setLevel(Logger.LEVEL_WARN); // Set to DEBUG to display sync process in console
|
||||
|
||||
BaseItem.loadClass('Note', Note);
|
||||
BaseItem.loadClass('Folder', Folder);
|
||||
@@ -75,6 +81,8 @@ BaseItem.loadClass('MasterKey', MasterKey);
|
||||
Setting.setConstant('appId', 'net.cozic.joplin-cli');
|
||||
Setting.setConstant('appType', 'cli');
|
||||
|
||||
BaseService.logger_ = logger;
|
||||
|
||||
Setting.autoSaveEnabled = false;
|
||||
|
||||
function syncTargetId() {
|
||||
@@ -118,8 +126,9 @@ async function clearDatabase(id = null) {
|
||||
'DELETE FROM tags',
|
||||
'DELETE FROM note_tags',
|
||||
'DELETE FROM master_keys',
|
||||
'DELETE FROM settings',
|
||||
|
||||
'DELETE FROM item_changes',
|
||||
'DELETE FROM note_resources',
|
||||
'DELETE FROM settings',
|
||||
'DELETE FROM deleted_items',
|
||||
'DELETE FROM sync_items',
|
||||
];
|
||||
@@ -243,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;
|
||||
@@ -302,8 +301,9 @@ function asyncTest(callback) {
|
||||
await callback();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -22,6 +22,7 @@ const AlarmServiceDriverNode = require('lib/services/AlarmServiceDriverNode');
|
||||
const DecryptionWorker = require('lib/services/DecryptionWorker');
|
||||
const InteropService = require('lib/services/InteropService');
|
||||
const InteropServiceHelper = require('./InteropServiceHelper.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
const Menu = bridge().Menu;
|
||||
@@ -37,6 +38,7 @@ const appDefaultState = Object.assign({}, defaultState, {
|
||||
fileToImport: null,
|
||||
windowCommand: null,
|
||||
noteVisiblePanes: ['editor', 'viewer'],
|
||||
sidebarVisibility: true,
|
||||
windowContentSize: bridge().windowContentSize(),
|
||||
});
|
||||
|
||||
@@ -84,7 +86,7 @@ class Application extends BaseApplication {
|
||||
|
||||
action = newAction;
|
||||
}
|
||||
|
||||
|
||||
if (!goingBack) newNavHistory.push(currentRoute);
|
||||
newState.navHistory = newNavHistory
|
||||
newState.route = action;
|
||||
@@ -122,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);
|
||||
@@ -169,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;
|
||||
}
|
||||
|
||||
@@ -194,7 +211,7 @@ class Application extends BaseApplication {
|
||||
Setting.setValue('notes.sortOrder.field', field);
|
||||
this.refreshMenu();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const importItems = [];
|
||||
@@ -205,7 +222,7 @@ class Application extends BaseApplication {
|
||||
const module = ioModules[i];
|
||||
if (module.type === 'exporter') {
|
||||
exportItems.push({
|
||||
label: module.format + ' - ' + module.description,
|
||||
label: module.fullLabel(),
|
||||
screens: ['Main'],
|
||||
click: async () => {
|
||||
await InteropServiceHelper.export(this.dispatch.bind(this), module);
|
||||
@@ -214,12 +231,8 @@ class Application extends BaseApplication {
|
||||
} else {
|
||||
for (let j = 0; j < module.sources.length; j++) {
|
||||
const moduleSource = module.sources[j];
|
||||
let label = [module.format + ' - ' + module.description];
|
||||
if (module.sources.length > 1) {
|
||||
label.push('(' + (moduleSource === 'file' ? _('File') : _('Directory')) + ')');
|
||||
}
|
||||
importItems.push({
|
||||
label: label.join(' '),
|
||||
label: module.fullLabel(moduleSource),
|
||||
screens: ['Main'],
|
||||
click: async () => {
|
||||
let path = null;
|
||||
@@ -269,6 +282,17 @@ class Application extends BaseApplication {
|
||||
}
|
||||
}
|
||||
|
||||
exportItems.push({
|
||||
label: 'PDF - ' + _('PDF File'),
|
||||
screens: ['Main'],
|
||||
click: async () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'exportPdf',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const template = [
|
||||
{
|
||||
label: _('File'),
|
||||
@@ -304,31 +328,24 @@ class Application extends BaseApplication {
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
// }, {
|
||||
// label: _('Import Evernote notes'),
|
||||
// click: () => {
|
||||
// const filePaths = bridge().showOpenDialog({
|
||||
// properties: ['openFile', 'createDirectory'],
|
||||
// filters: [
|
||||
// { name: _('Evernote Export Files'), extensions: ['enex'] },
|
||||
// ]
|
||||
// });
|
||||
// if (!filePaths || !filePaths.length) return;
|
||||
|
||||
// this.dispatch({
|
||||
// type: 'NAV_GO',
|
||||
// routeName: 'Import',
|
||||
// props: {
|
||||
// filePath: filePaths[0],
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
}, {
|
||||
label: _('Import'),
|
||||
submenu: importItems,
|
||||
}, {
|
||||
label: _('Export'),
|
||||
submenu: exportItems,
|
||||
}, {
|
||||
type: 'separator',
|
||||
}, {
|
||||
label: _('Print'),
|
||||
accelerator: 'CommandOrControl+P',
|
||||
screens: ['Main'],
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'print',
|
||||
});
|
||||
}
|
||||
}, {
|
||||
type: 'separator',
|
||||
platforms: ['darwin'],
|
||||
@@ -348,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',
|
||||
}, {
|
||||
@@ -367,17 +384,27 @@ class Application extends BaseApplication {
|
||||
}, {
|
||||
label: _('Search in all the notes'),
|
||||
screens: ['Main'],
|
||||
accelerator: 'F6',
|
||||
accelerator: 'CommandOrControl+F',
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: 'search',
|
||||
name: 'focus_search',
|
||||
});
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
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',
|
||||
@@ -447,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: () => {
|
||||
@@ -509,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;
|
||||
@@ -546,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 }));
|
||||
@@ -595,7 +623,7 @@ class Application extends BaseApplication {
|
||||
bridge().checkForUpdates(true, bridge().window(), this.checkForUpdateLoggerPath());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Initial check on startup
|
||||
setTimeout(() => { runAutoUpdateCheck() }, 5000);
|
||||
// Then every x hours
|
||||
@@ -608,6 +636,8 @@ class Application extends BaseApplication {
|
||||
AlarmService.garbageCollect();
|
||||
}, 1000 * 60 * 60);
|
||||
|
||||
ResourceService.runInBackground();
|
||||
|
||||
if (Setting.value('env') === 'dev') {
|
||||
AlarmService.updateAllNotifications();
|
||||
} else {
|
||||
@@ -630,4 +660,4 @@ function app() {
|
||||
return application_;
|
||||
}
|
||||
|
||||
module.exports = { app };
|
||||
module.exports = { app };
|
||||
|
@@ -1,31 +1,15 @@
|
||||
const { dialog } = require('electron')
|
||||
const { autoUpdater } = require('electron-updater')
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const fetch = require('node-fetch');
|
||||
const packageInfo = require('./packageInfo.js');
|
||||
const compareVersions = require('compare-versions');
|
||||
|
||||
let autoUpdateLogger_ = new Logger();
|
||||
let checkInBackground_ = false;
|
||||
let isCheckingForUpdate_ = false;
|
||||
let parentWindow_ = null;
|
||||
|
||||
// Note: Electron Builder's autoUpdater is incredibly buggy so currently it's only used
|
||||
// to detect if a new version is present. If it is, the download link is simply opened
|
||||
// in a new browser window.
|
||||
autoUpdater.autoDownload = false;
|
||||
|
||||
function htmlToText_(html) {
|
||||
let output = html.replace(/\n/g, '');
|
||||
output = output.replace(/<li>/g, '- ');
|
||||
output = output.replace(/<p>/g, '');
|
||||
output = output.replace(/<\/p>/g, '\n');
|
||||
output = output.replace(/<\/li>/g, '\n');
|
||||
output = output.replace(/<ul>/g, '');
|
||||
output = output.replace(/<\/ul>/g, '');
|
||||
output = output.replace(/<.*?>/g, '');
|
||||
output = output.replace(/<\/.*?>/g, '');
|
||||
return output;
|
||||
}
|
||||
|
||||
function showErrorMessageBox(message) {
|
||||
return dialog.showMessageBox(parentWindow_, {
|
||||
type: 'error',
|
||||
@@ -43,81 +27,45 @@ function onCheckEnded() {
|
||||
isCheckingForUpdate_ = false;
|
||||
}
|
||||
|
||||
autoUpdater.on('error', (error) => {
|
||||
autoUpdateLogger_.error(error);
|
||||
if (checkInBackground_) return onCheckEnded();
|
||||
async function fetchLatestRelease() {
|
||||
const response = await fetch('https://api.github.com/repos/laurent22/joplin/releases/latest');
|
||||
|
||||
let msg = error == null ? "unknown" : (error.stack || error).toString();
|
||||
// Error messages can be very long even without stack trace so shorten
|
||||
// then so that the dialog box doesn't take the whole screen.
|
||||
msg = msg.substr(0,512).replace(/\\n/g, '\n');
|
||||
showErrorMessageBox(msg)
|
||||
if (!response.ok) {
|
||||
const responseText = await response.text();
|
||||
throw new Error('Cannot get latest release info: ' + responseText.substr(0,500));
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
|
||||
onCheckEnded();
|
||||
})
|
||||
const version = json.tag_name.substr(1);
|
||||
let downloadUrl = null;
|
||||
const platform = process.platform;
|
||||
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) {
|
||||
found = true;
|
||||
} else if (platform === 'darwin' && asset.name.indexOf('.dmg') >= 0) {
|
||||
found = true;
|
||||
} else if (platform === 'linux' && asset.name.indexOf('.AppImage') >= 0) {
|
||||
found = true;
|
||||
}
|
||||
|
||||
function findDownloadFilename_(info) {
|
||||
// { version: '1.0.64',
|
||||
// files:
|
||||
// [ { url: 'Joplin-1.0.64-mac.zip',
|
||||
// sha512: 'OlemXqhq/fSifx7EutvMzfoCI/1kGNl10i8nkvACEDfVXwP8hankDBXEC0+GxSArsZuxOh3U1+C+4j72SfIUew==' },
|
||||
// { url: 'Joplin-1.0.64.dmg',
|
||||
// sha512: 'jAewQQoJ3nCaOj8hWDgf0sc3LBbAWQtiKqfTflK8Hc3Dh7fAy9jRHfFAZKFUZ9ll95Bun0DVsLq8wLSUrdsMXw==',
|
||||
// size: 77104485 } ],
|
||||
// path: 'Joplin-1.0.64-mac.zip',
|
||||
// sha512: 'OlemXqhq/fSifx7EutvMzfoCI/1kGNl10i8nkvACEDfVXwP8hankDBXEC0+GxSArsZuxOh3U1+C+4j72SfIUew==',
|
||||
// releaseDate: '2018-02-16T00:13:01.634Z',
|
||||
// releaseName: 'v1.0.64',
|
||||
// releaseNotes: '<p>Still more fixes and im...' }
|
||||
|
||||
if (!info) return null;
|
||||
|
||||
if (!info.files) {
|
||||
// info.path seems to contain a default, though not a good one,
|
||||
// so the loop below if preferable to find the right file.
|
||||
return info.path;
|
||||
if (found) {
|
||||
downloadUrl = asset.browser_download_url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < info.files.length; i++) {
|
||||
const f = info.files[i].url; // Annoyingly this is called "url" but it's obviously not a url, so hopefully it won't change later on and become one.
|
||||
if (f.indexOf('.exe') >= 0) return f;
|
||||
if (f.indexOf('.dmg') >= 0) return f;
|
||||
}
|
||||
if (!downloadUrl) throw new Error('Cannot find download Url: ' + JSON.stringify(json).substr(0,500));
|
||||
|
||||
return info.path;
|
||||
return {
|
||||
version: version,
|
||||
downloadUrl: downloadUrl,
|
||||
notes: json.body,
|
||||
};
|
||||
}
|
||||
|
||||
autoUpdater.on('update-available', (info) => {
|
||||
const filename = findDownloadFilename_(info);
|
||||
|
||||
if (!info.version || !filename) {
|
||||
if (checkInBackground_) return onCheckEnded();
|
||||
showErrorMessageBox(('Could not get version info: ' + JSON.stringify(info)));
|
||||
return onCheckEnded();
|
||||
}
|
||||
|
||||
const downloadUrl = 'https://github.com/laurent22/joplin/releases/download/v' + info.version + '/' + filename;
|
||||
|
||||
let releaseNotes = info.releaseNotes + '';
|
||||
if (releaseNotes) releaseNotes = '\n\n' + _('Release notes:\n\n%s', htmlToText_(releaseNotes));
|
||||
|
||||
const buttonIndex = dialog.showMessageBox(parentWindow_, {
|
||||
type: 'info',
|
||||
message: _('An update is available, do you want to download it now?' + releaseNotes),
|
||||
buttons: [_('Yes'), _('No')]
|
||||
});
|
||||
|
||||
onCheckEnded();
|
||||
|
||||
if (buttonIndex === 0) require('electron').shell.openExternal(downloadUrl);
|
||||
})
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
if (checkInBackground_) return onCheckEnded();
|
||||
dialog.showMessageBox({ message: _('Current version is up-to-date.') })
|
||||
onCheckEnded();
|
||||
})
|
||||
|
||||
function checkForUpdates(inBackground, window, logFilePath) {
|
||||
if (isCheckingForUpdate_) {
|
||||
autoUpdateLogger_.info('checkForUpdates: Skipping check because it is already running');
|
||||
@@ -133,18 +81,30 @@ function checkForUpdates(inBackground, window, logFilePath) {
|
||||
autoUpdateLogger_.addTarget('file', { path: logFilePath });
|
||||
autoUpdateLogger_.setLevel(Logger.LEVEL_DEBUG);
|
||||
autoUpdateLogger_.info('checkForUpdates: Initializing...');
|
||||
autoUpdater.logger = autoUpdateLogger_;
|
||||
}
|
||||
|
||||
checkInBackground_ = inBackground;
|
||||
|
||||
try {
|
||||
autoUpdater.checkForUpdates()
|
||||
} catch (error) {
|
||||
fetchLatestRelease().then(release => {
|
||||
if (compareVersions(release.version, packageInfo.version) <= 0) {
|
||||
if (!checkInBackground_) dialog.showMessageBox({ message: _('Current version is up-to-date.') })
|
||||
} else {
|
||||
const releaseNotes = release.notes.trim() ? "\n\n" + release.notes.trim() : '';
|
||||
|
||||
const buttonIndex = dialog.showMessageBox(parentWindow_, {
|
||||
type: 'info',
|
||||
message: _('An update is available, do you want to download it now?' + releaseNotes),
|
||||
buttons: [_('Yes'), _('No')]
|
||||
});
|
||||
|
||||
if (buttonIndex === 0) require('electron').shell.openExternal(release.downloadUrl);
|
||||
}
|
||||
}).catch(error => {
|
||||
autoUpdateLogger_.error(error);
|
||||
if (!checkInBackground_) showErrorMessageBox(error.message);
|
||||
}).then(() => {
|
||||
onCheckEnded();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports.checkForUpdates = checkForUpdates
|
62
ElectronClient/app/gui/DropboxLoginScreen.jsx
Normal file
62
ElectronClient/app/gui/DropboxLoginScreen.jsx
Normal 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 };
|
@@ -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}
|
||||
|
@@ -6,6 +6,63 @@ const { _ } = require('lib/locale.js');
|
||||
|
||||
class HeaderComponent extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
searchQuery: '',
|
||||
};
|
||||
|
||||
this.scheduleSearchChangeEventIid_ = null;
|
||||
this.searchOnQuery_ = null;
|
||||
this.searchElement_ = null;
|
||||
|
||||
const triggerOnQuery = (query) => {
|
||||
clearTimeout(this.scheduleSearchChangeEventIid_);
|
||||
if (this.searchOnQuery_) this.searchOnQuery_(query);
|
||||
this.scheduleSearchChangeEventIid_ = null;
|
||||
}
|
||||
|
||||
this.search_onChange = (event) => {
|
||||
this.setState({ searchQuery: event.target.value });
|
||||
|
||||
if (this.scheduleSearchChangeEventIid_) clearTimeout(this.scheduleSearchChangeEventIid_);
|
||||
|
||||
this.scheduleSearchChangeEventIid_ = setTimeout(() => {
|
||||
triggerOnQuery(this.state.searchQuery);
|
||||
}, 500);
|
||||
};
|
||||
|
||||
this.search_onClear = (event) => {
|
||||
this.setState({ searchQuery: '' });
|
||||
triggerOnQuery('');
|
||||
}
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.windowCommand) {
|
||||
this.doCommand(nextProps.windowCommand);
|
||||
}
|
||||
}
|
||||
|
||||
async doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
let commandProcessed = true;
|
||||
|
||||
if (command.name === 'focus_search' && this.searchElement_) {
|
||||
this.searchElement_.focus();
|
||||
} else {
|
||||
commandProcessed = false;
|
||||
}
|
||||
|
||||
if (commandProcessed) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
back_click() {
|
||||
this.props.dispatch({ type: 'NAV_BACK' });
|
||||
}
|
||||
@@ -15,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>
|
||||
}
|
||||
|
||||
@@ -40,6 +98,59 @@ class HeaderComponent extends React.Component {
|
||||
</a>
|
||||
}
|
||||
|
||||
makeSearch(key, style, options, state) {
|
||||
const inputStyle = {
|
||||
display: 'flex',
|
||||
flex: 1,
|
||||
paddingLeft: 4,
|
||||
paddingRight: 4,
|
||||
color: style.color,
|
||||
fontSize: style.fontSize,
|
||||
fontFamily: style.fontFamily,
|
||||
};
|
||||
|
||||
const searchButton = {
|
||||
paddingLeft: 4,
|
||||
paddingRight: 4,
|
||||
paddingTop: 2,
|
||||
paddingBottom: 2,
|
||||
textDecoration: 'none',
|
||||
};
|
||||
|
||||
const iconStyle = {
|
||||
display: 'flex',
|
||||
fontSize: Math.round(style.fontSize) * 1.2,
|
||||
color: style.color,
|
||||
};
|
||||
|
||||
const containerStyle = {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
};
|
||||
|
||||
const iconName = state.searchQuery ? 'fa-times' : 'fa-search';
|
||||
const icon = <i style={iconStyle} className={"fa " + iconName}></i>
|
||||
if (options.onQuery) this.searchOnQuery_ = options.onQuery;
|
||||
|
||||
return (
|
||||
<div key={key} style={containerStyle}>
|
||||
<input
|
||||
type="text"
|
||||
style={inputStyle}
|
||||
placeholder={options.title}
|
||||
value={state.searchQuery}
|
||||
onChange={this.search_onChange}
|
||||
ref={elem => this.searchElement_ = elem}
|
||||
/>
|
||||
<a
|
||||
href="#"
|
||||
style={searchButton}
|
||||
onClick={this.search_onClear}
|
||||
>{icon}</a>
|
||||
</div>);
|
||||
}
|
||||
|
||||
render() {
|
||||
const style = Object.assign({}, this.props.style);
|
||||
const theme = themeStyle(this.props.theme);
|
||||
@@ -50,9 +161,9 @@ class HeaderComponent extends React.Component {
|
||||
style.borderBottom = '1px solid ' + theme.dividerColor;
|
||||
style.boxSizing = 'border-box';
|
||||
|
||||
const buttons = [];
|
||||
const items = [];
|
||||
|
||||
const buttonStyle = {
|
||||
const itemStyle = {
|
||||
height: theme.headerHeight,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -67,19 +178,24 @@ class HeaderComponent extends React.Component {
|
||||
};
|
||||
|
||||
if (showBackButton) {
|
||||
buttons.push(this.makeButton('back', buttonStyle, { title: _('Back'), onClick: () => this.back_click(), iconName: 'fa-chevron-left ' }));
|
||||
items.push(this.makeButton('back', itemStyle, { title: _('Back'), onClick: () => this.back_click(), iconName: 'fa-chevron-left ' }));
|
||||
}
|
||||
|
||||
if (this.props.buttons) {
|
||||
for (let i = 0; i < this.props.buttons.length; i++) {
|
||||
const o = this.props.buttons[i];
|
||||
buttons.push(this.makeButton('btn_' + i + '_' + o.title, buttonStyle, o));
|
||||
if (this.props.items) {
|
||||
for (let i = 0; i < this.props.items.length; i++) {
|
||||
const item = this.props.items[i];
|
||||
|
||||
if (item.type === 'search') {
|
||||
items.push(this.makeSearch('item_' + i + '_search', itemStyle, item, this.state));
|
||||
} else {
|
||||
items.push(this.makeButton('item_' + i + '_' + item.title, itemStyle, item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="header" style={style}>
|
||||
{ buttons }
|
||||
{ items }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -87,7 +203,10 @@ class HeaderComponent extends React.Component {
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return { theme: state.settings.theme };
|
||||
return {
|
||||
theme: state.settings.theme,
|
||||
windowCommand: state.windowCommand,
|
||||
};
|
||||
};
|
||||
|
||||
const Header = connect(mapStateToProps)(HeaderComponent);
|
||||
|
@@ -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);
|
||||
}
|
||||
@@ -140,35 +146,31 @@ class MainScreenComponent extends React.Component {
|
||||
},
|
||||
});
|
||||
} else if (command.name === 'search') {
|
||||
this.setState({
|
||||
promptOptions: {
|
||||
label: _('Search:'),
|
||||
onClose: async (answer) => {
|
||||
if (answer !== null) {
|
||||
const searchId = uuid.create();
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'SEARCH_ADD',
|
||||
search: {
|
||||
id: searchId,
|
||||
title: answer,
|
||||
query_pattern: answer,
|
||||
query_folder_id: null,
|
||||
type_: BaseModel.TYPE_SEARCH,
|
||||
},
|
||||
});
|
||||
if (!this.searchId_) this.searchId_ = uuid.create();
|
||||
|
||||
this.props.dispatch({
|
||||
type: 'SEARCH_SELECT',
|
||||
id: searchId,
|
||||
});
|
||||
}
|
||||
this.setState({ promptOptions: null });
|
||||
}
|
||||
this.props.dispatch({
|
||||
type: 'SEARCH_UPDATE',
|
||||
search: {
|
||||
id: this.searchId_,
|
||||
title: command.query,
|
||||
query_pattern: command.query,
|
||||
query_folder_id: null,
|
||||
type_: BaseModel.TYPE_SEARCH,
|
||||
},
|
||||
});
|
||||
|
||||
if (command.query) {
|
||||
this.props.dispatch({
|
||||
type: 'SEARCH_SELECT',
|
||||
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') {
|
||||
@@ -209,7 +211,7 @@ class MainScreenComponent extends React.Component {
|
||||
this.setState({ promptOptions: null });
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
} else {
|
||||
commandProcessed = false;
|
||||
}
|
||||
@@ -222,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);
|
||||
@@ -252,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)),
|
||||
@@ -278,7 +285,7 @@ class MainScreenComponent extends React.Component {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor: theme.backgroundColorTransparent,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
width: width - 20,
|
||||
height: height - 20,
|
||||
padding: 10,
|
||||
@@ -293,46 +300,55 @@ 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 headerButtons = [];
|
||||
const headerItems = [];
|
||||
|
||||
headerButtons.push({
|
||||
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' }) },
|
||||
});
|
||||
|
||||
headerButtons.push({
|
||||
|
||||
headerItems.push({
|
||||
title: _('New to-do'),
|
||||
iconName: 'fa-check-square-o',
|
||||
enabled: !!folders.length && !onConflictFolder,
|
||||
onClick: () => { this.doCommand({ name: 'newTodo' }) },
|
||||
});
|
||||
|
||||
headerButtons.push({
|
||||
headerItems.push({
|
||||
title: _('New notebook'),
|
||||
iconName: 'fa-folder-o',
|
||||
onClick: () => { this.doCommand({ name: 'newNotebook' }) },
|
||||
});
|
||||
|
||||
headerButtons.push({
|
||||
title: _('Search'),
|
||||
iconName: 'fa-search',
|
||||
onClick: () => { this.doCommand({ name: 'search' }) },
|
||||
});
|
||||
|
||||
headerButtons.push({
|
||||
headerItems.push({
|
||||
title: _('Layout'),
|
||||
iconName: 'fa-columns',
|
||||
enabled: !!notes.length,
|
||||
onClick: () => { this.doCommand({ name: 'toggleVisiblePanes' }) },
|
||||
});
|
||||
|
||||
headerItems.push({
|
||||
title: _('Search...'),
|
||||
iconName: 'fa-search',
|
||||
onQuery: (query) => { this.doCommand({ name: 'search', query: query }) },
|
||||
type: 'search',
|
||||
});
|
||||
|
||||
if (!this.promptOnClose_) {
|
||||
this.promptOnClose_ = (answer, buttonType) => {
|
||||
return this.state.promptOptions.onClose(answer, buttonType);
|
||||
@@ -389,7 +405,7 @@ class MainScreenComponent extends React.Component {
|
||||
visible={!!this.state.promptOptions}
|
||||
buttons={promptOptions && ('buttons' in promptOptions) ? promptOptions.buttons : null}
|
||||
inputType={promptOptions && ('inputType' in promptOptions) ? promptOptions.inputType : null} />
|
||||
<Header style={styles.header} showBackButton={false} buttons={headerButtons} />
|
||||
<Header style={styles.header} showBackButton={false} items={headerItems} />
|
||||
{messageComp}
|
||||
<SideBar style={styles.sideBar} />
|
||||
<NoteList style={styles.noteList} />
|
||||
@@ -405,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 };
|
||||
|
@@ -11,6 +11,8 @@ const MenuItem = bridge().MenuItem;
|
||||
const eventManager = require('../eventManager');
|
||||
const InteropService = require('lib/services/InteropService');
|
||||
const InteropServiceHelper = require('../InteropServiceHelper.js');
|
||||
const Search = require('lib/models/Search');
|
||||
const Mark = require('mark.js/dist/mark.min.js');
|
||||
|
||||
class NoteListComponent extends React.Component {
|
||||
|
||||
@@ -94,11 +96,22 @@ class NoteListComponent extends React.Component {
|
||||
}
|
||||
}}));
|
||||
|
||||
menu.append(new MenuItem({label: _('Export'), click: async () => {
|
||||
const ioService = new InteropService();
|
||||
const module = ioService.moduleByFormat_('exporter', 'jex');
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceNoteIds: noteIds });
|
||||
}}));
|
||||
const exportMenu = new Menu();
|
||||
|
||||
const ioService = new InteropService();
|
||||
const ioModules = ioService.modules();
|
||||
for (let i = 0; i < ioModules.length; i++) {
|
||||
const module = ioModules[i];
|
||||
if (module.type !== 'exporter') continue;
|
||||
|
||||
exportMenu.append(new MenuItem({ label: module.fullLabel() , click: async () => {
|
||||
await InteropServiceHelper.export(this.props.dispatch.bind(this), module, { sourceNoteIds: noteIds });
|
||||
}}));
|
||||
}
|
||||
|
||||
const exportMenuItem = new MenuItem({label: _('Export'), submenu: exportMenu});
|
||||
|
||||
menu.append(exportMenuItem);
|
||||
}
|
||||
|
||||
menu.append(new MenuItem({label: _('Delete'), click: async () => {
|
||||
@@ -153,6 +166,12 @@ class NoteListComponent extends React.Component {
|
||||
|
||||
const hPadding = 10;
|
||||
|
||||
let highlightedWords = [];
|
||||
if (this.props.notesParentType === 'Search') {
|
||||
const search = BaseModel.byId(this.props.searches, this.props.selectedSearchId);
|
||||
highlightedWords = search ? Search.keywords(search.query_pattern) : [];
|
||||
}
|
||||
|
||||
let style = Object.assign({ width: width }, this.style().listItem);
|
||||
|
||||
if (this.props.selectedNoteIds.indexOf(item.id) >= 0) {
|
||||
@@ -171,8 +190,30 @@ class NoteListComponent extends React.Component {
|
||||
listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4;
|
||||
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted);
|
||||
|
||||
let displayTitle = Note.displayTitle(item);
|
||||
let titleComp = null;
|
||||
|
||||
if (highlightedWords.length) {
|
||||
const titleElement = document.createElement('span');
|
||||
titleElement.textContent = displayTitle;
|
||||
const mark = new Mark(titleElement, {
|
||||
exclude: ['img'],
|
||||
acrossElements: true,
|
||||
});
|
||||
mark.mark(highlightedWords);
|
||||
|
||||
// Note: in this case it is safe to use dangerouslySetInnerHTML because titleElement
|
||||
// is a span tag that we created and that contains data that's been inserted as plain text
|
||||
// with `textContent` so it cannot contain any XSS attacks. We use this feature because
|
||||
// mark.js can only deal with DOM elements.
|
||||
// https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
|
||||
titleComp = <span dangerouslySetInnerHTML={{ __html: titleElement.outerHTML }}></span>
|
||||
} else {
|
||||
titleComp = <span>{displayTitle}</span>
|
||||
}
|
||||
|
||||
// Need to include "todo_completed" in key so that checkbox is updated when
|
||||
// item is changed via sync.
|
||||
// item is changed via sync.
|
||||
return <div key={item.id + '_' + item.todo_completed} style={style}>
|
||||
{checkbox}
|
||||
<a
|
||||
@@ -185,7 +226,7 @@ class NoteListComponent extends React.Component {
|
||||
onDragStart={(event) => onDragStart(event) }
|
||||
data-id={item.id}
|
||||
>
|
||||
{Note.displayTitle(item)}
|
||||
{titleComp}
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
@@ -228,7 +269,9 @@ const mapStateToProps = (state) => {
|
||||
folders: state.folders,
|
||||
selectedNoteIds: state.selectedNoteIds,
|
||||
theme: state.settings.theme,
|
||||
// uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
|
||||
notesParentType: state.notesParentType,
|
||||
searches: state.searches,
|
||||
selectedSearchId: state.selectedSearchId,
|
||||
};
|
||||
};
|
||||
|
||||
|
47
ElectronClient/app/gui/NoteStatusBar.jsx
Normal file
47
ElectronClient/app/gui/NoteStatusBar.jsx
Normal file
@@ -0,0 +1,47 @@
|
||||
const React = require('react');
|
||||
const { connect } = require('react-redux');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const { themeStyle } = require('../theme.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class NoteStatusBarComponent extends React.Component {
|
||||
|
||||
style() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
const itemHeight = 34;
|
||||
|
||||
let style = {
|
||||
root: Object.assign({}, theme.textStyle, {
|
||||
backgroundColor: theme.backgroundColor,
|
||||
color: theme.colorFaded,
|
||||
}),
|
||||
};
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
const style = this.props.style;
|
||||
const note = this.props.note;
|
||||
|
||||
return (
|
||||
<div style={this.style().root}>{time.formatMsToLocal(note.user_updated_time)}</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
return {
|
||||
// notes: state.notes,
|
||||
// folders: state.folders,
|
||||
// selectedNoteIds: state.selectedNoteIds,
|
||||
theme: state.settings.theme,
|
||||
};
|
||||
};
|
||||
|
||||
const NoteStatusBar = connect(mapStateToProps)(NoteStatusBarComponent);
|
||||
|
||||
module.exports = { NoteStatusBar };
|
@@ -1,5 +1,7 @@
|
||||
const React = require('react');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Search = require('lib/models/Search.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { IconButton } = require('./IconButton.min.js');
|
||||
@@ -195,7 +197,9 @@ class NoteTextComponent extends React.Component {
|
||||
this.editorSetScrollTop(1);
|
||||
this.restoreScrollTop_ = 0;
|
||||
|
||||
if (note) {
|
||||
// If a search is in progress we don't focus any field otherwise it will
|
||||
// take the focus out of the search box.
|
||||
if (note && this.props.notesParentType !== 'Search') {
|
||||
const focusSettingName = !!note.is_todo ? 'newTodoFocus' : 'newNoteFocus';
|
||||
|
||||
if (Setting.value(focusSettingName) === 'title') {
|
||||
@@ -240,6 +244,10 @@ class NoteTextComponent extends React.Component {
|
||||
if ('syncStarted' in nextProps && !nextProps.syncStarted && !this.isModified()) {
|
||||
await this.reloadNote(nextProps, { noReloadIfLocalChanges: true });
|
||||
}
|
||||
|
||||
if (nextProps.windowCommand) {
|
||||
this.doCommand(nextProps.windowCommand);
|
||||
}
|
||||
}
|
||||
|
||||
isModified() {
|
||||
@@ -389,6 +397,18 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
if (this.editor_) {
|
||||
this.editor_.editor.renderer.on('afterRender', this.onAfterEditorRender_);
|
||||
|
||||
const cancelledKeys = ['Ctrl+F', 'Ctrl+T', 'Ctrl+P', 'Ctrl+Q', 'Ctrl+L', 'Ctrl+,'];
|
||||
for (let i = 0; i < cancelledKeys.length; i++) {
|
||||
const k = cancelledKeys[i];
|
||||
this.editor_.editor.commands.bindKey(k, () => {
|
||||
// HACK: Ace doesn't seem to provide a way to override its shortcuts, but throwing
|
||||
// an exception from this undocumented function seems to cancel it without any
|
||||
// side effect.
|
||||
// https://stackoverflow.com/questions/36075846
|
||||
throw new Error('HACK: Overriding Ace Editor shortcut: ' + k);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,6 +446,38 @@ class NoteTextComponent extends React.Component {
|
||||
this.scheduleSave();
|
||||
}
|
||||
|
||||
async doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
let commandProcessed = true;
|
||||
|
||||
if (command.name === 'exportPdf' && this.webview_) {
|
||||
const path = bridge().showSaveDialog({
|
||||
filters: [{ name: _('PDF File'), extensions: ['pdf']}]
|
||||
});
|
||||
|
||||
if (path) {
|
||||
this.webview_.printToPDF({}, (error, data) => {
|
||||
if (error) {
|
||||
bridge().showErrorMessageBox(error.message);
|
||||
} else {
|
||||
shim.fsDriver().writeFile(path, data, 'buffer');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (command.name === 'print' && this.webview_) {
|
||||
this.webview_.print();
|
||||
} else {
|
||||
commandProcessed = false;
|
||||
}
|
||||
|
||||
if (commandProcessed) {
|
||||
this.props.dispatch({
|
||||
type: 'WINDOW_COMMAND',
|
||||
name: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async commandAttachFile() {
|
||||
const filePaths = bridge().showOpenDialog({
|
||||
@@ -530,6 +582,7 @@ class NoteTextComponent extends React.Component {
|
||||
marginBottom: 0,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
};
|
||||
|
||||
const titleEditorStyle = {
|
||||
@@ -606,6 +659,10 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
const html = this.mdToHtml().render(bodyToRender, theme, mdOptions);
|
||||
this.webview_.send('setHtml', html);
|
||||
|
||||
const search = BaseModel.byId(this.props.searches, this.props.selectedSearchId);
|
||||
const keywords = search ? Search.keywords(search.query_pattern) : [];
|
||||
this.webview_.send('setMarkers', keywords);
|
||||
}
|
||||
|
||||
const toolbarItems = [];
|
||||
@@ -649,6 +706,8 @@ class NoteTextComponent extends React.Component {
|
||||
display: 'flex',
|
||||
}} iconName="fa-caret-down" theme={this.props.theme} onClick={() => { this.itemContextMenu() }} />
|
||||
|
||||
const titleBarDate = <span style={Object.assign({}, theme.textStyle, {color: theme.colorFaded})}>{time.formatMsToLocal(note.user_updated_time)}</span>
|
||||
|
||||
const viewer = <webview
|
||||
style={viewerStyle}
|
||||
nodeintegration="1"
|
||||
@@ -656,6 +715,24 @@ class NoteTextComponent extends React.Component {
|
||||
ref={(elem) => { this.webview_ref(elem); } }
|
||||
/>
|
||||
|
||||
// const markers = [{
|
||||
// startRow: 2,
|
||||
// startCol: 3,
|
||||
// endRow: 2,
|
||||
// endCol: 6,
|
||||
// type: 'text',
|
||||
// className: 'test-marker'
|
||||
// }];
|
||||
|
||||
// markers={markers}
|
||||
// editorProps={{$useWorker: false}}
|
||||
|
||||
// #note-editor .test-marker {
|
||||
// background-color: red;
|
||||
// color: yellow;
|
||||
// position: absolute;
|
||||
// }
|
||||
|
||||
const editorRootStyle = Object.assign({}, editorStyle);
|
||||
delete editorRootStyle.width;
|
||||
delete editorRootStyle.height;
|
||||
@@ -682,14 +759,15 @@ class NoteTextComponent extends React.Component {
|
||||
editorProps={{$blockScrolling: true}}
|
||||
|
||||
// This is buggy (gets outside the container)
|
||||
highlightActiveLine={false}
|
||||
highlightActiveLine={false}
|
||||
/>
|
||||
|
||||
return (
|
||||
<div style={rootStyle}>
|
||||
<div style={titleBarStyle}>
|
||||
{ titleEditor }
|
||||
{ titleBarMenuButton }
|
||||
{ titleBarDate }
|
||||
{ false ? titleBarMenuButton : null }
|
||||
</div>
|
||||
{ toolbar }
|
||||
{ editor }
|
||||
@@ -710,6 +788,10 @@ const mapStateToProps = (state) => {
|
||||
showAdvancedOptions: state.settings.showAdvancedOptions,
|
||||
syncStarted: state.syncStarted,
|
||||
newNote: state.newNote,
|
||||
windowCommand: state.windowCommand,
|
||||
notesParentType: state.notesParentType,
|
||||
searches: state.searches,
|
||||
selectedSearchId: state.selectedSearchId,
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -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') },
|
||||
|
@@ -345,17 +345,17 @@ class SideBarComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
if (this.props.searches.length) {
|
||||
items.push(this.makeHeader("searchHeader", _("Searches"), "fa-search"));
|
||||
// if (this.props.searches.length) {
|
||||
// items.push(this.makeHeader("searchHeader", _("Searches"), "fa-search"));
|
||||
|
||||
const searchItems = shared.renderSearches(this.props, this.searchItem.bind(this));
|
||||
// const searchItems = shared.renderSearches(this.props, this.searchItem.bind(this));
|
||||
|
||||
items.push(
|
||||
<div className="searches" key="search_items">
|
||||
{searchItems}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// items.push(
|
||||
// <div className="searches" key="search_items">
|
||||
// {searchItems}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
let lines = Synchronizer.reportToLines(this.props.syncReport);
|
||||
const syncReportText = [];
|
||||
|
@@ -1,6 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<style>
|
||||
body {
|
||||
overflow: hidden;
|
||||
@@ -13,12 +15,18 @@
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
mark {
|
||||
background: #CF3F00;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.katex { font-size: 1.3em; } /* This controls the global Katex font size*/
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body id="body">
|
||||
<div id="hlScriptContainer"></div>
|
||||
<div id="markScriptContainer"></div>
|
||||
<div id="content" ondragstart="return false;" ondrop="return false;"></div>
|
||||
|
||||
<script>
|
||||
@@ -38,7 +46,7 @@
|
||||
const script = document.createElement('script');
|
||||
script.onload = function () {
|
||||
hljsLoaded = true;
|
||||
applyHljs();
|
||||
applyHljs();
|
||||
};
|
||||
script.src = 'highlight/highlight.pack.js';
|
||||
document.getElementById('hlScriptContainer').appendChild(script);
|
||||
@@ -160,6 +168,36 @@
|
||||
setPercentScroll(percent);
|
||||
});
|
||||
|
||||
let mark_ = null;
|
||||
function setMarkers(keywords) {
|
||||
if (!mark_) {
|
||||
mark_ = new Mark(document.getElementById('content'), {
|
||||
exclude: ['img'],
|
||||
acrossElements: true,
|
||||
});
|
||||
}
|
||||
|
||||
mark_.mark(keywords);
|
||||
}
|
||||
|
||||
let markLoaded_ = false;
|
||||
ipcRenderer.on('setMarkers', (event, keywords) => {
|
||||
if (!keywords.length && !markLoaded_) return;
|
||||
|
||||
if (!markLoaded_) {
|
||||
const script = document.createElement('script');
|
||||
script.onload = function() {
|
||||
setMarkers(keywords);
|
||||
};
|
||||
|
||||
script.src = '../../node_modules/mark.js/dist/mark.min.js';
|
||||
document.getElementById('markScriptContainer').appendChild(script);
|
||||
markLoaded_ = true;
|
||||
} else {
|
||||
setMarkers(keywords);
|
||||
}
|
||||
});
|
||||
|
||||
function maxScrollTop() {
|
||||
return Math.max(0, contentElement.scrollHeight - contentElement.clientHeight);
|
||||
}
|
||||
|
@@ -17,6 +17,10 @@
|
||||
.smalltalk .page {
|
||||
max-width: 30em;
|
||||
}
|
||||
mark {
|
||||
background: #CF3F00;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
1
ElectronClient/app/locales/cs_CZ.json
Normal file
1
ElectronClient/app/locales/cs_CZ.json
Normal file
File diff suppressed because one or more lines are too long
1
ElectronClient/app/locales/da_DK.json
Normal file
1
ElectronClient/app/locales/da_DK.json
Normal file
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
1
ElectronClient/app/locales/gl_ES.json
Normal file
1
ElectronClient/app/locales/gl_ES.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,9 +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
@@ -73,7 +73,7 @@ app().start(bridge().processArgv()).then(() => {
|
||||
if (error.fileName) msg.push(error.fileName);
|
||||
if (error.lineNumber) msg.push(error.lineNumber);
|
||||
if (error.stack) msg.push(error.stack);
|
||||
bridge().showErrorMessageBox(msg.join('\n'));
|
||||
bridge().showErrorMessageBox(msg.join('\n\n'));
|
||||
}
|
||||
|
||||
bridge().electronApp().exit(1);
|
||||
|
@@ -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);
|
||||
|
||||
|
972
ElectronClient/app/package-lock.json
generated
972
ElectronClient/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.71",
|
||||
"version": "1.0.83",
|
||||
"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.2.0"
|
||||
"electron-builder": "^20.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"7zip-bin-mac": "^1.0.1",
|
||||
@@ -59,9 +75,9 @@
|
||||
"app-module-path": "^2.2.0",
|
||||
"async-mutex": "^0.1.3",
|
||||
"base-64": "^0.1.0",
|
||||
"compare-versions": "^3.1.0",
|
||||
"electron-context-menu": "^0.9.1",
|
||||
"electron-log": "^2.2.11",
|
||||
"electron-updater": "^2.18.2",
|
||||
"electron-is-dev": "^0.3.0",
|
||||
"electron-window-state": "^4.1.1",
|
||||
"follow-redirects": "^1.2.5",
|
||||
"form-data": "^2.3.1",
|
||||
@@ -72,6 +88,7 @@
|
||||
"katex": "^0.9.0-beta1",
|
||||
"levenshtein": "^1.0.5",
|
||||
"lodash": "^4.17.4",
|
||||
"mark.js": "^8.11.1",
|
||||
"markdown-it": "^8.4.0",
|
||||
"markdown-it-katex": "^2.0.3",
|
||||
"md5": "^2.2.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",
|
||||
|
@@ -36,12 +36,14 @@ table td, table th {
|
||||
|
||||
.side-bar .list-item:hover,
|
||||
.side-bar .synchronize-button:hover {
|
||||
background-color: #453E53;
|
||||
/*background-color: #453E53;*/
|
||||
background-color: #01427B;
|
||||
}
|
||||
|
||||
.side-bar .list-item:active,
|
||||
.side-bar .synchronize-button:active {
|
||||
background-color: #564B6C;
|
||||
/*background-color: #564B6C;*/
|
||||
background-color: #0465BB;
|
||||
}
|
||||
|
||||
.editor-toolbar .button:not(.disabled):hover,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
|
||||
const globalStyle = {
|
||||
fontSize: 12 * Setting.value('style.zoom')/100,
|
||||
fontSize: 12 * Setting.value('style.zoom') / 100,
|
||||
fontFamily: 'sans-serif',
|
||||
margin: 15, // No text and no interactive component should be within this margin
|
||||
itemMarginTop: 10,
|
||||
@@ -21,9 +21,11 @@ const globalStyle = {
|
||||
buttonMinHeight: 30,
|
||||
textAreaLineHeight: 17,
|
||||
|
||||
backgroundColor2: "#2B2634",
|
||||
//backgroundColor2: "#2B2634",
|
||||
backgroundColor2: "#162B3D",
|
||||
color2: "#ffffff",
|
||||
selectedColor2: "#5A4D70",
|
||||
//selectedColor2: "#5A4D70",
|
||||
selectedColor2: "#0269C2",
|
||||
colorError2: "#ff6c6c",
|
||||
|
||||
warningBackgroundColor: "#FFD08D",
|
||||
@@ -60,6 +62,7 @@ globalStyle.icon = {
|
||||
globalStyle.lineInput = {
|
||||
color: globalStyle.color,
|
||||
backgroundColor: globalStyle.backgroundColor,
|
||||
fontFamily: globalStyle.fontFamily,
|
||||
};
|
||||
|
||||
globalStyle.textStyle = {
|
||||
|
@@ -1,9 +0,0 @@
|
||||
License MIT
|
||||
|
||||
Copyright (c) 2016-2018 Laurent Cozic
|
||||
|
||||
L'autorisation est accordée, gracieusement, à toute personne acquérant une copie de ce logiciel et des fichiers de documentation associés (le "Logiciel"), de commercialiser le Logiciel sans restriction, notamment les droits d'utiliser, de copier, de modifier, de fusionner, de publier, de distribuer, de sous-licencier et/ou de vendre des copies du Logiciel, ainsi que d'autoriser les personnes auxquelles le Logiciel est fourni à le faire, sous réserve des conditions suivantes :
|
||||
|
||||
La déclaration de copyright ci-dessus et la présente autorisation doivent être incluses dans toutes copies ou parties substantielles du Logiciel.
|
||||
|
||||
LE LOGICIEL EST FOURNI "TEL QUEL", SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE, NOTAMMENT SANS GARANTIE DE QUALITÉ MARCHANDE, D’ADÉQUATION À UN USAGE PARTICULIER ET D'ABSENCE DE CONTREFAÇON. EN AUCUN CAS, LES AUTEURS OU TITULAIRES DU DROIT D'AUTEUR NE SERONT RESPONSABLES DE TOUT DOMMAGE, RÉCLAMATION OU AUTRE RESPONSABILITÉ, QUE CE SOIT DANS LE CADRE D'UN CONTRAT, D'UN DÉLIT OU AUTRE, EN PROVENANCE DE, CONSÉCUTIF À OU EN RELATION AVEC LE LOGICIEL OU SON UTILISATION, OU AVEC D'AUTRES ÉLÉMENTS DU LOGICIEL.
|
170
README.md
170
README.md
@@ -1,14 +1,16 @@
|
||||
# Joplin
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [](https://joplin.cozic.net/donate/#bitcoin) [](https://travis-ci.org/laurent22/joplin) [](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 targets 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
|
||||
|
||||
@@ -16,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.70/Joplin-Setup-1.0.70.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.70/Joplin-1.0.70.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.70/Joplin-1.0.70-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 (64-bit only) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.83/Joplin-Setup-1.0.83.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.83/Joplin-1.0.83.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.83/Joplin-1.0.83-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.106/joplin-v1.0.106.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.118/joplin-v1.0.118.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 pakage 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.
|
||||
@@ -79,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
|
||||
|
||||
@@ -87,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
|
||||
|
||||
@@ -95,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
|
||||
|
||||
@@ -102,31 +122,44 @@ 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
|
||||
|
||||
On the **desktop application** or **mobile application**, go to the config screen and select Nextcloud as the synchronisation target. Then input [the WebDAV URL](https://docs.nextcloud.com/server/9/user_manual/files/access_webdav.html), this is normally `https://example.com/nextcloud/remote.php/dav/files/USERNAME/Joplin` (make sure to create the "Joplin" directory in Nextcloud and to replace USERNAME by your Nextcloud username), and set the username and password.
|
||||
<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.
|
||||
|
||||
WebDAV-compatible services that are known to work with Joplin:
|
||||
WebDAV-compatible services that are known to work with Joplin.
|
||||
|
||||
- [Box.com](https://www.box.com/)
|
||||
- [DriveHQ](https://www.drivehq.com)
|
||||
- [HiDrive](https://www.strato.fr/stockage-en-ligne/) from Strato. [Setup help](https://github.com/laurent22/joplin/issues/309)
|
||||
- [OwnCloud](https://owncloud.org/)
|
||||
- [Seafile](https://www.seafile.com/)
|
||||
- [Stack](https://www.transip.nl/stack/)
|
||||
@@ -136,22 +169,22 @@ 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.
|
||||
|
||||
# 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:
|
||||
@@ -174,29 +207,29 @@ Joplin uses and renders [Github-flavoured Markdown](https://github.com/adam-p/ma
|
||||
|
||||
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.
|
||||
|
||||
@@ -204,7 +237,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
|
||||
|
||||
@@ -228,24 +267,27 @@ Current translations:
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
| Language | Po File | Last translator | Percent done
|
||||
---|---|---|---|---
|
||||
 | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 80%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić <trbuhom@net.hr> | 65%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Tobias Strobel <git@strobeltobias.de> | 83%
|
||||
 | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín <f@mrtn.es> | 99%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
 | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 67%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 81%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | | 66%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov <artyom.karlov@gmail.com> | 84%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | RCJacH <RCJacH@outlook.com> | 67%
|
||||
 | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | | 65%
|
||||
 | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 76%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić <trbuhom@net.hr> | 62%
|
||||
 | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt <lukas@aiya.cz> | 96%
|
||||
 | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér <mjjzf@syntaktisk. | 98%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Tobias Grasse <mail@tobias-grasse.net> | 95%
|
||||
 | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín <f@mrtn.es> | 99%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
 | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans <marcoslansgarza@gmail.com> | 97%
|
||||
 | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 63%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 77%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos <rnbastos@gmail.com> | 99%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov <artyom.karlov@gmail.com> | 95%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 92%
|
||||
 | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | | 62%
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
|
||||
# Known bugs
|
||||
|
||||
- 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.
|
||||
- While the mobile can sync and load tags, it is not currently possible to create new ones. The desktop and terminal apps can create, delete and edit tags.
|
||||
- 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.
|
||||
|
||||
# License
|
||||
|
||||
|
@@ -90,8 +90,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 22
|
||||
versionCode 2097284
|
||||
versionName "1.0.106"
|
||||
versionCode 2097296
|
||||
versionName "1.0.118"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -29,14 +29,17 @@ 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');
|
||||
|
||||
SyncTargetRegistry.addClass(SyncTargetFilesystem);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDriveDev);
|
||||
SyncTargetRegistry.addClass(SyncTargetNextcloud);
|
||||
SyncTargetRegistry.addClass(SyncTargetWebDAV);
|
||||
SyncTargetRegistry.addClass(SyncTargetDropbox);
|
||||
|
||||
class BaseApplication {
|
||||
|
||||
@@ -259,7 +262,7 @@ class BaseApplication {
|
||||
const newState = store.getState();
|
||||
let refreshNotes = false;
|
||||
|
||||
if (action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE') {
|
||||
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;
|
||||
refreshNotes = true;
|
||||
@@ -365,11 +368,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';
|
||||
@@ -420,12 +423,19 @@ 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'));
|
||||
}
|
||||
|
||||
BaseService.logger_ = this.logger_;
|
||||
EncryptionService.instance().setLogger(this.logger_);
|
||||
BaseItem.encryptionService_ = EncryptionService.instance();
|
||||
DecryptionWorker.instance().setLogger(this.logger_);
|
||||
|
@@ -1,4 +1,3 @@
|
||||
const { Log } = require('lib/log.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
@@ -122,15 +121,6 @@ class BaseModel {
|
||||
return id.substr(0, 5);
|
||||
}
|
||||
|
||||
// static minimalPartialId(id) {
|
||||
// let length = 2;
|
||||
// while (true) {
|
||||
// const partialId = id.substr(0, length);
|
||||
// const r = await this.db().selectOne('SELECT count(*) as total FROM `' + this.tableName() + '` WHERE `id` LIKE ?', [partialId + '%']);
|
||||
// if (r['total'] <= 1) return partialId;
|
||||
// }
|
||||
// }
|
||||
|
||||
static loadByPartialId(partialId) {
|
||||
return this.modelSelectAll('SELECT * FROM `' + this.tableName() + '` WHERE `id` LIKE ?', [partialId + '%']);
|
||||
}
|
||||
@@ -222,20 +212,6 @@ class BaseModel {
|
||||
}
|
||||
if ('type_' in newModel) output.type_ = newModel.type_;
|
||||
return output;
|
||||
// let output = {};
|
||||
// let type = null;
|
||||
// for (let n in newModel) {
|
||||
// if (!newModel.hasOwnProperty(n)) continue;
|
||||
// if (n == 'type_') {
|
||||
// type = newModel[n];
|
||||
// continue;
|
||||
// }
|
||||
// if (!(n in oldModel) || newModel[n] !== oldModel[n]) {
|
||||
// output[n] = newModel[n];
|
||||
// }
|
||||
// }
|
||||
// if (type !== null) output.type_ = type;
|
||||
// return output;
|
||||
}
|
||||
|
||||
static diffObjectsFields(oldModel, newModel) {
|
||||
@@ -422,11 +398,10 @@ class BaseModel {
|
||||
}
|
||||
|
||||
output = this.filter(o);
|
||||
} catch (error) {
|
||||
Log.error('Cannot save model', error);
|
||||
} finally {
|
||||
this.releaseSaveMutex(o, mutexRelease);
|
||||
}
|
||||
|
||||
this.releaseSaveMutex(o, mutexRelease);
|
||||
|
||||
|
||||
return output;
|
||||
}
|
||||
@@ -505,6 +480,8 @@ BaseModel.typeEnum_ = [
|
||||
['TYPE_SEARCH', 7],
|
||||
['TYPE_ALARM', 8],
|
||||
['TYPE_MASTER_KEY', 9],
|
||||
['TYPE_ITEM_CHANGE', 10],
|
||||
['TYPE_NOTE_RESOURCE', 11],
|
||||
];
|
||||
|
||||
for (let i = 0; i < BaseModel.typeEnum_.length; i++) {
|
||||
@@ -512,16 +489,6 @@ for (let i = 0; i < BaseModel.typeEnum_.length; i++) {
|
||||
BaseModel[e[0]] = e[1];
|
||||
}
|
||||
|
||||
// BaseModel.TYPE_NOTE = 1;
|
||||
// BaseModel.TYPE_FOLDER = 2;
|
||||
// BaseModel.TYPE_SETTING = 3;
|
||||
// BaseModel.TYPE_RESOURCE = 4;
|
||||
// BaseModel.TYPE_TAG = 5;
|
||||
// BaseModel.TYPE_NOTE_TAG = 6;
|
||||
// BaseModel.TYPE_SEARCH = 7;
|
||||
// BaseModel.TYPE_ALARM = 8;
|
||||
// BaseModel.TYPE_MASTER_KEY = 9;
|
||||
|
||||
BaseModel.db_ = null;
|
||||
BaseModel.dispatch = function(o) {};
|
||||
BaseModel.saveMutexes_ = {};
|
||||
|
@@ -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';
|
||||
}
|
||||
|
214
ReactNativeClient/lib/DropboxApi.js
Normal file
214
ReactNativeClient/lib/DropboxApi.js
Normal 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;
|
@@ -32,4 +32,4 @@ class EventDispatcher {
|
||||
|
||||
}
|
||||
|
||||
module.exports = { EventDispatcher };
|
||||
module.exports = EventDispatcher;
|
@@ -3,7 +3,9 @@ const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = (new Entities()).encode;
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const ModelCache = require('lib/ModelCache');
|
||||
const ObjectUtils = require('lib/ObjectUtils');
|
||||
const { shim } = require('lib/shim.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const md5 = require('md5');
|
||||
const MdToHtml_Katex = require('lib/MdToHtml_Katex');
|
||||
|
||||
@@ -54,11 +56,11 @@ class MdToHtml {
|
||||
return output.join(' ');
|
||||
}
|
||||
|
||||
getAttr_(attrs, name) {
|
||||
getAttr_(attrs, name, defaultValue = null) {
|
||||
for (let i = 0; i < attrs.length; i++) {
|
||||
if (attrs[i][0] === name) return attrs[i].length > 1 ? attrs[i][1] : null;
|
||||
}
|
||||
return null;
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
setAttr_(attrs, name, value) {
|
||||
@@ -182,11 +184,23 @@ class MdToHtml {
|
||||
return null;
|
||||
}
|
||||
|
||||
urldecode_(str) {
|
||||
try {
|
||||
return decodeURIComponent((str+'').replace(/\+/g, '%20'));
|
||||
} catch (error) {
|
||||
// decodeURIComponent can throw if the string contains non-encoded data (for example "100%")
|
||||
// so in this case just return the non encoded string.
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
renderTokens_(markdownIt, tokens, options) {
|
||||
let output = [];
|
||||
let previousToken = null;
|
||||
let anchorAttrs = [];
|
||||
let extraCssBlocks = {};
|
||||
let anchorHrefs = [];
|
||||
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let t = tokens[i];
|
||||
@@ -196,12 +210,13 @@ class MdToHtml {
|
||||
let openTag = null;
|
||||
let closeTag = null;
|
||||
let attrs = t.attrs ? t.attrs : [];
|
||||
let tokenContent = t.content ? t.content : null;
|
||||
let tokenContent = t.content ? t.content : '';
|
||||
const isCodeBlock = tag === 'code' && t.block;
|
||||
const isInlineCode = t.type === 'code_inline';
|
||||
const codeBlockLanguage = t && t.info ? t.info : null;
|
||||
let rendererPlugin = null;
|
||||
let rendererPluginOptions = { tagType: 'inline' };
|
||||
let linkHref = null;
|
||||
|
||||
if (isCodeBlock) rendererPlugin = this.rendererPlugin_(codeBlockLanguage);
|
||||
|
||||
@@ -233,6 +248,7 @@ class MdToHtml {
|
||||
if (openTag) {
|
||||
if (openTag === 'a') {
|
||||
anchorAttrs.push(attrs);
|
||||
anchorHrefs.push(this.getAttr_(attrs, 'href'));
|
||||
output.push(this.renderOpenLink_(attrs, options));
|
||||
} else {
|
||||
const attrsHtml = this.renderAttrs_(attrs);
|
||||
@@ -317,7 +333,33 @@ class MdToHtml {
|
||||
|
||||
if (closeTag) {
|
||||
if (closeTag === 'a') {
|
||||
output.push(this.renderCloseLink_(anchorAttrs.pop(), options));
|
||||
const currentAnchorAttrs = anchorAttrs.pop();
|
||||
|
||||
// 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
|
||||
// from imported HTML, which can contain many such links and make the text unreadble. An example
|
||||
// would be a movie review that has multiple links to allow a user to rate the film from 1 to 5 stars.
|
||||
// In the original page, it might be rendered as stars, via CSS, but in the imported note it would look like this:
|
||||
// http://example.com/rate/1 http://example.com/rate/2 http://example.com/rate/3
|
||||
// http://example.com/rate/4 http://example.com/rate/5
|
||||
// which would take a lot of screen space even though it doesn't matter since the user is unlikely
|
||||
// to rate the film from the note. This is actually a nice example, still readable, but there is way
|
||||
// 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)'));
|
||||
// }
|
||||
|
||||
output.push(this.renderCloseLink_(currentAnchorAttrs, options));
|
||||
} else {
|
||||
output.push('</' + closeTag + '>');
|
||||
}
|
||||
@@ -336,14 +378,16 @@ class MdToHtml {
|
||||
|
||||
// Insert the extra CSS at the top of the HTML
|
||||
|
||||
const temp = ['<style>'];
|
||||
for (let n in extraCssBlocks) {
|
||||
if (!extraCssBlocks.hasOwnProperty(n)) continue;
|
||||
temp.push(extraCssBlocks[n]);
|
||||
}
|
||||
temp.push('</style>');
|
||||
if (!ObjectUtils.isEmpty(extraCssBlocks)) {
|
||||
const temp = ['<style>'];
|
||||
for (let n in extraCssBlocks) {
|
||||
if (!extraCssBlocks.hasOwnProperty(n)) continue;
|
||||
temp.push(extraCssBlocks[n]);
|
||||
}
|
||||
temp.push('</style>');
|
||||
|
||||
output = temp.concat(output);
|
||||
output = temp.concat(output);
|
||||
}
|
||||
|
||||
return output.join('');
|
||||
}
|
||||
@@ -451,7 +495,7 @@ class MdToHtml {
|
||||
position: relative;
|
||||
top: .5em;
|
||||
text-decoration: none;
|
||||
width: 1.2em;
|
||||
width: 1.15em;
|
||||
height: 1.5em;
|
||||
margin-right: 0.4em;
|
||||
background-color: ` + style.htmlColor + `;
|
||||
@@ -495,13 +539,34 @@ class MdToHtml {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.katex .mfrac .frac-line:before {
|
||||
/* top: 50%; */
|
||||
/* padding-bottom: .7em; */
|
||||
@media print {
|
||||
body {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
a.checkbox {
|
||||
border: 1pt solid ` + style.htmlColor + `;
|
||||
border-radius: 2pt;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
text-align: center;
|
||||
top: .4em;
|
||||
}
|
||||
|
||||
a.checkbox.tick:after {
|
||||
content: "X";
|
||||
}
|
||||
|
||||
a.checkbox.tick {
|
||||
top: 0;
|
||||
left: -0.02em;
|
||||
color: ` + style.htmlColor + `;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const styleHtml = '<style>' + normalizeCss + "\n" + css + '</style>'; //+ '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css">';
|
||||
const styleHtml = '<style>' + normalizeCss + "\n" + css + '</style>';
|
||||
|
||||
const output = styleHtml + renderedBody;
|
||||
|
||||
|
@@ -44,4 +44,18 @@ ObjectUtils.fieldsEqual = function(o1, o2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ObjectUtils.convertValuesToFunctions = function(o) {
|
||||
const output = {};
|
||||
for (let n in o) {
|
||||
if (!o.hasOwnProperty(n)) continue;
|
||||
output[n] = () => { return typeof o[n] === 'function' ? o[n]() : o[n]; }
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
ObjectUtils.isEmpty = function(o) {
|
||||
if (!o) return true;
|
||||
return Object.keys(o).length === 0 && o.constructor === Object;
|
||||
}
|
||||
|
||||
module.exports = ObjectUtils;
|
73
ReactNativeClient/lib/SyncTargetDropbox.js
Normal file
73
ReactNativeClient/lib/SyncTargetDropbox.js
Normal 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;
|
@@ -19,7 +19,7 @@ class SyncTargetFilesystem extends BaseSyncTarget {
|
||||
return _('File system');
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
async isAuthenticated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ class SyncTargetMemory extends BaseSyncTarget {
|
||||
return 'Memory';
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
async isAuthenticated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,7 @@ class SyncTargetNextcloud extends BaseSyncTarget {
|
||||
return _('Nextcloud');
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
async isAuthenticated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ class SyncTargetNextcloud extends BaseSyncTarget {
|
||||
|
||||
async initFileApi() {
|
||||
const fileApi = await SyncTargetWebDAV.newFileApi_(SyncTargetNextcloud.id(), {
|
||||
path: Setting.value('sync.5.path'),
|
||||
username: Setting.value('sync.5.username'),
|
||||
password: Setting.value('sync.5.password'),
|
||||
path: () => Setting.value('sync.5.path'),
|
||||
username: () => Setting.value('sync.5.username'),
|
||||
password: () => Setting.value('sync.5.password'),
|
||||
});
|
||||
|
||||
fileApi.setLogger(this.logger());
|
||||
|
@@ -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'));
|
||||
}
|
||||
|
||||
|
@@ -24,15 +24,15 @@ class SyncTargetWebDAV extends BaseSyncTarget {
|
||||
return _('WebDAV');
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
async isAuthenticated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static async newFileApi_(syncTargetId, options) {
|
||||
const apiOptions = {
|
||||
baseUrl: () => options.path,
|
||||
username: () => options.username,
|
||||
password: () => options.password,
|
||||
baseUrl: () => options.path(),
|
||||
username: () => options.username(),
|
||||
password: () => options.password(),
|
||||
};
|
||||
|
||||
const api = new WebDavApi(apiOptions);
|
||||
@@ -65,9 +65,9 @@ class SyncTargetWebDAV extends BaseSyncTarget {
|
||||
|
||||
async initFileApi() {
|
||||
const fileApi = await SyncTargetWebDAV.newFileApi_(SyncTargetWebDAV.id(), {
|
||||
path: Setting.value('sync.6.path'),
|
||||
username: Setting.value('sync.6.username'),
|
||||
password: Setting.value('sync.6.password'),
|
||||
path: () => Setting.value('sync.6.path'),
|
||||
username: () => Setting.value('sync.6.username'),
|
||||
password: () => Setting.value('sync.6.password'),
|
||||
});
|
||||
|
||||
fileApi.setLogger(this.logger());
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -30,16 +30,17 @@ class ModalDialog extends React.Component {
|
||||
borderColor:theme.dividerColor,
|
||||
margin: 20,
|
||||
padding: 10,
|
||||
borderRadius: 5,
|
||||
},
|
||||
modalContentWrapper2: {
|
||||
paddingTop: 10,
|
||||
flex:1,
|
||||
},
|
||||
title: {
|
||||
title: Object.assign({}, theme.normalText, {
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
paddingBottom: 10,
|
||||
},
|
||||
fontWeight: 'bold',
|
||||
}),
|
||||
buttonRow: {
|
||||
flexDirection: 'row',
|
||||
borderTopWidth: 1,
|
||||
@@ -54,21 +55,22 @@ class ModalDialog extends React.Component {
|
||||
|
||||
render() {
|
||||
const ContentComponent = this.props.ContentComponent;
|
||||
const buttonBarEnabled = this.props.buttonBarEnabled !== false;
|
||||
|
||||
return (
|
||||
<View style={this.styles().modalWrapper}>
|
||||
<Modal transparent={true} visible={true} onRequestClose={() => { }} >
|
||||
<View style={this.styles().modalContentWrapper}>
|
||||
<Text style={this.styles().title}>Title</Text>
|
||||
<View elevation={10} style={this.styles().modalContentWrapper}>
|
||||
<Text style={this.styles().title}>{this.props.title}</Text>
|
||||
<View style={this.styles().modalContentWrapper2}>
|
||||
{ContentComponent}
|
||||
</View>
|
||||
<View style={this.styles().buttonRow}>
|
||||
<View style={{flex:1}}>
|
||||
<Button title={_('OK')} onPress={() => {}}></Button>
|
||||
<Button disabled={!buttonBarEnabled} title={_('OK')} onPress={this.props.onOkPress}></Button>
|
||||
</View>
|
||||
<View style={{flex:1, marginLeft: 5}}>
|
||||
<Button title={_('Cancel')} onPress={() => {}}></Button>
|
||||
<Button disabled={!buttonBarEnabled} title={_('Cancel')} onPress={this.props.onCancelPress}></Button>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
@@ -4,7 +4,6 @@ const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||
const ReactNativeActionButton = require('react-native-action-button').default;
|
||||
const { connect } = require('react-redux');
|
||||
const { globalStyle } = require('lib/components/global-style.js');
|
||||
const { Log } = require('lib/log.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
@@ -27,7 +26,7 @@ class ActionButtonComponent extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
if ('buttonIndex' in newProps) {
|
||||
this.setState({ buttonIndex: newProps.buttonIndex });
|
||||
}
|
||||
|
@@ -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));
|
||||
|
@@ -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 });
|
||||
}
|
||||
|
@@ -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,29 +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.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";
|
||||
@@ -69,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 };
|
@@ -18,7 +18,7 @@ class NoteBodyViewer extends Component {
|
||||
this.isMounted_ = false;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
UNSAFE_componentWillMount() {
|
||||
this.mdToHtml_ = new MdToHtml({ supportsResourceLinks: false });
|
||||
this.isMounted_ = true;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ class NoteBodyViewer extends Component {
|
||||
style={webViewStyle}
|
||||
source={source}
|
||||
onLoadEnd={() => this.onLoadEnd()}
|
||||
onError={(e) => reg.logger().error('WebView error', e) }
|
||||
onError={() => reg.logger().error('WebView error') }
|
||||
onMessage={(event) => {
|
||||
let msg = event.nativeEvent.data;
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
const { ListView, Text, TouchableOpacity , View, StyleSheet } = require('react-native');
|
||||
const { Log } = require('lib/log.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { Checkbox } = require('lib/components/checkbox.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
|
@@ -1,7 +1,6 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
const { ListView, Text, TouchableHighlight, Switch, View, StyleSheet } = require('react-native');
|
||||
const { Log } = require('lib/log.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { Checkbox } = require('lib/components/checkbox.js');
|
||||
const { NoteItem } = require('lib/components/note-item.js');
|
||||
@@ -69,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)),
|
||||
|
@@ -2,7 +2,6 @@ const React = require('react'); const Component = React.Component;
|
||||
const { connect } = require('react-redux');
|
||||
const { Platform, View, Text, Button, StyleSheet, TouchableOpacity, Image, ScrollView, Dimensions } = require('react-native');
|
||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||
const { Log } = require('lib/log.js');
|
||||
const { BackButtonService } = require('lib/services/back-button.js');
|
||||
const NavService = require('lib/services/NavService.js');
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
@@ -129,6 +128,8 @@ class ScreenHeaderComponent extends Component {
|
||||
color: theme.raisedHighlightedColor,
|
||||
fontWeight: 'bold',
|
||||
fontSize: theme.fontSize,
|
||||
paddingTop: 15,
|
||||
paddingBottom: 15,
|
||||
},
|
||||
warningBox: {
|
||||
backgroundColor: "#ff9900",
|
||||
@@ -429,15 +430,19 @@ class ScreenHeaderComponent extends Component {
|
||||
</TouchableOpacity>
|
||||
) : null;
|
||||
|
||||
const showSideMenuButton = this.props.showSideMenuButton !== false && !this.props.noteSelectionEnabled;
|
||||
const showSearchButton = this.props.showSearchButton !== false && !this.props.noteSelectionEnabled;
|
||||
const showContextMenuButton = this.props.showContextMenuButton !== false;
|
||||
|
||||
const titleComp = createTitleComponent();
|
||||
const sideMenuComp = this.props.noteSelectionEnabled ? null : sideMenuButton(this.styles(), () => this.sideMenuButton_press());
|
||||
const sideMenuComp = !showSideMenuButton ? null : sideMenuButton(this.styles(), () => this.sideMenuButton_press());
|
||||
const backButtonComp = backButton(this.styles(), () => this.backButton_press(), !this.props.historyCanGoBack);
|
||||
const searchButtonComp = this.props.noteSelectionEnabled ? null : searchButton(this.styles(), () => this.searchButton_press());
|
||||
const searchButtonComp = !showSearchButton ? null : searchButton(this.styles(), () => this.searchButton_press());
|
||||
const deleteButtonComp = this.props.noteSelectionEnabled ? deleteButton(this.styles(), () => this.deleteButton_press()) : null;
|
||||
const sortButtonComp = this.props.sortButton_press ? sortButton(this.styles(), () => this.props.sortButton_press()) : null;
|
||||
const windowHeight = Dimensions.get('window').height - 50;
|
||||
|
||||
const menuComp = (
|
||||
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}> ⋮</Text>
|
||||
|
199
ReactNativeClient/lib/components/screens/NoteTagsDialog.js
Normal file
199
ReactNativeClient/lib/components/screens/NoteTagsDialog.js
Normal file
@@ -0,0 +1,199 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { ListView, StyleSheet, View, Text, Button, FlatList, TouchableOpacity, TextInput } = require('react-native');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { connect } = require('react-redux');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { ScreenHeader } = require('lib/components/screen-header.js');
|
||||
const { time } = require('lib/time-utils');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { globalStyle, themeStyle } = require('lib/components/global-style.js');
|
||||
const Icon = require('react-native-vector-icons/Ionicons').default;
|
||||
const ModalDialog = require('lib/components/ModalDialog');
|
||||
const naturalCompare = require('string-natural-compare');
|
||||
|
||||
class NoteTagsDialogComponent extends React.Component {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.styles_ = {};
|
||||
this.state = {
|
||||
noteTagIds: [],
|
||||
noteId: null,
|
||||
tagListData: [],
|
||||
newTags: '',
|
||||
savingTags: false,
|
||||
};
|
||||
|
||||
const noteHasTag = (tagId) => {
|
||||
for (let i = 0; i < this.state.tagListData.length; i++) {
|
||||
if (this.state.tagListData[i].id === tagId) return this.state.tagListData[i].selected;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const newTagTitles = () => {
|
||||
return this.state.newTags
|
||||
.split(',')
|
||||
.map(t => t.trim().toLowerCase())
|
||||
.filter(t => !!t);
|
||||
}
|
||||
|
||||
this.tag_press = (tagId) => {
|
||||
const newData = this.state.tagListData.slice();
|
||||
for (let i = 0; i < newData.length; i++) {
|
||||
const t = newData[i];
|
||||
if (t.id === tagId) {
|
||||
const newTag = Object.assign({}, t);
|
||||
newTag.selected = !newTag.selected;
|
||||
newData[i] = newTag;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ tagListData: newData });
|
||||
}
|
||||
|
||||
this.renderTag = (data) => {
|
||||
const tag = data.item;
|
||||
const iconName = noteHasTag(tag.id) ? 'md-checkbox-outline' : 'md-square-outline';
|
||||
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 style={this.styles().tagText}>{tag.title}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
|
||||
this.tagKeyExtractor = (tag, index) => tag.id;
|
||||
|
||||
this.okButton_press = async () => {
|
||||
this.setState({ savingTags: true });
|
||||
|
||||
try {
|
||||
const tagIds = this.state.tagListData.filter(t => t.selected).map(t => t.id);
|
||||
await Tag.setNoteTagsByIds(this.state.noteId, tagIds);
|
||||
|
||||
const extraTitles = newTagTitles();
|
||||
for (let i = 0; i < extraTitles.length; i++) {
|
||||
await Tag.addNoteTagByTitle(this.state.noteId, extraTitles[i]);
|
||||
}
|
||||
} finally {
|
||||
this.setState({ savingTags: false });
|
||||
}
|
||||
|
||||
if (this.props.onCloseRequested) this.props.onCloseRequested();
|
||||
}
|
||||
|
||||
this.cancelButton_press = () => {
|
||||
if (this.props.onCloseRequested) this.props.onCloseRequested();
|
||||
}
|
||||
}
|
||||
|
||||
UNSAFE_componentWillMount() {
|
||||
const noteId = this.props.noteId;
|
||||
this.setState({ noteId: noteId });
|
||||
this.loadNoteTags(noteId);
|
||||
}
|
||||
|
||||
async loadNoteTags(noteId) {
|
||||
const tags = await Tag.tagsByNoteId(noteId);
|
||||
const tagIds = tags.map(t => t.id);
|
||||
|
||||
const tagListData = this.props.tags.map(tag => { return {
|
||||
id: tag.id,
|
||||
title: tag.title,
|
||||
selected: tagIds.indexOf(tag.id) >= 0,
|
||||
}});
|
||||
|
||||
tagListData.sort((a, b) => {
|
||||
return naturalCompare.caseInsensitive(a.title, b.title);
|
||||
});
|
||||
|
||||
this.setState({ tagListData: tagListData });
|
||||
}
|
||||
|
||||
styles() {
|
||||
const themeId = this.props.theme;
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
if (this.styles_[themeId]) return this.styles_[themeId];
|
||||
this.styles_ = {};
|
||||
|
||||
let styles = {
|
||||
tag: {
|
||||
padding: 10,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.dividerColor,
|
||||
},
|
||||
tagIconText: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
tagText: Object.assign({}, theme.normalText),
|
||||
tagCheckbox: {
|
||||
marginRight: 8,
|
||||
fontSize: 20,
|
||||
color: theme.color,
|
||||
},
|
||||
newTagBox: {
|
||||
flexDirection:'row',
|
||||
alignItems: 'center',
|
||||
paddingLeft: theme.marginLeft,
|
||||
paddingRight: theme.marginRight,
|
||||
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);
|
||||
return this.styles_[themeId];
|
||||
}
|
||||
|
||||
render() {
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
const dialogContent = (
|
||||
<View style={{flex:1}}>
|
||||
<View style={this.styles().newTagBox}>
|
||||
<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}
|
||||
renderItem={this.renderTag}
|
||||
keyExtractor={this.tagKeyExtractor}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
return <ModalDialog
|
||||
theme={this.props.theme}
|
||||
ContentComponent={dialogContent}
|
||||
title={_('Type new tags or select from list')}
|
||||
onOkPress={this.okButton_press}
|
||||
onCancelPress={this.cancelButton_press}
|
||||
buttonBarEnabled={!this.state.savingTags}
|
||||
/>
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const NoteTagsDialog = connect(
|
||||
(state) => {
|
||||
return {
|
||||
theme: state.settings.theme,
|
||||
tags: state.tags,
|
||||
noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
|
||||
};
|
||||
}
|
||||
)(NoteTagsDialogComponent)
|
||||
|
||||
module.exports = NoteTagsDialog;
|
@@ -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>
|
||||
|
83
ReactNativeClient/lib/components/screens/dropbox-login.js
Normal file
83
ReactNativeClient/lib/components/screens/dropbox-login.js
Normal 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 };
|
@@ -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>
|
||||
|
@@ -1,7 +1,6 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { View, Button, TextInput, StyleSheet } = require('react-native');
|
||||
const { connect } = require('react-redux');
|
||||
const { Log } = require('lib/log.js');
|
||||
const { ActionButton } = require('lib/components/action-button.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
@@ -44,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({
|
||||
@@ -104,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}>
|
||||
@@ -113,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>
|
||||
);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user