You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-09-02 20:46:21 +02:00
Compare commits
25 Commits
android-v1
...
cli-v1.0.1
Author | SHA1 | Date | |
---|---|---|---|
|
65065a62d8 | ||
|
482e9340bc | ||
|
69d490996e | ||
|
3494937e34 | ||
|
41ba1043be | ||
|
cc57de60c0 | ||
|
60a2b9e5c6 | ||
|
8e1fb666a5 | ||
|
f4ad777bbf | ||
|
2eacf6146a | ||
|
fe2ba34cb4 | ||
|
84daa0db61 | ||
|
b9118a90be | ||
|
ef2ffd4e52 | ||
|
5e3063abe0 | ||
|
f460b2497a | ||
|
c080d7054f | ||
|
61dd4cefbc | ||
|
63d99b2d70 | ||
|
55332d7671 | ||
|
16635defcd | ||
|
595cf3fcad | ||
|
c9b9f82130 | ||
|
f5bca733d7 | ||
|
494e235e18 |
@@ -1099,6 +1099,10 @@ msgstr "Tmavý"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Nedokončené to-do listy nahoře"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Nedokončené to-do listy nahoře"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Řadit poznámky podle"
|
||||
|
||||
|
@@ -1108,6 +1108,10 @@ msgstr "Mørkt"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Ufærdige opgaver øverst"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Ufærdige opgaver øverst"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Sorter noter efter"
|
||||
|
||||
|
@@ -1141,6 +1141,10 @@ msgstr "Dunkel"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Zeige unvollständige To-Dos an oberster Stelle"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Zeige unvollständige To-Dos an oberster Stelle"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Sortiere Notizen nach"
|
||||
|
||||
|
@@ -1013,6 +1013,9 @@ msgstr ""
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show completed to-dos"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -368,13 +368,12 @@ msgstr "Elimina la libreta dada."
|
||||
msgid "Deletes the notebook without asking for confirmation."
|
||||
msgstr "Elimina una libreta sin pedir confirmación."
|
||||
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Delete notebook? All notes and sub-notebooks within this notebook will also "
|
||||
"be deleted."
|
||||
msgstr ""
|
||||
"¿Desea eliminar la libreta? Todas las notas dentro de esta libreta también "
|
||||
"serán eliminadas."
|
||||
"¿Desea eliminar la libreta? Todas las notas y sublibretas dentro de esta "
|
||||
"libreta también serán eliminadas."
|
||||
|
||||
msgid "Deletes the notes matching <note-pattern>."
|
||||
msgstr "Elimina las notas que coinciden con <note-pattern>."
|
||||
@@ -1061,9 +1060,8 @@ msgstr "Los elementos cifrados no pueden ser modificados"
|
||||
msgid "Conflicts"
|
||||
msgstr "Conflictos"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Cannot move notebook to this location"
|
||||
msgstr "No se ha podido mover la nota a la libreta «%s»"
|
||||
msgstr "No se puede mover la libreta a este lugar"
|
||||
|
||||
#, javascript-format
|
||||
msgid "A notebook with this title already exists: \"%s\""
|
||||
@@ -1119,6 +1117,10 @@ msgstr "Oscuro"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Mostrar tareas incompletas al inicio de las listas"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Mostrar tareas incompletas al inicio de las listas"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Ordenar notas por"
|
||||
|
||||
|
@@ -1125,6 +1125,10 @@ msgstr "Iluna"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Bete gabeko zereginak erakutsi zerrendaren goiko partean"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Bete gabeko zereginak erakutsi zerrendaren goiko partean"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -14,8 +14,6 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.0.3\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
msgid "To delete a tag, untag the associated notes."
|
||||
msgstr "Pour supprimer une vignette, enlever là des notes associées."
|
||||
@@ -1126,6 +1124,9 @@ msgstr "Sombre"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Tâches non-terminées en haut"
|
||||
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Afficher les tâches complétées"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Trier les notes par"
|
||||
|
||||
|
@@ -1107,6 +1107,10 @@ msgstr "Escuro"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Tarefas sen completar arriba"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Tarefas sen completar arriba"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Ordenar notas por"
|
||||
|
||||
|
@@ -1108,6 +1108,10 @@ msgstr "Tamna"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Prikaži nezavršene zadatke na vrhu liste"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Prikaži nezavršene zadatke na vrhu liste"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -1097,6 +1097,10 @@ msgstr "Scuro"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Mostra todo inclompleti in cima alla lista"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Mostra todo inclompleti in cima alla lista"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -1102,6 +1102,10 @@ msgstr "暗い"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "未完のToDoをリストの上部に表示"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "未完のToDoをリストの上部に表示"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -1013,6 +1013,9 @@ msgstr ""
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr ""
|
||||
|
||||
msgid "Show completed to-dos"
|
||||
msgstr ""
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -1129,6 +1129,10 @@ msgstr "Donker"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Toon onvoltooide to-do's aan de top van de lijsten"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Toon onvoltooide to-do's aan de top van de lijsten"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr ""
|
||||
|
||||
|
@@ -1120,6 +1120,10 @@ msgstr "Dark"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Mostrar tarefas incompletas no topo"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Mostrar tarefas incompletas no topo"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Ordenar notas por"
|
||||
|
||||
|
@@ -1117,6 +1117,10 @@ msgstr "Тёмная"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "Незавершённые задачи сверху"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "Незавершённые задачи сверху"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "Сортировать заметки по"
|
||||
|
||||
|
@@ -1069,6 +1069,10 @@ msgstr "深色"
|
||||
msgid "Uncompleted to-dos on top"
|
||||
msgstr "未完成的待办事项在顶端"
|
||||
|
||||
#, fuzzy
|
||||
msgid "Show completed to-dos"
|
||||
msgstr "未完成的待办事项在顶端"
|
||||
|
||||
msgid "Sort notes by"
|
||||
msgstr "排序笔记"
|
||||
|
||||
|
2
CliClient/package-lock.json
generated
2
CliClient/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "joplin",
|
||||
"version": "1.0.106",
|
||||
"version": "1.0.107",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@@ -19,7 +19,7 @@
|
||||
],
|
||||
"owner": "Laurent Cozic"
|
||||
},
|
||||
"version": "1.0.106",
|
||||
"version": "1.0.107",
|
||||
"bin": {
|
||||
"joplin": "./main.js"
|
||||
},
|
||||
|
@@ -44,4 +44,13 @@ describe('ArrayUtils', function() {
|
||||
done();
|
||||
});
|
||||
|
||||
it('should compare arrays', async (done) => {
|
||||
expect(ArrayUtils.contentEquals([], [])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['a'], ['a'])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['b', 'a'], ['a', 'b'])).toBe(true);
|
||||
expect(ArrayUtils.contentEquals(['b'], ['a', 'b'])).toBe(false);
|
||||
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
@@ -164,7 +164,7 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
if (["NOTE_UPDATE_ONE", "NOTE_DELETE", "FOLDER_UPDATE_ONE", "FOLDER_DELETE"].indexOf(action.type) >= 0) {
|
||||
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(30, { syncSteps: ["update_remote", "delete_remote"] });
|
||||
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(30 * 1000, { syncSteps: ["update_remote", "delete_remote"] });
|
||||
}
|
||||
|
||||
if (['EVENT_NOTE_ALARM_FIELD_CHANGE', 'NOTE_DELETE'].indexOf(action.type) >= 0) {
|
||||
@@ -437,6 +437,14 @@ class Application extends BaseApplication {
|
||||
click: () => {
|
||||
Setting.setValue('uncompletedTodosOnTop', !Setting.value('uncompletedTodosOnTop'));
|
||||
},
|
||||
}, {
|
||||
label: Setting.settingMetadata('showCompletedTodos').label(),
|
||||
type: 'checkbox',
|
||||
checked: Setting.value('showCompletedTodos'),
|
||||
screens: ['Main'],
|
||||
click: () => {
|
||||
Setting.setValue('showCompletedTodos', !Setting.value('showCompletedTodos'));
|
||||
},
|
||||
}],
|
||||
}, {
|
||||
label: _('Tools'),
|
||||
|
@@ -20,6 +20,10 @@ const MenuItem = bridge().MenuItem;
|
||||
const { shim } = require('lib/shim.js');
|
||||
const eventManager = require('../eventManager');
|
||||
const fs = require('fs-extra');
|
||||
const {clipboard} = require('electron')
|
||||
const md5 = require('md5');
|
||||
const mimeUtils = require('lib/mime-utils.js').mime;
|
||||
const ArrayUtils = require('lib/ArrayUtils');
|
||||
|
||||
require('brace/mode/markdown');
|
||||
// https://ace.c9.io/build/kitchen-sink.html
|
||||
@@ -47,6 +51,7 @@ class NoteTextComponent extends React.Component {
|
||||
// changed by the user, this variable contains that note ID. Used
|
||||
// to automatically set the title.
|
||||
newAndNoTitleChangeNoteId: null,
|
||||
bodyHtml: '',
|
||||
};
|
||||
|
||||
this.lastLoadedNoteId_ = null;
|
||||
@@ -55,6 +60,8 @@ class NoteTextComponent extends React.Component {
|
||||
this.ignoreNextEditorScroll_ = false;
|
||||
this.scheduleSaveTimeout_ = null;
|
||||
this.restoreScrollTop_ = null;
|
||||
this.lastSetHtml_ = '';
|
||||
this.lastSetMarkers_ = [];
|
||||
|
||||
// Complicated but reliable method to get editor content height
|
||||
// https://github.com/ajaxorg/ace/issues/2046
|
||||
@@ -72,6 +79,62 @@ class NoteTextComponent extends React.Component {
|
||||
this.onAlarmChange_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
this.onNoteTypeToggle_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
this.onTodoToggle_ = (event) => { if (event.noteId === this.props.noteId) this.reloadNote(this.props); }
|
||||
|
||||
this.onEditorPaste_ = async (event) => {
|
||||
const formats = clipboard.availableFormats();
|
||||
for (let i = 0; i < formats.length; i++) {
|
||||
const format = formats[i].toLowerCase();
|
||||
const formatType = format.split('/')[0]
|
||||
if (formatType === 'image') {
|
||||
event.preventDefault();
|
||||
|
||||
const image = clipboard.readImage();
|
||||
|
||||
const fileExt = mimeUtils.toFileExtension(format);
|
||||
const filePath = Setting.value('tempDir') + '/' + md5(Date.now()) + '.' + fileExt;
|
||||
|
||||
await shim.writeImageToFile(image, format, filePath);
|
||||
await this.commandAttachFile([filePath]);
|
||||
await shim.fsDriver().remove(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.onDrop_ = async (event) => {
|
||||
const files = event.dataTransfer.files;
|
||||
if (!files || !files.length) return;
|
||||
|
||||
const filesToAttach = [];
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files[i];
|
||||
if (!file.path) continue;
|
||||
filesToAttach.push(file.path);
|
||||
}
|
||||
|
||||
await this.commandAttachFile(filesToAttach);
|
||||
}
|
||||
}
|
||||
|
||||
cursorPosition() {
|
||||
if (!this.editor_ || !this.editor_.editor || !this.state.note || !this.state.note.body) return 0;
|
||||
|
||||
const cursorPos = this.editor_.editor.getCursorPosition();
|
||||
const noteLines = this.state.note.body.split('\n');
|
||||
|
||||
let pos = 0;
|
||||
for (let i = 0; i < noteLines.length; i++) {
|
||||
if (i > 0) pos++; // Need to add the newline that's been removed in the split() call above
|
||||
|
||||
if (i === cursorPos.row) {
|
||||
pos += cursorPos.column;
|
||||
break;
|
||||
} else {
|
||||
pos += noteLines[i].length;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
mdToHtml() {
|
||||
@@ -243,7 +306,12 @@ class NoteTextComponent extends React.Component {
|
||||
newState.newAndNoTitleChangeNoteId = null;
|
||||
}
|
||||
|
||||
this.lastSetHtml_ = '';
|
||||
this.lastSetMarkers_ = [];
|
||||
|
||||
this.setState(newState);
|
||||
|
||||
this.updateHtml(newState.note ? newState.note.body : '');
|
||||
}
|
||||
|
||||
async componentWillReceiveProps(nextProps) {
|
||||
@@ -421,6 +489,7 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
if (this.editor_) {
|
||||
this.editor_.editor.renderer.off('afterRender', this.onAfterEditorRender_);
|
||||
document.querySelector('#note-editor').removeEventListener('paste', this.onEditorPaste_, true);
|
||||
}
|
||||
|
||||
this.editor_ = element;
|
||||
@@ -428,7 +497,14 @@ class NoteTextComponent extends React.Component {
|
||||
if (this.editor_) {
|
||||
this.editor_.editor.renderer.on('afterRender', this.onAfterEditorRender_);
|
||||
|
||||
const cancelledKeys = ['Ctrl+F', 'Ctrl+T', 'Ctrl+P', 'Ctrl+Q', 'Ctrl+L', 'Ctrl+,'];
|
||||
const cancelledKeys = [];
|
||||
const letters = ['F', 'T', 'P', 'Q', 'L', ','];
|
||||
for (let i = 0; i < letters.length; i++) {
|
||||
const l = letters[i];
|
||||
cancelledKeys.push('Ctrl+' + l);
|
||||
cancelledKeys.push('Command+' + l);
|
||||
}
|
||||
|
||||
for (let i = 0; i < cancelledKeys.length; i++) {
|
||||
const k = cancelledKeys[i];
|
||||
this.editor_.editor.commands.bindKey(k, () => {
|
||||
@@ -439,6 +515,8 @@ class NoteTextComponent extends React.Component {
|
||||
throw new Error('HACK: Overriding Ace Editor shortcut: ' + k);
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector('#note-editor').addEventListener('paste', this.onEditorPaste_, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,9 +551,52 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
aceEditor_change(body) {
|
||||
shared.noteComponent_change(this, 'body', body);
|
||||
this.scheduleHtmlUpdate();
|
||||
this.scheduleSave();
|
||||
}
|
||||
|
||||
scheduleHtmlUpdate(timeout = 500) {
|
||||
if (this.scheduleHtmlUpdateIID_) {
|
||||
clearTimeout(this.scheduleHtmlUpdateIID_);
|
||||
this.scheduleHtmlUpdateIID_ = null;
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
this.scheduleHtmlUpdateIID_ = setTimeout(() => {
|
||||
this.updateHtml();
|
||||
}, timeout);
|
||||
} else {
|
||||
this.updateHtml();
|
||||
}
|
||||
}
|
||||
|
||||
updateHtml(body = null) {
|
||||
const mdOptions = {
|
||||
onResourceLoaded: () => {
|
||||
this.updateHtml();
|
||||
this.forceUpdate();
|
||||
},
|
||||
postMessageSyntax: 'ipcRenderer.sendToHost',
|
||||
};
|
||||
|
||||
const theme = themeStyle(this.props.theme);
|
||||
|
||||
let bodyToRender = body;
|
||||
if (bodyToRender === null) bodyToRender = this.state.note && this.state.note.body ? this.state.note.body : '';
|
||||
let bodyHtml = '';
|
||||
|
||||
const visiblePanes = this.props.visiblePanes || ['editor', 'viewer'];
|
||||
|
||||
if (!bodyToRender.trim() && visiblePanes.indexOf('viewer') >= 0 && visiblePanes.indexOf('editor') < 0) {
|
||||
// Fixes https://github.com/laurent22/joplin/issues/217
|
||||
bodyToRender = '*' + _('This note has no content. Click on "%s" to toggle the editor and edit the note.', _('Layout')) + '*';
|
||||
}
|
||||
|
||||
bodyHtml = this.mdToHtml().render(bodyToRender, theme, mdOptions);
|
||||
|
||||
this.setState({ bodyHtml: bodyHtml });
|
||||
}
|
||||
|
||||
async doCommand(command) {
|
||||
if (!command) return;
|
||||
|
||||
@@ -509,25 +630,31 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
async commandAttachFile() {
|
||||
const filePaths = bridge().showOpenDialog({
|
||||
properties: ['openFile', 'createDirectory', 'multiSelections'],
|
||||
});
|
||||
if (!filePaths || !filePaths.length) return;
|
||||
async commandAttachFile(filePaths = null) {
|
||||
if (!filePaths) {
|
||||
filePaths = bridge().showOpenDialog({
|
||||
properties: ['openFile', 'createDirectory', 'multiSelections'],
|
||||
});
|
||||
if (!filePaths || !filePaths.length) return;
|
||||
}
|
||||
|
||||
await this.saveIfNeeded(true);
|
||||
let note = await Note.load(this.state.note.id);
|
||||
|
||||
const position = this.cursorPosition();
|
||||
|
||||
for (let i = 0; i < filePaths.length; i++) {
|
||||
const filePath = filePaths[i];
|
||||
try {
|
||||
reg.logger().info('Attaching ' + filePath);
|
||||
note = await shim.attachFileToNote(note, filePath);
|
||||
note = await shim.attachFileToNote(note, filePath, position);
|
||||
reg.logger().info('File was attached.');
|
||||
this.setState({
|
||||
note: Object.assign({}, note),
|
||||
lastSavedNote: Object.assign({}, note),
|
||||
});
|
||||
|
||||
this.updateHtml(note.body);
|
||||
} catch (error) {
|
||||
reg.logger().error(error);
|
||||
bridge().showErrorMessageBox(error.message);
|
||||
@@ -675,25 +802,21 @@ class NoteTextComponent extends React.Component {
|
||||
}
|
||||
|
||||
if (this.state.webviewReady) {
|
||||
const mdOptions = {
|
||||
onResourceLoaded: () => {
|
||||
this.forceUpdate();
|
||||
},
|
||||
postMessageSyntax: 'ipcRenderer.sendToHost',
|
||||
};
|
||||
let html = this.state.bodyHtml;
|
||||
|
||||
let bodyToRender = body;
|
||||
if (!bodyToRender.trim() && visiblePanes.indexOf('viewer') >= 0 && visiblePanes.indexOf('editor') < 0) {
|
||||
// Fixes https://github.com/laurent22/joplin/issues/217
|
||||
bodyToRender = '*' + _('This note has no content. Click on "%s" to toggle the editor and edit the note.', _('Layout')) + '*';
|
||||
const htmlHasChanged = this.lastSetHtml_ !== html;
|
||||
if (htmlHasChanged) {
|
||||
this.webview_.send('setHtml', html);
|
||||
this.lastSetHtml_ = html;
|
||||
}
|
||||
|
||||
const html = this.mdToHtml().render(bodyToRender, theme, mdOptions);
|
||||
this.webview_.send('setHtml', html);
|
||||
|
||||
const search = BaseModel.byId(this.props.searches, this.props.selectedSearchId);
|
||||
const keywords = search ? Search.keywords(search.query_pattern) : [];
|
||||
this.webview_.send('setMarkers', keywords);
|
||||
|
||||
if (htmlHasChanged || !ArrayUtils.contentEquals(this.lastSetMarkers_, keywords)) {
|
||||
this.lastSetMarkers_ = [];
|
||||
this.webview_.send('setMarkers', keywords);
|
||||
}
|
||||
}
|
||||
|
||||
const toolbarItems = [];
|
||||
@@ -739,7 +862,7 @@ class NoteTextComponent extends React.Component {
|
||||
|
||||
const titleBarDate = <span style={Object.assign({}, theme.textStyle, {color: theme.colorFaded})}>{time.formatMsToLocal(note.user_updated_time)}</span>
|
||||
|
||||
const viewer = <webview
|
||||
const viewer = <webview
|
||||
style={viewerStyle}
|
||||
nodeintegration="1"
|
||||
src="gui/note-viewer/index.html"
|
||||
@@ -794,7 +917,7 @@ class NoteTextComponent extends React.Component {
|
||||
/>
|
||||
|
||||
return (
|
||||
<div style={rootStyle}>
|
||||
<div style={rootStyle} onDrop={this.onDrop_}>
|
||||
<div style={titleBarStyle}>
|
||||
{ titleEditor }
|
||||
{ titleBarDate }
|
||||
|
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
2357
ElectronClient/app/package-lock.json
generated
2357
ElectronClient/app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.0.89",
|
||||
"version": "1.0.91",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -92,6 +92,7 @@
|
||||
"markdown-it": "^8.4.0",
|
||||
"markdown-it-katex": "^2.0.3",
|
||||
"md5": "^2.2.1",
|
||||
"mermaid": "^8.0.0-rc.8",
|
||||
"mime": "^2.0.3",
|
||||
"moment": "^2.19.1",
|
||||
"node-fetch": "^1.7.3",
|
||||
|
39
README.md
39
README.md
@@ -20,15 +20,15 @@ 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.89/Joplin-1.0.89.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> |
|
||||
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.89/Joplin-1.0.89.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.89/Joplin-1.0.89-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package [is also available](#terminal-application).
|
||||
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.91/Joplin-1.0.91.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> |
|
||||
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.91/Joplin-1.0.91.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.91/Joplin-1.0.91-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package [is also available](#terminal-application).
|
||||
|
||||
## Mobile applications
|
||||
|
||||
Operating System | Download | Alt. Download
|
||||
-----------------|----------|----------------
|
||||
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.123/joplin-v1.0.123.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.125/joplin-v1.0.125.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
|
||||
@@ -183,7 +183,9 @@ For a more technical description, mostly relevant for development or to review t
|
||||
|
||||
Any kind of file can be attached to a note. In Markdown, links to these files are represented as a simple ID to the resource. In the note viewer, these files, if they are images, will be displayed or, if they are other files (PDF, text files, etc.) they will be displayed as links. Clicking on this link will open the file in the default application.
|
||||
|
||||
Resources that are not attached to any note will be automatically deleted after a day or two.
|
||||
On the **desktop application**, images can be attached either by clicking on "Attach file" or by pasting (with Ctrl+V) an image directly in the editor, or by drag and dropping an image.
|
||||
|
||||
Resources that are not attached to any note will be automatically deleted after a day or two (see [rationale](https://github.com/laurent22/joplin/issues/154#issuecomment-356582366)).
|
||||
|
||||
**Important:** Resources larger than 10 MB are not currently supported on mobile. They will crash the application when synchronising so it is recommended not to attach such resources at the moment. The issue is being looked at.
|
||||
|
||||
@@ -253,6 +255,10 @@ Checkboxes can be added like so:
|
||||
|
||||
The checkboxes can then be ticked in the mobile and desktop applications.
|
||||
|
||||
## HTML support
|
||||
|
||||
Only the `<br>` tag is supported - it can be used to force a new line, which is convenient to insert new lines inside table cells. For security reasons, other HTML tags are not supported.
|
||||
|
||||
# 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.
|
||||
@@ -262,6 +268,7 @@ Please see the [donation page](https://joplin.cozic.net/donate/) for information
|
||||
# Community
|
||||
|
||||
- For general discussion about Joplin, user support, software development questions, and to discuss new features, go to the [Joplin Forum](https://discourse.joplin.cozic.net/). It is possible to login with your GitHub account.
|
||||
- Also see here for information about [the latest releases and general news](https://discourse.joplin.cozic.net/c/news).
|
||||
- For bug reports and feature requests, go to the [GitHub Issue Tracker](https://github.com/laurent22/joplin/issues).
|
||||
- The latest news are often posted [on this Twitter account](https://twitter.com/laurent2233).
|
||||
|
||||
@@ -288,19 +295,19 @@ Current translations:
|
||||
| Language | Po File | Last translator | Percent done
|
||||
---|---|---|---|---
|
||||
 | Basque | [eu](https://github.com/laurent22/joplin/blob/master/CliClient/locales/eu.po) | juan.abasolo@ehu.eus | 75%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić <trbuhom@net.hr> | 61%
|
||||
 | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt <lukas@aiya.cz> | 95%
|
||||
 | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér <mjjzf@syntaktisk. | 97%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Philipp Zumstein <zuphilip@gmail.com> | 98%
|
||||
 | Croatian | [hr_HR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po) | Hrvoje Mandić (trbuhom@net.hr) | 61%
|
||||
 | Czech | [cs_CZ](https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po) | Lukas Helebrandt (lukas@aiya.cz) | 95%
|
||||
 | Dansk | [da_DK](https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po) | Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk. | 97%
|
||||
 | Deutsch | [de_DE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po) | Philipp Zumstein (zuphilip@gmail.com) | 98%
|
||||
 | English | [en_GB](https://github.com/laurent22/joplin/blob/master/CliClient/locales/en_GB.po) | | 100%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín <f@mrtn.es> | 99%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 98%
|
||||
 | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans <marcoslansgarza@gmail.com> | 95%
|
||||
 | Español | [es_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po) | Fernando Martín (f@mrtn.es) | 99%
|
||||
 | Français | [fr_FR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
 | Galician | [gl_ES](https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po) | Marcos Lans (marcoslansgarza@gmail.com) | 95%
|
||||
 | Italiano | [it_IT](https://github.com/laurent22/joplin/blob/master/CliClient/locales/it_IT.po) | | 63%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 76%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos <rnbastos@gmail.com> | 97%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov <artyom.karlov@gmail.com> | 94%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 91%
|
||||
 | Nederlands | [nl_BE](https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po) | | 75%
|
||||
 | Português (Brasil) | [pt_BR](https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po) | Renato Nunes Bastos (rnbastos@gmail.com) | 97%
|
||||
 | Русский | [ru_RU](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po) | Artyom Karlov (artyom.karlov@gmail.com) | 94%
|
||||
 | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po) | | 90%
|
||||
 | 日本語 | [ja_JP](https://github.com/laurent22/joplin/blob/master/CliClient/locales/ja_JP.po) | | 61%
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
|
||||
|
@@ -90,8 +90,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 26
|
||||
versionCode 2097301
|
||||
versionName "1.0.123"
|
||||
versionCode 2097303
|
||||
versionName "1.0.125"
|
||||
ndk {
|
||||
abiFilters "armeabi-v7a", "x86"
|
||||
}
|
||||
|
@@ -38,15 +38,6 @@
|
||||
<!-- ==================================== -->
|
||||
<!-- START react-native-push-notification -->
|
||||
<!-- ==================================== -->
|
||||
<receiver
|
||||
android:name="com.google.android.gms.gcm.GcmReceiver"
|
||||
android:exported="true"
|
||||
android:permission="com.google.android.c2dm.permission.SEND" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
|
||||
<category android:name="${applicationId}" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
|
||||
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
|
||||
@@ -55,13 +46,6 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
<service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>
|
||||
<service
|
||||
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerService"
|
||||
android:exported="false" >
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
<!-- ================================== -->
|
||||
<!-- END react-native-push-notification -->
|
||||
<!-- ================================== -->
|
||||
|
@@ -45,4 +45,17 @@ ArrayUtils.findByKey = function(array, key, value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayUtils.contentEquals = function(array1, array2) {
|
||||
if (array1 === array2) return true;
|
||||
if (!array1.length && !array2.length) return true;
|
||||
if (array1.length !== array2.length) return false;
|
||||
|
||||
for (let i = 0; i < array1.length; i++) {
|
||||
const a1 = array1[i];
|
||||
if (array2.indexOf(a1) < 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
module.exports = ArrayUtils;
|
@@ -199,6 +199,7 @@ class BaseApplication {
|
||||
let options = {
|
||||
order: stateUtils.notesOrder(state.settings),
|
||||
uncompletedTodosOnTop: Setting.value('uncompletedTodosOnTop'),
|
||||
showCompletedTodos: Setting.value('showCompletedTodos'),
|
||||
caseInsensitive: true,
|
||||
};
|
||||
|
||||
@@ -283,6 +284,10 @@ class BaseApplication {
|
||||
refreshNotes = true;
|
||||
}
|
||||
|
||||
if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key == 'showCompletedTodos') || action.type == 'SETTING_UPDATE_ALL')) {
|
||||
refreshNotes = true;
|
||||
}
|
||||
|
||||
if (this.hasGui() && ((action.type == 'SETTING_UPDATE_ONE' && action.key.indexOf('notes.sortOrder') === 0) || action.type == 'SETTING_UPDATE_ALL')) {
|
||||
refreshNotes = true;
|
||||
}
|
||||
|
@@ -157,9 +157,12 @@ class MdToHtml {
|
||||
rendererPlugin_(language) {
|
||||
if (!language) return null;
|
||||
|
||||
const handlers = {};
|
||||
handlers['katex'] = new MdToHtml_Katex();
|
||||
return language in handlers ? handlers[language] : null;
|
||||
if (!this.rendererPlugins_) {
|
||||
this.rendererPlugins_ = {};
|
||||
this.rendererPlugins_['katex'] = new MdToHtml_Katex();
|
||||
}
|
||||
|
||||
return language in this.rendererPlugins_ ? this.rendererPlugins_[language] : null;
|
||||
}
|
||||
|
||||
parseInlineCodeLanguage_(content) {
|
||||
@@ -389,7 +392,7 @@ class MdToHtml {
|
||||
const md = new MarkdownIt({
|
||||
breaks: true,
|
||||
linkify: true,
|
||||
html: true,
|
||||
html: false, // For security, HTML tags are not supported - https://github.com/laurent22/joplin/issues/500
|
||||
});
|
||||
|
||||
// This is currently used only so that the $expression$ and $$\nexpression\n$$ blocks are translated
|
||||
@@ -435,6 +438,9 @@ class MdToHtml {
|
||||
}
|
||||
}
|
||||
|
||||
// Support <br> tag to allow newlines inside table cells
|
||||
renderedBody = renderedBody.replace(/<br>/gi, '<br>');
|
||||
|
||||
// https://necolas.github.io/normalize.css/
|
||||
const normalizeCss = `
|
||||
html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
|
||||
|
@@ -5,15 +5,28 @@ const Setting = require('lib/models/Setting');
|
||||
|
||||
class MdToHtml_Katex {
|
||||
|
||||
constructor() {
|
||||
this.cache_ = {};
|
||||
this.assetsLoaded_ = false;
|
||||
}
|
||||
|
||||
name() {
|
||||
return 'katex';
|
||||
}
|
||||
|
||||
processContent(renderedTokens, content, tagType) {
|
||||
try {
|
||||
let renderered = katex.renderToString(content, {
|
||||
displayMode: tagType === 'block',
|
||||
});
|
||||
const cacheKey = tagType + '_' + content;
|
||||
let renderered = null;
|
||||
|
||||
if (this.cache_[cacheKey]) {
|
||||
renderered = this.cache_[cacheKey];
|
||||
} else {
|
||||
renderered = katex.renderToString(content, {
|
||||
displayMode: tagType === 'block',
|
||||
});
|
||||
this.cache_[cacheKey] = renderered;
|
||||
}
|
||||
|
||||
if (tagType === 'block') renderered = '<p>' + renderered + '</p>';
|
||||
|
||||
@@ -29,6 +42,8 @@ class MdToHtml_Katex {
|
||||
}
|
||||
|
||||
async loadAssets() {
|
||||
if (this.assetsLoaded_) return;
|
||||
|
||||
// In node, the fonts are simply copied using copycss to where Katex expects to find them, which is under app/gui/note-viewer/fonts
|
||||
|
||||
// In React Native, it's more complicated and we need to download and copy them to the right directory. Ideally, we should embed
|
||||
@@ -43,6 +58,8 @@ class MdToHtml_Katex {
|
||||
await shim.fetchBlob('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-beta1/fonts/KaTeX_Math-Italic.woff2', { overwrite: false, path: baseDir + '/fonts/KaTeX_Math-Italic.woff2' });
|
||||
await shim.fetchBlob('https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.9.0-beta1/fonts/KaTeX_Size1-Regular.woff2', { overwrite: false, path: baseDir + '/fonts/KaTeX_Size1-Regular.woff2' });
|
||||
}
|
||||
|
||||
this.assetsLoaded_ = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -39,6 +39,19 @@ class NoteBodyViewer extends Component {
|
||||
}, 100);
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
// To address https://github.com/laurent22/joplin/issues/433
|
||||
// If a checkbox in a note is ticked, the body changes, which normally would trigger a re-render
|
||||
// of this component, which has the unfortunate side effect of making the view scroll back to the top.
|
||||
// This re-rendering however is uncessary since the component is already visually updated via JS.
|
||||
// So here, if the note has not changed, we prevent the component from updating.
|
||||
// This fixes the above issue. A drawback of this is if the note is updated via sync, this change
|
||||
// will not be displayed immediately.
|
||||
const currentNoteId = this.props && this.props.note ? this.props.note.id : null;
|
||||
const nextNoteId = nextProps && nextProps.note ? nextProps.note.id : null;
|
||||
return currentNoteId !== nextNoteId || nextState.webViewLoaded !== this.state.webViewLoaded;
|
||||
}
|
||||
|
||||
render() {
|
||||
const note = this.props.note;
|
||||
const style = this.props.style;
|
||||
@@ -109,7 +122,7 @@ class NoteBodyViewer extends Component {
|
||||
let msg = event.nativeEvent.data;
|
||||
|
||||
if (msg.indexOf('checkboxclick:') === 0) {
|
||||
const newBody = this.mdToHtml_.handleCheckboxClick(msg, note.body);
|
||||
const newBody = this.mdToHtml_.handleCheckboxClick(msg, this.props.note.body);
|
||||
if (onCheckboxChange) onCheckboxChange(newBody);
|
||||
} else if (msg.indexOf('bodyscroll:') === 0) {
|
||||
//msg = msg.split(':');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { View, Button, Text, TextInput, TouchableOpacity, StyleSheet } = require('react-native');
|
||||
const { View, Button, Text, TextInput, TouchableOpacity, StyleSheet, ScrollView } = require('react-native');
|
||||
const { connect } = require('react-redux');
|
||||
const { ScreenHeader } = require('lib/components/screen-header.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
@@ -53,7 +53,7 @@ class DropboxLoginScreenComponent extends BaseScreenComponent {
|
||||
<View style={this.styles().screen}>
|
||||
<ScreenHeader title={_('Login with Dropbox')}/>
|
||||
|
||||
<View style={this.styles().container}>
|
||||
<ScrollView style={this.styles().container}>
|
||||
<Text style={this.styles().stepText}>{_('To allow Joplin to synchronise with Dropbox, please follow the steps below:')}</Text>
|
||||
<Text style={this.styles().stepText}>{_('Step 1: Open this URL in your browser to authorise the application:')}</Text>
|
||||
<View>
|
||||
@@ -65,7 +65,10 @@ class DropboxLoginScreenComponent extends BaseScreenComponent {
|
||||
<TextInput selectionColor={theme.textSelectionColor} value={this.state.authCode} onChangeText={this.shared_.authCodeInput_change} style={theme.lineInput}/>
|
||||
|
||||
<Button disabled={this.state.checkingAuthToken} title={_("Submit")} onPress={this.shared_.submit_click}></Button>
|
||||
</View>
|
||||
|
||||
{/* Add this extra padding to make sure the view is scrollable when the keyboard is visible on small screens (iPhone SE) */}
|
||||
<View style={{ height: 200 }}></View>
|
||||
</ScrollView>
|
||||
|
||||
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
|
||||
</View>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { Platform, Clipboard, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image } = require('react-native');
|
||||
const { Platform, Clipboard, Keyboard, BackHandler, View, Button, TextInput, WebView, Text, StyleSheet, Linking, Image, Share } = require('react-native');
|
||||
const { connect } = require('react-redux');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const RNFS = require('react-native-fs');
|
||||
@@ -409,6 +409,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.setState({ noteTagDialogShown: true });
|
||||
}
|
||||
|
||||
async share_onPress() {
|
||||
await Share.share({
|
||||
message: this.state.note.title + '\n\n' + this.state.note.body,
|
||||
title: this.state.note.title,
|
||||
});
|
||||
}
|
||||
|
||||
setAlarm_onPress() {
|
||||
this.setState({ alarmDialogShown: true });
|
||||
}
|
||||
@@ -468,6 +475,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
output.push({ title: _('Set alarm'), onPress: () => { this.setState({ alarmDialogShown: true }) }});;
|
||||
}
|
||||
|
||||
output.push({ title: _('Share'), onPress: () => { this.share_onPress(); } });
|
||||
if (isSaved) output.push({ title: _('Tags'), onPress: () => { this.tags_onPress(); } });
|
||||
output.push({ title: isTodo ? _('Convert to note') : _('Convert to todo'), onPress: () => { this.toggleIsTodo_onPress(); } });
|
||||
if (isSaved) output.push({ title: _('Copy Markdown link'), onPress: () => { this.copyMarkdownLink_onPress(); } });
|
||||
@@ -512,7 +520,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.saveOneProperty('body', newBody);
|
||||
};
|
||||
|
||||
bodyComponent = <NoteBodyViewer onJoplinLinkClick={this.onJoplinLinkClick_} style={this.styles().noteBodyViewer} webViewStyle={theme} note={note} onCheckboxChange={(newBody) => { onCheckboxChange(newBody) }}/>
|
||||
bodyComponent = <NoteBodyViewer
|
||||
onJoplinLinkClick={this.onJoplinLinkClick_}
|
||||
style={this.styles().noteBodyViewer}
|
||||
webViewStyle={theme}
|
||||
note={note}
|
||||
onCheckboxChange={(newBody) => { onCheckboxChange(newBody) }}
|
||||
/>
|
||||
} else {
|
||||
const focusBody = !isNew && !!note.title;
|
||||
|
||||
|
@@ -53,6 +53,11 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
id: { name: 'uncompletedTodosOnTop', value: !Setting.value('uncompletedTodosOnTop') },
|
||||
});
|
||||
|
||||
buttons.push({
|
||||
text: makeCheckboxText(Setting.value('showCompletedTodos'), 'tick', '[ ' + Setting.settingMetadata('showCompletedTodos').label() + ' ]'),
|
||||
id: { name: 'showCompletedTodos', value: !Setting.value('showCompletedTodos') },
|
||||
});
|
||||
|
||||
const r = await dialogs.pop(this, Setting.settingMetadata('notes.sortOrder.field').label(), buttons);
|
||||
if (!r) return;
|
||||
|
||||
@@ -79,6 +84,7 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
let options = {
|
||||
order: props.notesOrder,
|
||||
uncompletedTodosOnTop: props.uncompletedTodosOnTop,
|
||||
showCompletedTodos: props.showCompletedTodos,
|
||||
caseInsensitive: true,
|
||||
};
|
||||
|
||||
@@ -219,6 +225,7 @@ const NotesScreen = connect(
|
||||
notes: state.notes,
|
||||
notesSource: state.notesSource,
|
||||
uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
|
||||
showCompletedTodos: state.settings.showCompletedTodos,
|
||||
theme: state.settings.theme,
|
||||
noteSelectionEnabled: state.noteSelectionEnabled,
|
||||
notesOrder: stateUtils.notesOrder(state.settings),
|
||||
|
@@ -2,6 +2,7 @@ const { reg } = require('lib/registry.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
|
||||
const shared = {};
|
||||
|
||||
@@ -20,7 +21,9 @@ shared.saveNoteButton_press = async function(comp, folderId = null) {
|
||||
if (folderId) {
|
||||
note.parent_id = folderId;
|
||||
} else if (!note.parent_id) {
|
||||
let folder = await Folder.defaultFolder();
|
||||
const activeFolderId = Setting.value('activeFolderId');
|
||||
let folder = await Folder.load(activeFolderId);
|
||||
if (!folder) folder = await Folder.defaultFolder();
|
||||
if (!folder) return;
|
||||
note.parent_id = folder.id;
|
||||
}
|
||||
|
@@ -311,6 +311,7 @@ async function basicDelta(path, getDirStatFn, options) {
|
||||
// Clear temporary info from context. It's especially important to remove deletedItemsProcessed
|
||||
// so that they are processed again on the next sync.
|
||||
newContext.statsCache = null;
|
||||
newContext.statIdsCache = null;
|
||||
delete newContext.deletedItemsProcessed;
|
||||
}
|
||||
|
||||
|
@@ -237,6 +237,7 @@ class Note extends BaseItem {
|
||||
if (!options.conditionsParams) options.conditionsParams = [];
|
||||
if (!options.fields) options.fields = this.previewFields();
|
||||
if (!options.uncompletedTodosOnTop) options.uncompletedTodosOnTop = false;
|
||||
if (!('showCompletedTodos' in options)) options.showCompletedTodos = true;
|
||||
|
||||
if (parentId == BaseItem.getClass('Folder').conflictFolderId()) {
|
||||
options.conditions.push('is_conflict = 1');
|
||||
@@ -265,6 +266,10 @@ class Note extends BaseItem {
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.showCompletedTodos) {
|
||||
options.conditions.push('todo_completed <= 0');
|
||||
}
|
||||
|
||||
if (options.uncompletedTodosOnTop && hasTodos) {
|
||||
let cond = options.conditions.slice();
|
||||
cond.push('is_todo = 1');
|
||||
|
@@ -61,6 +61,7 @@ class Setting extends BaseModel {
|
||||
return output;
|
||||
}},
|
||||
'uncompletedTodosOnTop': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Uncompleted to-dos on top') },
|
||||
'showCompletedTodos': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['cli'], label: () => _('Show completed to-dos') },
|
||||
'notes.sortOrder.field': { value: 'user_updated_time', type: Setting.TYPE_STRING, isEnum: true, public: true, appTypes: ['cli'], label: () => _('Sort notes by'), options: () => {
|
||||
const Note = require('lib/models/Note');
|
||||
const noteSortFields = ['user_updated_time', 'user_created_time', 'title'];
|
||||
|
@@ -59,10 +59,10 @@ reg.scheduleSync = async (delay = null, syncOptions = null) => {
|
||||
|
||||
reg.logger().info('Scheduling sync operation...');
|
||||
|
||||
if (Setting.value("env") === "dev" && delay !== 0) {
|
||||
reg.logger().info("Schedule sync DISABLED!!!");
|
||||
return;
|
||||
}
|
||||
// if (Setting.value("env") === "dev" && delay !== 0) {
|
||||
// reg.logger().info("Schedule sync DISABLED!!!");
|
||||
// return;
|
||||
// }
|
||||
|
||||
const timeoutCallback = async () => {
|
||||
reg.scheduleSyncId_ = null;
|
||||
|
@@ -35,6 +35,23 @@ function shimInit() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
// For Electron only
|
||||
shim.writeImageToFile = async function(nativeImage, mime, targetPath) {
|
||||
let buffer = null;
|
||||
|
||||
mime = mime.toLowerCase();
|
||||
|
||||
if (mime === 'image/png') {
|
||||
buffer = nativeImage.toPNG();
|
||||
} else if (mime === 'image/jpg' || mime === 'image/jpeg') {
|
||||
buffer = nativeImage.toJPEG(90);
|
||||
}
|
||||
|
||||
if (!buffer) throw new Error('Cannot reisze image because mime type "' + mime + '" is not supported: ' + targetPath);
|
||||
|
||||
await shim.fsDriver().writeFile(targetPath, buffer, 'buffer');
|
||||
}
|
||||
|
||||
const resizeImage_ = async function(filePath, targetPath, mime) {
|
||||
if (shim.isElectron()) { // For Electron
|
||||
const nativeImage = require('electron').nativeImage;
|
||||
@@ -58,17 +75,7 @@ function shimInit() {
|
||||
|
||||
image = image.resize(options);
|
||||
|
||||
let buffer = null;
|
||||
|
||||
if (mime === 'image/png') {
|
||||
buffer = image.toPNG();
|
||||
} else if (mime === 'image/jpg' || mime === 'image/jpeg') {
|
||||
buffer = image.toJPEG(90);
|
||||
}
|
||||
|
||||
if (!buffer) throw new Error('Cannot reisze image because mime type "' + mime + '" is not supported: ' + targetPath);
|
||||
|
||||
await shim.fsDriver().writeFile(targetPath, buffer, 'buffer');
|
||||
await shim.writeImageToFile(image, mime, targetPath);
|
||||
} else { // For the CLI tool
|
||||
const sharp = require('sharp');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
@@ -89,7 +96,7 @@ function shimInit() {
|
||||
}
|
||||
}
|
||||
|
||||
shim.attachFileToNote = async function(note, filePath) {
|
||||
shim.attachFileToNote = async function(note, filePath, position = null) {
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const { basename, fileExtension, safeFileExtension } = require('lib/path-utils.js');
|
||||
@@ -120,8 +127,14 @@ function shimInit() {
|
||||
await Resource.save(resource, { isNew: true });
|
||||
|
||||
const newBody = [];
|
||||
if (note.body) newBody.push(note.body);
|
||||
|
||||
if (position === null) {
|
||||
position = note.body ? note.body.length : 0;
|
||||
}
|
||||
|
||||
if (note.body && position) newBody.push(note.body.substr(0, position));
|
||||
newBody.push(Resource.markdownTag(resource));
|
||||
newBody.push(note.body.substr(position));
|
||||
|
||||
const newNote = Object.assign({}, note, {
|
||||
body: newBody.join('\n\n'),
|
||||
|
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
@@ -94,7 +94,7 @@ const generalMiddleware = store => next => async (action) => {
|
||||
if (action.type == "NAV_GO") Keyboard.dismiss();
|
||||
|
||||
if (["NOTE_UPDATE_ONE", "NOTE_DELETE", "FOLDER_UPDATE_ONE", "FOLDER_DELETE"].indexOf(action.type) >= 0) {
|
||||
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(5, { syncSteps: ["update_remote", "delete_remote"] });
|
||||
if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(5 * 1000, { syncSteps: ["update_remote", "delete_remote"] });
|
||||
}
|
||||
|
||||
if (['EVENT_NOTE_ALARM_FIELD_CHANGE', 'NOTE_DELETE'].indexOf(action.type) >= 0) {
|
||||
|
@@ -143,20 +143,10 @@ async function translationStatus(isDefault, poFile) {
|
||||
translatorName = extractTranslator(/Language-Team:\s*?(.*)/, content);
|
||||
}
|
||||
|
||||
// "Last-Translator: Hrvoje Mandić <trbuhom@net.hr>\n"
|
||||
// let translatorMatch = content.match(/Last-Translator:\s*?(.*)/);
|
||||
// if (translatorMatch.length < 1) {
|
||||
// translatorMatch = content.match(/Last-Team:\s*?(.*)/);
|
||||
// }
|
||||
|
||||
// if (translatorMatch.length >= 1) {
|
||||
// translatorName = translatorMatch[1];
|
||||
// translatorName = translatorName.replace(/["\s]+$/, '');
|
||||
// translatorName = translatorName.replace(/\\n$/, '');
|
||||
// translatorName = translatorName.replace(/^\s*/, '');
|
||||
// }
|
||||
|
||||
// if (translatorName.indexOf('FULL NAME') >= 0) translatorName = '';
|
||||
// Remove <> around email otherwise it's converted to HTML with (apparently) non-deterministic
|
||||
// encoding, so it changes on every update.
|
||||
translatorName = translatorName.replace(/ </, ' (');
|
||||
translatorName = translatorName.replace(/>/, ')');
|
||||
|
||||
return {
|
||||
percentDone: isDefault ? 100 : percentDone,
|
||||
|
@@ -247,6 +247,16 @@
|
||||
</ul>
|
||||
</div>
|
||||
<h1 id="joplin-changelog">Joplin changelog</h1>
|
||||
<h2 id="-v1-0-91-https-github-com-laurent22-joplin-releases-tag-v1-0-91-2018-05-10t14-48-04z"><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.91">v1.0.91</a> - 2018-05-10T14:48:04Z</h2>
|
||||
<p>Same as v1.0.90 but with a fix for <a href="https://github.com/laurent22/joplin/issues/510">#510</a> </p>
|
||||
<ul>
|
||||
<li>New: Resolves <a href="https://github.com/laurent22/joplin/issues/345">#345</a>: Option to hide completed todos</li>
|
||||
<li>New: Resolves <a href="https://github.com/laurent22/joplin/issues/200">#200</a>, Resolves <a href="https://github.com/laurent22/joplin/issues/416">#416</a>: Allow attaching images by pasting them in. Allow attaching files by drag and dropping them. Insert attachment at cursor position.</li>
|
||||
<li>Improved: Resolves <a href="https://github.com/laurent22/joplin/issues/443">#443</a>: Various optimisations to make dealing with large notes easier and make Katex re-rendering faster</li>
|
||||
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/481">#481</a>: Keyboard shortcuts were not working when text editor had focus in macOS</li>
|
||||
<li>Fixed: Tag display</li>
|
||||
<li>Security: Resolves <a href="https://github.com/laurent22/joplin/issues/500">#500</a>: Fixed XSS security vulnerability</li>
|
||||
</ul>
|
||||
<h2 id="-v1-0-89-https-github-com-laurent22-joplin-releases-tag-v1-0-89-2018-05-09t13-05-05z"><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.89">v1.0.89</a> - 2018-05-09T13:05:05Z</h2>
|
||||
<ul>
|
||||
<li>New: Resolves <a href="https://github.com/laurent22/joplin/issues/122">#122</a>: Added support for sub-notebooks. Please see doc for more info: <a href="https://joplin.cozic.net/#sub-notebooks">https://joplin.cozic.net/#sub-notebooks</a></li>
|
||||
@@ -449,10 +459,6 @@
|
||||
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/85">#85</a>: Don't record deleted_items entries for folders deleted via sync</li>
|
||||
<li>Updated translations</li>
|
||||
</ul>
|
||||
<h2 id="-v0-10-43-https-github-com-laurent22-joplin-releases-tag-v0-10-43-2018-01-08t10-12-10z"><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.43">v0.10.43</a> - 2018-01-08T10:12:10Z</h2>
|
||||
<ul>
|
||||
<li>Fixed saving and loading of settings, which could affect synchronisation</li>
|
||||
</ul>
|
||||
|
||||
<script>
|
||||
function stickyHeader() {
|
||||
|
@@ -267,17 +267,17 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Windows (32 and 64-bit)</td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.89/Joplin-1.0.89.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a></td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.91/Joplin-1.0.91.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>macOS</td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.89/Joplin-1.0.89.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a></td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.91/Joplin-1.0.91.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux</td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.89/Joplin-1.0.89-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a></td>
|
||||
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.91/Joplin-1.0.91-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a></td>
|
||||
<td>An Arch Linux package <a href="#terminal-application">is also available</a>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@@ -295,7 +295,7 @@
|
||||
<tr>
|
||||
<td>Android</td>
|
||||
<td><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></td>
|
||||
<td>or <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.0.123/joplin-v1.0.123.apk">Download APK File</a></td>
|
||||
<td>or <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.0.125/joplin-v1.0.125.apk">Download APK File</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>iOS</td>
|
||||
@@ -409,7 +409,8 @@
|
||||
<p>For a more technical description, mostly relevant for development or to review the method being used, please see the <a href="https://joplin.cozic.net/spec">Encryption specification</a>.</p>
|
||||
<h1 id="attachments-resources">Attachments / Resources</h1>
|
||||
<p>Any kind of file can be attached to a note. In Markdown, links to these files are represented as a simple ID to the resource. In the note viewer, these files, if they are images, will be displayed or, if they are other files (PDF, text files, etc.) they will be displayed as links. Clicking on this link will open the file in the default application.</p>
|
||||
<p>Resources that are not attached to any note will be automatically deleted after a day or two.</p>
|
||||
<p>On the <strong>desktop application</strong>, images can be attached either by clicking on "Attach file" or by pasting (with Ctrl+V) an image directly in the editor, or by drag and dropping an image.</p>
|
||||
<p>Resources that are not attached to any note will be automatically deleted after a day or two (see <a href="https://github.com/laurent22/joplin/issues/154#issuecomment-356582366">rationale</a>).</p>
|
||||
<p><strong>Important:</strong> Resources larger than 10 MB are not currently supported on mobile. They will crash the application when synchronising so it is recommended not to attach such resources at the moment. The issue is being looked at.</p>
|
||||
<h1 id="notifications">Notifications</h1>
|
||||
<p>On the desktop and mobile apps, an alarm can be associated with any to-do. It will be triggered at the given time by displaying a notification. How the notification will be displayed depends on the operating system since each has a different way to handle this. Please see below for the requirements for the desktop applications:</p>
|
||||
@@ -454,12 +455,15 @@ $$
|
||||
- [ ] Rice
|
||||
- [ ] Eggs
|
||||
</code></pre><p>The checkboxes can then be ticked in the mobile and desktop applications.</p>
|
||||
<h2 id="html-support">HTML support</h2>
|
||||
<p>Only the <code><br></code> tag is supported - it can be used to force a new line, which is convenient to insert new lines inside table cells. For security reasons, other HTML tags are not supported.</p>
|
||||
<h1 id="donations">Donations</h1>
|
||||
<p>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.</p>
|
||||
<p>Please see the <a href="https://joplin.cozic.net/donate/">donation page</a> for information on how to support the development of Joplin.</p>
|
||||
<h1 id="community">Community</h1>
|
||||
<ul>
|
||||
<li>For general discussion about Joplin, user support, software development questions, and to discuss new features, go to the <a href="https://discourse.joplin.cozic.net/">Joplin Forum</a>. It is possible to login with your GitHub account.</li>
|
||||
<li>Also see here for information about <a href="https://discourse.joplin.cozic.net/c/news">the latest releases and general news</a>.</li>
|
||||
<li>For bug reports and feature requests, go to the <a href="https://github.com/laurent22/joplin/issues">GitHub Issue Tracker</a>.</li>
|
||||
<li>The latest news are often posted <a href="https://twitter.com/laurent2233">on this Twitter account</a>.</li>
|
||||
</ul>
|
||||
@@ -499,28 +503,28 @@ $$
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/hr.png" alt=""></td>
|
||||
<td>Croatian</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/hr_HR.po">hr_HR</a></td>
|
||||
<td>Hrvoje Mandić <a href="mailto:trbuhom@net.hr">trbuhom@net.hr</a></td>
|
||||
<td>Hrvoje Mandić (trbuhom@net.hr)</td>
|
||||
<td>61%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/cz.png" alt=""></td>
|
||||
<td>Czech</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/cs_CZ.po">cs_CZ</a></td>
|
||||
<td>Lukas Helebrandt <a href="mailto:lukas@aiya.cz">lukas@aiya.cz</a></td>
|
||||
<td>Lukas Helebrandt (lukas@aiya.cz)</td>
|
||||
<td>95%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/dk.png" alt=""></td>
|
||||
<td>Dansk</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/da_DK.po">da_DK</a></td>
|
||||
<td>Morten Juhl-Johansen Zölde-Fejér <mjjzf@syntaktisk.</td>
|
||||
<td>Morten Juhl-Johansen Zölde-Fejér (mjjzf@syntaktisk.</td>
|
||||
<td>97%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/de.png" alt=""></td>
|
||||
<td>Deutsch</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/de_DE.po">de_DE</a></td>
|
||||
<td>Philipp Zumstein <a href="mailto:zuphilip@gmail.com">zuphilip@gmail.com</a></td>
|
||||
<td>Philipp Zumstein (zuphilip@gmail.com)</td>
|
||||
<td>98%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -534,7 +538,7 @@ $$
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/es.png" alt=""></td>
|
||||
<td>Español</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/es_ES.po">es_ES</a></td>
|
||||
<td>Fernando Martín <a href="mailto:f@mrtn.es">f@mrtn.es</a></td>
|
||||
<td>Fernando Martín (f@mrtn.es)</td>
|
||||
<td>99%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -542,13 +546,13 @@ $$
|
||||
<td>Français</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/fr_FR.po">fr_FR</a></td>
|
||||
<td>Laurent Cozic</td>
|
||||
<td>98%</td>
|
||||
<td>100%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/es.png" alt=""></td>
|
||||
<td>Galician</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/gl_ES.po">gl_ES</a></td>
|
||||
<td>Marcos Lans <a href="mailto:marcoslansgarza@gmail.com">marcoslansgarza@gmail.com</a></td>
|
||||
<td>Marcos Lans (marcoslansgarza@gmail.com)</td>
|
||||
<td>95%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -563,20 +567,20 @@ $$
|
||||
<td>Nederlands</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/nl_BE.po">nl_BE</a></td>
|
||||
<td></td>
|
||||
<td>76%</td>
|
||||
<td>75%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/br.png" alt=""></td>
|
||||
<td>Português (Brasil)</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/pt_BR.po">pt_BR</a></td>
|
||||
<td>Renato Nunes Bastos <a href="mailto:rnbastos@gmail.com">rnbastos@gmail.com</a></td>
|
||||
<td>Renato Nunes Bastos (rnbastos@gmail.com)</td>
|
||||
<td>97%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/ru.png" alt=""></td>
|
||||
<td>Русский</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/ru_RU.po">ru_RU</a></td>
|
||||
<td>Artyom Karlov <a href="mailto:artyom.karlov@gmail.com">artyom.karlov@gmail.com</a></td>
|
||||
<td>Artyom Karlov (artyom.karlov@gmail.com)</td>
|
||||
<td>94%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -584,7 +588,7 @@ $$
|
||||
<td>中文 (简体)</td>
|
||||
<td><a href="https://github.com/laurent22/joplin/blob/master/CliClient/locales/zh_CN.po">zh_CN</a></td>
|
||||
<td></td>
|
||||
<td>91%</td>
|
||||
<td>90%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://joplin.cozic.net/images/flags/country-4x3/jp.png" alt=""></td>
|
||||
|
@@ -257,15 +257,15 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Total Windows downloads</td>
|
||||
<td>27630</td>
|
||||
<td>24647</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total macOs downloads</td>
|
||||
<td>14983</td>
|
||||
<td>13470</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total Linux downloads</td>
|
||||
<td>11596</td>
|
||||
<td>10490</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Windows %</td>
|
||||
@@ -277,7 +277,7 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux %</td>
|
||||
<td>21%</td>
|
||||
<td>22%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -294,28 +294,36 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.91">v1.0.91</a></td>
|
||||
<td>2018-05-10T14:48:04Z</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>1</td>
|
||||
<td>1 </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.89">v1.0.89</a></td>
|
||||
<td>2018-05-09T13:05:05Z</td>
|
||||
<td>4</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>4 </td>
|
||||
<td>427</td>
|
||||
<td>196</td>
|
||||
<td>84</td>
|
||||
<td>707</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.85">v1.0.85</a></td>
|
||||
<td>2018-05-01T21:08:24Z</td>
|
||||
<td>1620</td>
|
||||
<td>917</td>
|
||||
<td>603</td>
|
||||
<td>3140</td>
|
||||
<td>1623</td>
|
||||
<td>923</td>
|
||||
<td>604</td>
|
||||
<td>3150</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.83">v1.0.83</a></td>
|
||||
<td>2018-04-04T19:43:58Z</td>
|
||||
<td>4350</td>
|
||||
<td>4354</td>
|
||||
<td>2366</td>
|
||||
<td>2618</td>
|
||||
<td>9334</td>
|
||||
<td>2619</td>
|
||||
<td>9339</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.82">v1.0.82</a></td>
|
||||
@@ -330,8 +338,8 @@
|
||||
<td>2018-03-28T08:13:58Z</td>
|
||||
<td>976</td>
|
||||
<td>562</td>
|
||||
<td>735</td>
|
||||
<td>2273</td>
|
||||
<td>736</td>
|
||||
<td>2274</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.79">v1.0.79</a></td>
|
||||
@@ -376,10 +384,10 @@
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.67">v1.0.67</a></td>
|
||||
<td>2018-02-19T22:51:08Z</td>
|
||||
<td>1629</td>
|
||||
<td>1635</td>
|
||||
<td>576</td>
|
||||
<td></td>
|
||||
<td>2205</td>
|
||||
<td>2211</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.66">v1.0.66</a></td>
|
||||
@@ -417,9 +425,9 @@
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.62">v1.0.62</a></td>
|
||||
<td>2018-02-12T20:19:58Z</td>
|
||||
<td>540</td>
|
||||
<td>269</td>
|
||||
<td>270</td>
|
||||
<td>345</td>
|
||||
<td>1154</td>
|
||||
<td>1155</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.61">v0.10.61</a></td>
|
||||
@@ -477,14 +485,6 @@
|
||||
<td>58</td>
|
||||
<td>1913</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://github.com/laurent22/joplin/releases/tag/v0.10.43">v0.10.43</a></td>
|
||||
<td>2018-01-08T10:12:10Z</td>
|
||||
<td>3419</td>
|
||||
<td>1716</td>
|
||||
<td>1194</td>
|
||||
<td>6329</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@@ -1,5 +1,16 @@
|
||||
# Joplin changelog
|
||||
|
||||
## [v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) - 2018-05-10T14:48:04Z
|
||||
|
||||
Same as v1.0.90 but with a fix for [#510](https://github.com/laurent22/joplin/issues/510)
|
||||
|
||||
- New: Resolves [#345](https://github.com/laurent22/joplin/issues/345): Option to hide completed todos
|
||||
- New: Resolves [#200](https://github.com/laurent22/joplin/issues/200), Resolves [#416](https://github.com/laurent22/joplin/issues/416): Allow attaching images by pasting them in. Allow attaching files by drag and dropping them. Insert attachment at cursor position.
|
||||
- Improved: Resolves [#443](https://github.com/laurent22/joplin/issues/443): Various optimisations to make dealing with large notes easier and make Katex re-rendering faster
|
||||
- Fixes [#481](https://github.com/laurent22/joplin/issues/481): Keyboard shortcuts were not working when text editor had focus in macOS
|
||||
- Fixed: Tag display
|
||||
- Security: Resolves [#500](https://github.com/laurent22/joplin/issues/500): Fixed XSS security vulnerability
|
||||
|
||||
## [v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) - 2018-05-09T13:05:05Z
|
||||
|
||||
- New: Resolves [#122](https://github.com/laurent22/joplin/issues/122): Added support for sub-notebooks. Please see doc for more info: https://joplin.cozic.net/#sub-notebooks
|
||||
@@ -204,8 +215,4 @@ IMPORTANT: If you use Nextcloud it is recommended to sync all your notes before
|
||||
- Fixed logic to save, and make sure scheduled save always happen even when changing note
|
||||
- Fixed OneDrive sync when resync is requested
|
||||
- Fixes [#85](https://github.com/laurent22/joplin/issues/85): Don't record deleted_items entries for folders deleted via sync
|
||||
- Updated translations
|
||||
|
||||
## [v0.10.43](https://github.com/laurent22/joplin/releases/tag/v0.10.43) - 2018-01-08T10:12:10Z
|
||||
|
||||
- Fixed saving and loading of settings, which could affect synchronisation
|
||||
- Updated translations
|
@@ -2,36 +2,36 @@
|
||||
|
||||
Name | Value
|
||||
--- | ---
|
||||
Total Windows downloads | 27630
|
||||
Total macOs downloads | 14983
|
||||
Total Linux downloads | 11596
|
||||
Total Windows downloads | 24647
|
||||
Total macOs downloads | 13470
|
||||
Total Linux downloads | 10490
|
||||
Windows % | 51%
|
||||
macOS % | 28%
|
||||
Linux % | 21%
|
||||
Linux % | 22%
|
||||
|
||||
Version | Date | Windows | macOS | Linux | Total
|
||||
--- | --- | --- | --- | --- | ---
|
||||
[v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 4 | | | 4
|
||||
[v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1620 | 917 | 603 | 3140
|
||||
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4350 | 2366 | 2618 | 9334
|
||||
[v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | | | 1 | 1
|
||||
[v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 427 | 196 | 84 | 707
|
||||
[v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1623 | 923 | 604 | 3150
|
||||
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4354 | 2366 | 2619 | 9339
|
||||
[v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 679 | 379 | 89 | 1147
|
||||
[v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 976 | 562 | 735 | 2273
|
||||
[v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 976 | 562 | 736 | 2274
|
||||
[v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 908 | 503 | 350 | 1761
|
||||
[v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1291 | 829 | 838 | 2958
|
||||
[v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 163 | 83 | 23 | 269
|
||||
[v1.0.72](https://github.com/laurent22/joplin/releases/tag/v1.0.72) | 2018-03-14T09:44:35Z | 394 | 229 | 30 | 653
|
||||
[v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1836 | 1016 | 1218 | 4070
|
||||
[v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1629 | 576 | | 2205
|
||||
[v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1635 | 576 | | 2211
|
||||
[v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) | 2018-02-18T23:09:09Z | 312 | 104 | 71 | 487
|
||||
[v1.0.65](https://github.com/laurent22/joplin/releases/tag/v1.0.65) | 2018-02-17T20:02:25Z | 183 | 102 | 113 | 398
|
||||
[v1.0.64](https://github.com/laurent22/joplin/releases/tag/v1.0.64) | 2018-02-16T00:58:20Z | 1065 | 525 | 1113 | 2703
|
||||
[v1.0.63](https://github.com/laurent22/joplin/releases/tag/v1.0.63) | 2018-02-14T19:40:36Z | 284 | 141 | 81 | 506
|
||||
[v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 540 | 269 | 345 | 1154
|
||||
[v1.0.62](https://github.com/laurent22/joplin/releases/tag/v1.0.62) | 2018-02-12T20:19:58Z | 540 | 270 | 345 | 1155
|
||||
[v0.10.61](https://github.com/laurent22/joplin/releases/tag/v0.10.61) | 2018-02-08T18:27:39Z | 955 | 601 | 939 | 2495
|
||||
[v0.10.60](https://github.com/laurent22/joplin/releases/tag/v0.10.60) | 2018-02-06T13:09:56Z | 710 | 490 | 538 | 1738
|
||||
[v0.10.54](https://github.com/laurent22/joplin/releases/tag/v0.10.54) | 2018-01-31T20:21:30Z | 1805 | 826 | 305 | 2936
|
||||
[v0.10.52](https://github.com/laurent22/joplin/releases/tag/v0.10.52) | 2018-01-31T19:25:18Z | 30 | 8 | 4 | 42
|
||||
[v0.10.51](https://github.com/laurent22/joplin/releases/tag/v0.10.51) | 2018-01-28T18:47:02Z | 1308 | 977 | 317 | 2602
|
||||
[v0.10.48](https://github.com/laurent22/joplin/releases/tag/v0.10.48) | 2018-01-23T11:19:51Z | 1954 | 1124 | 14 | 3092
|
||||
[v0.10.47](https://github.com/laurent22/joplin/releases/tag/v0.10.47) | 2018-01-16T17:27:17Z | 1215 | 640 | 58 | 1913
|
||||
[v0.10.43](https://github.com/laurent22/joplin/releases/tag/v0.10.43) | 2018-01-08T10:12:10Z | 3419 | 1716 | 1194 | 6329
|
||||
[v0.10.47](https://github.com/laurent22/joplin/releases/tag/v0.10.47) | 2018-01-16T17:27:17Z | 1215 | 640 | 58 | 1913
|
Reference in New Issue
Block a user