1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-23 23:33:01 +02:00

Compare commits

..

39 Commits

Author SHA1 Message Date
Laurent Cozic
e7ec2ce6cf Electron release v1.0.115 2018-11-13 23:18:08 +00:00
Laurent Cozic
61dbdd5f7c Update translations 2018-11-13 23:17:56 +00:00
Laurent Cozic
e6888c451d Fixing Katex version number 2018-11-13 22:42:06 +00:00
Laurent Cozic
899219abd2 Merge branch 'master' of github.com:laurent22/joplin 2018-11-13 22:38:32 +00:00
Joybin Chen
7a4c7a13eb Fix image fetching error. For url like http://example.com/favicon.ico?ver=1.0 will be changed to http://example.com/favicon.ico?ver=1.0?ver=1.0 (#970) 2018-11-13 22:37:39 +00:00
Laurent Cozic
e8797f49b9 Mobile: Display number of resources being fetched in side bar 2018-11-13 22:27:58 +00:00
Laurent Cozic
e17f3051f0 Display number of resources being fetched in side bar 2018-11-13 22:25:23 +00:00
Laurent Cozic
06091933e1 All: Moved resource app-specific state to different table 2018-11-13 00:45:08 +00:00
Laurent Cozic
b30c65dd89 Update CONTRIBUTING.md 2018-11-11 20:23:55 +00:00
Ben Fisher
0eb18d206d Patch to implement feature, exporting notes to JSON (#912, issues/912). (#927)
* Patch to implement feature, exporting notes to JSON (#912, issues/912).

* Revising based on feedback

* Directly calling JSON.stringify on the item
2018-11-11 20:17:43 +00:00
Laurent Cozic
3a9948e528 Build doc 2018-11-08 01:21:18 +00:00
Laurent Cozic
2bcddd38b2 Update API doc 2018-11-08 01:17:46 +00:00
Laurent Cozic
5ff8808f69 API: Allow setting the ID of newly created notes. 2018-11-08 01:14:13 +00:00
Laurent Cozic
28b1d8a324 Desktop: Fixes #953 (maybe): Improved the way internal links to notes are loaded to make it more reliable 2018-11-08 00:58:06 +00:00
Laurent Cozic
5c1dd79435 All: Fixes #952: Upgraded Katex lib to fix bug 2018-11-07 23:44:59 +00:00
Laurent Cozic
706d59a6cc Doc 2018-11-07 23:43:48 +00:00
Ben Fisher
251f1bba55 Show note title in pdf export (#890) (#937)
* Show note title in pdf export (#890)

An example of a possible approach, to temporarily change the html in the webview to show the note title. Works, but there may be a more elegant fix.

* Show title in pdf export

Revising based on feedback
Also, a couple changes to tests so that they pass in Windows.
2018-11-07 23:35:14 +00:00
Caleb John
cb1fd85ca4 Add support for custom css across all notes (#925) 2018-11-07 22:52:31 +00:00
Laurent Cozic
11ddc55911 Fixed theme handling for new tag feature 2018-11-07 22:47:34 +00:00
Caleb John
ee106105d8 Joplin desktop Dark Mode (#921)
* Added support for the dark mode on desktop

* Add dark highlighting to the code tags

* Update app/theme.js to be more clear and more easily support additional themes
Update more files to conform to theming
2018-11-07 22:37:13 +00:00
Laurent Cozic
19f5a144e5 Added comment 2018-11-07 22:22:26 +00:00
Abijeet Patro
18717bac79 Adds functionality to display tags under the open note. (#893)
* Adds functionality to display tags under the open note.

Towards #469

Signed-off-by: Abijeet <abijeetpatro@gmail.com>

* Ensured tags in the dialog box and under the note appear in the same order.

Few formatting tweaks.

Signed-off-by: Abijeet <abijeetpatro@gmail.com>

* Fixes issues raised during code review.

Signed-off-by: Abijeet <abijeetpatro@gmail.com>

* Refactored code to always display tags in ascending order.

This changes the order of the tags in the dialog box and below the tag title.

Signed-off-by: Abijeet <abijeetpatro@gmail.com>
2018-11-07 22:16:05 +00:00
Laurent Cozic
28fa83c406 Merge branch 'master' of github.com:laurent22/joplin 2018-11-02 19:56:18 +00:00
Laurent Cozic
258e514a91 Marked password cache as secure, and only display stars if the value is non-empty 2018-11-02 19:22:49 +00:00
Ben Fisher
f92546d6eb Adding some tips for building and debugging Joplin on Windows (#938) 2018-11-02 01:06:48 +00:00
sensor-freak
693456164b Minor fix for translation of 'Location' (#936) 2018-11-02 00:53:05 +00:00
Helmut K. C. Tessarek
7cd3e6b1f7 mobile: add version info (#930) 2018-11-02 00:43:42 +00:00
FoxMaSk
764e63d869 new French Translations (#923) 2018-11-02 00:24:28 +00:00
Laurent Cozic
2c6f47f277 Update README.md
Removed Hacktoberfest news
2018-11-01 17:45:05 +00:00
Laurent Cozic
e41896d6f3 All: Resolves #918: Skip properties that are on sync target but not handled by local client 2018-10-31 00:35:57 +00:00
Laurent Cozic
990591cc80 Minor improvments 2018-10-30 00:17:50 +00:00
Laurent Cozic
7b85c33213 CLI v1.0.117 2018-10-29 23:24:19 +00:00
Laurent Cozic
4b4d0e8b25 Update website 2018-10-24 21:14:38 +01:00
Laurent Cozic
4fb6af3c62 Android release v1.0.175 2018-10-24 19:59:37 +01:00
Laurent Cozic
d7ffe7e294 Electron release v1.0.114 2018-10-24 19:52:07 +01:00
Laurent Cozic
3ff139d445 Merge branch 'master' of github.com:laurent22/joplin 2018-10-24 19:51:16 +01:00
Laurent Cozic
40443e0134 Android v153 2018-10-24 19:50:26 +01:00
Laurent Cozic
1f927c1285 iOS v26 2018-10-24 19:48:09 +01:00
Laurent Cozic
f93fca7c5b Revert "Android: Updated project to build on macOS"
This reverts commit b547f9aa13.
2018-10-13 11:35:21 +01:00
146 changed files with 2436 additions and 747 deletions

View File

@@ -58,6 +58,8 @@ If node-gyp does not works (MSBUILD: error MSB3428: Could not load the Visual C+
If `yarn dist` fails, it may need administrative rights.
The [building\_win32\_tips on this page](./readme/building_win32_tips.md) might be helpful.
# Building the Mobile application
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "Building Projects with Native Code" tab.

View File

@@ -18,9 +18,11 @@ If you want to add a new feature, consider asking about it before implementing i
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/master/BUILD.md) for more details.
Pull requests that automatically change many files tend to be rejected (for example changes that automatically update the code styling, or to add new lines to many files, or to automatically convert images to a different format) so if you have such a pull request in mind, please discuss it first in the forum.
# Coding style
There are only two rules, but not following them means the pull request will not be accepted (it can be accepted once the issues are fixed):
- **Please use tabs, NOT spaces.**
- **Please do not add or remove optional characters, such as spaces or colons.** Please setup your editor so that it only changes what you are working on and is not making automated changes elsewhere. The reason for this is that small white space changes make diff hard to read and can cause needless conflicts.
- **Please do not add or remove optional characters, such as spaces or colons.** Please setup your editor so that it only changes what you are working on and is not making automated changes elsewhere. The reason for this is that small white space changes make diff hard to read and can cause needless conflicts.

View File

@@ -69,7 +69,8 @@ class Command extends BaseCommand {
lines.push(' }');
lines.push('}');
lines.push('```');
lines.push('');
lines.push('# Authorisation')
lines.push('');
lines.push('To prevent unauthorised applications from accessing the API, the calls must be authentified. To do so, you must provide a token as a query parameter for each API call. You can get this token from the Joplin desktop application, on the Web Clipper Options screen.');
@@ -79,6 +80,7 @@ class Command extends BaseCommand {
lines.push('\tcurl http://localhost:41184/notes?token=ABCD123ABCD123ABCD123ABCD123ABCD123');
lines.push('');
lines.push('In the documentation below, the token will not be specified every time however you will need to include it.');
lines.push('');
lines.push('# Using the API');
lines.push('');
@@ -253,6 +255,12 @@ class Command extends BaseCommand {
lines.push('');
lines.push(' curl --data \'{ "title": "Image test", "body": "Here is Joplin icon:", "image_data_url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAANZJREFUeNoAyAA3/wFwtO3K6gUB/vz2+Prw9fj/+/r+/wBZKAAExOgF4/MC9ff+MRH6Ui4E+/0Bqc/zutj6AgT+/Pz7+vv7++nu82c4DlMqCvLs8goA/gL8/fz09fb59vXa6vzZ6vjT5fbn6voD/fwC8vX4UiT9Zi//APHyAP8ACgUBAPv5APz7BPj2+DIaC2o3E+3o6ywaC5fT6gD6/QD9/QEVf9kD+/dcLQgJA/7v8vqfwOf18wA1IAIEVycAyt//v9XvAPv7APz8LhoIAPz9Ri4OAgwARgx4W/6fVeEAAAAASUVORK5CYII="}\' http://127.0.0.1:41184/notes');
lines.push('');
lines.push('### Creating a note with a specific ID');
lines.push('');
lines.push('When a new note is created, it is automatically assigned a new unique ID so **normally you do not need to set the ID**. However, if for some reason you want to set it, you can supply it as the `id` property. It needs to be a 32 characters long hexadecimal string. **Make sure it is unique**, for example by generating it using whatever GUID function is available in your programming language.');
lines.push('');
lines.push(' curl --data \'{ "id": "00a87474082744c1a8515da6aa5792d2", "title": "My note with custom ID"}\' http://127.0.0.1:41184/notes');
lines.push('');
}
lines.push('## PUT /' + tableName + '/:id');

View File

@@ -26,7 +26,7 @@ class Command extends BaseCommand {
const md = Setting.settingMetadata(name);
let value = Setting.value(name);
if (typeof value === 'object' || Array.isArray(value)) value = JSON.stringify(value);
if (md.secure) value = '********';
if (md.secure && value) value = '********';
if (Setting.isEnum(name)) {
return _('%s = %s (%s)', name, value, Setting.enumOptionsDoc(name));

View File

@@ -196,6 +196,7 @@ class Command extends BaseCommand {
// not going to be running in the background, so the resources need to be
// explicitely downloaded below.
if (!app().hasGui()) {
this.stdout(_('Downloading resources...'));
await ResourceFetcher.instance().fetchAll();
await ResourceFetcher.instance().waitForAllFinished();
}

View File

@@ -460,6 +460,9 @@ msgstr "No es pot inicialitzar el sincronitzador."
msgid "Starting synchronisation..."
msgstr "Està començant la sincronització..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "S'està cancel·lant... Espereu."
@@ -984,6 +987,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Obre..."
@@ -1000,6 +1006,9 @@ msgstr "Copia el camí al porta-retalls"
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Missatge o enllaç no suportat: %s"
@@ -1037,9 +1046,6 @@ msgstr "Estableix una alarma"
msgid "In: %s"
msgstr "A: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1117,6 +1123,14 @@ msgstr "Sincronitza"
msgid "Notebooks"
msgstr "Blocs de notes"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Elements obtinguts: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Recursos: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Seleccioneu on s'hauria d'exportar l'estat de la sincronització"
@@ -1208,10 +1222,6 @@ msgstr "Elements remots suprimits: %d."
msgid "Fetched items: %d/%d."
msgstr "Elements obtinguts: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Estat: %s"
msgid "Cancelling..."
msgstr "S'està cancel·lant..."
@@ -1323,6 +1333,12 @@ msgstr "Mostra la icona a la safata"
msgid "Note: Does not work in all desktop environments."
msgstr "Nota: no funciona en tots els entorns d'escriptori."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1451,6 +1467,10 @@ msgstr "Directori d'exportació del Joplin"
msgid "Evernote Export File"
msgstr "Fitxer d'exportació de l'Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Directori d'exportació del Joplin"
msgid "Directory"
msgstr "Directori"
@@ -1525,6 +1545,12 @@ msgstr "Alarmes programades"
msgid "On %s: %s"
msgstr "A les %s.%s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Ara mateix no hi ha cap nota. Creeu-ne una fent clic en el botó (+)."
@@ -1569,10 +1595,6 @@ msgstr "Confirmació"
msgid "Cancel synchronisation"
msgstr "Cancel·la la sincronització"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Elements obtinguts: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "S'està cancel·lant... Espereu."
@@ -1714,6 +1736,9 @@ msgstr "Mostra les metadades"
msgid "View on map"
msgstr "Mostra-ho al mapa"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Suprimeix el bloc de notes"
@@ -1737,5 +1762,8 @@ msgstr ""
msgid "Welcome"
msgstr "Benvingut"
#~ msgid "State: %s."
#~ msgstr "Estat: %s"
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Ja existeix un bloc de notes amb aquest títol: «%s»"

View File

@@ -448,6 +448,9 @@ msgstr "Nelze zavézt synchronizátor."
msgid "Starting synchronisation..."
msgstr "Zahajuji synchronizaci..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Zastavuji, chvíli strpení."
@@ -955,6 +958,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Otevřít..."
@@ -971,6 +977,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Nepodporovaný link či zpráva: %s"
@@ -1006,9 +1015,6 @@ msgstr "Nastavit alarm"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1087,6 +1093,14 @@ msgstr "Synchronizovat"
msgid "Notebooks"
msgstr "Zápisníky"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Získané položky: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Zdroje: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Prosím vyberte, kam má být stav synchronizace exportován"
@@ -1178,10 +1192,6 @@ msgstr "Položky smazané na vzdáleném úložišti: %d."
msgid "Fetched items: %d/%d."
msgstr "Získané položky: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Stav: %s."
msgid "Cancelling..."
msgstr "Zastavuji..."
@@ -1298,6 +1308,12 @@ msgstr "Zobrazovat ikonu v panelu"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1426,6 +1442,10 @@ msgstr "Složka pro export"
msgid "Evernote Export File"
msgstr "Soubor Evernote Exportu"
#, fuzzy
msgid "Json Export Directory"
msgstr "Složka pro export"
msgid "Directory"
msgstr "Adresář"
@@ -1500,6 +1520,12 @@ msgstr "Nadcházející alarmy"
msgid "On %s: %s"
msgstr "Na %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Nemáte žádné poznámky. Vytvořte jednu kliknutím na tlačítko (+)."
@@ -1545,10 +1571,6 @@ msgstr "Potvrdit"
msgid "Cancel synchronisation"
msgstr "Zrušit synchronizaci"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Získané položky: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Zastavuji, chvíli strpení."
@@ -1683,6 +1705,9 @@ msgstr "Zobrazit metadata"
msgid "View on map"
msgstr "Zobrazit na map+"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Smazat zápisník"
@@ -1705,6 +1730,9 @@ msgstr "Nemáte žádný zápisník. Vytvořte jeden kliknutím na tlačítko (+
msgid "Welcome"
msgstr "Vítejte"
#~ msgid "State: %s."
#~ msgstr "Stav: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Zápisník s tímto názvem již existuje: \"%s\""

View File

@@ -452,6 +452,9 @@ msgstr "Kan ikke initialisere synkroniseringen."
msgid "Starting synchronisation..."
msgstr "Starter synkronisering."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Annullerer... Vent venligst."
@@ -964,6 +967,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Åben..."
@@ -980,6 +986,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Ugyldigt- eller ulovligt link eller besked: %s"
@@ -1015,9 +1024,6 @@ msgstr "Indstil alarm"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1096,6 +1102,14 @@ msgstr "Synkroniser"
msgid "Notebooks"
msgstr "Notesbøger"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Hentede emner: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Ressourcer: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Vælg hvor sync status skal eksporteres til"
@@ -1187,10 +1201,6 @@ msgstr "Slettede fjern-emner: %d."
msgid "Fetched items: %d/%d."
msgstr "Hentede emner: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Tilstand: %s."
msgid "Cancelling..."
msgstr "Annullerer..."
@@ -1307,6 +1317,12 @@ msgstr "Vis ikon på bundbjælke"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1435,6 +1451,10 @@ msgstr "Joplin eksport mappe"
msgid "Evernote Export File"
msgstr "Evernote eksport fil"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin eksport mappe"
msgid "Directory"
msgstr "Indeks"
@@ -1509,6 +1529,12 @@ msgstr "Kommende alarmer"
msgid "On %s: %s"
msgstr "På %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Der er ingen noter. Opret note ved at klikke på (+) knappen."
@@ -1554,10 +1580,6 @@ msgstr "Bekræft"
msgid "Cancel synchronisation"
msgstr "Afbryd synkronisering"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Hentede emner: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Annullerer... Vent venligst."
@@ -1692,6 +1714,9 @@ msgstr "Vis metadata"
msgid "View on map"
msgstr "Vis på kort"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Slet notesbog"
@@ -1714,6 +1739,9 @@ msgstr "Du har ingen notesbøger. Opret en ved at klikke på (+) knappen."
msgid "Welcome"
msgstr "Velkommen"
#~ msgid "State: %s."
#~ msgstr "Tilstand: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "En notesbog bruger allerede dette navn: \"%s\""

View File

@@ -15,8 +15,6 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
msgid "To delete a tag, untag the associated notes."
msgstr ""
@@ -473,6 +471,9 @@ msgstr "Kann Synchronisierer nicht initialisieren."
msgid "Starting synchronisation..."
msgstr "Starte Synchronisation..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Abbrechen… Bitte warten."
@@ -990,12 +991,16 @@ msgstr ""
"Momentan existieren noch keine Notizbücher. Erstelle eines, indem du auf "
"\"Neues Notizbuch\" drückst."
# Please note: The term 'Location' is assumed to be the geographical location where the note has been created. For this the german word 'Standort' fits better than the previously used 'Ablageort'. The latter one is used for the folder where files are stored.
msgid "Location"
msgstr "Ablageort"
msgstr "Standort"
msgid "URL"
msgstr "URL"
msgid "Note properties"
msgstr "Notiz-Eigenschaften"
msgid "Open..."
msgstr "Öffne..."
@@ -1012,6 +1017,9 @@ msgstr "Pfad in Zwischenablage kopieren"
msgid "Copy Link Address"
msgstr "Link-Adresse kopieren"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Nicht unterstützter Link oder Nachricht: %s"
@@ -1049,9 +1057,6 @@ msgstr "Alarm erstellen"
msgid "In: %s"
msgstr "In: %s"
msgid "Note properties"
msgstr "Notiz-Eigenschaften"
msgid "Hyperlink"
msgstr "Weblink"
@@ -1128,6 +1133,14 @@ msgstr "Synchronisieren"
msgid "Notebooks"
msgstr "Notizbücher"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Entschlüsselte Objekte: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Anhänge: %d."
msgid "Please select where the sync status should be exported to"
msgstr ""
"Bitte wähle aus, wohin der Synchronisations-Status exportiert werden soll"
@@ -1220,10 +1233,6 @@ msgstr "Remote-Objekte gelöscht: %d."
msgid "Fetched items: %d/%d."
msgstr "Geladene Objekte: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Status: %s."
msgid "Cancelling..."
msgstr "Breche ab…"
@@ -1336,6 +1345,12 @@ msgstr "Zeige Tray-Icon"
msgid "Note: Does not work in all desktop environments."
msgstr "Hinweis: Funktioniert nicht in allen Desktopumgebungen."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr "Starte die Anwendung minimiert im Tray"
@@ -1472,6 +1487,10 @@ msgstr "Joplin Export Verzeichnis"
msgid "Evernote Export File"
msgstr "Evernote Export Datei"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin Export Verzeichnis"
msgid "Directory"
msgstr "Verzeichnis"
@@ -1547,6 +1566,12 @@ msgstr "Anstehende Alarme"
msgid "On %s: %s"
msgstr "Auf %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
"Momentan existieren noch keine Notizen. Erstelle eine, indem du auf den (+) "
@@ -1592,10 +1617,6 @@ msgstr "Bestätigen"
msgid "Cancel synchronisation"
msgstr "Synchronisation abbrechen"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Entschlüsselte Objekte: %d/%d"
msgid "Checking... Please wait."
msgstr "Überprüfe… Bitte warten."
@@ -1741,6 +1762,9 @@ msgstr "Metadaten anzeigen"
msgid "View on map"
msgstr "Auf der Karte anzeigen"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Notizbuch löschen"
@@ -1766,6 +1790,9 @@ msgstr ""
msgid "Welcome"
msgstr "Willkommen"
#~ msgid "State: %s."
#~ msgstr "Status: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Ein Notizbuch mit diesem Titel existiert bereits : \"%s\""

View File

@@ -408,6 +408,9 @@ msgstr ""
msgid "Starting synchronisation..."
msgstr ""
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr ""
@@ -874,6 +877,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr ""
@@ -890,6 +896,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr ""
@@ -925,9 +934,6 @@ msgstr ""
msgid "In: %s"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1004,6 +1010,14 @@ msgstr ""
msgid "Notebooks"
msgstr ""
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr ""
#, javascript-format
msgid "Fetching resources: %d"
msgstr ""
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -1087,10 +1101,6 @@ msgstr ""
msgid "Fetched items: %d/%d."
msgstr ""
#, javascript-format
msgid "State: %s."
msgstr ""
msgid "Cancelling..."
msgstr ""
@@ -1202,6 +1212,12 @@ msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1319,6 +1335,9 @@ msgstr ""
msgid "Evernote Export File"
msgstr ""
msgid "Json Export Directory"
msgstr ""
msgid "Directory"
msgstr ""
@@ -1388,6 +1407,12 @@ msgstr ""
msgid "On %s: %s"
msgstr ""
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
@@ -1431,10 +1456,6 @@ msgstr ""
msgid "Cancel synchronisation"
msgstr ""
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr ""
msgid "Checking... Please wait."
msgstr ""
@@ -1565,6 +1586,9 @@ msgstr ""
msgid "View on map"
msgstr ""
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr ""

View File

@@ -457,6 +457,9 @@ msgstr "No se puede inicializar sincronizador."
msgid "Starting synchronisation..."
msgstr "Iniciando sincronización..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Cancelando... Por favor espere."
@@ -977,6 +980,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Abrir..."
@@ -993,6 +999,9 @@ msgstr "Copiar la ruta en el portapapeles"
msgid "Copy Link Address"
msgstr "Copiar enlace"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Enlace o mensaje no soportado: %s"
@@ -1030,9 +1039,6 @@ msgstr "Establecer alarma"
msgid "In: %s"
msgstr "En: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Hipervínculo"
@@ -1109,6 +1115,14 @@ msgstr "Sincronizar"
msgid "Notebooks"
msgstr "Libretas"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Descifrando elementos: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Recursos: %d."
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"
@@ -1200,10 +1214,6 @@ msgstr "Elementos remotos borrados: %d."
msgid "Fetched items: %d/%d."
msgstr "Elementos obtenidos: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Estado: «%s»."
msgid "Cancelling..."
msgstr "Cancelando..."
@@ -1316,6 +1326,12 @@ msgstr "Mostrar icono en la bandeja"
msgid "Note: Does not work in all desktop environments."
msgstr "Nota: No funciona en todos los entornos de escritorio."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1449,6 +1465,10 @@ msgstr "Directorio para exportar de Joplin"
msgid "Evernote Export File"
msgstr "Archivo exportado de Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Directorio para exportar de Joplin"
msgid "Directory"
msgstr "Directorio"
@@ -1523,6 +1543,12 @@ msgstr "Alarmas próximas"
msgid "On %s: %s"
msgstr "En %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "No hay notas. Cree una pulsando en el botón (+)."
@@ -1567,10 +1593,6 @@ msgstr "Confirmar"
msgid "Cancel synchronisation"
msgstr "Cancelar sincronización"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Descifrando elementos: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Cancelando... Por favor espere."
@@ -1712,6 +1734,9 @@ msgstr "Mostrar metadatos"
msgid "View on map"
msgstr "Ver en un mapa"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Borrar libreta"
@@ -1735,6 +1760,9 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenido"
#~ msgid "State: %s."
#~ msgstr "Estado: «%s»."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Ya existe una libreta con este nombre: «%s»"

View File

@@ -455,6 +455,9 @@ msgstr "Ezin has daiteke sinkronizazio prozesua."
msgid "Starting synchronisation..."
msgstr "Sinkronizazioa hasten..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Bertan behera uzten... itxaron, mesedez."
@@ -973,6 +976,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr ""
@@ -990,6 +996,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Esteka edo mezu ez dago onartua: %s"
@@ -1025,9 +1034,6 @@ msgstr "Ezarri alarma"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1109,6 +1115,14 @@ msgstr "Sinkronizatu"
msgid "Notebooks"
msgstr "Koadernoak"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Itemak eskuratuta: %d%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Baliabideak: %d."
#, fuzzy
msgid "Please select where the sync status should be exported to"
msgstr "Aukeratu nora esportatu sinkronizazioaren egoera, mesedez"
@@ -1202,10 +1216,6 @@ msgstr "Urruneko itemak ezabatuta: %d."
msgid "Fetched items: %d/%d."
msgstr "Itemak eskuratuta: %d%d."
#, fuzzy, javascript-format
msgid "State: %s."
msgstr "Egoera: \"%s\"."
msgid "Cancelling..."
msgstr "Bertan behera uzten..."
@@ -1327,6 +1337,12 @@ msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1458,6 +1474,10 @@ msgstr ""
msgid "Evernote Export File"
msgstr "Evernotetik esportatutako fitxategiak"
#, fuzzy
msgid "Json Export Directory"
msgstr "Evernotetik esportatutako fitxategiak"
msgid "Directory"
msgstr ""
@@ -1530,6 +1550,12 @@ msgstr "Hurrengo alarmak"
msgid "On %s: %s"
msgstr "On %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Ez dago oharrik. Sortu bat (+) botoian klik eginaz."
@@ -1575,10 +1601,6 @@ msgstr "Baieztatu"
msgid "Cancel synchronisation"
msgstr "Sinkronizazioa utzi"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Itemak eskuratuta: %d%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Bertan behera uzten... itxaron, mesedez."
@@ -1713,6 +1735,9 @@ msgstr "Erakutsi metadatuak"
msgid "View on map"
msgstr "Ikusi mapan"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Ezabatu koadernoa"
@@ -1735,6 +1760,10 @@ msgstr "Oraindik ez duzu koadernorik. Sortu bat (+) botoian sakatuta."
msgid "Welcome"
msgstr "Ongi etorri!"
#, fuzzy
#~ msgid "State: %s."
#~ msgstr "Egoera: \"%s\"."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Dagoeneko bada koaderno bat izen horrekin: \"%s\""

View File

@@ -458,6 +458,9 @@ msgstr "Impossible d'initialiser la synchronisation."
msgid "Starting synchronisation..."
msgstr "Commencement de la synchronisation..."
msgid "Downloading resources..."
msgstr "Téléchargement des ressources..."
msgid "Cancelling... Please wait."
msgstr "Annulation... Veuillez attendre."
@@ -981,6 +984,9 @@ msgstr "Lieu"
msgid "URL"
msgstr "URL"
msgid "Note properties"
msgstr "Propriétés de la note"
msgid "Open..."
msgstr "Ouvrir..."
@@ -997,6 +1003,9 @@ msgstr "Copier le chemin"
msgid "Copy Link Address"
msgstr "Copier l'adresse du lien"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr "Cette pièce jointe n'est pas téléchargée ou pas encore déchiffrée"
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Lien ou message non géré : %s"
@@ -1034,9 +1043,6 @@ msgstr "Régler alarme"
msgid "In: %s"
msgstr "Dans : %s"
msgid "Note properties"
msgstr "Propriétés de la note"
msgid "Hyperlink"
msgstr "Lien"
@@ -1113,6 +1119,14 @@ msgstr "Synchroniser"
msgid "Notebooks"
msgstr "Carnets"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Déchiffrement des objets : %d/%d"
#, javascript-format
msgid "Fetching resources: %d"
msgstr "Tél. ressources : %d"
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"
@@ -1205,10 +1219,6 @@ msgstr "Objets distants supprimés : %d."
msgid "Fetched items: %d/%d."
msgstr "Téléchargés : %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "État : %s."
msgid "Cancelling..."
msgstr "Annulation..."
@@ -1320,6 +1330,15 @@ msgstr "Afficher l'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 ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
"Cela permettra à Joplin de s'exécuter en arrière-plan. Il est recommandé "
"d'activer ce réglage pour que vos notes soient constamment synchronisées, "
"donc réduire le nombre de conflits."
msgid "Start application minimised in the tray icon"
msgstr "Démarrer minimisé dans la zone de notification"
@@ -1455,6 +1474,9 @@ msgstr "Dossier d'export Joplin"
msgid "Evernote Export File"
msgstr "Fichiers d'export Evernote"
msgid "Json Export Directory"
msgstr "Dossier d'export JSON"
msgid "Directory"
msgstr "Dossier"
@@ -1529,6 +1551,12 @@ msgstr "Alarmes à venir"
msgid "On %s: %s"
msgstr "Le %s : %s"
msgid "Permission to use camera"
msgstr "Permission d'utiliser l'appareil photo"
msgid "Your permission to use your camera is required."
msgstr "Votre permission est requise pour utiliser l'appareil photo"
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
"Ce carnet ne contient aucune note. Créez-en une en appuyant sur le bouton "
@@ -1574,10 +1602,6 @@ msgstr "Confirmer"
msgid "Cancel synchronisation"
msgstr "Annuler synchronisation"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Déchiffrement des objets : %d/%d"
msgid "Checking... Please wait."
msgstr "Vérification... Veuillez attendre."
@@ -1722,6 +1746,9 @@ msgstr "Voir métadonnées"
msgid "View on map"
msgstr "Voir sur carte"
msgid "Go to source URL"
msgstr "Aller à l'URL source"
msgid "Delete notebook"
msgstr "Supprimer le carnet"
@@ -1746,6 +1773,9 @@ msgstr ""
msgid "Welcome"
msgstr "Bienvenue"
#~ msgid "State: %s."
#~ msgstr "État : %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Un carnet avec ce titre existe déjà : \"%s\""

View File

@@ -452,6 +452,9 @@ msgstr "Non é posíbel iniciar o sincronizador."
msgid "Starting synchronisation..."
msgstr "Iniciando sincronización..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Cancelando... Agarde."
@@ -961,6 +964,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Abrir…"
@@ -977,6 +983,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Ligazón ou mensaxe incompatíbeis: %s"
@@ -1014,9 +1023,6 @@ msgstr "Estabelecer alarma"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1095,6 +1101,14 @@ msgstr "Sincronizar"
msgid "Notebooks"
msgstr "Cadernos"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Elementos obtidos: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Recursos: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Seleccione onde exportar o estado da sincronización"
@@ -1186,10 +1200,6 @@ msgstr "Elementos remotos borrados: %d."
msgid "Fetched items: %d/%d."
msgstr "Elementos obtidos: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Estado: %s."
msgid "Cancelling..."
msgstr "Cancelando..."
@@ -1306,6 +1316,12 @@ msgstr "Mostrar a icona na bandexa"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1434,6 +1450,10 @@ msgstr "Cartafol de exportación do Joplin"
msgid "Evernote Export File"
msgstr "Ficheiro de exportación de Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Cartafol de exportación do Joplin"
msgid "Directory"
msgstr "Cartafol"
@@ -1508,6 +1528,12 @@ msgstr "Alarmas próximas"
msgid "On %s: %s"
msgstr "En %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Non ten notas actualmente. Cree unha premendo no botón (+)."
@@ -1553,10 +1579,6 @@ msgstr "Confirmar"
msgid "Cancel synchronisation"
msgstr "Cancelar sincronización"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Elementos obtidos: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Cancelando... Agarde."
@@ -1691,6 +1713,9 @@ msgstr "Mostrar metadatos"
msgid "View on map"
msgstr "Ver no mapa"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Eliminar caderno"
@@ -1713,5 +1738,8 @@ msgstr "Non ten cadernos actualmente. Cree un premendo no botón (+)."
msgid "Welcome"
msgstr "Benvido/a"
#~ msgid "State: %s."
#~ msgstr "Estado: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Xa existe un caderno con ese título: «%s»"

View File

@@ -455,6 +455,9 @@ msgstr "Ne mogu započeti sinkronizaciju."
msgid "Starting synchronisation..."
msgstr "Započinjem sinkronizaciju..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Prekidam... Pričekaj."
@@ -960,6 +963,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr ""
@@ -977,6 +983,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Nepodržana poveznica ili poruka: %s"
@@ -1012,9 +1021,6 @@ msgstr "Postavi upozorenje"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1095,6 +1101,14 @@ msgstr "Sinkroniziraj"
msgid "Notebooks"
msgstr "Bilježnice"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Stvorene lokalne stavke: %d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Resursi: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Odaberi lokaciju za izvoz statusa sinkronizacije"
@@ -1184,10 +1198,6 @@ msgstr "Obrisane udaljene stavke: %d."
msgid "Fetched items: %d/%d."
msgstr "Stvorene lokalne stavke: %d."
#, fuzzy, javascript-format
msgid "State: %s."
msgstr "Stanje: \"%s\"."
msgid "Cancelling..."
msgstr "Prekidam..."
@@ -1310,6 +1320,12 @@ msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1435,6 +1451,10 @@ msgstr ""
msgid "Evernote Export File"
msgstr "Evernote izvozne datoteke"
#, fuzzy
msgid "Json Export Directory"
msgstr "Evernote izvozne datoteke"
msgid "Directory"
msgstr ""
@@ -1505,6 +1525,12 @@ msgstr "Nadolazeća upozorenja"
msgid "On %s: %s"
msgstr "On %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Trenutno nema bilješki. Stvori novu klikom na (+) gumb."
@@ -1550,10 +1576,6 @@ msgstr "Potvrdi"
msgid "Cancel synchronisation"
msgstr "Prekini sinkronizaciju"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Stvorene lokalne stavke: %d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Prekidam... Pričekaj."
@@ -1689,6 +1711,9 @@ msgstr "Prikaži metapodatke"
msgid "View on map"
msgstr "Vidi na karti"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Obriši bilježnicu"
@@ -1711,6 +1736,10 @@ msgstr "Trenutno nemaš nijednu bilježnicu. Stvori novu klikom na (+) gumb."
msgid "Welcome"
msgstr "Dobro došli"
#, fuzzy
#~ msgid "State: %s."
#~ msgstr "Stanje: \"%s\"."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Bilježnica s ovim naslovom već postoji: \"%s\""

View File

@@ -461,6 +461,9 @@ msgstr "Non è possibile inizializzare il sincronizzatore."
msgid "Starting synchronisation..."
msgstr "Inizio sincronizzazione..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Cancellazione... Attendere per favore."
@@ -977,6 +980,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Apri ..."
@@ -993,6 +999,9 @@ msgstr "Copia il percorso negli appunti"
msgid "Copy Link Address"
msgstr "Copia l'indirizzo del link"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Link o Messaggio non supportato: %s"
@@ -1030,9 +1039,6 @@ msgstr "Imposta Allarme"
msgid "In: %s"
msgstr "In: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Collegamento ipertestuale"
@@ -1110,6 +1116,14 @@ msgstr "Sincronizza"
msgid "Notebooks"
msgstr "Taccuini"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Decrittografia Elementi: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Risorse: %d."
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -1201,10 +1215,6 @@ msgstr "Elementi remoti eliminati: %d."
msgid "Fetched items: %d/%d."
msgstr "Elementi recuperati: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Stato: %s."
msgid "Cancelling..."
msgstr "Cancellazione..."
@@ -1316,6 +1326,12 @@ msgstr "Visualizza tray icon"
msgid "Note: Does not work in all desktop environments."
msgstr "Nota: non funziona in tutti gli ambienti desktop."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1448,6 +1464,10 @@ msgstr "Cartella di esportazione di Joplin"
msgid "Evernote Export File"
msgstr "Esporta files di Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Cartella di esportazione di Joplin"
msgid "Directory"
msgstr "Cartella"
@@ -1522,6 +1542,12 @@ msgstr "Avviso imminente"
msgid "On %s: %s"
msgstr "Su %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Al momento non ci sono note. Creane una cliccando sul bottone (+)."
@@ -1566,10 +1592,6 @@ msgstr "Conferma"
msgid "Cancel synchronisation"
msgstr "Cancella la sincronizzazione"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Decrittografia Elementi: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "Cancellazione... Attendere per favore."
@@ -1712,6 +1734,9 @@ msgstr "Mostra i metadati"
msgid "View on map"
msgstr "Guarda sulla mappa"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Cancella Taccuino"
@@ -1735,6 +1760,9 @@ msgstr ""
msgid "Welcome"
msgstr "Benvenuto"
#~ msgid "State: %s."
#~ msgstr "Stato: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Esiste già un Taccuino col titolo \"%s\""

View File

@@ -445,6 +445,9 @@ msgstr "同期プロセスを初期化できませんでした。"
msgid "Starting synchronisation..."
msgstr "同期を開始中..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "中止中...お待ちください。"
@@ -961,6 +964,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "開く..."
@@ -977,6 +983,9 @@ msgstr "クリップボードにパスを保存"
msgid "Copy Link Address"
msgstr "リンクアドレスをコピー"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "次のリンクまたはメッセージはサポートしていません: %s"
@@ -1014,9 +1023,6 @@ msgstr "アラームをセット"
msgid "In: %s"
msgstr "内: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "ハイパーリンク"
@@ -1093,6 +1099,14 @@ msgstr "同期"
msgid "Notebooks"
msgstr "ノートブック"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "復号中のアイテム: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "リソース: %d."
msgid "Please select where the sync status should be exported to"
msgstr "同期状況の出力先を選択してください"
@@ -1184,10 +1198,6 @@ msgstr "リモートアイテムの削除: %d."
msgid "Fetched items: %d/%d."
msgstr "取得したアイテム: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "状態: \"%s\"."
msgid "Cancelling..."
msgstr "中止中..."
@@ -1301,6 +1311,12 @@ msgstr "トレイアイコンの表示"
msgid "Note: Does not work in all desktop environments."
msgstr "注意: すべてのデスクトップ環境で動作するわけではありません。"
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr "アプリケーションをトレイアンコンで最小化して起動"
@@ -1433,6 +1449,10 @@ msgstr "Joplin エクスポートディレクトリ"
msgid "Evernote Export File"
msgstr "Evernote エクスポートファイル"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin エクスポートディレクトリ"
msgid "Directory"
msgstr "ディレクトリ"
@@ -1507,6 +1527,12 @@ msgstr "直近のアラーム"
msgid "On %s: %s"
msgstr "日時 %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "ノートがありません。(+)ボタンを押して新しいノートを作成してください。"
@@ -1551,10 +1577,6 @@ msgstr "確認"
msgid "Cancel synchronisation"
msgstr "同期の中止"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "復号中のアイテム: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "中止中...お待ちください。"
@@ -1692,6 +1714,9 @@ msgstr "メタデータを表示"
msgid "View on map"
msgstr "地図上に表示"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "ノートブックを削除"
@@ -1716,6 +1741,9 @@ msgstr ""
msgid "Welcome"
msgstr "ようこそ"
#~ msgid "State: %s."
#~ msgstr "状態: \"%s\"."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "次の名前のノートブックはすでに存在しています: \"%s\""

View File

@@ -408,6 +408,9 @@ msgstr ""
msgid "Starting synchronisation..."
msgstr ""
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr ""
@@ -874,6 +877,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr ""
@@ -890,6 +896,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr ""
@@ -925,9 +934,6 @@ msgstr ""
msgid "In: %s"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1004,6 +1010,14 @@ msgstr ""
msgid "Notebooks"
msgstr ""
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr ""
#, javascript-format
msgid "Fetching resources: %d"
msgstr ""
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -1087,10 +1101,6 @@ msgstr ""
msgid "Fetched items: %d/%d."
msgstr ""
#, javascript-format
msgid "State: %s."
msgstr ""
msgid "Cancelling..."
msgstr ""
@@ -1202,6 +1212,12 @@ msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1319,6 +1335,9 @@ msgstr ""
msgid "Evernote Export File"
msgstr ""
msgid "Json Export Directory"
msgstr ""
msgid "Directory"
msgstr ""
@@ -1388,6 +1407,12 @@ msgstr ""
msgid "On %s: %s"
msgstr ""
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
@@ -1431,10 +1456,6 @@ msgstr ""
msgid "Cancel synchronisation"
msgstr ""
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr ""
msgid "Checking... Please wait."
msgstr ""
@@ -1565,6 +1586,9 @@ msgstr ""
msgid "View on map"
msgstr ""
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr ""

View File

@@ -446,6 +446,9 @@ msgstr "동기화를 시작할 수 없습니다."
msgid "Starting synchronisation..."
msgstr "동기화를 시작합니다..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "취소하는 중입니다... 잠시만 기다리세요."
@@ -955,6 +958,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "열기..."
@@ -971,6 +977,9 @@ msgstr "경로를 클립보드에 복사"
msgid "Copy Link Address"
msgstr "링크 주소 복사"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "지원하지 않는 링크 또는 메세지: %s"
@@ -1008,9 +1017,6 @@ msgstr "알람 설정"
msgid "In: %s"
msgstr "내부: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "하이퍼링크"
@@ -1087,6 +1093,14 @@ msgstr "동기화"
msgid "Notebooks"
msgstr "노트북"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "복호화 항목: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "리소스: %d."
msgid "Please select where the sync status should be exported to"
msgstr "동기화 상태를 내보낼 대상을 선택하세요"
@@ -1178,10 +1192,6 @@ msgstr "원격 항목 삭제됨: %d."
msgid "Fetched items: %d/%d."
msgstr "가져온 항목: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "상태: %s."
msgid "Cancelling..."
msgstr "취소하는 중..."
@@ -1293,6 +1303,12 @@ msgstr "트레이 아이콘 표시"
msgid "Note: Does not work in all desktop environments."
msgstr "참고사항: 모든 데스크탑 환경에서 작동하는 것은 아닙니다."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1423,6 +1439,10 @@ msgstr "조플린 내보내기 폴더"
msgid "Evernote Export File"
msgstr "에버노트 내보내기 파일"
#, fuzzy
msgid "Json Export Directory"
msgstr "조플린 내보내기 폴더"
msgid "Directory"
msgstr "폴더"
@@ -1497,6 +1517,12 @@ msgstr "다가오는 예정된 알람"
msgid "On %s: %s"
msgstr "%s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "노트가 없습니다. (+) 버튼을 선택해 새로 만드세요."
@@ -1541,10 +1567,6 @@ msgstr "확인"
msgid "Cancel synchronisation"
msgstr "동기화 취소"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "복호화 항목: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "취소하는 중입니다... 잠시만 기다리세요."
@@ -1682,6 +1704,9 @@ msgstr "메타데이터 표시"
msgid "View on map"
msgstr "지도에 표시"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "노트북 삭제"
@@ -1704,5 +1729,8 @@ msgstr "노트북이 없습니다. (+) 버튼을 눌러 새로 만드세요."
msgid "Welcome"
msgstr "환영합니다"
#~ msgid "State: %s."
#~ msgstr "상태: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "같은 제목의 노트북이 이미 있습니다: \"%s\""

View File

@@ -456,6 +456,9 @@ msgstr "Kan de synchronisatie niet starten."
msgid "Starting synchronisation..."
msgstr "Synchronisatie starten..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Annuleren.. Even geduld."
@@ -977,6 +980,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr ""
@@ -994,6 +1000,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Link of bericht \"%s\" wordt niet ondersteund"
@@ -1029,9 +1038,6 @@ msgstr "Zet melding"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1112,6 +1118,14 @@ msgstr "Synchroniseer"
msgid "Notebooks"
msgstr "Notitieboeken"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Opgehaalde items: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Middelen: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Selecteer waar de synchronisatie status naar geëxporteerd moet worden"
@@ -1204,10 +1218,6 @@ msgstr "Verwijderde remote items: %d."
msgid "Fetched items: %d/%d."
msgstr "Opgehaalde items: %d/%d."
#, fuzzy, javascript-format
msgid "State: %s."
msgstr "Status: \"%s\""
msgid "Cancelling..."
msgstr "Annuleren..."
@@ -1330,6 +1340,12 @@ msgstr ""
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1458,6 +1474,10 @@ msgstr ""
msgid "Evernote Export File"
msgstr "Exporteer Evernote bestanden"
#, fuzzy
msgid "Json Export Directory"
msgstr "Exporteer Evernote bestanden"
msgid "Directory"
msgstr ""
@@ -1531,6 +1551,12 @@ msgstr "Meldingen"
msgid "On %s: %s"
msgstr "Op %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
"Er zijn momenteel geen notities. Maak een notitie door op (+) te klikken."
@@ -1577,10 +1603,6 @@ msgstr "Bevestig"
msgid "Cancel synchronisation"
msgstr "Annuleer synchronisatie"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Opgehaalde items: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Annuleren.. Even geduld."
@@ -1715,6 +1737,9 @@ msgstr "Toon metadata"
msgid "View on map"
msgstr "Toon op de kaart"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Verwijder notitieboek"
@@ -1739,6 +1764,10 @@ msgstr ""
msgid "Welcome"
msgstr "Welkom"
#, fuzzy
#~ msgid "State: %s."
#~ msgstr "Status: \"%s\""
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Er bestaat al een notitieboek met \"%s\" als titel"

View File

@@ -457,6 +457,9 @@ msgstr "De synchronisatie kan niet worden geïnitaliseerd."
msgid "Starting synchronisation..."
msgstr "Bezig met starten van synchronisatie..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Bezig met annuleren... Even geduld."
@@ -983,6 +986,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Openen..."
@@ -999,6 +1005,9 @@ msgstr "Pad kopiëren naar klembord"
msgid "Copy Link Address"
msgstr "Linkadres kopiëren"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Niet-ondersteunde link of bericht: %s"
@@ -1036,9 +1045,6 @@ msgstr "Alarm instellen"
msgid "In: %s"
msgstr "In: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Hyperlink"
@@ -1115,6 +1121,14 @@ msgstr "Synchroniseren"
msgid "Notebooks"
msgstr "Notitieboeken"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Bezig met ontsleutelen van items: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Bronnen: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Kies waar de synchronisatiestatus naar moet worden geëxporteerd"
@@ -1206,10 +1220,6 @@ msgstr "Externe items verwijderd: %d."
msgid "Fetched items: %d/%d."
msgstr "Items opgehaald: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Status: %s."
msgid "Cancelling..."
msgstr "Bezig met annuleren..."
@@ -1321,6 +1331,12 @@ msgstr "Systeemvakpictogram tonen"
msgid "Note: Does not work in all desktop environments."
msgstr "Let op: dit werkt niet in alle werkomgevingen."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1454,6 +1470,10 @@ msgstr "Joplin-exportmap"
msgid "Evernote Export File"
msgstr "Evernote-exportbestand"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin-exportmap"
msgid "Directory"
msgstr "Map"
@@ -1530,6 +1550,12 @@ msgstr "Aankomende alarmen"
msgid "On %s: %s"
msgstr "Op %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
"Er zijn momenteel geen notities. Creëer een notitie door te drukken op de "
@@ -1576,10 +1602,6 @@ msgstr "Bevestigen"
msgid "Cancel synchronisation"
msgstr "Synchronisatie annuleren"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Bezig met ontsleutelen van items: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "Bezig met annuleren... Even geduld."
@@ -1718,6 +1740,9 @@ msgstr "Metagegevens tonen"
msgid "View on map"
msgstr "Tonen op kaart"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Notitieboek verwijderen"
@@ -1742,5 +1767,8 @@ msgstr ""
msgid "Welcome"
msgstr "Welkom"
#~ msgid "State: %s."
#~ msgstr "Status: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Er bestaat al een notitieboek met deze titel: \"%s\""

View File

@@ -453,6 +453,9 @@ msgstr "Kan ikke starte synkronisering."
msgid "Starting synchronisation..."
msgstr "Starter synkronisering..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Stopper… Vennligst vent."
@@ -968,6 +971,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Åpne..."
@@ -984,6 +990,9 @@ msgstr "Kopier sti til utklippshanteren"
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Kobling eller melding som ikke støttes: %s"
@@ -1021,9 +1030,6 @@ msgstr "Angi Alarm"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1102,6 +1108,14 @@ msgstr "Synkroniser"
msgid "Notebooks"
msgstr "Notisbøker"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Hentede elementer: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Ressurser: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Velg hvor synkroniseringsstatusen skal eksporteres til"
@@ -1193,10 +1207,6 @@ msgstr "Slett eksterne elementer: %d."
msgid "Fetched items: %d/%d."
msgstr "Hentede elementer: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Status: %s."
msgid "Cancelling..."
msgstr "Stopper… Vennligst vent."
@@ -1311,6 +1321,12 @@ msgstr "Vis ikon i systemkurven"
msgid "Note: Does not work in all desktop environments."
msgstr "Merk: fungerer ikke i alle skrivebordsmiljøer."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1440,6 +1456,10 @@ msgstr "Joplin Export Katalog"
msgid "Evernote Export File"
msgstr "Evernote Export Fil"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin Export Katalog"
msgid "Directory"
msgstr "Katalog"
@@ -1514,6 +1534,12 @@ msgstr "Kommende alarmer"
msgid "On %s: %s"
msgstr "Pa %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Du har ennå ingen notater. Lag en ved å klikke på (+) knappen."
@@ -1559,10 +1585,6 @@ msgstr "Bekreft"
msgid "Cancel synchronisation"
msgstr "Stopp Synkronisering"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Hentede elementer: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Stopper… Vennligst vent."
@@ -1700,6 +1722,9 @@ msgstr "Vis Metadata"
msgid "View on map"
msgstr "Se på kart"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Slett notisbok"
@@ -1722,5 +1747,8 @@ msgstr "Du har ennå ingen notisbok. Lag en ved å klikke på (+) knappen."
msgid "Welcome"
msgstr "Velkommen"
#~ msgid "State: %s."
#~ msgstr "Status: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "En notisblokk med denne tittelen eksisterer allerede: \"%s\""

View File

@@ -454,6 +454,9 @@ msgstr "Não é possível inicializar o sincronizador."
msgid "Starting synchronisation..."
msgstr "Iniciando sincronização..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Cancelando... Aguarde."
@@ -973,6 +976,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Abrir..."
@@ -989,6 +995,9 @@ msgstr "Copiar caminho para a área de transferência"
msgid "Copy Link Address"
msgstr "Copiar endereço do link"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Link ou mensagem não suportada: %s"
@@ -1026,9 +1035,6 @@ msgstr "Definir alarme"
msgid "In: %s"
msgstr "Em: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Hiperlink"
@@ -1105,6 +1111,14 @@ msgstr "Sincronizar"
msgid "Notebooks"
msgstr "Cadernos"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Decriptando itens: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Recursos: %d."
msgid "Please select where the sync status should be exported to"
msgstr ""
"Favor selecionar o local para onde o status de sincronia deveria ser "
@@ -1198,10 +1212,6 @@ msgstr "Itens remotos excluídos: %d."
msgid "Fetched items: %d/%d."
msgstr "Itens pesquisados: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Estado: \"%s\"."
msgid "Cancelling..."
msgstr "Cancelando..."
@@ -1314,6 +1324,12 @@ msgstr "Exibir tray icon"
msgid "Note: Does not work in all desktop environments."
msgstr "Nota: não funciona em todos os ambientes de desktop"
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1445,6 +1461,10 @@ msgstr "Diretório de Exportação do Joplin"
msgid "Evernote Export File"
msgstr "Arquivo de Exportação do Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Diretório de Exportação do Joplin"
msgid "Directory"
msgstr "DIretório"
@@ -1520,6 +1540,12 @@ msgstr "Próximos alarmes"
msgid "On %s: %s"
msgstr "Em %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Atualmente, não há notas. Crie uma, clicando no botão (+)."
@@ -1564,10 +1590,6 @@ msgstr "Confirmar"
msgid "Cancel synchronisation"
msgstr "Cancelar sincronização"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Decriptando itens: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Cancelando... Aguarde."
@@ -1708,6 +1730,9 @@ msgstr "Exibir metadados"
msgid "View on map"
msgstr "Ver no mapa"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Excluir caderno"
@@ -1730,6 +1755,9 @@ msgstr "Você não possui cadernos. Crie um clicando no botão (+)."
msgid "Welcome"
msgstr "Bem-vindo"
#~ msgid "State: %s."
#~ msgstr "Estado: \"%s\"."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Já existe caderno com este título: \"%s\""

View File

@@ -414,6 +414,9 @@ msgstr "Nu se poate inițializa sincronizatorul."
msgid "Starting synchronisation..."
msgstr "Se începe sincronizarea..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Se anulează... Vă rugăm să așteptați."
@@ -891,6 +894,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Deschideți..."
@@ -907,6 +913,9 @@ msgstr "Copiați locația în clipboard"
msgid "Copy Link Address"
msgstr "Copați adresa link-ului"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr ""
@@ -942,9 +951,6 @@ msgstr "Setați alarma"
msgid "In: %s"
msgstr "În: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Hyperlink"
@@ -1021,6 +1027,14 @@ msgstr "Sincronizați"
msgid "Notebooks"
msgstr "Caiete de notițe"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Se decriptează itemi: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Resurse: %d."
msgid "Please select where the sync status should be exported to"
msgstr ""
@@ -1104,10 +1118,6 @@ msgstr ""
msgid "Fetched items: %d/%d."
msgstr ""
#, javascript-format
msgid "State: %s."
msgstr "Statut: %s."
msgid "Cancelling..."
msgstr "Se amână..."
@@ -1219,6 +1229,12 @@ msgstr "Afișați iconița coșul de gunoi"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1336,6 +1352,9 @@ msgstr ""
msgid "Evernote Export File"
msgstr ""
msgid "Json Export Directory"
msgstr ""
msgid "Directory"
msgstr ""
@@ -1405,6 +1424,12 @@ msgstr "Alarmele următoare"
msgid "On %s: %s"
msgstr "Pe %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
@@ -1449,10 +1474,6 @@ msgstr "Confirmați"
msgid "Cancel synchronisation"
msgstr "Amânați sincronizarea"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Se decriptează itemi: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "Se anulează... Vă rugăm să așteptați."
@@ -1584,6 +1605,9 @@ msgstr "Afișați metadatele"
msgid "View on map"
msgstr "Vizualizați pe hartă"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Ștergeți caiet de notițe"
@@ -1607,5 +1631,8 @@ msgstr ""
msgid "Welcome"
msgstr "Bine ați venit"
#~ msgid "State: %s."
#~ msgstr "Statut: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Un caiet de notițe cu acest titlu există deja: \"%s\""

View File

@@ -456,6 +456,9 @@ msgstr "Не удалось инициировать синхронизацию.
msgid "Starting synchronisation..."
msgstr "Начало синхронизации..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Отмена... Пожалуйста, ожидайте."
@@ -971,6 +974,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Открыть..."
@@ -987,6 +993,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Неподдерживаемая ссыка или сообщение: %s"
@@ -1024,9 +1033,6 @@ msgstr "Установить напоминание"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1105,6 +1111,14 @@ msgstr "Синхронизировать"
msgid "Notebooks"
msgstr "Блокноты"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Получено элементов: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Ресурсов: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Выберите, куда должен быть экспортирован статус синхронизации"
@@ -1196,10 +1210,6 @@ msgstr "Удалено удалённых элементов: %d."
msgid "Fetched items: %d/%d."
msgstr "Получено элементов: %d/%d."
#, fuzzy, javascript-format
msgid "State: %s."
msgstr "Статус: «%s»."
msgid "Cancelling..."
msgstr "Отмена..."
@@ -1316,6 +1326,12 @@ msgstr "Показывать иконку в панели задач"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1444,6 +1460,10 @@ msgstr "Папка экспорта Joplin"
msgid "Evernote Export File"
msgstr "Файл экспорта Evernote"
#, fuzzy
msgid "Json Export Directory"
msgstr "Папка экспорта Joplin"
msgid "Directory"
msgstr "Директория"
@@ -1519,6 +1539,12 @@ msgstr "Грядущие напоминания"
msgid "On %s: %s"
msgstr "В %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Сейчас здесь нет заметок. Создаёте новую, нажав кнопку (+)."
@@ -1564,10 +1590,6 @@ msgstr "Подтвердить"
msgid "Cancel synchronisation"
msgstr "Отменить синхронизацию"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Получено элементов: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "Отмена... Пожалуйста, ожидайте."
@@ -1702,6 +1724,9 @@ msgstr "Показать метаданные"
msgid "View on map"
msgstr "Посмотреть на карте"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Удалить блокнот"
@@ -1724,6 +1749,10 @@ msgstr "У вас сейчас нет блокнота. Создайте его
msgid "Welcome"
msgstr "Добро пожаловать"
#, fuzzy
#~ msgid "State: %s."
#~ msgstr "Статус: «%s»."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Блокнот с таким названием уже существует: «%s»"

View File

@@ -455,6 +455,9 @@ msgstr "Ni moč zagnati sinhronizatorja."
msgid "Starting synchronisation..."
msgstr "Sinhronizacija se začenja."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "V preklicu...Prosim počakajte."
@@ -975,6 +978,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Odpri..."
@@ -991,6 +997,9 @@ msgstr ""
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Nepodprta povezava ali sporočilo: %s"
@@ -1028,9 +1037,6 @@ msgstr "Nastavi alarm"
msgid "In: %s"
msgstr "%s: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr ""
@@ -1109,6 +1115,14 @@ msgstr "Sinhroniziraj"
msgid "Notebooks"
msgstr "Beležnice"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Preneseni predmeti: %d/%d."
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Viri: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Prosim izberite, kam želite izvoziti sinhronizacijski status"
@@ -1200,10 +1214,6 @@ msgstr "Izbrisani oddaljeni predmeti: %d."
msgid "Fetched items: %d/%d."
msgstr "Preneseni predmeti: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Stanje: %s."
msgid "Cancelling..."
msgstr "V preklicu..."
@@ -1320,6 +1330,12 @@ msgstr "Pokaži ikono v območju za obvestila(opravilna vrstica)"
msgid "Note: Does not work in all desktop environments."
msgstr ""
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1448,6 +1464,10 @@ msgstr "Joplin izvozno mesto"
msgid "Evernote Export File"
msgstr "Evernote izvozna datoteka"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin izvozno mesto"
msgid "Directory"
msgstr "Mesto datoteke"
@@ -1522,6 +1542,12 @@ msgstr "Prihajajoči alarmi"
msgid "On %s: %s"
msgstr "Vključeno %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "Trenutno ni zabeležk. Ustvarite jo s klikom na (+) gumb."
@@ -1567,10 +1593,6 @@ msgstr "Potrdi"
msgid "Cancel synchronisation"
msgstr "Prekliči sinhronizacijo"
#, fuzzy, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Preneseni predmeti: %d/%d."
#, fuzzy
msgid "Checking... Please wait."
msgstr "V preklicu...Prosim počakajte."
@@ -1705,6 +1727,9 @@ msgstr "Prikaži meta podatke"
msgid "View on map"
msgstr "Prikaži na zemljevidu"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Izbriši beležnico"
@@ -1727,6 +1752,9 @@ msgstr "Trenutno nimate nobene beležnice. Ustvarite jo s klikom na (+) gumb."
msgid "Welcome"
msgstr "Dobrodošli"
#~ msgid "State: %s."
#~ msgstr "Stanje: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "Beležnica s tem naslovom že obstaja: \"%s\""

View File

@@ -461,6 +461,9 @@ msgstr "Kan inte initiera synkroniseraren."
msgid "Starting synchronisation..."
msgstr "Startar synkronisering..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "Avbryter... vänta."
@@ -984,6 +987,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "Öppna..."
@@ -1000,6 +1006,9 @@ msgstr "Kopiera sökväg till urklipp"
msgid "Copy Link Address"
msgstr "Kopiera länkadress"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "Länk eller meddelande stöds inte: %s"
@@ -1037,9 +1046,6 @@ msgstr "Sätt alarm"
msgid "In: %s"
msgstr "I: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "Hyperlänk"
@@ -1116,6 +1122,14 @@ msgstr "Synkronisera"
msgid "Notebooks"
msgstr "Anteckningsböcker"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Dekrypterar objekt: %d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "Resurser: %d."
msgid "Please select where the sync status should be exported to"
msgstr "Välj vart synkroniseringstillståndet ska exporteras till"
@@ -1207,10 +1221,6 @@ msgstr "Borttagna fjärrobjekt: %d."
msgid "Fetched items: %d/%d."
msgstr "Hämtade objekt: %d/%d."
#, javascript-format
msgid "State: %s."
msgstr "Tillstånd: %s."
msgid "Cancelling..."
msgstr "Avbryter..."
@@ -1323,6 +1333,12 @@ msgstr "Visa fältikon"
msgid "Note: Does not work in all desktop environments."
msgstr "Obs: Fungerar inte i alla skrivbordsmiljöer."
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1455,6 +1471,10 @@ msgstr "Joplin-exporteringskatalog"
msgid "Evernote Export File"
msgstr "Evernote-exporteringsfil"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin-exporteringskatalog"
msgid "Directory"
msgstr "Katalog"
@@ -1529,6 +1549,12 @@ msgstr "Kommande larm"
msgid "On %s: %s"
msgstr "På %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr ""
"Det finns för närvarande inga anteckningar. Skapa en genom att klicka på (+)-"
@@ -1575,10 +1601,6 @@ msgstr "Bekräfta"
msgid "Cancel synchronisation"
msgstr "Avbryt synkronisering"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "Dekrypterar objekt: %d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "Avbryter... vänta."
@@ -1721,6 +1743,9 @@ msgstr "Visa metadata"
msgid "View on map"
msgstr "Visa på karta"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "Ta bort anteckningsbok"
@@ -1746,5 +1771,8 @@ msgstr ""
msgid "Welcome"
msgstr "Välkommen"
#~ msgid "State: %s."
#~ msgstr "Tillstånd: %s."
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "En anteckningsbok med denna titel finns redan: \"%s\""

View File

@@ -431,6 +431,9 @@ msgstr "无法初始化同步。"
msgid "Starting synchronisation..."
msgstr "开始同步..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "正在取消... 请稍后。"
@@ -929,6 +932,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "打开…"
@@ -945,6 +951,9 @@ msgstr "复制路径到剪切板"
msgid "Copy Link Address"
msgstr ""
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "不支持的链接或信息:%s"
@@ -980,9 +989,6 @@ msgstr "设置提醒"
msgid "In: %s"
msgstr "在: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "超链接"
@@ -1059,6 +1065,14 @@ msgstr "同步"
msgid "Notebooks"
msgstr "笔记本"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "解密项目:%d/%d"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "资源:%d。"
msgid "Please select where the sync status should be exported to"
msgstr "请选择同步状态的导出位置"
@@ -1148,10 +1162,6 @@ msgstr "已删除远程项目: %d。"
msgid "Fetched items: %d/%d."
msgstr "已提取项目:%d/%d."
#, javascript-format
msgid "State: %s."
msgstr "状态:%s。"
msgid "Cancelling..."
msgstr "正在取消..."
@@ -1263,6 +1273,12 @@ msgstr "显示托盘图标"
msgid "Note: Does not work in all desktop environments."
msgstr "注意:在所有的桌面环境中都不能工作。"
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr "启动应用程序时在托盘中最小化"
@@ -1391,6 +1407,10 @@ msgstr "Joplin 导出目录"
msgid "Evernote Export File"
msgstr "Evernote 导出文件"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin 导出目录"
msgid "Directory"
msgstr "文件目录"
@@ -1462,6 +1482,12 @@ msgstr "临近提醒"
msgid "On %s: %s"
msgstr "%s:%s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "当前没有任何笔记。点击(+)按钮创建。"
@@ -1506,10 +1532,6 @@ msgstr "确认"
msgid "Cancel synchronisation"
msgstr "取消同步"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "解密项目:%d/%d"
#, fuzzy
msgid "Checking... Please wait."
msgstr "正在取消... 请稍后。"
@@ -1645,6 +1667,9 @@ msgstr "显示元数据"
msgid "View on map"
msgstr "查看地图"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "删除笔记本"
@@ -1665,6 +1690,9 @@ msgstr "您目前未有笔记本。点击(+)按钮创建。"
msgid "Welcome"
msgstr "欢迎"
#~ msgid "State: %s."
#~ msgstr "状态:%s。"
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "以此标题命名的笔记本已存在:\"%s\""

View File

@@ -431,6 +431,9 @@ msgstr "無法初始化同步器。"
msgid "Starting synchronisation..."
msgstr "正在啟動同步..."
msgid "Downloading resources..."
msgstr ""
msgid "Cancelling... Please wait."
msgstr "正在取消中...請稍候。"
@@ -929,6 +932,9 @@ msgstr ""
msgid "URL"
msgstr ""
msgid "Note properties"
msgstr ""
msgid "Open..."
msgstr "開啟..."
@@ -945,6 +951,9 @@ msgstr "複製路徑到剪貼板"
msgid "Copy Link Address"
msgstr "複製鏈接位址"
msgid "This attachment is not downloaded or not decrypted yet."
msgstr ""
#, javascript-format
msgid "Unsupported link or message: %s"
msgstr "不支援的鏈接或訊息: %s"
@@ -980,9 +989,6 @@ msgstr "設置提醒"
msgid "In: %s"
msgstr "在: %s"
msgid "Note properties"
msgstr ""
msgid "Hyperlink"
msgstr "超連結"
@@ -1059,6 +1065,14 @@ msgstr "進行同步"
msgid "Notebooks"
msgstr "記事本"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "正在解密項目: %d/%d 項"
#, fuzzy, javascript-format
msgid "Fetching resources: %d"
msgstr "資源: %d。"
msgid "Please select where the sync status should be exported to"
msgstr "請選擇將同步狀態導出到的位置"
@@ -1147,10 +1161,6 @@ msgstr "已刪除的遠端項目: %d 項"
msgid "Fetched items: %d/%d."
msgstr "已擷取的本地項目: %d/%d 項"
#, javascript-format
msgid "State: %s."
msgstr "狀態: %s。"
msgid "Cancelling..."
msgstr "正在取消中..."
@@ -1262,6 +1272,12 @@ msgstr "顯示系統匣圖示"
msgid "Note: Does not work in all desktop environments."
msgstr "注意: 不是在全部桌面環境中都能發揮作用。"
msgid ""
"This will allow Joplin to run in the background. It is recommended to enable "
"this setting so that your notes are constantly being synchronised, thus "
"reducing the number of conflicts."
msgstr ""
msgid "Start application minimised in the tray icon"
msgstr ""
@@ -1388,6 +1404,10 @@ msgstr "Joplin 匯出目錄"
msgid "Evernote Export File"
msgstr "Evernote 匯出檔"
#, fuzzy
msgid "Json Export Directory"
msgstr "Joplin 匯出目錄"
msgid "Directory"
msgstr "目錄"
@@ -1459,6 +1479,12 @@ msgstr "將會發生的提醒事項"
msgid "On %s: %s"
msgstr "在 %s: %s"
msgid "Permission to use camera"
msgstr ""
msgid "Your permission to use your camera is required."
msgstr ""
msgid "There are currently no notes. Create one by clicking on the (+) button."
msgstr "您當前沒有任何筆記。通過按一下 (+) 鍵去新增一則筆記。"
@@ -1503,10 +1529,6 @@ msgstr "確認"
msgid "Cancel synchronisation"
msgstr "取消同步"
#, javascript-format
msgid "Decrypting items: %d/%d"
msgstr "正在解密項目: %d/%d 項"
#, fuzzy
msgid "Checking... Please wait."
msgstr "正在取消中...請稍候。"
@@ -1642,6 +1664,9 @@ msgstr "顯示後設資料 (metadata)"
msgid "View on map"
msgstr "在地圖上顯示"
msgid "Go to source URL"
msgstr ""
msgid "Delete notebook"
msgstr "刪除記事本"
@@ -1662,5 +1687,8 @@ msgstr "您當前沒有任何筆記本。通過按一下 (+) 鍵去建立一本
msgid "Welcome"
msgstr "歡迎"
#~ msgid "State: %s."
#~ msgstr "狀態: %s。"
#~ msgid "A notebook with this title already exists: \"%s\""
#~ msgstr "同名筆記本已經存在: \"%s\""

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.0.116",
"version": "1.0.117",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -19,7 +19,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.0.116",
"version": "1.0.117",
"bin": {
"joplin": "./main.js"
},

View File

@@ -25,6 +25,7 @@ npm test tests-build/ArrayUtils.js
npm test tests-build/EnexToMd.js
npm test tests-build/HtmlToMd.js
npm test tests-build/markdownUtils.js
npm test tests-build/models_BaseItem.js
npm test tests-build/models_Folder.js
npm test tests-build/models_Note.js
npm test tests-build/models_Tag.js

View File

@@ -1,5 +1,6 @@
require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
@@ -37,9 +38,14 @@ describe('EnexToMd', function() {
// if (htmlFilename !== 'text2.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
const expectedMd = await shim.fsDriver().readFile(mdPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
const actualMd = await enexXmlToMd('<div>' + html + '</div>', []);
let actualMd = await enexXmlToMd('<div>' + html + '</div>', []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n')
actualMd = actualMd.replace(/\r\n/g, '\n')
}
if (actualMd !== expectedMd) {
console.info('');

View File

@@ -1,5 +1,6 @@
require('app-module-path').addPath(__dirname);
const os = require('os');
const { time } = require('lib/time-utils.js');
const { filename } = require('lib/path-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
@@ -39,9 +40,14 @@ describe('HtmlToMd', function() {
// if (htmlFilename !== 'anchor_with_url_with_spaces.html') continue;
const html = await shim.fsDriver().readFile(htmlPath);
const expectedMd = await shim.fsDriver().readFile(mdPath);
let expectedMd = await shim.fsDriver().readFile(mdPath);
const actualMd = await htmlToMd.parse('<div>' + html + '</div>', []);
let actualMd = await htmlToMd.parse('<div>' + html + '</div>', []);
if (os.EOL === '\r\n') {
expectedMd = expectedMd.replace(/\r\n/g, '\n')
actualMd = actualMd.replace(/\r\n/g, '\n')
}
if (actualMd !== expectedMd) {
console.info('');

View File

@@ -0,0 +1,51 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const BaseItem = require('lib/models/BaseItem.js');
const Resource = require('lib/models/Resource.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
async function allItems() {
let folders = await Folder.all();
let notes = await Note.all();
return folders.concat(notes);
}
describe('models_BaseItem', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
// it('should be able to exclude keys when syncing', asyncTest(async () => {
// 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];
// console.info(await Resource.serializeForSync(resource1));
// }));
// This is to handle the case where a property is removed from a BaseItem table - in that case files in
// the sync target will still have the old property but we don't need it locally.
it('should ignore properties that are present in sync file but not in database when serialising', asyncTest(async () => {
let folder = await Folder.save({ title: "folder1" });
let serialized = await Folder.serialize(folder);
serialized += "\nignore_me: true"
let unserialized = await Folder.unserialize(serialized);
expect('ignore_me' in unserialized).toBe(false);
}));
});

View File

@@ -25,7 +25,35 @@ describe('models_Resource', function() {
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];
console.info(resource1);
let ls = await Resource.localState(resource1);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
}));
it('should have a default local state', asyncTest(async () => {
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 ls = await Resource.localState(resource1);
expect(!ls.id).toBe(true);
expect(ls.resource_id).toBe(resource1.id);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
}));
it('should save and delete local state', asyncTest(async () => {
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];
await Resource.setLocalState(resource1, { fetch_status: Resource.FETCH_STATUS_IDLE });
let ls = await Resource.localState(resource1);
expect(!!ls.id).toBe(true);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_IDLE);
await Resource.delete(resource1.id);
ls = await Resource.localState(resource1);
expect(!ls.id).toBe(true);
}));
});

View File

@@ -310,4 +310,25 @@ describe('services_InteropService', function() {
expect(note2_2.body.indexOf(note1_2.id) >= 0).toBe(true);
}));
it('should export into json format', asyncTest(async () => {
const service = new InteropService();
let folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await Note.load(note1.id);
const filePath = exportDir();
await service.export({ path: filePath, format: 'json' });
// verify that the json files exist and can be parsed
const items = [folder1, note1];
for (let i = 0; i < items.length; i++) {
const jsonFile = filePath + '/' + items[i].id + '.json';
let json = await fs.readFile(jsonFile, 'utf-8');
let obj = JSON.parse(json);
expect(obj.id).toBe(items[i].id);
expect(obj.type_).toBe(items[i].type_);
expect(obj.title).toBe(items[i].title);
expect(obj.body).toBe(items[i].body);
}
}));
});

View File

@@ -156,6 +156,20 @@ describe('services_rest_Api', function() {
done();
});
it('should create notes with supplied ID', async (done) => {
let response = null;
const f = await Folder.save({ title: "mon carnet" });
response = await api.route('POST', 'notes', null, JSON.stringify({
id: '12345678123456781234567812345678',
title: 'testing',
parent_id: f.id,
}));
expect(response.id).toBe('12345678123456781234567812345678');
done();
});
it('should create notes with images', async (done) => {
let response = null;
const f = await Folder.save({ title: "mon carnet" });

View File

@@ -873,15 +873,17 @@ describe('Synchronizer', function() {
let allResources = await Resource.all();
expect(allResources.length).toBe(1);
let resource1_2 = allResources[0];
let ls = await Resource.localState(resource1_2);
expect(resource1_2.id).toBe(resource1.id);
expect(resource1_2.fetch_status).toBe(Resource.FETCH_STATUS_IDLE);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_IDLE);
const fetcher = new ResourceFetcher(() => { return synchronizer().api() });
fetcher.queueDownload(resource1_2.id);
await fetcher.waitForAllFinished();
resource1_2 = await Resource.load(resource1.id);
expect(resource1_2.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
ls = await Resource.localState(resource1_2);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_DONE);
let resourcePath1_2 = Resource.fullPath(resource1_2);
expect(fileContentEqual(resourcePath1, resourcePath1_2)).toBe(true);
@@ -909,8 +911,9 @@ describe('Synchronizer', function() {
await fetcher.waitForAllFinished();
resource1 = await Resource.load(resource1.id);
expect(resource1.fetch_status).toBe(Resource.FETCH_STATUS_ERROR);
expect(resource1.fetch_error).toBe('did not work');
let ls = await Resource.localState(resource1);
expect(ls.fetch_status).toBe(Resource.FETCH_STATUS_ERROR);
expect(ls.fetch_error).toBe('did not work');
}));
it('should delete resources', asyncTest(async () => {

View File

@@ -676,6 +676,23 @@ class Application extends BaseApplication {
document.head.appendChild(styleTag);
}
async loadCustomCss(filePath) {
let cssString = '';
if (await fs.pathExists(filePath)) {
try {
cssString = await fs.readFile(filePath, 'utf-8');
} catch (error) {
let msg = error.message ? error.message : '';
msg = 'Could not load custom css from ' + filePath + '\n' + msg;
error.message = msg;
throw error;
}
}
return cssString;
}
async start(argv) {
const electronIsDev = require('electron-is-dev');
@@ -729,6 +746,13 @@ class Application extends BaseApplication {
ids: Setting.value('collapsedFolderIds'),
});
const cssString = await this.loadCustomCss(Setting.value('profileDir') + '/userstyle.css');
this.store().dispatch({
type: 'LOAD_CUSTOM_CSS',
css: cssString
});
// Note: Auto-update currently doesn't work in Linux: it downloads the update
// but then doesn't install it on exit.
if (shim.isWindows() || shim.isMac()) {

View File

@@ -45,15 +45,21 @@ class ClipperConfigScreenComponent extends React.Component {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const containerStyle = Object.assign({}, theme.containerStyle, {
overflowY: 'scroll',
height:style.height,
});
const buttonStyle = Object.assign({}, theme.buttonStyle, { marginRight: 10 });
const stepBoxStyle = {
border: "1px solid #ccc",
padding: 15,
paddingTop: 0,
marginBottom: 15,
backgroundColor: theme.backgroundColor,
};
let webClipperStatusComps = [];
@@ -68,7 +74,7 @@ class ClipperConfigScreenComponent extends React.Component {
webClipperStatusComps.push(<button key="disable_button" onClick={this.disableClipperServer_click}>{_('Disable Web Clipper Service')}</button>)
} else {
webClipperStatusComps.push(<p key="text_4" style={theme.textStyle}>{_('The web clipper service is not enabled.')}</p>)
webClipperStatusComps.push(<button key="enable_button" onClick={this.enableClipperServer_click}>{_('Enable Web Clipper Service')}</button>)
webClipperStatusComps.push(<button key="enable_button" style={buttonStyle} onClick={this.enableClipperServer_click}>{_('Enable Web Clipper Service')}</button>)
}
const apiTokenStyle = Object.assign({}, theme.textStyle, {
@@ -81,7 +87,7 @@ class ClipperConfigScreenComponent extends React.Component {
return (
<div>
<Header style={headerStyle} />
<div style={{overflowY:'scroll', height:style.height}}>
<div style={containerStyle}>
<div style={{padding: theme.margin}}>
<p style={theme.textStyle}>{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}</p>
<p style={theme.textStyle}>{_('In order to use the web clipper, you need to do the following:')}</p>
@@ -106,7 +112,7 @@ class ClipperConfigScreenComponent extends React.Component {
<div style={stepBoxStyle}>
<p style={theme.h1Style}>{_('Advanced options')}</p>
<p style={theme.textStyle}>{_('Authorisation token:')}</p>
<p style={apiTokenStyle}>{this.props.apiToken} <a href="#" onClick={this.copyToken_click}>{_('Copy token')}</a></p>
<p style={apiTokenStyle}>{this.props.apiToken} <a style={theme.urlStyle} href="#" onClick={this.copyToken_click}>{_('Copy token')}</a></p>
<p style={theme.textStyle}>{_('This authorisation token is only needed to allow third-party applications to access Joplin.')}</p>
</div>
</div>
@@ -128,4 +134,4 @@ const mapStateToProps = (state) => {
const ClipperConfigScreen = connect(mapStateToProps)(ClipperConfigScreenComponent);
module.exports = { ClipperConfigScreen };
module.exports = { ClipperConfigScreen };

View File

@@ -53,10 +53,13 @@ class ConfigScreenComponent extends React.Component {
const labelStyle = Object.assign({}, theme.textStyle, {
display: 'inline-block',
marginRight: 10,
color: theme.color,
});
const controlStyle = {
display: 'inline-block',
color: theme.color,
backgroundColor: theme.backgroundColor,
};
const descriptionStyle = Object.assign({}, theme.textStyle, {
@@ -120,7 +123,10 @@ class ConfigScreenComponent extends React.Component {
updateSettingValue(key, event.target.value);
}
const inputStyle = Object.assign({}, controlStyle, { width: '50%', minWidth: '20em' });
const inputStyle = Object.assign({}, controlStyle, {
width: '50%',
minWidth: '20em',
border: '1px solid' });
const inputType = md.secure === true ? 'password' : 'text';
return (
@@ -164,21 +170,19 @@ class ConfigScreenComponent extends React.Component {
render() {
const theme = themeStyle(this.props.theme);
const style = Object.assign({}, this.props.style, { overflow: 'auto' });
const style = Object.assign({
backgroundColor: theme.backgroundColor
}, this.props.style, { overflow: 'auto' });
const settings = this.state.settings;
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const containerStyle = {
padding: 10,
};
const containerStyle = Object.assign({}, theme.containerStyle, { padding: 10 });
const buttonStyle = {
const buttonStyle = Object.assign({}, theme.buttonStyle, {
display: this.state.changedSettingKeys.length ? 'inline-block' : 'none',
marginRight: 10,
}
});
const settingComps = shared.settingsToComponents(this, 'desktop', settings);
@@ -195,7 +199,7 @@ class ConfigScreenComponent extends React.Component {
settingComps.push(
<div key="check_sync_config_button" style={this.rowStyle_}>
<button disabled={this.state.checkSyncConfigResult === 'checking'} onClick={this.checkSyncConfig_}>{_('Check synchronisation configuration')}</button>
<button style={buttonStyle} disabled={this.state.checkSyncConfigResult === 'checking'} onClick={this.checkSyncConfig_}>{_('Check synchronisation configuration')}</button>
{ statusComp }
</div>);
}
@@ -228,4 +232,4 @@ const mapStateToProps = (state) => {
const ConfigScreen = connect(mapStateToProps)(ConfigScreenComponent);
module.exports = { ConfigScreen };
module.exports = { ConfigScreen };

View File

@@ -28,16 +28,18 @@ class DropboxLoginScreenComponent extends React.Component {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const containerStyle = Object.assign({}, theme.containerStyle, {
padding: theme.margin,
height: style.height - theme.headerHeight - theme.margin * 2,
});
const inputStyle = Object.assign({}, theme.inputStyle, { width: 500 });
return (
<div>
<Header style={headerStyle} />
<div style={{padding: theme.margin}}>
<div style={containerStyle}>
<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>
@@ -59,4 +61,4 @@ const mapStateToProps = (state) => {
const DropboxLoginScreen = connect(mapStateToProps)(DropboxLoginScreenComponent);
module.exports = { DropboxLoginScreen };
module.exports = { DropboxLoginScreen };

View File

@@ -50,6 +50,13 @@ class EncryptionConfigScreenComponent extends React.Component {
renderMasterKey(mk) {
const theme = themeStyle(this.props.theme);
const passwordStyle = {
color: theme.color,
backgroundColor: theme.backgroundColor,
border: '1px solid',
borderColor: theme.dividerColor,
}
const onSaveClick = () => {
return shared.onSavePasswordClick(this, mk);
}
@@ -69,7 +76,7 @@ class EncryptionConfigScreenComponent extends React.Component {
<td style={theme.textStyle}>{mk.source_application}</td>
<td style={theme.textStyle}>{time.formatMsToLocal(mk.created_time)}</td>
<td style={theme.textStyle}>{time.formatMsToLocal(mk.updated_time)}</td>
<td style={theme.textStyle}><input type="password" value={password} onChange={(event) => onPasswordChange(event)}/> <button onClick={() => onSaveClick()}>{_('Save')}</button></td>
<td style={theme.textStyle}><input type="password" style={passwordStyle} value={password} onChange={(event) => onPasswordChange(event)}/> <button style={theme.buttonStyle} onClick={() => onSaveClick()}>{_('Save')}</button></td>
<td style={theme.textStyle}>{passwordOk}</td>
</tr>
);
@@ -81,15 +88,13 @@ class EncryptionConfigScreenComponent extends React.Component {
const masterKeys = this.state.masterKeys;
const containerPadding = 10;
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const containerStyle = {
const containerStyle = Object.assign({}, theme.containerStyle, {
padding: containerPadding,
overflow: 'auto',
height: style.height - theme.headerHeight - containerPadding * 2,
};
});
const mkComps = [];
let nonExistingMasterKeyIds = this.props.notLoadedMasterKeys.slice();
@@ -126,7 +131,7 @@ class EncryptionConfigScreenComponent extends React.Component {
}
const decryptedItemsInfo = <p style={theme.textStyle}>{shared.decryptedStatText(this)}</p>;
const toggleButton = <button onClick={() => { onToggleButtonClick() }}>{this.props.encryptionEnabled ? _('Disable encryption') : _('Enable encryption')}</button>
const toggleButton = <button style={theme.buttonStyle} onClick={() => { onToggleButtonClick() }}>{this.props.encryptionEnabled ? _('Disable encryption') : _('Enable encryption')}</button>
let masterKeySection = null;
@@ -213,4 +218,4 @@ const mapStateToProps = (state) => {
const EncryptionConfigScreen = connect(mapStateToProps)(EncryptionConfigScreenComponent);
module.exports = { EncryptionConfigScreen };
module.exports = { EncryptionConfigScreen };

View File

@@ -108,6 +108,9 @@ class HeaderComponent extends React.Component {
color: style.color,
fontSize: style.fontSize,
fontFamily: style.fontFamily,
backgroundColor: style.searchColor,
border: '1px solid',
borderColor: style.dividerColor,
};
const searchButton = {
@@ -171,6 +174,8 @@ class HeaderComponent extends React.Component {
paddingLeft: theme.headerButtonHPadding,
paddingRight: theme.headerButtonHPadding,
color: theme.color,
searchColor: theme.backgroundColor,
dividerColor: theme.dividerColor,
textDecoration: 'none',
fontFamily: theme.fontFamily,
fontSize: theme.fontSize,
@@ -212,4 +217,4 @@ const mapStateToProps = (state) => {
const Header = connect(mapStateToProps)(HeaderComponent);
module.exports = { Header };
module.exports = { Header };

View File

@@ -35,4 +35,4 @@ class IconButton extends React.Component {
}
module.exports = { IconButton };
module.exports = { IconButton };

View File

@@ -120,7 +120,7 @@ class MainScreenComponent extends React.Component {
});
} else if (command.name === 'setTags') {
const tags = await Tag.tagsByNoteId(command.noteId);
const tagTitles = tags.map((a) => { return a.title });
const tagTitles = tags.map((a) => { return a.title }).sort();
this.setState({
promptOptions: {
@@ -158,7 +158,7 @@ class MainScreenComponent extends React.Component {
},
});
} else if (command.name === 'renameTag') {
const tag = await Tag.load(command.id);
const tag = await Tag.load(command.id);
if(!tag) return;
this.setState({
@@ -173,12 +173,12 @@ class MainScreenComponent extends React.Component {
} catch (error) {
bridge().showErrorMessageBox(error.message);
}
}
}
this.setState({promptOptions: null });
}
}
})
} else if (command.name === 'search') {
if (!this.searchId_) this.searchId_ = uuid.create();
@@ -336,14 +336,17 @@ class MainScreenComponent extends React.Component {
}
render() {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const style = Object.assign({
color: theme.color,
backgroundColor: theme.backgroundColor,
}, this.props.style);
const promptOptions = this.state.promptOptions;
const folders = this.props.folders;
const notes = this.props.notes;
const messageBoxVisible = this.props.hasDisabledSyncItems || this.props.showMissingMasterKeyMessage;
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();

View File

@@ -349,7 +349,7 @@ class NotePropertiesDialog extends React.Component {
return (
<div style={modalLayerStyle}>
<div style={styles.dialogBox}>
<div style={styles.dialogTitle}>Note properties</div>
<div style={styles.dialogTitle}>{_('Note properties')}</div>
<div>{noteComps}</div>
<div style={{ textAlign: 'right', marginTop: 10 }}>
{buttonComps}
@@ -361,4 +361,4 @@ class NotePropertiesDialog extends React.Component {
}
module.exports = NotePropertiesDialog;
module.exports = NotePropertiesDialog;

View File

@@ -6,8 +6,9 @@ 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');
const { urlDecode } = require('lib/string-utils');
const { urlDecode, escapeHtml } = require('lib/string-utils');
const Toolbar = require('./Toolbar.min.js');
const TagList = require('./TagList.min.js');
const { connect } = require('react-redux');
const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
@@ -36,6 +37,7 @@ require('brace/mode/markdown');
// https://ace.c9.io/build/kitchen-sink.html
// https://highlightjs.org/static/demo/
require('brace/theme/chrome');
require('brace/theme/twilight');
class NoteTextComponent extends React.Component {
@@ -53,6 +55,7 @@ class NoteTextComponent extends React.Component {
scrollHeight: null,
editorScrollTop: 0,
newNote: null,
noteTags: [],
// If the current note was just created, and the title has never been
// changed by the user, this variable contains that note ID. Used
@@ -213,7 +216,7 @@ class NoteTextComponent extends React.Component {
// Note:
// - What's called "cursor position" is expressed as { row: x, column: y } and is how Ace Editor get/set the cursor position
// - A "range" defines a selection with a start and end cusor position, expressed as { start: <CursorPos>, end: <CursorPos> }
// - A "range" defines a selection with a start and end cusor position, expressed as { start: <CursorPos>, end: <CursorPos> }
// - A "text offset" below is the absolute position of the cursor in the string, as would be used in the indexOf() function.
// The functions below are used to convert between the different types.
rangeToTextOffsets(range, body) {
@@ -261,7 +264,7 @@ class NoteTextComponent extends React.Component {
}
row++;
currentOffset += line.length + 1;
currentOffset += line.length + 1;
}
}
@@ -275,11 +278,12 @@ class NoteTextComponent extends React.Component {
async componentWillMount() {
let note = null;
let noteTags = [];
if (this.props.newNote) {
note = Object.assign({}, this.props.newNote);
} else if (this.props.noteId) {
note = await Note.load(this.props.noteId);
noteTags = this.props.noteTags || [];
}
const folder = note ? Folder.byId(this.props.folders, note.parent_id) : null;
@@ -289,6 +293,7 @@ class NoteTextComponent extends React.Component {
note: note,
folder: folder,
isLoading: false,
noteTags: noteTags
});
this.lastLoadedNoteId_ = note ? note.id : null;
@@ -361,6 +366,7 @@ class NoteTextComponent extends React.Component {
let note = null;
let loadingNewNote = true;
let parentFolder = null;
let noteTags = [];
if (props.newNote) {
note = Object.assign({}, props.newNote);
@@ -369,6 +375,7 @@ class NoteTextComponent extends React.Component {
} else {
noteId = props.noteId;
loadingNewNote = stateNoteId !== noteId;
noteTags = await Tag.tagsByNoteId(noteId);
this.lastLoadedNoteId_ = noteId;
note = noteId ? await Note.load(noteId) : null;
if (noteId !== this.lastLoadedNoteId_) return; // Race condition - current note was changed while this one was loading
@@ -446,6 +453,7 @@ class NoteTextComponent extends React.Component {
webviewReady: webviewReady,
folder: parentFolder,
lastKeys: [],
noteTags: noteTags
};
if (!note) {
@@ -459,6 +467,20 @@ class NoteTextComponent extends React.Component {
this.setState(newState);
// https://github.com/laurent22/joplin/pull/893#discussion_r228025210
// @Abijeet: Had to add this check. If not, was going into an infinite loop where state was getting updated repeatedly.
// Since I'm updating the state, the componentWillReceiveProps was getting triggered again, where nextProps.newNote was still true, causing reloadNote to trigger again and again.
// Notes from Laurent: The selected note tags are part of the global Redux state because they need to be updated whenever tags are changed or deleted
// anywhere in the app. Thus it's not possible simple to load the tags here (as we won't have a way to know if they're updated afterwards).
// Perhaps a better way would be to move that code in the middleware, check for TAGS_DELETE, TAGS_UPDATE, etc. actions and update the
// selected note tags accordingly.
if (!this.props.newNote) {
this.props.dispatch({
type: "SET_NOTE_TAGS",
items: noteTags,
});
}
this.updateHtml(newState.note ? newState.note.body : '');
}
@@ -467,6 +489,10 @@ class NoteTextComponent extends React.Component {
await this.reloadNote(nextProps);
} else if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) {
await this.reloadNote(nextProps);
} else if ('noteTags' in nextProps && this.areNoteTagsModified(nextProps.noteTags, this.state.noteTags)) {
this.setState({
noteTags: nextProps.noteTags
});
}
if ('syncStarted' in nextProps && !nextProps.syncStarted && !this.isModified()) {
@@ -482,6 +508,24 @@ class NoteTextComponent extends React.Component {
return shared.isModified(this);
}
areNoteTagsModified(newTags, oldTags) {
if (!oldTags) return true;
if (newTags.length !== oldTags.length) return true;
for (let i = 0; i < newTags.length; ++i) {
let currNewTag = newTags[i];
for (let j = 0; j < oldTags.length; ++j) {
let currOldTag = oldTags[j];
if (currOldTag.id === currNewTag.id && currOldTag.updated_time !== currNewTag.updated_time) {
return true;
}
}
}
return false;
}
refreshNoteMetadata(force = null) {
return shared.refreshNoteMetadata(this, force);
}
@@ -567,7 +611,8 @@ class NoteTextComponent extends React.Component {
if (!item) throw new Error('No item with ID ' + itemId);
if (item.type_ === BaseModel.TYPE_RESOURCE) {
if (item.fetch_status !== Resource.FETCH_STATUS_DONE || !!item.encryption_blob_encrypted) {
const localState = await Resource.localState(item);
if (localState.fetch_status !== Resource.FETCH_STATUS_DONE || !!item.encryption_blob_encrypted) {
bridge().showErrorMessageBox(_('This attachment is not downloaded or not decrypted yet.'));
return;
}
@@ -575,16 +620,10 @@ class NoteTextComponent extends React.Component {
bridge().openItem(filePath);
} else if (item.type_ === BaseModel.TYPE_NOTE) {
this.props.dispatch({
type: "FOLDER_SELECT",
id: item.parent_id,
type: "FOLDER_AND_NOTE_SELECT",
folderId: item.parent_id,
noteId: item.id,
});
setTimeout(() => {
this.props.dispatch({
type: 'NOTE_SELECT',
id: item.id,
});
}, 10);
} else {
throw new Error('Unsupported item type: ' + item.type_);
}
@@ -799,6 +838,7 @@ class NoteTextComponent extends React.Component {
let bodyToRender = body;
if (bodyToRender === null) bodyToRender = this.state.note && this.state.note.body ? this.state.note.body : '';
bodyToRender = '<style>' + this.props.customCss + '</style>\n' + bodyToRender;
let bodyHtml = '';
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
@@ -819,20 +859,7 @@ class NoteTextComponent extends React.Component {
let commandProcessed = true;
if (command.name === 'exportPdf' && this.webview_) {
const path = bridge().showSaveDialog({
filters: [{ name: _('PDF File'), extensions: ['pdf']}],
defaultPath: safeFilename(this.state.note.title),
});
if (path) {
this.webview_.printToPDF({}, (error, data) => {
if (error) {
bridge().showErrorMessageBox(error.message);
} else {
shim.fsDriver().writeFile(path, data, 'buffer');
}
});
}
this.commandSavePdf();
} else if (command.name === 'print' && this.webview_) {
this.webview_.print();
} else if (command.name === 'textBold') {
@@ -897,6 +924,44 @@ class NoteTextComponent extends React.Component {
});
}
commandSavePdf() {
const path = bridge().showSaveDialog({
filters: [{ name: _('PDF File'), extensions: ['pdf']}],
defaultPath: safeFilename(this.state.note.title),
});
if (path) {
// Temporarily add a <h2> title in the webview
const newHtml = this.insertHtmlHeading_(this.lastSetHtml_, this.state.note.title);
this.webview_.send('setHtml', newHtml);
setTimeout(() => {
this.webview_.printToPDF({}, (error, data) => {
if (error) {
bridge().showErrorMessageBox(error.message);
} else {
shim.fsDriver().writeFile(path, data, 'buffer');
}
// Refresh the webview, restoring the previous content
this.lastSetHtml_ = '';
this.forceUpdate();
});
}, 100);
}
}
insertHtmlHeading_(s, heading) {
const tag = 'h2';
const marker = '<!-- START_OF_DOCUMENT -->'
let splitStyle = s.split(marker);
const index = splitStyle.length > 1 ? 1 : 0;
let toInsert = escapeHtml(heading);
toInsert = '<' + tag + '>' + toInsert + '</' + tag + '>';
splitStyle[index] = toInsert + splitStyle[index];
return splitStyle.join(marker);
}
externalEditWatcher() {
if (!this.externalEditWatcher_) {
this.externalEditWatcher_ = new ExternalEditWatcher((action) => { return this.props.dispatch(action) });
@@ -1358,13 +1423,20 @@ class NoteTextComponent extends React.Component {
paddingLeft: 8,
paddingRight: 8,
marginRight: rootStyle.paddingLeft,
color: theme.color,
backgroundColor: theme.backgroundColor,
border: '1px solid',
borderColor: theme.dividerColor,
};
const toolbarStyle = {
};
const tagStyle = {
marginBottom: 10,
};
const bottomRowHeight = rootStyle.height - titleBarStyle.height - titleBarStyle.marginBottom - titleBarStyle.marginTop - theme.toolbarHeight - toolbarStyle.marginBottom;
const bottomRowHeight = rootStyle.height - titleBarStyle.height - titleBarStyle.marginBottom - titleBarStyle.marginTop - theme.toolbarHeight;
const viewerStyle = {
width: Math.floor(innerWidth / 2),
@@ -1386,6 +1458,9 @@ class NoteTextComponent extends React.Component {
paddingTop: paddingTop + 'px',
lineHeight: theme.textAreaLineHeight + 'px',
fontSize: theme.fontSize + 'px',
color: theme.color,
backgroundColor: theme.backgroundColor,
editorTheme: theme.editorTheme,
};
if (visiblePanes.indexOf('viewer') < 0) {
@@ -1416,7 +1491,8 @@ class NoteTextComponent extends React.Component {
const htmlHasChanged = this.lastSetHtml_ !== html;
if (htmlHasChanged) {
this.webview_.send('setHtml', html);
let options = {codeTheme: theme.codeThemeCss};
this.webview_.send('setHtml', html, options);
this.lastSetHtml_ = html;
}
@@ -1445,6 +1521,11 @@ class NoteTextComponent extends React.Component {
placeholder={ this.props.newNote ? _('Creating new %s...', isTodo ? _('to-do') : _('note')) : '' }
/>
const tagList = <TagList
style={tagStyle}
items={this.state.noteTags}
/>;
const titleBarMenuButton = <IconButton style={{
display: 'flex',
}} iconName="fa-caret-down" theme={this.props.theme} onClick={() => { this.itemContextMenu() }} />
@@ -1484,7 +1565,7 @@ class NoteTextComponent extends React.Component {
const editor = <AceEditor
value={body}
mode="markdown"
theme="chrome"
theme={editorRootStyle.editorTheme}
style={editorRootStyle}
width={editorStyle.width + 'px'}
height={editorStyle.height + 'px'}
@@ -1516,6 +1597,7 @@ class NoteTextComponent extends React.Component {
{ false ? titleBarMenuButton : null }
</div>
{ toolbar }
{ tagList }
{ editor }
{ viewer }
</div>
@@ -1527,6 +1609,7 @@ class NoteTextComponent extends React.Component {
const mapStateToProps = (state) => {
return {
noteId: state.selectedNoteIds.length === 1 ? state.selectedNoteIds[0] : null,
noteTags: state.selectedNoteTags,
folderId: state.selectedFolderId,
itemType: state.selectedItemType,
folders: state.folders,
@@ -1539,9 +1622,10 @@ const mapStateToProps = (state) => {
searches: state.searches,
selectedSearchId: state.selectedSearchId,
watchedNoteFiles: state.watchedNoteFiles,
customCss: state.customCss,
};
};
const NoteText = connect(mapStateToProps)(NoteTextComponent);
module.exports = { NoteText };
module.exports = { NoteText };

View File

@@ -73,14 +73,14 @@ class OneDriveLoginScreenComponent extends React.Component {
const style = this.props.style;
const theme = themeStyle(this.props.theme);
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const webviewStyle = {
width: this.props.style.width,
height: this.props.style.height - theme.headerHeight,
overflow: 'hidden',
color: theme.color,
backgroundColor: theme.backgroundColor,
};
const headerButtons = [
@@ -109,4 +109,4 @@ const mapStateToProps = (state) => {
const OneDriveLoginScreen = connect(mapStateToProps)(OneDriveLoginScreenComponent);
module.exports = { OneDriveLoginScreen };
module.exports = { OneDriveLoginScreen };

View File

@@ -59,7 +59,7 @@ class PromptDialog extends React.Component {
};
this.styles_.promptDialog = {
backgroundColor: 'white',
backgroundColor: theme.backgroundColor,
padding: 16,
display: 'inline-block',
boxShadow: '6px 6px 20px rgba(0,0,0,0.5)',
@@ -69,6 +69,10 @@ class PromptDialog extends React.Component {
minWidth: theme.buttonMinWidth,
minHeight: theme.buttonMinHeight,
marginLeft: 5,
color: theme.color,
backgroundColor: theme.backgroundColor,
border: '1px solid',
borderColor: theme.dividerColor,
};
this.styles_.label = {
@@ -82,6 +86,10 @@ class PromptDialog extends React.Component {
this.styles_.input = {
width: 0.5 * width,
maxWidth: 400,
color: theme.color,
backgroundColor: theme.backgroundColor,
border: '1px solid',
borderColor: theme.dividerColor,
};
this.styles_.desc = Object.assign({}, theme.textStyle, {
@@ -142,6 +150,7 @@ class PromptDialog extends React.Component {
if (this.props.inputType === 'datetime') {
inputComp = <Datetime
value={this.state.answer}
inputProps={{style: styles.input}}
dateFormat={time.dateFormat()}
timeFormat={time.timeFormat()}
onChange={(momentObject) => onDateTimeChange(momentObject)}
@@ -166,7 +175,7 @@ class PromptDialog extends React.Component {
<div style={styles.modalLayer}>
<div style={styles.promptDialog}>
<label style={styles.label}>{this.props.label ? this.props.label : ''}</label>
<div style={{display: 'inline-block'}}>
<div style={{display: 'inline-block', color: 'black', backgroundColor: theme.backgroundColor}}>
{inputComp}
{descComp}
</div>
@@ -180,4 +189,4 @@ class PromptDialog extends React.Component {
}
module.exports = { PromptDialog };
module.exports = { PromptDialog };

View File

@@ -505,7 +505,13 @@ class SideBarComponent extends React.Component {
decryptionReportText = _('Decrypting items: %d/%d', this.props.decryptionWorker.itemIndex + 1, this.props.decryptionWorker.itemCount);
}
let resourceFetcherText = '';
if (this.props.resourceFetcher && this.props.resourceFetcher.toFetchCount) {
resourceFetcherText = _('Fetching resources: %d', this.props.resourceFetcher.toFetchCount);
}
let lines = Synchronizer.reportToLines(this.props.syncReport);
if (resourceFetcherText) lines.push(resourceFetcherText);
if (decryptionReportText) lines.push(decryptionReportText);
const syncReportText = [];
for (let i = 0; i < lines.length; i++) {
@@ -547,6 +553,7 @@ const mapStateToProps = state => {
theme: state.settings.theme,
collapsedFolderIds: state.collapsedFolderIds,
decryptionWorker: state.decryptionWorker,
resourceFetcher: state.resourceFetcher,
};
};

View File

@@ -47,17 +47,14 @@ class StatusScreenComponent extends React.Component {
const theme = themeStyle(this.props.theme);
const style = this.props.style;
const headerStyle = {
width: style.width,
};
const headerStyle = Object.assign({}, theme.headerStyle, { width: style.width });
const containerPadding = 10;
const containerStyle = {
const containerStyle = Object.assign({}, theme.containerStyle, {
padding: containerPadding,
overflowY: 'auto',
height: style.height - theme.headerHeight - containerPadding * 2,
};
});
function renderSectionTitleHtml(key, title) {
return <h2 key={'section_' + key} style={theme.h2Style}>{title}</h2>
@@ -134,4 +131,4 @@ const mapStateToProps = (state) => {
const StatusScreen = connect(mapStateToProps)(StatusScreenComponent);
module.exports = { StatusScreen };
module.exports = { StatusScreen };

View File

@@ -0,0 +1,21 @@
const React = require('react');
const { connect } = require('react-redux');
const { themeStyle } = require('../theme.js');
class TagItemComponent extends React.Component {
render() {
const theme = themeStyle(this.props.theme);
const style = Object.assign({}, theme.tagStyle);
const title = this.props.title;
return <span style={style}>{title}</span>;
}
}
const mapStateToProps = (state) => {
return { theme: state.settings.theme };
};
const TagItem = connect(mapStateToProps)(TagItemComponent);
module.exports = TagItem;

View File

@@ -0,0 +1,50 @@
const React = require('react');
const { connect } = require('react-redux');
const { themeStyle } = require('../theme.js');
const TagItem = require('./TagItem.min.js');
class TagListComponent extends React.Component {
render() {
const style = Object.assign({}, this.props.style);
const theme = themeStyle(this.props.theme);
const tags = this.props.items;
style.display = 'flex';
style.flexDirection = 'row';
style.borderBottom = '1px solid ' + theme.dividerColor;
style.boxSizing = 'border-box';
style.fontSize = theme.fontSize;
const tagItems = [];
if (tags || tags.length > 0) {
// Sort by id for now, but probably needs to be changed in the future.
tags.sort((a, b) => { return a.title < b.title ? -1 : +1; });
for (let i = 0; i < tags.length; i++) {
const props = {
title: tags[i].title,
key: tags[i].id
};
tagItems.push(<TagItem {...props} />);
}
}
if (tagItems.length === 0) {
style.visibility = 'hidden';
}
return (
<div className="tag-list" style={style}>
{ tagItems }
</div>
)
}
}
const mapStateToProps = (state) => {
return { theme: state.settings.theme };
};
const TagList = connect(mapStateToProps)(TagListComponent);
module.exports = TagList;

View File

@@ -30,4 +30,4 @@ class Dialogs {
const dialogs = new Dialogs();
module.exports = dialogs;
module.exports = dialogs;

View File

@@ -59,7 +59,7 @@
let hljsScriptAdded = false;
let hljsLoaded = false;
function loadHljs(callback) {
function loadHljs(options) {
hljsScriptAdded = true;
const script = document.createElement('script');
@@ -74,16 +74,16 @@
link.rel = 'stylesheet';
// https://ace.c9.io/build/kitchen-sink.html
// https://highlightjs.org/static/demo/
link.href = 'highlight/styles/atom-one-light.css';
link.href = 'highlight/styles/' + options.codeTheme;
document.getElementById('hlScriptContainer').appendChild(link);
}
function loadAndApplyHljs() {
function loadAndApplyHljs(options) {
var codeElements = document.getElementsByClassName('code');
if (!codeElements.length) return;
if (!hljsScriptAdded) {
this.loadHljs();
this.loadHljs(options);
return;
}
@@ -142,7 +142,7 @@
contentElement.innerHTML = html;
loadAndApplyHljs();
loadAndApplyHljs(event.options);
// Remove the bullet from "ul" for checkbox lists and extra padding
// const checkboxes = document.getElementsByClassName('checkbox');
@@ -319,4 +319,4 @@
</script>
</body>
</html>
</html>

View File

@@ -5,8 +5,8 @@
const ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('setHtml', (event, html) => {
window.postMessage({ target: 'webview', name: 'setHtml', data: { html: html } }, '*');
ipcRenderer.on('setHtml', (event, html, options) => {
window.postMessage({ target: 'webview', name: 'setHtml', data: { html: html, options: options } }, '*');
});
ipcRenderer.on('setPercentScroll', (event, percent) => {
@@ -33,4 +33,4 @@ window.addEventListener('message', (event) => {
} else {
throw new Error('Unsupported number of args');
}
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.0.113",
"version": "1.0.115",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -4057,17 +4057,17 @@
"integrity": "sha1-FHshJTaQNcpLL30hDcU58Amz3po="
},
"katex": {
"version": "0.10.0-rc.1",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.10.0-rc.1.tgz",
"integrity": "sha512-JmnreLp0lWPA1z1krzO5drN1qBrkhqzMg5qv0l5y+Fr97sqgOuh37k9ky7VD1k/Ec+yvOe2BptiYSR9OoShkFg==",
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/katex/-/katex-0.10.0.tgz",
"integrity": "sha512-/WRvx+L1eVBrLwX7QzKU1dQuaGnE7E8hDvx3VWfZh9HbMiCfsKWJNnYZ0S8ZMDAfAyDSofdyXIrH/hujF1fYXg==",
"requires": {
"commander": "^2.16.0"
},
"dependencies": {
"commander": {
"version": "2.17.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
"integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
}
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.0.113",
"version": "1.0.115",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {
@@ -95,7 +95,7 @@
"joplin-turndown": "^4.0.9",
"joplin-turndown-plugin-gfm": "^1.0.7",
"jssha": "^2.3.1",
"katex": "^0.10.0-rc.1",
"katex": "^0.10.0",
"levenshtein": "^1.0.5",
"lodash": "^4.17.10",
"mark.js": "^8.11.1",

View File

@@ -81,4 +81,4 @@ table td, table th {
.note-property-box .rdt {
display: inline-block;
}
}

View File

@@ -2,52 +2,29 @@ const Setting = require('lib/models/Setting.js');
const zoomRatio = Setting.value('style.zoom') / 100;
// globalStyle should be used for properties that do not change across themes
// i.e. should not be used for colors
const globalStyle = {
fontSize: Math.round(12 * zoomRatio),
fontFamily: 'sans-serif',
margin: 15, // No text and no interactive component should be within this margin
itemMarginTop: 10,
itemMarginBottom: 10,
backgroundColor: "#ffffff",
backgroundColorTransparent: 'rgba(255,255,255,0.9)',
oddBackgroundColor: "#dddddd",
color: "#222222", // For regular text
colorError: "red",
colorWarn: "#9A5B00",
colorFaded: "#777777", // For less important text
fontSizeSmaller: 14,
dividerColor: "#dddddd",
selectedColor: '#e5e5e5',
disabledOpacity: 0.3,
buttonMinWidth: 50,
buttonMinHeight: 30,
textAreaLineHeight: 17,
//backgroundColor2: "#2B2634",
backgroundColor2: "#162B3D",
color2: "#ffffff",
//selectedColor2: "#5A4D70",
selectedColor2: "#0269C2",
colorError2: "#ff6c6c",
warningBackgroundColor: "#FFD08D",
headerHeight: 35,
headerButtonHPadding: 6,
toolbarHeight: 35,
raisedBackgroundColor: "#0080EF",
raisedColor: "#003363",
raisedHighlightedColor: "#ffffff",
tagItemPadding: 3,
};
// For WebView - must correspond to the properties above
globalStyle.htmlFontSize = globalStyle.fontSize + 'px';
globalStyle.htmlColor ='black'; // Note: CSS in WebView component only supports named colors or rgb() notation
globalStyle.htmlBackgroundColor ='white';
globalStyle.htmlDividerColor = 'rgb(150,150,150)';
globalStyle.htmlLinkColor ='blue';
globalStyle.htmlLineHeight = Math.round(20 * zoomRatio) + 'px';
globalStyle.marginRight = globalStyle.margin;
@@ -57,28 +34,22 @@ globalStyle.marginBottom = globalStyle.margin;
globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em';
globalStyle.icon = {
color: globalStyle.color,
fontSize: 30,
};
globalStyle.lineInput = {
color: globalStyle.color,
backgroundColor: globalStyle.backgroundColor,
fontFamily: globalStyle.fontFamily,
};
globalStyle.textStyle = {
color: globalStyle.color,
fontFamily: globalStyle.fontFamily,
fontSize: globalStyle.fontSize,
lineHeight: '1.6em',
};
globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, {
color: globalStyle.color2,
});
globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, {});
globalStyle.urlStyle = Object.assign({}, globalStyle.textStyle, { color: "#155BDA", textDecoration: 'underline' });
globalStyle.urlStyle = Object.assign({}, globalStyle.textStyle, { textDecoration: 'underline' });
globalStyle.h1Style = Object.assign({}, globalStyle.textStyle);
globalStyle.h1Style.fontSize *= 1.5;
@@ -95,7 +66,6 @@ globalStyle.toolbarStyle = {
alignItems: 'center',
paddingLeft: globalStyle.headerButtonHPadding,
paddingRight: globalStyle.headerButtonHPadding,
color: globalStyle.color,
textDecoration: 'none',
fontFamily: globalStyle.fontFamily,
fontSize: globalStyle.fontSize,
@@ -104,31 +74,213 @@ globalStyle.toolbarStyle = {
justifyContent: 'center',
};
globalStyle.headerStyle = {};
globalStyle.inputStyle = {
border: '1px solid',
};
globalStyle.containerStyle = {
overflow: 'auto',
overflowY: 'auto',
};
globalStyle.buttonStyle = {
marginRight: 10,
border: '1px solid',
};
const lightStyle = {
backgroundColor: "#ffffff",
backgroundColorTransparent: 'rgba(255,255,255,0.9)',
oddBackgroundColor: "#dddddd",
color: "#222222", // For regular text
colorError: "red",
colorWarn: "#9A5B00",
colorFaded: "#777777", // For less important text
dividerColor: "#dddddd",
selectedColor: '#e5e5e5',
urlColor: '#155BDA',
backgroundColor2: "#162B3D",
color2: "#ffffff",
selectedColor2: "#0269C2",
colorError2: "#ff6c6c",
raisedBackgroundColor: "#e5e5e5",
raisedColor: "#222222",
warningBackgroundColor: "#FFD08D",
codeColor: "#EFF0F1",
codeBorderColor: '#CBCBCB',
htmlColor:'black', // Note: CSS in WebView component only supports named colors or rgb() notation
htmlBackgroundColor: 'white',
htmlDividerColor: 'rgb(150,150,150)',
htmlLinkColor: 'blue',
htmlCodeColor: 'rgb(239, 240, 241)',
htmlCodeBorderColor: 'rgb(203, 203, 203)',
editorTheme: "chrome",
codeThemeCss: "atom-one-light.css",
};
const darkStyle = {
backgroundColor: '#1D2024',
backgroundColorTransparent: 'rgba(255,255,255,0.9)',
oddBackgroundColor: "#dddddd",
color: '#dddddd',
colorFaded: '#777777',
colorError: "red",
colorWarn: "#9A5B00",
colorFaded: "#777777", // For less important text
dividerColor: '#555555',
selectedColor: '#333333',
urlColor: '#4E87EE',
backgroundColor2: "#162B3D",
color2: "#ffffff",
selectedColor2: "#0269C2",
colorError2: "#ff6c6c",
raisedBackgroundColor: "#474747",
raisedColor: "#ffffff",
warningBackgroundColor: "#CC6600",
codeColor: "#2F3031",
codeBorderColor: '#464646',
htmlColor: 'rgb(220,220,220)', // Note: CSS in WebView component only supports named colors or rgb() notation
htmlBackgroundColor: 'rgb(29,32,36)',
htmlDividerColor: 'rgb(150,150,150)',
htmlLinkColor: 'rgb(166,166,255)',
htmlCodeColor: 'rgb(47, 48, 49)',
htmlCodeBorderColor: 'rgb(70, 70, 70)',
editorTheme: 'twilight',
codeThemeCss: "atom-one-dark-reasonable.css",
};
function addExtraStyles(style) {
style.tagStyle = {
fontSize: style.fontSize,
fontFamily: style.fontFamily,
marginTop: style.itemMarginTop * 0.4,
marginBottom: style.itemMarginBottom * 0.4,
marginRight: style.margin * 0.3,
paddingTop: style.tagItemPadding,
paddingBottom: style.tagItemPadding,
paddingRight: style.tagItemPadding * 2,
paddingLeft: style.tagItemPadding * 2,
backgroundColor: style.raisedBackgroundColor,
color: style.raisedColor,
};
return style;
}
let themeCache_ = {};
function themeStyle(theme) {
if (!theme) throw new Error('Theme must be specified');
if (themeCache_[theme]) return themeCache_[theme];
let output = Object.assign({}, globalStyle);
if (theme == Setting.THEME_LIGHT) return output;
let output = {};
if (theme == Setting.THEME_LIGHT) {
output = Object.assign({}, globalStyle, lightStyle);
}
else if (theme == Setting.THEME_DARK) {
output = Object.assign({}, globalStyle, darkStyle);
}
output.backgroundColor = '#1D2024';
output.color = '#dddddd';
output.colorFaded = '#777777';
output.dividerColor = '#555555';
output.selectedColor = '#333333';
// TODO: All the theme specific things should go in addExtraStyles
// so that their definition is not split between here and the
// beginning of the file. At least new styles should go in
// addExtraStyles.
output.raisedBackgroundColor = "#0F2051";
output.raisedColor = "#788BC3";
output.raisedHighlightedColor = "#ffffff";
output.textStyle = Object.assign({},
output.textStyle,
{ color: output.color }
);
output.htmlColor = 'rgb(220,220,220)';
output.htmlBackgroundColor = 'rgb(29,32,36)';
output.htmlLinkColor = 'rgb(166,166,255)';
output.icon = Object.assign({},
output.icon,
{ color: output.color }
);
output.lineInput = Object.assign({},
output.lineInput,
{
color: output.color,
backgroundColor: output.backgroundColor,
}
);
output.textStyle2 = Object.assign({},
output.textStyle2,
{ color: output.color2, }
);
output.urlStyle = Object.assign({},
output.urlStyle,
{ color: output.urlColor }
);
output.h1Style = Object.assign({},
output.h1Style,
{ color: output.color }
);
output.h2Style = Object.assign({},
output.h2Style,
{ color: output.color }
);
output.toolbarStyle = Object.assign({},
output.toolbarStyle,
{ color: output.color }
);
output.headerStyle = Object.assign({},
output.headerStyle,
{
color: output.color,
backgroundColor: output.backgroundColor,
}
);
output.inputStyle = Object.assign({},
output.inputStyle,
{
color: output.color,
backgroundColor: output.backgroundColor,
borderColor: output.dividerColor,
}
);
output.containerStyle = Object.assign({},
output.containerStyle,
{
color: output.color,
backgroundColor: output.backgroundColor,
}
);
output.buttonStyle = Object.assign({},
output.buttonStyle,
{
color: output.color,
backgroundColor: output.backgroundColor,
borderColor: output.dividerColor,
}
);
output = addExtraStyles(output);
themeCache_[theme] = output;
return themeCache_[theme];
}
module.exports = { themeStyle };
module.exports = { themeStyle };

View File

@@ -2,20 +2,6 @@
[![Donate](https://joplin.cozic.net/images/badges/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=E8JMYD2LQ8MMA&lc=GB&item_name=Joplin+Development&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted) [![Become a patron](https://joplin.cozic.net/images/badges/Patreon-Badge.svg)](https://www.patreon.com/joplin) [![Travis Build Status](https://travis-ci.org/laurent22/joplin.svg?branch=master)](https://travis-ci.org/laurent22/joplin) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/laurent22/joplin?branch=master&passingText=master%20-%20OK&svg=true)](https://ci.appveyor.com/project/laurent22/joplin)
* * *
**Joplin and Hacktobertfest 2018 :jack_o_lantern:**
The [Hacktobertfest event](https://hacktoberfest.digitalocean.com/) has started - it allows you to contribute to Joplin and, at the end of the month, after having done 5 PR, you'll earn a limited edition T-shirt.
To participate, go on [https://hacktoberfest.digitalocean.com/ ](https://hacktoberfest.digitalocean.com/) log in (with you github account) and you are ready to get in.
Next, go dive into the Joplin issues list labelled ["Hacktoberfest"](https://github.com/laurent22/joplin/labels/Hacktoberfest%20%3Ajack_o_lantern%3A)
We hope you will enjoy that event by contributing to the project which is a nice moment of sharing good vibe :jack_o_lantern: :tada:
_PS: the 5 Pull Request don't have to be done __only__ on Joplin project, those can be done on any FOSS projects._
* * *
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.
@@ -34,9 +20,9 @@ Three types of applications are available: for the **desktop** (Windows, macOS a
Operating System | Download | Alternative
-----------------|--------|-------------------
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-Setup-1.0.111.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> | or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-1.0.111.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.111/Joplin-1.0.111-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package<br>[is also available](#terminal-application).
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-Setup-1.0.114.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> | or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-1.0.114.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.114/Joplin-1.0.114-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package<br>[is also available](#terminal-application).
The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
@@ -50,7 +36,7 @@ wget -O - https://raw.githubusercontent.com/laurent22/joplin/master/Joplin_insta
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://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.174/joplin-v1.0.174.apk)
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.175/joplin-v1.0.175.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
@@ -294,6 +280,10 @@ It is generally recommended to enter the notes as Markdown as it makes the notes
This is <s>strikethrough text</s> mixed with regular **Markdown**.
## Custom CSS
Rendered markdown can be customized by placing a userstyle file in the profile directory `~/.config/joplin-desktop/userstyle.css` (This path might be different on your device - check at the top of the Config screen for the exact path). This file supports standard CSS syntax.
# Donations
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.
@@ -329,29 +319,29 @@ Current translations:
<!-- LOCALE-TABLE-AUTO-GENERATED -->
&nbsp; | Language | Po File | Last translator | Percent done
---|---|---|---|---
![](https://joplin.cozic.net/images/flags/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 62%
![](https://joplin.cozic.net/images/flags/es/catalonia.png) | Catalan | [ca](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ca.po) | jmontane, 2018 | 88%
![](https://joplin.cozic.net/images/flags/country-4x3/hr.png) | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić (trbuhom@net.hr) | 50%
![](https://joplin.cozic.net/images/flags/country-4x3/cz.png) | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt (lukas@aiya.cz) | 78%
![](https://joplin.cozic.net/images/flags/country-4x3/dk.png) | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk. | 80%
![](https://joplin.cozic.net/images/flags/country-4x3/de.png) | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Michael Sonntag (ms@editorei.de) | 100%
![](https://joplin.cozic.net/images/flags/es/basque_country.png) | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 61%
![](https://joplin.cozic.net/images/flags/es/catalonia.png) | Catalan | [ca](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ca.po) | jmontane, 2018 | 87%
![](https://joplin.cozic.net/images/flags/country-4x3/hr.png) | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić (trbuhom@net.hr) | 49%
![](https://joplin.cozic.net/images/flags/country-4x3/cz.png) | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt (lukas@aiya.cz) | 77%
![](https://joplin.cozic.net/images/flags/country-4x3/dk.png) | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk. | 78%
![](https://joplin.cozic.net/images/flags/country-4x3/de.png) | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Michael Sonntag (ms@editorei.de) | 98%
![](https://joplin.cozic.net/images/flags/country-4x3/gb.png) | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
![](https://joplin.cozic.net/images/flags/country-4x3/es.png) | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín (f@mrtn.es) | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/es.png) | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín (f@mrtn.es) | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/fr.png) | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
![](https://joplin.cozic.net/images/flags/es/galicia.png) | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans (marcoslansgarza@gmail.com) | 79%
![](https://joplin.cozic.net/images/flags/country-4x3/it.png) | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/nl.png) | Nederlands | [nl_NL](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_NL.po) | Heimen Stoffels (vistausss@outlook.com) | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/be.png) | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 62%
![](https://joplin.cozic.net/images/flags/country-4x3/no.png) | Norwegian | [no](https://github.com/laurent22/joplin/blob/master/CliClient/locales/no.po) | | 84%
![](https://joplin.cozic.net/images/flags/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos (rnbastos@gmail.com) | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/ro.png) | Română | [ro](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ro.po) | | 62%
![](https://joplin.cozic.net/images/flags/country-4x3/si.png) | Slovenian | [sl_SI](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sl_SI.po) | | 78%
![](https://joplin.cozic.net/images/flags/country-4x3/se.png) | Svenska | [sv](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sv.po) | Jonatan Nyberg (jonatan@autistici.org) | 94%
![](https://joplin.cozic.net/images/flags/country-4x3/ru.png) | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov (artyom.karlov@gmail.com) | 78%
![](https://joplin.cozic.net/images/flags/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 94%
![](https://joplin.cozic.net/images/flags/country-4x3/tw.png) | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_TW.po) | penguinsam (samliu@gmail.com) | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/jp.png) | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | AWASHIRO Ikuya (ikunya@gmail.com) | 95%
![](https://joplin.cozic.net/images/flags/country-4x3/kr.png) | 한국말 | [ko](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ko.po) | | 95%
![](https://joplin.cozic.net/images/flags/es/galicia.png) | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans (marcoslansgarza@gmail.com) | 77%
![](https://joplin.cozic.net/images/flags/country-4x3/it.png) | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 92%
![](https://joplin.cozic.net/images/flags/country-4x3/nl.png) | Nederlands | [nl_NL](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_NL.po) | Heimen Stoffels (vistausss@outlook.com) | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/be.png) | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 61%
![](https://joplin.cozic.net/images/flags/country-4x3/no.png) | Norwegian | [no](https://github.com/laurent22/joplin/blob/master/CliClient/locales/no.po) | | 83%
![](https://joplin.cozic.net/images/flags/country-4x3/br.png) | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos (rnbastos@gmail.com) | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/ro.png) | Română | [ro](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ro.po) | | 61%
![](https://joplin.cozic.net/images/flags/country-4x3/si.png) | Slovenian | [sl_SI](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sl_SI.po) | | 76%
![](https://joplin.cozic.net/images/flags/country-4x3/se.png) | Svenska | [sv](https://github.com/laurent22/joplin/blob/master/CliClient/locales/sv.po) | Jonatan Nyberg (jonatan@autistici.org) | 92%
![](https://joplin.cozic.net/images/flags/country-4x3/ru.png) | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov (artyom.karlov@gmail.com) | 76%
![](https://joplin.cozic.net/images/flags/country-4x3/cn.png) | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/tw.png) | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_TW.po) | penguinsam (samliu@gmail.com) | 93%
![](https://joplin.cozic.net/images/flags/country-4x3/jp.png) | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | AWASHIRO Ikuya (ikunya@gmail.com) | 94%
![](https://joplin.cozic.net/images/flags/country-4x3/kr.png) | 한국말 | [ko](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ko.po) | | 93%
<!-- LOCALE-TABLE-AUTO-GENERATED -->
# Known bugs

View File

@@ -90,8 +90,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097410
versionName "1.0.174"
versionCode 2097411
versionName "1.0.175"
ndk {
abiFilters "armeabi-v7a", "x86"
}
@@ -153,6 +153,7 @@ dependencies {
compile project(':react-native-document-picker')
compile project(':react-native-image-resizer')
compile project(':react-native-share-extension')
compile project(':react-native-version-info')
compile "com.facebook.react:react-native:+"
// To fix the error below, which happened after adding react-native-camera.

View File

@@ -22,6 +22,8 @@ import org.pgsqlite.SQLitePluginPackage;
import com.alinz.parkerdan.shareextension.SharePackage;
import cx.evermeet.versioninfo.RNVersionInfoPackage;
import java.util.Arrays;
import java.util.List;
@@ -48,7 +50,8 @@ public class MainApplication extends Application implements ReactApplication {
new RNFSPackage(),
new SQLitePluginPackage(),
new VectorIconsPackage(),
new SharePackage()
new SharePackage(),
new RNVersionInfoPackage()
);
}
};

View File

@@ -31,3 +31,5 @@ project(':react-native-document-picker').projectDir = new File(rootProject.proje
include ':app', ':react-native-share-extension'
project(':react-native-share-extension').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share-extension/android')
include ':react-native-version-info'
project(':react-native-version-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-version-info/android')

View File

@@ -12,6 +12,7 @@
00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
065B3D792187B61200002863 /* libRNVersionInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 065B3D772187B5E300002863 /* libRNVersionInfo.a */; };
0DAD2E67F6A14BDC8250B927 /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 82214D3345D846709A314868 /* libRNDocumentPicker.a */; };
12AE298E1C0E445682922DAB /* libRNCamera.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E132B594F4FB4C96A2E2B0FF /* libRNCamera.a */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
@@ -84,6 +85,13 @@
remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
remoteInfo = RCTVibration;
};
065B3D762187B5E300002863 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 065B3D412187B5E300002863 /* RNVersionInfo.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNVersionInfo;
};
139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
@@ -409,6 +417,7 @@
00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = "<group>"; };
00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = "<group>"; };
02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNDocumentPicker.xcodeproj; path = "../node_modules/react-native-document-picker/ios/RNDocumentPicker.xcodeproj"; sourceTree = "<group>"; };
065B3D412187B5E300002863 /* RNVersionInfo.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RNVersionInfo.xcodeproj; path = "../node_modules/react-native-version-info/ios/RNVersionInfo.xcodeproj"; sourceTree = "<group>"; };
0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = "<group>"; };
139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = "<group>"; };
@@ -463,6 +472,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
065B3D792187B61200002863 /* libRNVersionInfo.a in Frameworks */,
4DDA31241FC88F2400B5A80D /* libRCTPushNotification.a in Frameworks */,
ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */,
5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */,
@@ -544,6 +554,14 @@
name = Frameworks;
sourceTree = "<group>";
};
065B3D422187B5E300002863 /* Products */ = {
isa = PBXGroup;
children = (
065B3D772187B5E300002863 /* libRNVersionInfo.a */,
);
name = Products;
sourceTree = "<group>";
};
139105B71AF99BAD00B5F7CC /* Products */ = {
isa = PBXGroup;
children = (
@@ -748,6 +766,7 @@
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
isa = PBXGroup;
children = (
065B3D412187B5E300002863 /* RNVersionInfo.xcodeproj */,
4DDA31011FC88EEA00B5A80D /* RCTPushNotification.xcodeproj */,
5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */,
146833FF1AC3E56700842450 /* React.xcodeproj */,
@@ -960,6 +979,10 @@
ProductGroup = 4D2A85B71FBCE3AC0028537D /* Products */;
ProjectRef = 711CBD21F0894B83A2D8E234 /* RNVectorIcons.xcodeproj */;
},
{
ProductGroup = 065B3D422187B5E300002863 /* Products */;
ProjectRef = 065B3D412187B5E300002863 /* RNVersionInfo.xcodeproj */;
},
{
ProductGroup = 4D2A85B51FBCE3AC0028537D /* Products */;
ProjectRef = CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */;
@@ -1008,6 +1031,13 @@
remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
065B3D772187B5E300002863 /* libRNVersionInfo.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNVersionInfo.a;
remoteRef = 065B3D762187B5E300002863 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>10.0.24</string>
<string>10.0.26</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>24</string>
<string>26</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@@ -181,7 +181,7 @@ class BaseApplication {
process.exit(code);
}
async refreshNotes(state) {
async refreshNotes(state, useSelectedNoteId = false) {
let parentType = state.notesParentType;
let parentId = null;
@@ -233,10 +233,17 @@ class BaseApplication {
notesSource: source,
});
this.store().dispatch({
type: 'NOTE_SELECT',
id: notes.length ? notes[0].id : null,
});
if (useSelectedNoteId) {
this.store().dispatch({
type: 'NOTE_SELECT',
id: state.selectedNoteIds && state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
});
} else {
this.store().dispatch({
type: 'NOTE_SELECT',
id: notes.length ? notes[0].id : null,
});
}
}
reducerActionToString(action) {
@@ -273,13 +280,16 @@ class BaseApplication {
const result = next(action);
const newState = store.getState();
let refreshNotes = false;
let refreshNotesUseSelectedNoteId = false;
reduxSharedMiddleware(store, next, action);
if (action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) {
if (action.type == 'FOLDER_SELECT' || action.type === 'FOLDER_DELETE' || action.type === 'FOLDER_AND_NOTE_SELECT' || (action.type === 'SEARCH_UPDATE' && newState.notesParentType === 'Folder')) {
Setting.setValue('activeFolderId', newState.selectedFolderId);
this.currentFolder_ = newState.selectedFolderId ? await Folder.load(newState.selectedFolderId) : null;
refreshNotes = true;
if (action.type === 'FOLDER_AND_NOTE_SELECT') refreshNotesUseSelectedNoteId = true;
}
if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key == 'uncompletedTodosOnTop') || action.type == 'SETTING_UPDATE_ALL')) {
@@ -303,7 +313,7 @@ class BaseApplication {
}
if (refreshNotes) {
await this.refreshNotes(newState);
await this.refreshNotes(newState, refreshNotesUseSelectedNoteId);
}
if ((action.type == 'SETTING_UPDATE_ONE' && (action.key == 'dateFormat' || action.key == 'timeFormat')) || (action.type == 'SETTING_UPDATE_ALL')) {
@@ -379,6 +389,7 @@ class BaseApplication {
reg.dispatch = this.store().dispatch;
BaseSyncTarget.dispatch = this.store().dispatch;
DecryptionWorker.instance().dispatch = this.store().dispatch;
ResourceFetcher.instance().dispatch = this.store().dispatch;
}
async readFlagsFromFile(flagPath) {

View File

@@ -92,6 +92,16 @@ class BaseModel {
return this.db().tableFields(this.tableName());
}
static removeUnknownFields(model) {
const newModel = {};
for (let n in model) {
if (!model.hasOwnProperty(n)) continue;
if (!this.hasField(n) && n !== 'type_') continue;
newModel[n] = model[n];
}
return newModel;
}
static new() {
let fields = this.fields();
let output = {};
@@ -472,7 +482,9 @@ class BaseModel {
static batchDelete(ids, options = null) {
if (!ids.length) return;
options = this.modOptions(options);
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id IN ("' + ids.join('","') + '")');
const idFieldName = options.idFieldName ? options.idFieldName : 'id';
const sql = 'DELETE FROM ' + this.tableName() + ' WHERE ' + idFieldName + ' IN ("' + ids.join('","') + '")';
return this.db().exec(sql);
}
static db() {
@@ -498,6 +510,7 @@ BaseModel.typeEnum_ = [
['TYPE_MASTER_KEY', 9],
['TYPE_ITEM_CHANGE', 10],
['TYPE_NOTE_RESOURCE', 11],
['TYPE_RESOURCE_LOCAL_STATE', 12],
];
for (let i = 0; i < BaseModel.typeEnum_.length; i++) {

View File

@@ -94,7 +94,9 @@ class MdToHtml {
return;
}
if (resource.fetch_status !== Resource.FETCH_STATUS_DONE) {
const localState = await Resource.localState(resource);
if (localState.fetch_status !== Resource.FETCH_STATUS_DONE) {
delete this.loadedResources_[id];
console.info('Resource not yet fetched: ' + id);
return;
@@ -393,6 +395,8 @@ class MdToHtml {
previousToken = t;
}
output.unshift('<!-- START_OF_DOCUMENT -->');
// Insert the extra CSS at the top of the HTML
if (!ObjectUtils.isEmpty(extraCssBlocks)) {
@@ -599,8 +603,8 @@ class MdToHtml {
max-width: 100%;
}
.inline-code {
border: 1px solid #CBCBCB;
background-color: #eff0f1;
border: 1px solid ` + style.htmlCodeBorderColor + `;
background-color: ` + style.htmlCodeColor + `;
padding-right: .2em;
padding-left: .2em;
}

View File

@@ -9,9 +9,10 @@ const { themeStyle } = require('lib/components/global-style.js');
const Setting = require('lib/models/Setting.js');
const shared = require('lib/components/shared/config-shared.js');
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
import VersionInfo from 'react-native-version-info';
class ConfigScreenComponent extends BaseScreenComponent {
static navigationOptions(options) {
return { header: null };
}
@@ -229,7 +230,7 @@ class ConfigScreenComponent extends BaseScreenComponent {
</TouchableOpacity>
</View>
);
settingComps.push(
<View key="website_link" style={this.styles().settingContainer}>
<TouchableOpacity onPress={() => { Linking.openURL('https://joplin.cozic.net/') }}>
@@ -246,6 +247,12 @@ class ConfigScreenComponent extends BaseScreenComponent {
</View>
);
settingComps.push(
<View key="version_info" style={this.styles().settingContainer}>
<Text key="version" style={this.styles().settingText}>Version {VersionInfo.appVersion}</Text>
</View>
);
return (
<View style={this.rootStyle(this.props.theme).root}>
<ScreenHeader
@@ -272,4 +279,4 @@ const ConfigScreen = connect(
}
)(ConfigScreenComponent)
module.exports = { ConfigScreen };
module.exports = { ConfigScreen };

View File

@@ -139,7 +139,7 @@ class NoteScreenComponent extends BaseScreenComponent {
});
}, 5);
} else if (item.type_ === BaseModel.TYPE_RESOURCE) {
if (!Resource.isReady(item)) throw new Error(_('This attachment is not downloaded or not decrypted yet.'));
if (!(await Resource.isReady(item))) throw new Error(_('This attachment is not downloaded or not decrypted yet.'));
const resourcePath = Resource.fullPath(item);
await FileViewer.open(resourcePath);
} else {

View File

@@ -225,9 +225,15 @@ class SideMenuContentComponent extends Component {
decryptionReportText = _('Decrypting items: %d/%d', this.props.decryptionWorker.itemIndex + 1, this.props.decryptionWorker.itemCount);
}
let resourceFetcherText = '';
if (this.props.resourceFetcher && this.props.resourceFetcher.toFetchCount) {
resourceFetcherText = _('Fetching resources: %d', this.props.resourceFetcher.toFetchCount);
}
let fullReport = [];
if (syncReportText) fullReport.push(syncReportText);
if (fullReport.length) fullReport.push('');
// if (fullReport.length) fullReport.push('');
if (resourceFetcherText) lines.push(resourceFetcherText);
if (decryptionReportText) fullReport.push(decryptionReportText);
while (fullReport.length < 12) fullReport.push(''); // Add blank lines so that height of report text is fixed and doesn't affect scrolling
@@ -272,6 +278,7 @@ const SideMenuContent = connect(
opacity: state.sideMenuOpenPercent,
collapsedFolderIds: state.collapsedFolderIds,
decryptionWorker: state.decryptionWorker,
resourceFetcher: state.resourceFetcher,
};
}
)(SideMenuContentComponent)

View File

@@ -161,6 +161,16 @@ class JoplinDatabase extends Database {
return output;
}
createDefaultRow(tableName) {
const row = {};
const fields = this.tableFields('resource_local_states');
for (let i = 0; i < fields.length; i++) {
const f = fields[i];
row[f.name] = Database.formatValue(f.type, f.default);
}
return row;
}
fieldDescription(tableName, fieldName) {
const sp = sprintf;
@@ -250,7 +260,7 @@ class JoplinDatabase extends Database {
// default value and thus might cause problems. In that case, the default value
// must be set in the synchronizer too.
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
const existingDatabaseVersions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
let currentVersionIndex = existingDatabaseVersions.indexOf(fromVersion);
@@ -402,6 +412,39 @@ class JoplinDatabase extends Database {
queries.push({ sql: 'UPDATE resources SET fetch_status = ?', params: [Resource.FETCH_STATUS_DONE] });
}
if (targetVersion == 14) {
const resourceLocalStates = `
CREATE TABLE resource_local_states (
id INTEGER PRIMARY KEY,
resource_id TEXT NOT NULL,
fetch_status INT NOT NULL DEFAULT "2",
fetch_error TEXT NOT NULL DEFAULT ""
);
`;
queries.push(this.sqlStringToLines(resourceLocalStates)[0]);
queries.push('INSERT INTO resource_local_states SELECT null, id, fetch_status, fetch_error FROM resources');
queries.push('CREATE INDEX resource_local_states_resource_id ON resource_local_states (resource_id)');
queries.push('CREATE INDEX resource_local_states_resource_fetch_status ON resource_local_states (fetch_status)');
queries = queries.concat(this.alterColumnQueries('resources', {
id: 'TEXT PRIMARY KEY',
title: 'TEXT NOT NULL DEFAULT ""',
mime: 'TEXT NOT NULL',
filename: 'TEXT NOT NULL DEFAULT ""',
created_time: 'INT NOT NULL',
updated_time: 'INT NOT NULL',
user_created_time: 'INT NOT NULL DEFAULT 0',
user_updated_time: 'INT NOT NULL DEFAULT 0',
file_extension: 'TEXT NOT NULL DEFAULT ""',
encryption_cipher_text: 'TEXT NOT NULL DEFAULT ""',
encryption_applied: 'INT NOT NULL DEFAULT 0',
encryption_blob_encrypted: 'INT NOT NULL DEFAULT 0',
}));
}
queries.push({ sql: 'UPDATE version SET version = ?', params: [targetVersion] });
await this.transactionExecBatch(queries);

View File

@@ -75,9 +75,14 @@ class BaseItem extends BaseModel {
return r.total;
}
static systemPath(itemOrId) {
if (typeof itemOrId === 'string') return itemOrId + '.md';
return itemOrId.id + '.md';
static systemPath(itemOrId, extension = null) {
if (extension === null)
extension = 'md';
if (typeof itemOrId === 'string')
return itemOrId + '.' + extension;
else
return itemOrId.id + '.' + extension;
}
static isSystemPath(path) {
@@ -224,7 +229,7 @@ class BaseItem extends BaseModel {
static unserialize_format(type, propName, propValue) {
if (propName[propName.length - 1] == '_') return propValue; // Private property
let ItemClass = this.itemClass(type);
const ItemClass = this.itemClass(type);
if (['created_time', 'updated_time', 'user_created_time', 'user_updated_time'].indexOf(propName) >= 0) {
if (!propValue) return 0;
@@ -291,13 +296,13 @@ class BaseItem extends BaseModel {
let shownKeys = ItemClass.fieldNames();
shownKeys.push('type_');
if (ItemClass.syncExcludedKeys) {
const keys = ItemClass.syncExcludedKeys();
for (let i = 0; i < keys.length; i++) {
const idx = shownKeys.indexOf(keys[i]);
shownKeys.splice(idx, 1);
}
}
// if (ItemClass.syncExcludedKeys) {
// const keys = ItemClass.syncExcludedKeys();
// for (let i = 0; i < keys.length; i++) {
// const idx = shownKeys.indexOf(keys[i]);
// shownKeys.splice(idx, 1);
// }
// }
const serialized = await ItemClass.serialize(item, shownKeys);
@@ -378,6 +383,9 @@ class BaseItem extends BaseModel {
if (output.type_ === BaseModel.TYPE_NOTE) output.body = body.join("\n");
const ItemClass = this.itemClass(output.type_);
output = ItemClass.removeUnknownFields(output);
for (let n in output) {
if (!output.hasOwnProperty(n)) continue;
output[n] = await this.unserialize_format(output.type_, n, output[n]);

View File

@@ -1,6 +1,7 @@
const BaseModel = require('lib/BaseModel.js');
const BaseItem = require('lib/models/BaseItem.js');
const NoteResource = require('lib/models/NoteResource.js');
const ResourceLocalState = require('lib/models/ResourceLocalState.js');
const Setting = require('lib/models/Setting.js');
const ArrayUtils = require('lib/ArrayUtils.js');
const pathUtils = require('lib/path-utils.js');
@@ -30,25 +31,15 @@ class Resource extends BaseItem {
return imageMimeTypes.indexOf(type.toLowerCase()) >= 0;
}
static resetStartedFetchStatus() {
return this.db().exec('UPDATE resources SET fetch_status = ? WHERE fetch_status = ?', [Resource.FETCH_STATUS_IDLE, Resource.FETCH_STATUS_STARTED]);
}
static needToBeFetched(limit = null) {
let sql = 'SELECT * FROM resources WHERE fetch_status = ? ORDER BY updated_time DESC';
let sql = 'SELECT * FROM resources WHERE id IN (SELECT resource_id FROM resource_local_states WHERE fetch_status = ?) ORDER BY updated_time DESC';
if (limit !== null) sql += ' LIMIT ' + limit;
return this.modelSelectAll(sql, [Resource.FETCH_STATUS_IDLE]);
}
static async saveFetchStatus(resourceId, status, error = null) {
const o = {
id: resourceId,
fetch_status: status,
}
if (error !== null) o.fetch_error = error;
return Resource.save(o, { autoTimestamp: false });
static async needToBeFetchedCount() {
const r = await this.db().selectOne('SELECT count(*) as total FROM resource_local_states WHERE fetch_status = ?', [Resource.FETCH_STATUS_IDLE]);
return r ? r['total'] : 0;
}
static fsDriver() {
@@ -63,10 +54,6 @@ class Resource extends BaseItem {
return resource.id + extension;
}
static syncExcludedKeys() {
return ['fetch_status', 'fetch_error'];
}
static friendlyFilename(resource) {
let output = safeFilename(resource.title); // Make sure not to allow spaces or any special characters as it's not supported in HTTP headers
if (!output) output = resource.id;
@@ -80,8 +67,9 @@ class Resource extends BaseItem {
return Setting.value('resourceDir') + '/' + this.filename(resource, encryptedBlob);
}
static isReady(resource) {
return resource && resource.fetch_status === Resource.FETCH_STATUS_DONE && !resource.encryption_blob_encrypted;
static async isReady(resource) {
const ls = await this.localState(resource);
return resource && ls.fetch_status === Resource.FETCH_STATUS_DONE && !resource.encryption_blob_encrypted;
}
// For resources, we need to decrypt the item (metadata) and the resource binary blob.
@@ -201,6 +189,15 @@ class Resource extends BaseItem {
return url.substr(2);
}
static localState(resourceOrId) {
return ResourceLocalState.byResourceId(typeof resourceOrId === 'object' ? resourceOrId.id : resourceOrId);
}
static async setLocalState(resourceOrId, state) {
const id = typeof resourceOrId === 'object' ? resourceOrId.id : resourceOrId;
await ResourceLocalState.save(Object.assign({}, state, { resource_id: id }));
}
static async batchDelete(ids, options = null) {
// For resources, there's not really batch deleting since there's the file data to delete
// too, so each is processed one by one with the item being deleted last (since the db
@@ -215,6 +212,8 @@ class Resource extends BaseItem {
await super.batchDelete([id], options);
await NoteResource.deleteByResource(id); // Clean up note/resource relationships
}
await ResourceLocalState.batchDelete(ids);
}
}

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