mirror of
https://github.com/zadam/trilium.git
synced 2025-10-27 16:26:31 +01:00
Compare commits
9 Commits
v0.51.1-be
...
v0.51.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26e1ff4e16 | ||
|
|
b3763eed61 | ||
|
|
f9c01851ef | ||
|
|
6b61b0604a | ||
|
|
f705c432fd | ||
|
|
70edd9a210 | ||
|
|
0a45b58784 | ||
|
|
dbd312c88d | ||
|
|
11578b1bc3 |
BIN
db/demo.zip
BIN
db/demo.zip
Binary file not shown.
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.51.1-beta",
|
||||
"version": "0.51.2",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
|
||||
@@ -71,7 +71,6 @@ export default class ButtonWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
|
||||
this.$widget
|
||||
.attr("title", this.settings.title)
|
||||
.addClass(this.settings.icon);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import ButtonWidget from "./button_widget.js";
|
||||
import appContext from "../../services/app_context.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
import protectedSessionHolder from "../../services/protected_session_holder.js";
|
||||
|
||||
export default class EditButton extends ButtonWidget {
|
||||
isEnabled() {
|
||||
@@ -22,9 +24,29 @@ export default class EditButton extends ButtonWidget {
|
||||
}
|
||||
|
||||
async refreshWithNote(note) {
|
||||
if (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||
this.toggleInt(false);
|
||||
}
|
||||
else {
|
||||
// prevent flickering by assuming hidden before async operation
|
||||
this.toggleInt(false);
|
||||
|
||||
// can't do this in isEnabled() since isReadOnly is async
|
||||
this.toggleInt(await this.noteContext.isReadOnly());
|
||||
}
|
||||
|
||||
await super.refreshWithNote(note);
|
||||
}
|
||||
|
||||
entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.getAttributes().find(
|
||||
attr => attr.type === 'label'
|
||||
&& attr.name.toLowerCase().includes("readonly")
|
||||
&& attributeService.isAffecting(attr, this.note)
|
||||
)) {
|
||||
this.noteContext.readOnlyTemporarilyDisabled = false;
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
await this.initialized;
|
||||
|
||||
this.textEditor.model.change(writer => {
|
||||
const insertPosition = this.textEditor.model.document.selection.getFirstPosition();
|
||||
const insertPosition = this.textEditor.model.document.selection.getLastPosition();
|
||||
writer.insertText(text, insertPosition);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import appContext from "../../services/app_context.js";
|
||||
|
||||
export default class TypeWidget extends NoteContextAwareWidget {
|
||||
// for overriding
|
||||
@@ -34,7 +35,7 @@ export default class TypeWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.$widget.is(":visible");
|
||||
return this.$widget.is(":visible") && this.noteContext?.ntxId === appContext.tabManager.activeNtxId;
|
||||
}
|
||||
|
||||
getContent() {}
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2022-04-22T00:07:59+02:00", buildRevision: "3b58b83f8bb93c04263081f60d75f211320ed065" };
|
||||
module.exports = { buildDate:"2022-05-01T23:18:35+02:00", buildRevision: "b3763eed610fa3f2aabbcbdbd21efca704a5dd08" };
|
||||
|
||||
@@ -10,7 +10,7 @@ const utils = require("../../utils");
|
||||
|
||||
// FIXME: create common subclass with NoteContentUnprotectedFulltextExp to avoid duplication
|
||||
class NoteContentProtectedFulltextExp extends Expression {
|
||||
constructor(operator, tokens, raw) {
|
||||
constructor(operator, {tokens, raw, flatText}) {
|
||||
super();
|
||||
|
||||
if (operator !== '*=*') {
|
||||
@@ -19,6 +19,7 @@ class NoteContentProtectedFulltextExp extends Expression {
|
||||
|
||||
this.tokens = tokens;
|
||||
this.raw = !!raw;
|
||||
this.flatText = !!flatText;
|
||||
}
|
||||
|
||||
execute(inputNoteSet) {
|
||||
@@ -33,7 +34,7 @@ class NoteContentProtectedFulltextExp extends Expression {
|
||||
for (let {noteId, type, mime, content} of sql.iterateRows(`
|
||||
SELECT noteId, type, mime, content
|
||||
FROM notes JOIN note_contents USING (noteId)
|
||||
WHERE type IN ('text', 'code') AND isDeleted = 0 AND isProtected = 1`)) {
|
||||
WHERE type IN ('text', 'code', 'mermaid') AND isDeleted = 0 AND isProtected = 1`)) {
|
||||
|
||||
if (!inputNoteSet.hasNoteId(noteId) || !(noteId in becca.notes)) {
|
||||
continue;
|
||||
@@ -49,7 +50,17 @@ class NoteContentProtectedFulltextExp extends Expression {
|
||||
|
||||
content = this.preprocessContent(content, type, mime);
|
||||
|
||||
if (!this.tokens.find(token => !content.includes(token))) {
|
||||
const nonMatchingToken = this.tokens.find(token =>
|
||||
!content.includes(token) &&
|
||||
(
|
||||
// in case of default fulltext search we should consider both title, attrs and content
|
||||
// so e.g. "hello world" should match when "hello" is in title and "world" in content
|
||||
!this.flatText
|
||||
|| !becca.notes[noteId].getFlatText().includes(token)
|
||||
)
|
||||
);
|
||||
|
||||
if (!nonMatchingToken) {
|
||||
resultNoteSet.add(becca.notes[noteId]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ const utils = require("../../utils");
|
||||
|
||||
// FIXME: create common subclass with NoteContentProtectedFulltextExp to avoid duplication
|
||||
class NoteContentUnprotectedFulltextExp extends Expression {
|
||||
constructor(operator, tokens, raw) {
|
||||
constructor(operator, {tokens, raw, flatText}) {
|
||||
super();
|
||||
|
||||
if (operator !== '*=*') {
|
||||
@@ -17,6 +17,7 @@ class NoteContentUnprotectedFulltextExp extends Expression {
|
||||
|
||||
this.tokens = tokens;
|
||||
this.raw = !!raw;
|
||||
this.flatText = !!flatText;
|
||||
}
|
||||
|
||||
execute(inputNoteSet) {
|
||||
@@ -27,7 +28,7 @@ class NoteContentUnprotectedFulltextExp extends Expression {
|
||||
for (let {noteId, type, mime, content} of sql.iterateRows(`
|
||||
SELECT noteId, type, mime, content
|
||||
FROM notes JOIN note_contents USING (noteId)
|
||||
WHERE type IN ('text', 'code') AND isDeleted = 0 AND isProtected = 0`)) {
|
||||
WHERE type IN ('text', 'code', 'mermaid') AND isDeleted = 0 AND isProtected = 0`)) {
|
||||
|
||||
if (!inputNoteSet.hasNoteId(noteId) || !(noteId in becca.notes)) {
|
||||
continue;
|
||||
@@ -35,7 +36,17 @@ class NoteContentUnprotectedFulltextExp extends Expression {
|
||||
|
||||
content = this.preprocessContent(content, type, mime);
|
||||
|
||||
if (!this.tokens.find(token => !content.includes(token))) {
|
||||
const nonMatchingToken = this.tokens.find(token =>
|
||||
!content.includes(token) &&
|
||||
(
|
||||
// in case of default fulltext search we should consider both title, attrs and content
|
||||
// so e.g. "hello world" should match when "hello" is in title and "world" in content
|
||||
!this.flatText
|
||||
|| !becca.notes[noteId].getFlatText().includes(token)
|
||||
)
|
||||
);
|
||||
|
||||
if (!nonMatchingToken) {
|
||||
resultNoteSet.add(becca.notes[noteId]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,8 @@ function getFulltext(tokens, searchContext) {
|
||||
if (!searchContext.fastSearch) {
|
||||
return new OrExp([
|
||||
new NoteFlatTextExp(tokens),
|
||||
new NoteContentProtectedFulltextExp('*=*', tokens),
|
||||
new NoteContentUnprotectedFulltextExp('*=*', tokens)
|
||||
new NoteContentProtectedFulltextExp('*=*', {tokens, flatText: true}),
|
||||
new NoteContentUnprotectedFulltextExp('*=*', {tokens, flatText: true})
|
||||
]);
|
||||
}
|
||||
else {
|
||||
@@ -141,8 +141,8 @@ function getExpression(tokens, searchContext, level = 0) {
|
||||
i++;
|
||||
|
||||
return new OrExp([
|
||||
new NoteContentUnprotectedFulltextExp(operator, [tokens[i].token], raw),
|
||||
new NoteContentProtectedFulltextExp(operator, [tokens[i].token], raw)
|
||||
new NoteContentUnprotectedFulltextExp(operator, {tokens: [tokens[i].token], raw }),
|
||||
new NoteContentProtectedFulltextExp(operator, {tokens: [tokens[i].token], raw })
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -196,8 +196,8 @@ function getExpression(tokens, searchContext, level = 0) {
|
||||
|
||||
return new OrExp([
|
||||
new PropertyComparisonExp(searchContext, 'title', '*=*', tokens[i].token),
|
||||
new NoteContentProtectedFulltextExp('*=*', [tokens[i].token]),
|
||||
new NoteContentUnprotectedFulltextExp('*=*', [tokens[i].token])
|
||||
new NoteContentProtectedFulltextExp('*=*', {tokens: [tokens[i].token]}),
|
||||
new NoteContentUnprotectedFulltextExp('*=*', {tokens: [tokens[i].token]})
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,16 +62,18 @@ function register(router) {
|
||||
});
|
||||
|
||||
router.get('/share/:shareId', (req, res, next) => {
|
||||
const {shareId} = req.params;
|
||||
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const {shareId} = req.params;
|
||||
|
||||
const note = shaca.aliasToNote[shareId] || shaca.notes[shareId];
|
||||
|
||||
renderNote(note, res);
|
||||
});
|
||||
|
||||
router.get('/share/api/notes/:noteId', (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const {noteId} = req.params;
|
||||
const note = shaca.getNote(noteId);
|
||||
|
||||
@@ -85,6 +87,8 @@ function register(router) {
|
||||
});
|
||||
|
||||
router.get('/share/api/notes/:noteId/download', (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const {noteId} = req.params;
|
||||
const note = shaca.getNote(noteId);
|
||||
|
||||
@@ -107,6 +111,8 @@ function register(router) {
|
||||
});
|
||||
|
||||
router.get('/share/api/images/:noteId/:filename', (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const image = shaca.getNote(req.params.noteId);
|
||||
|
||||
if (!image) {
|
||||
@@ -118,13 +124,15 @@ function register(router) {
|
||||
|
||||
addNoIndexHeader(image, res);
|
||||
|
||||
res.set('Content-Type', image.mime);
|
||||
res.setHeader('Content-Type', image.mime);
|
||||
|
||||
res.send(image.getContent());
|
||||
});
|
||||
|
||||
// used for PDF viewing
|
||||
router.get('/share/api/notes/:noteId/view', (req, res, next) => {
|
||||
shacaLoader.ensureLoad();
|
||||
|
||||
const {noteId} = req.params;
|
||||
const note = shaca.getNote(noteId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user