diff --git a/src/public/app/services/ws.js b/src/public/app/services/ws.js index 89fcdebcc..6c4e6e160 100644 --- a/src/public/app/services/ws.js +++ b/src/public/app/services/ws.js @@ -37,6 +37,10 @@ function subscribeToMessages(messageHandler) { // used to serialize sync operations let consumeQueuePromise = null; +// most sync events are sent twice - once immediatelly after finishing the transaction and once during the scheduled ping +// but we want to process only once +const receivedSyncIds = new Set(); + async function handleMessage(event) { const message = JSON.parse(event.data); @@ -52,14 +56,19 @@ async function handleMessage(event) { if (syncRows.length > 0) { const filteredRows = syncRows.filter(row => - row.entityName !== 'recent_notes' + !receivedSyncIds.has(row.id) + && row.entityName !== 'recent_notes' && (row.entityName !== 'options' || row.entityId !== 'openTabs')); if (filteredRows.length > 0) { console.debug(utils.now(), "Sync data: ", filteredRows); } - syncDataQueue.push(...syncRows); + for (const row of filteredRows) { + receivedSyncIds.add(row.id); + } + + syncDataQueue.push(...filteredRows); // we set lastAcceptedSyncId even before sync processing and send ping so that backend can start sending more updates lastAcceptedSyncId = Math.max(lastAcceptedSyncId, syncRows[syncRows.length - 1].id); diff --git a/src/public/app/widgets/note_tree.js b/src/public/app/widgets/note_tree.js index 69cb8a93c..e7c8a6c52 100644 --- a/src/public/app/widgets/note_tree.js +++ b/src/public/app/widgets/note_tree.js @@ -804,7 +804,9 @@ export default class NoteTreeWidget extends TabAwareWidget { async entitiesReloadedEvent({loadResults}) { const activeNode = this.getActiveNode(); + const nextNode = activeNode ? (activeNode.getNextSibling() || activeNode.getPrevSibling() || activeNode.getParent()) : null; const activeNotePath = activeNode ? treeService.getNotePath(activeNode) : null; + const nextNotePath = nextNode ? treeService.getNotePath(nextNode) : null; const activeNoteId = activeNode ? activeNode.data.noteId : null; const noteIdsToUpdate = new Set(); @@ -926,6 +928,17 @@ export default class NoteTreeWidget extends TabAwareWidget { if (node) { node.setActive(true, {noEvents: true}); } + else { + // this is used when original note has been deleted and we want to move the focus to the note above/below + node = await this.expandToNote(nextNotePath); + + if (node) { + this.tree.setFocus(); + node.setFocus(true); + + await appContext.tabManager.getActiveTabContext().setNote(nextNotePath); + } + } } } diff --git a/src/public/app/widgets/tab_row.js b/src/public/app/widgets/tab_row.js index 0ae79bcc5..ba8ee27fc 100644 --- a/src/public/app/widgets/tab_row.js +++ b/src/public/app/widgets/tab_row.js @@ -614,6 +614,7 @@ export default class TabRowWidget extends BasicWidget { if (!note) { this.updateTitle($tab, 'New tab'); + return; } this.updateTitle($tab, note.title); diff --git a/src/services/sql.js b/src/services/sql.js index 325dbc292..179b35103 100644 --- a/src/services/sql.js +++ b/src/services/sql.js @@ -221,6 +221,7 @@ async function transactional(func) { await commit(); + // note that sync rows sent from this action will be sent again by scheduled periodic ping require('./ws.js').sendPingToAllClients(); transactionActive = false; @@ -267,4 +268,4 @@ module.exports = { executeScript, transactional, upsert -}; \ No newline at end of file +};