mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge branch 'stable'
# Conflicts: # package-lock.json # src/public/javascripts/services/tree_context_menu.js # src/services/import/enex.js
This commit is contained in:
commit
90d10c1ff3
2
libraries/ckeditor/ckeditor.js
vendored
2
libraries/ckeditor/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -498,7 +498,7 @@
|
||||
t._started = false;
|
||||
onRenderStop();
|
||||
} else {
|
||||
setImmediate(step);
|
||||
requestIdleCallback(step, { timeout: 10 });
|
||||
}
|
||||
}
|
||||
|
||||
|
4061
package-lock.json
generated
4061
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.37.4",
|
||||
"version": "0.37.6",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
|
@ -818,6 +818,7 @@ class Note extends Entity {
|
||||
delete pojo.isContentAvailable;
|
||||
delete pojo.__attributeCache;
|
||||
delete pojo.content;
|
||||
/** zero references to contentHash, probably can be removed */
|
||||
delete pojo.contentHash;
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ export default class SidebarOptions {
|
||||
this.$sidebarMinWidth.val(options.sidebarMinWidth);
|
||||
this.$sidebarWidthPercent.val(options.sidebarWidthPercent);
|
||||
|
||||
if (parseInt(options.showSidebarInNewTab)) {
|
||||
if (options.showSidebarInNewTab === 'true') {
|
||||
this.$showSidebarInNewTab.attr("checked", "checked");
|
||||
}
|
||||
else {
|
||||
|
@ -274,7 +274,9 @@ async function filterTabs(noteId) {
|
||||
|
||||
async function noteDeleted(noteId) {
|
||||
for (const tc of tabContexts) {
|
||||
if (tc.notePath && tc.notePath.split("/").includes(noteId)) {
|
||||
// not removing active even if it contains deleted note since that one will move to another note (handled by deletion logic)
|
||||
// and we would lose tab context state (e.g. sidebar visibility)
|
||||
if (!tc.isActive() && tc.notePath && tc.notePath.split("/").includes(noteId)) {
|
||||
await tabRow.removeTab(tc.$tab[0]);
|
||||
}
|
||||
}
|
||||
|
@ -246,11 +246,15 @@ class TabContext {
|
||||
}
|
||||
|
||||
setCurrentNotePathToHash() {
|
||||
if (this.$tab[0] === this.tabRow.activeTabEl) {
|
||||
if (this.isActive()) {
|
||||
document.location.hash = (this.notePath || "") + "-" + this.tabId;
|
||||
}
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.$tab[0] === this.tabRow.activeTabEl;
|
||||
}
|
||||
|
||||
setupClasses() {
|
||||
for (const clazz of Array.from(this.$tab[0].classList)) { // create copy to safely iterate over while removing classes
|
||||
if (clazz !== 'note-tab') {
|
||||
|
@ -42,7 +42,7 @@ class TreeContextMenu {
|
||||
|| (selNodes.length === 1 && selNodes[0] === this.node);
|
||||
|
||||
const notSearch = note.type !== 'search';
|
||||
const parentNotSearch = parentNote.type !== 'search';
|
||||
const parentNotSearch = !parentNote || parentNote.type !== 'search';
|
||||
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
|
||||
|
||||
return [
|
||||
@ -78,8 +78,8 @@ class TreeContextMenu {
|
||||
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
|
||||
{ title: 'Paste after', cmd: "pasteAfter", uiIcon: "paste",
|
||||
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
|
||||
{ title: 'Duplicate note here', cmd: "duplicateNote", uiIcon: "empty",
|
||||
enabled: noSelectedNotes && parentNotSearch && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||
{ title: "Duplicate note here", cmd: "duplicateNote", uiIcon: "empty",
|
||||
enabled: noSelectedNotes && parentNotSearch && isNotRoot && !isHoisted && (!note.isProtected || protectedSessionHolder.isProtectedSessionAvailable()) },
|
||||
{ title: "----" },
|
||||
{ title: "Export", cmd: "export", uiIcon: "empty",
|
||||
enabled: notSearch && noSelectedNotes },
|
||||
|
@ -127,11 +127,13 @@ async function consumeSyncData() {
|
||||
}
|
||||
|
||||
function connectWebSocket() {
|
||||
const protocol = document.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
const loc = window.location;
|
||||
const webSocketUri = (loc.protocol === "https:" ? "wss:" : "ws:")
|
||||
+ "//" + loc.host + loc.pathname;
|
||||
|
||||
// use wss for secure messaging
|
||||
const ws = new WebSocket(protocol + "://" + location.host);
|
||||
ws.onopen = () => console.debug(utils.now(), "Connected to server with WebSocket");
|
||||
const ws = new WebSocket(webSocketUri);
|
||||
ws.onopen = () => console.debug(utils.now(), `Connected to server ${webSocketUri} with WebSocket`);
|
||||
ws.onmessage = handleMessage;
|
||||
// we're not handling ws.onclose here because reconnection is done in sendPing()
|
||||
|
||||
|
@ -97,6 +97,11 @@ body {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
#context-menu-container {
|
||||
max-height: 100vh;
|
||||
overflow: auto; /* make it scrollable when exceeding total height of the window */
|
||||
}
|
||||
|
||||
#context-menu-container, #context-menu-container .dropdown-menu {
|
||||
padding: 3px 0 0;
|
||||
z-index: 1111;
|
||||
|
@ -1 +1 @@
|
||||
module.exports = { buildDate:"2019-11-22T22:38:03+01:00", buildRevision: "7a2c7edd7e9b975bf64f732629e711379baecf48" };
|
||||
module.exports = { buildDate:"2019-11-26T22:50:08+01:00", buildRevision: "5193f073e9e55f5440fe2e71fbd2cdfcdb2d2c6b" };
|
||||
|
@ -3,6 +3,7 @@ const fileType = require('file-type');
|
||||
const stream = require('stream');
|
||||
const log = require("../log");
|
||||
const utils = require("../utils");
|
||||
const sql = require("../sql");
|
||||
const noteService = require("../notes");
|
||||
const imageService = require("../image");
|
||||
const protectedSessionService = require('../protected_session');
|
||||
@ -11,7 +12,7 @@ const protectedSessionService = require('../protected_session');
|
||||
function parseDate(text) {
|
||||
// insert - and : to make it ISO format
|
||||
text = text.substr(0, 4) + "-" + text.substr(4, 2) + "-" + text.substr(6, 2)
|
||||
+ "T" + text.substr(9, 2) + ":" + text.substr(11, 2) + ":" + text.substr(13, 2) + "Z";
|
||||
+ " " + text.substr(9, 2) + ":" + text.substr(11, 2) + ":" + text.substr(13, 2) + ".000Z";
|
||||
|
||||
return text;
|
||||
}
|
||||
@ -153,7 +154,7 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
} else if (currentTag === 'created') {
|
||||
note.utcDateCreated = parseDate(text);
|
||||
} else if (currentTag === 'updated') {
|
||||
// updated is currently ignored since utcDateModified is updated automatically with each save
|
||||
note.utcDateModified = parseDate(text);
|
||||
} else if (currentTag === 'tag') {
|
||||
note.attributes.push({
|
||||
type: 'label',
|
||||
@ -190,9 +191,27 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
}
|
||||
});
|
||||
|
||||
async function updateDates(noteId, utcDateCreated, utcDateModified) {
|
||||
// it's difficult to force custom dateCreated and dateModified to Note entity so we do it post-creation with SQL
|
||||
await sql.execute(`
|
||||
UPDATE notes
|
||||
SET dateCreated = ?,
|
||||
utcDateCreated = ?,
|
||||
dateModified = ?,
|
||||
utcDateModified = ?
|
||||
WHERE noteId = ?`,
|
||||
[utcDateCreated, utcDateCreated, utcDateModified, utcDateModified, noteId]);
|
||||
|
||||
await sql.execute(`
|
||||
UPDATE note_contents
|
||||
SET utcDateModified = ?
|
||||
WHERE noteId = ?`,
|
||||
[utcDateModified, noteId]);
|
||||
}
|
||||
|
||||
async function saveNote() {
|
||||
// make a copy because stream continues with the next async call and note gets overwritten
|
||||
let {title, content, attributes, resources, utcDateCreated} = note;
|
||||
let {title, content, attributes, resources, utcDateCreated, utcDateModified} = note;
|
||||
|
||||
content = extractContent(content);
|
||||
|
||||
@ -210,6 +229,10 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
await noteEntity.addAttribute(attr.type, attr.name, attr.value);
|
||||
}
|
||||
|
||||
utcDateCreated = utcDateCreated || noteEntity.utcDateCreated;
|
||||
// sometime date modified is not present in ENEX, then use date created
|
||||
utcDateModified = utcDateModified || utcDateCreated;
|
||||
|
||||
taskContext.increaseProgressCount();
|
||||
|
||||
let noteContent = await noteEntity.getContent();
|
||||
@ -239,6 +262,8 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
await noteEntity.addAttribute(attr.type, attr.name, attr.value);
|
||||
}
|
||||
|
||||
await updateDates(resourceNote.noteId, utcDateCreated, utcDateModified);
|
||||
|
||||
taskContext.increaseProgressCount();
|
||||
|
||||
const resourceLink = `<a href="#root/${resourceNote.noteId}">${utils.escapeHtml(resource.title)}</a>`;
|
||||
@ -250,7 +275,9 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
try {
|
||||
const originalName = "image." + resource.mime.substr(6);
|
||||
|
||||
const {url} = await imageService.saveImage(noteEntity.noteId, resource.content, originalName, taskContext.data.shrinkImages);
|
||||
const {url, note: imageNote} = await imageService.saveImage(noteEntity.noteId, resource.content, originalName, taskContext.data.shrinkImages);
|
||||
|
||||
await updateDates(imageNote.noteId, utcDateCreated, utcDateModified);
|
||||
|
||||
const imageLink = `<img src="${url}">`;
|
||||
|
||||
@ -272,6 +299,10 @@ async function importEnex(taskContext, file, parentNote) {
|
||||
|
||||
// save updated content with links to files/images
|
||||
await noteEntity.setContent(noteContent);
|
||||
|
||||
await noteService.scanForLinks(noteEntity.noteId);
|
||||
|
||||
await updateDates(noteEntity.noteId, utcDateCreated, utcDateModified);
|
||||
}
|
||||
|
||||
saxStream.on("closetag", async tag => {
|
||||
|
@ -37,7 +37,7 @@ function isProtectedSessionAvailable() {
|
||||
function decryptNotes(notes) {
|
||||
for (const note of notes) {
|
||||
if (note.isProtected) {
|
||||
note.title = decrypt(note.title);
|
||||
note.title = decryptString(note.title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user