mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +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", |   "name": "trilium", | ||||||
|   "productName": "Trilium Notes", |   "productName": "Trilium Notes", | ||||||
|   "description": "Trilium Notes", |   "description": "Trilium Notes", | ||||||
|   "version": "0.51.1-beta", |   "version": "0.51.2", | ||||||
|   "license": "AGPL-3.0-only", |   "license": "AGPL-3.0-only", | ||||||
|   "main": "electron.js", |   "main": "electron.js", | ||||||
|   "bin": { |   "bin": { | ||||||
|   | |||||||
| @@ -71,7 +71,6 @@ export default class ButtonWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         this.$widget |         this.$widget | ||||||
|             .attr("title", this.settings.title) |  | ||||||
|             .addClass(this.settings.icon); |             .addClass(this.settings.icon); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,5 +1,7 @@ | |||||||
| import ButtonWidget from "./button_widget.js"; | import ButtonWidget from "./button_widget.js"; | ||||||
| import appContext from "../../services/app_context.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 { | export default class EditButton extends ButtonWidget { | ||||||
|     isEnabled() { |     isEnabled() { | ||||||
| @@ -22,9 +24,29 @@ export default class EditButton extends ButtonWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async refreshWithNote(note) { |     async refreshWithNote(note) { | ||||||
|         // can't do this in isEnabled() since isReadOnly is async |         if (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) { | ||||||
|         this.toggleInt(await this.noteContext.isReadOnly()); |             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); |         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; |         await this.initialized; | ||||||
|  |  | ||||||
|         this.textEditor.model.change(writer => { |         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); |             writer.insertText(text, insertPosition); | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| import NoteContextAwareWidget from "../note_context_aware_widget.js"; | import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||||
|  | import appContext from "../../services/app_context.js"; | ||||||
|  |  | ||||||
| export default class TypeWidget extends NoteContextAwareWidget { | export default class TypeWidget extends NoteContextAwareWidget { | ||||||
|     // for overriding |     // for overriding | ||||||
| @@ -34,7 +35,7 @@ export default class TypeWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     isActive() { |     isActive() { | ||||||
|         return this.$widget.is(":visible"); |         return this.$widget.is(":visible") && this.noteContext?.ntxId === appContext.tabManager.activeNtxId; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     getContent() {} |     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 | // FIXME: create common subclass with NoteContentUnprotectedFulltextExp to avoid duplication | ||||||
| class NoteContentProtectedFulltextExp extends Expression { | class NoteContentProtectedFulltextExp extends Expression { | ||||||
|     constructor(operator, tokens, raw) { |     constructor(operator, {tokens, raw, flatText}) { | ||||||
|         super(); |         super(); | ||||||
|  |  | ||||||
|         if (operator !== '*=*') { |         if (operator !== '*=*') { | ||||||
| @@ -19,6 +19,7 @@ class NoteContentProtectedFulltextExp extends Expression { | |||||||
|  |  | ||||||
|         this.tokens = tokens; |         this.tokens = tokens; | ||||||
|         this.raw = !!raw; |         this.raw = !!raw; | ||||||
|  |         this.flatText = !!flatText; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     execute(inputNoteSet) { |     execute(inputNoteSet) { | ||||||
| @@ -33,7 +34,7 @@ class NoteContentProtectedFulltextExp extends Expression { | |||||||
|         for (let {noteId, type, mime, content} of sql.iterateRows(` |         for (let {noteId, type, mime, content} of sql.iterateRows(` | ||||||
|                 SELECT noteId, type, mime, content  |                 SELECT noteId, type, mime, content  | ||||||
|                 FROM notes JOIN note_contents USING (noteId)  |                 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)) { |             if (!inputNoteSet.hasNoteId(noteId) || !(noteId in becca.notes)) { | ||||||
|                 continue; |                 continue; | ||||||
| @@ -49,7 +50,17 @@ class NoteContentProtectedFulltextExp extends Expression { | |||||||
|  |  | ||||||
|             content = this.preprocessContent(content, type, mime); |             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]); |                 resultNoteSet.add(becca.notes[noteId]); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ const utils = require("../../utils"); | |||||||
|  |  | ||||||
| // FIXME: create common subclass with NoteContentProtectedFulltextExp to avoid duplication | // FIXME: create common subclass with NoteContentProtectedFulltextExp to avoid duplication | ||||||
| class NoteContentUnprotectedFulltextExp extends Expression { | class NoteContentUnprotectedFulltextExp extends Expression { | ||||||
|     constructor(operator, tokens, raw) { |     constructor(operator, {tokens, raw, flatText}) { | ||||||
|         super(); |         super(); | ||||||
|  |  | ||||||
|         if (operator !== '*=*') { |         if (operator !== '*=*') { | ||||||
| @@ -17,6 +17,7 @@ class NoteContentUnprotectedFulltextExp extends Expression { | |||||||
|  |  | ||||||
|         this.tokens = tokens; |         this.tokens = tokens; | ||||||
|         this.raw = !!raw; |         this.raw = !!raw; | ||||||
|  |         this.flatText = !!flatText; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     execute(inputNoteSet) { |     execute(inputNoteSet) { | ||||||
| @@ -27,7 +28,7 @@ class NoteContentUnprotectedFulltextExp extends Expression { | |||||||
|         for (let {noteId, type, mime, content} of sql.iterateRows(` |         for (let {noteId, type, mime, content} of sql.iterateRows(` | ||||||
|                 SELECT noteId, type, mime, content  |                 SELECT noteId, type, mime, content  | ||||||
|                 FROM notes JOIN note_contents USING (noteId)  |                 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)) { |             if (!inputNoteSet.hasNoteId(noteId) || !(noteId in becca.notes)) { | ||||||
|                 continue; |                 continue; | ||||||
| @@ -35,7 +36,17 @@ class NoteContentUnprotectedFulltextExp extends Expression { | |||||||
|  |  | ||||||
|             content = this.preprocessContent(content, type, mime); |             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]); |                 resultNoteSet.add(becca.notes[noteId]); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -32,8 +32,8 @@ function getFulltext(tokens, searchContext) { | |||||||
|     if (!searchContext.fastSearch) { |     if (!searchContext.fastSearch) { | ||||||
|         return new OrExp([ |         return new OrExp([ | ||||||
|             new NoteFlatTextExp(tokens), |             new NoteFlatTextExp(tokens), | ||||||
|             new NoteContentProtectedFulltextExp('*=*', tokens), |             new NoteContentProtectedFulltextExp('*=*', {tokens, flatText: true}), | ||||||
|             new NoteContentUnprotectedFulltextExp('*=*', tokens) |             new NoteContentUnprotectedFulltextExp('*=*', {tokens, flatText: true}) | ||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
| @@ -141,8 +141,8 @@ function getExpression(tokens, searchContext, level = 0) { | |||||||
|             i++; |             i++; | ||||||
|  |  | ||||||
|             return new OrExp([ |             return new OrExp([ | ||||||
|                 new NoteContentUnprotectedFulltextExp(operator, [tokens[i].token], raw), |                 new NoteContentUnprotectedFulltextExp(operator, {tokens: [tokens[i].token], raw }), | ||||||
|                 new NoteContentProtectedFulltextExp(operator, [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([ |             return new OrExp([ | ||||||
|                 new PropertyComparisonExp(searchContext, 'title', '*=*', tokens[i].token), |                 new PropertyComparisonExp(searchContext, 'title', '*=*', tokens[i].token), | ||||||
|                 new NoteContentProtectedFulltextExp('*=*', [tokens[i].token]), |                 new NoteContentProtectedFulltextExp('*=*', {tokens: [tokens[i].token]}), | ||||||
|                 new NoteContentUnprotectedFulltextExp('*=*', [tokens[i].token]) |                 new NoteContentUnprotectedFulltextExp('*=*', {tokens: [tokens[i].token]}) | ||||||
|             ]); |             ]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -62,16 +62,18 @@ function register(router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get('/share/:shareId', (req, res, next) => { |     router.get('/share/:shareId', (req, res, next) => { | ||||||
|         const {shareId} = req.params; |  | ||||||
|  |  | ||||||
|         shacaLoader.ensureLoad(); |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|  |         const {shareId} = req.params; | ||||||
|  |  | ||||||
|         const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; |         const note = shaca.aliasToNote[shareId] || shaca.notes[shareId]; | ||||||
|  |  | ||||||
|         renderNote(note, res); |         renderNote(note, res); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get('/share/api/notes/:noteId', (req, res, next) => { |     router.get('/share/api/notes/:noteId', (req, res, next) => { | ||||||
|  |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const {noteId} = req.params; |         const {noteId} = req.params; | ||||||
|         const note = shaca.getNote(noteId); |         const note = shaca.getNote(noteId); | ||||||
|  |  | ||||||
| @@ -85,6 +87,8 @@ function register(router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get('/share/api/notes/:noteId/download', (req, res, next) => { |     router.get('/share/api/notes/:noteId/download', (req, res, next) => { | ||||||
|  |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const {noteId} = req.params; |         const {noteId} = req.params; | ||||||
|         const note = shaca.getNote(noteId); |         const note = shaca.getNote(noteId); | ||||||
|  |  | ||||||
| @@ -107,6 +111,8 @@ function register(router) { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     router.get('/share/api/images/:noteId/:filename', (req, res, next) => { |     router.get('/share/api/images/:noteId/:filename', (req, res, next) => { | ||||||
|  |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const image = shaca.getNote(req.params.noteId); |         const image = shaca.getNote(req.params.noteId); | ||||||
|  |  | ||||||
|         if (!image) { |         if (!image) { | ||||||
| @@ -118,13 +124,15 @@ function register(router) { | |||||||
|  |  | ||||||
|         addNoIndexHeader(image, res); |         addNoIndexHeader(image, res); | ||||||
|  |  | ||||||
|         res.set('Content-Type', image.mime); |         res.setHeader('Content-Type', image.mime); | ||||||
|  |  | ||||||
|         res.send(image.getContent()); |         res.send(image.getContent()); | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     // used for PDF viewing |     // used for PDF viewing | ||||||
|     router.get('/share/api/notes/:noteId/view', (req, res, next) => { |     router.get('/share/api/notes/:noteId/view', (req, res, next) => { | ||||||
|  |         shacaLoader.ensureLoad(); | ||||||
|  |  | ||||||
|         const {noteId} = req.params; |         const {noteId} = req.params; | ||||||
|         const note = shaca.getNote(noteId); |         const note = shaca.getNote(noteId); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user