diff --git a/src/services/content_hash.js b/src/services/content_hash.js index d3320a057..d887ad1ef 100644 --- a/src/services/content_hash.js +++ b/src/services/content_hash.js @@ -12,6 +12,7 @@ const Attribute = require('../entities/attribute'); const NoteRevision = require('../entities/note_revision'); const RecentNote = require('../entities/recent_note'); const Option = require('../entities/option'); +const Link = require('../entities/link'); async function getHash(entityConstructor, whereBranch) { // subselect is necessary to have correct ordering in GROUP_CONCAT @@ -37,7 +38,8 @@ async function getHashes() { recent_notes: await getHash(RecentNote), options: await getHash(Option, "isSynced = 1"), attributes: await getHash(Attribute), - api_tokens: await getHash(ApiToken) + api_tokens: await getHash(ApiToken), + links: await getHash(Link) }; const elapseTimeMs = new Date().getTime() - startTime.getTime(); diff --git a/src/services/events.js b/src/services/events.js index 7921e92b4..d43e4bf57 100644 --- a/src/services/events.js +++ b/src/services/events.js @@ -5,13 +5,24 @@ const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION"; const ENTITY_CREATED = "ENTITY_CREATED"; const ENTITY_CHANGED = "ENTITY_CHANGED"; const ENTITY_DELETED = "ENTITY_DELETED"; +const ENTITY_SYNCED = "ENTITY_SYNCED"; const CHILD_NOTE_CREATED = "CHILD_NOTE_CREATED"; const eventListeners = {}; -function subscribe(eventType, listener) { - eventListeners[eventType] = eventListeners[eventType] || []; - eventListeners[eventType].push(listener); +/** + * @param eventTypes - can be either single event or an array of events + * @param listener + */ +function subscribe(eventTypes, listener) { + if (!Array.isArray(eventTypes)) { + eventTypes = [ eventTypes ]; + } + + for (const eventType of eventTypes) { + eventListeners[eventType] = eventListeners[eventType] || []; + eventListeners[eventType].push(listener); + } } async function emit(eventType, data) { @@ -39,5 +50,6 @@ module.exports = { ENTITY_CREATED, ENTITY_CHANGED, ENTITY_DELETED, + ENTITY_SYNCED, CHILD_NOTE_CREATED }; \ No newline at end of file diff --git a/src/services/note_cache.js b/src/services/note_cache.js index 5f98cf11b..e30aa87a5 100644 --- a/src/services/note_cache.js +++ b/src/services/note_cache.js @@ -299,7 +299,9 @@ function getNotePath(noteId) { } } -eventService.subscribe(eventService.ENTITY_CHANGED, async ({entityName, entity}) => { +eventService.subscribe([eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED, eventService.ENTITY_SYNCED], async ({entityName, entity}) => { + // note that entity can also be just POJO without methods if coming from sync + if (!loaded) { return; } diff --git a/src/services/sync_update.js b/src/services/sync_update.js index 826aa1a36..630f95ebc 100644 --- a/src/services/sync_update.js +++ b/src/services/sync_update.js @@ -2,6 +2,7 @@ const sql = require('./sql'); const log = require('./log'); const eventLogService = require('./event_log'); const syncTableService = require('./sync_table'); +const eventService = require('./events'); async function updateEntity(sync, entity, sourceId) { const {entityName} = sync; @@ -36,6 +37,15 @@ async function updateEntity(sync, entity, sourceId) { else { throw new Error(`Unrecognized entity type ${entityName}`); } + + // currently making exception for protected notes and note revisions because here + // the title and content are not available decrypted as listeners would expect + if ((entityName !== 'notes' && entityName !== 'note_revisions') || !entity.isProtected) { + await eventService.emit(eventService.ENTITY_SYNCED, { + entityName, + entity + }); + } } function deserializeNoteContentBuffer(note) {