reloading notes after script changes

This commit is contained in:
zadam 2019-10-20 12:29:34 +02:00
parent 78f5b7b288
commit 2305ad7405
21 changed files with 115 additions and 82 deletions

View file

@ -1581,7 +1581,7 @@
<h4 class="name" id="getActiveNote"><span class="type-signature"></span>getActiveNote<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="NoteFull.html">NoteFull</a>}</span></h4>
<h4 class="name" id="getActiveTabNote"><span class="type-signature"></span>getActiveTabNote<span class="signature">()</span><span class="type-signature"> &rarr; {<a href="NoteFull.html">NoteFull</a>}</span></h4>
@ -1687,7 +1687,7 @@
<h4 class="name" id="getActiveNotePath"><span class="type-signature"></span>getActiveNotePath<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;(string|null)>}</span></h4>
<h4 class="name" id="getActiveTabNotePath"><span class="type-signature"></span>getActiveTabNotePath<span class="signature">()</span><span class="type-signature"> &rarr; {Promise.&lt;(string|null)>}</span></h4>

View file

@ -236,7 +236,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @param {string} noteId
* @method
*/
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId);
this.reloadChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
/**
* @param {string} noteId
@ -303,13 +303,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method
* @returns {NoteFull} active note (loaded into right pane)
*/
this.getActiveNote = noteDetailService.getActiveNote;
this.getActiveTabNote = noteDetailService.getActiveTabNote;
/**
* @method
* @returns {Promise&lt;string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveNotePath = () => {
this.getActiveTabNotePath = () => {
const activeTabContext = noteDetailService.getActiveTabContext();
return activeTabContext ? activeTabContext.notePath : null;

View file

@ -29,8 +29,8 @@
async function validatorJavaScript(text, options) {
if (glob.isMobile()
|| glob.getActiveNote() == null
|| glob.getActiveNote().mime === 'application/json') {
|| glob.getActiveTabNote() == null
|| glob.getActiveTabNote().mime === 'application/json') {
// eslint doesn't seem to validate pure JSON well
return [];
}

View file

@ -43,7 +43,7 @@ window.glob.noteChanged = noteDetailService.noteChanged;
window.glob.refreshTree = treeService.reload;
// required for ESLint plugin
window.glob.getActiveNote = noteDetailService.getActiveNote;
window.glob.getActiveTabNote = noteDetailService.getActiveTabNote;
window.glob.requireLibrary = libraryLoader.requireLibrary;
window.glob.ESLINT = libraryLoader.ESLINT;

View file

@ -33,7 +33,7 @@ export async function showDialog(linkType) {
glob.activeDialog = $dialog;
if (noteDetailService.getActiveNoteType() === 'text') {
if (noteDetailService.getActiveTabNoteType() === 'text') {
$linkTypeHtml.prop('disabled', false);
setLinkType('html');
@ -110,14 +110,14 @@ $form.submit(() => {
else if (linkType === 'selected-to-active') {
const prefix = $clonePrefix.val();
cloningService.cloneNoteTo(noteId, noteDetailService.getActiveNoteId(), prefix);
cloningService.cloneNoteTo(noteId, noteDetailService.getActiveTabNoteId(), prefix);
$dialog.modal('hide');
}
else if (linkType === 'active-to-selected') {
const prefix = $clonePrefix.val();
cloningService.cloneNoteTo(noteDetailService.getActiveNoteId(), noteId, prefix);
cloningService.cloneNoteTo(noteDetailService.getActiveTabNoteId(), noteId, prefix);
$dialog.modal('hide');
}

View file

@ -92,7 +92,7 @@ function AttributesModel() {
}
this.loadAttributes = async function() {
const noteId = noteDetailService.getActiveNoteId();
const noteId = noteDetailService.getActiveTabNoteId();
const attributes = await server.get('notes/' + noteId + '/attributes');
@ -138,7 +138,7 @@ function AttributesModel() {
self.updateAttributePositions();
const noteId = noteDetailService.getActiveNoteId();
const noteId = noteDetailService.getActiveTabNoteId();
const attributesToSave = self.ownedAttributes()
.map(attribute => attribute())

View file

@ -23,7 +23,7 @@ export async function showDialog() {
// set default settings
$maxNotesInput.val(20);
const note = noteDetailService.getActiveNote();
const note = noteDetailService.getActiveTabNote();
if (!note) {
return;

View file

@ -16,7 +16,7 @@ export function showDialog() {
$dialog.modal();
const activeNote = noteDetailService.getActiveNote();
const activeNote = noteDetailService.getActiveTabNote();
$noteId.text(activeNote.noteId);
$dateCreated.text(activeNote.dateCreated);

View file

@ -11,7 +11,7 @@ let revisionItems = [];
let note;
export async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(noteDetailService.getActiveNoteId());
await showNoteRevisionsDialog(noteDetailService.getActiveTabNoteId());
}
export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
@ -24,7 +24,7 @@ export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
$list.empty();
$content.empty();
note = noteDetailService.getActiveNote();
note = noteDetailService.getActiveTabNote();
revisionItems = await server.get('notes/' + noteId + '/revisions');
for (const item of revisionItems) {

View file

@ -11,7 +11,7 @@ export function showDialog() {
$dialog.modal();
const noteText = noteDetailService.getActiveNote().content;
const noteText = noteDetailService.getActiveTabNote().content;
$noteSource.text(formatHtml(noteText));
}

View file

@ -162,9 +162,7 @@ async function deleteNodes(nodes) {
node.remove();
}
for (const parentNoteId of parentNoteIds) {
await treeService.reloadNote(parentNoteId);
}
await treeService.reloadNotes(parentNoteIds);
// activate after all the reloading
if (activeNotePath) {

View file

@ -14,7 +14,7 @@ async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
treeCache.addBranchRelationship(resp.branchId, childNoteId, parentNoteId);
await treeService.reloadNote(parentNoteId);
await treeService.reloadNotes([parentNoteId]);
}
// beware that first arg is noteId and second is branchId!
@ -30,7 +30,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
treeCache.addBranchRelationship(resp.branchId, noteId, afterBranch.parentNoteId);
await treeService.reloadNote(afterBranch.parentNoteId);
await treeService.reloadNotes([afterBranch.parentNoteId]);
}
export default {

View file

@ -210,7 +210,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @param {string} noteId
* @method
*/
this.reloadChildren = async noteId => await treeCache.reloadChildren(noteId);
this.reloadNotesAndTheirChildren = async noteId => await treeCache.reloadNotesAndTheirChildren(noteId);
/**
* @param {string} noteId
@ -277,17 +277,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method
* @returns {NoteFull} active note (loaded into right pane)
*/
this.getActiveNote = noteDetailService.getActiveNote;
this.getActiveTabNote = noteDetailService.getActiveTabNote;
/**
* @method
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveNotePath = () => {
const activeTabContext = noteDetailService.getActiveTabContext();
return activeTabContext ? activeTabContext.notePath : null;
};
this.getActiveTabNotePath = noteDetailService.getActiveTabNotePath;
/**
* This method checks whether user navigated away from the note from which the scripts has been started.

View file

@ -63,7 +63,7 @@ ws.subscribeToMessages(async message => {
toastService.showPersistent(toast);
await treeService.reloadNote(message.parentNoteId);
await treeService.reloadNotes([message.parentNoteId]);
if (message.result.importedNoteId) {
const node = await treeService.activateNote(message.result.importedNoteId);

View file

@ -8,7 +8,7 @@ const SELECTED_PATH_KEY = "data-note-path";
async function autocompleteSource(term, cb) {
const result = await server.get('autocomplete'
+ '?query=' + encodeURIComponent(term)
+ '&activeNoteId=' + noteDetailService.getActiveNoteId());
+ '&activeNoteId=' + noteDetailService.getActiveTabNoteId());
if (result.length === 0) {
result.push({

View file

@ -107,20 +107,26 @@ function getActiveTabContext() {
return tabContexts.find(tc => tc.tabId === tabId);
}
/** @returns {string|null} */
function getActiveTabNotePath() {
const activeContext = getActiveTabContext();
return activeContext ? activeContext.notePath : null;
}
/** @return {NoteFull} */
function getActiveNote() {
function getActiveTabNote() {
const activeContext = getActiveTabContext();
return activeContext ? activeContext.note : null;
}
function getActiveNoteId() {
const activeNote = getActiveNote();
function getActiveTabNoteId() {
const activeNote = getActiveTabNote();
return activeNote ? activeNote.noteId : null;
}
function getActiveNoteType() {
const activeNote = getActiveNote();
function getActiveTabNoteType() {
const activeNote = getActiveTabNote();
return activeNote ? activeNote.type : null;
}
@ -300,7 +306,7 @@ function addDetailLoadedListener(noteId, callback) {
function fireDetailLoaded() {
for (const {noteId, callback} of detailLoadedListeners) {
if (noteId === getActiveNoteId()) {
if (noteId === getActiveTabNoteId()) {
callback();
}
}
@ -337,7 +343,7 @@ $tabContentsContainer.on("dragover", e => e.preventDefault());
$tabContentsContainer.on("dragleave", e => e.preventDefault());
$tabContentsContainer.on("drop", async e => {
const activeNote = getActiveNote();
const activeNote = getActiveTabNote();
if (!activeNote) {
return;
@ -497,9 +503,6 @@ export default {
switchToNote,
loadNote,
loadNoteDetail,
getActiveNote,
getActiveNoteType,
getActiveNoteId,
focusOnTitle,
focusAndSelectTitle,
saveNotesIfChanged,
@ -508,6 +511,10 @@ export default {
switchToTab,
getTabContexts,
getActiveTabContext,
getActiveTabNotePath,
getActiveTabNote,
getActiveTabNoteType,
getActiveTabNoteId,
getActiveEditor,
activateOrOpenNote,
clearOpenTabsTask,

View file

@ -70,13 +70,13 @@ async function enterProtectedSessionOnServer(password) {
}
async function protectNoteAndSendToServer() {
if (!noteDetailService.getActiveNote() || noteDetailService.getActiveNote().isProtected) {
if (!noteDetailService.getActiveTabNote() || noteDetailService.getActiveTabNote().isProtected) {
return;
}
await enterProtectedSession();
const note = noteDetailService.getActiveNote();
const note = noteDetailService.getActiveTabNote();
note.isProtected = true;
await noteDetailService.getActiveTabContext().saveNote();
@ -87,7 +87,7 @@ async function protectNoteAndSendToServer() {
}
async function unprotectNoteAndSendToServer() {
const activeNote = noteDetailService.getActiveNote();
const activeNote = noteDetailService.getActiveTabNote();
if (!activeNote.isProtected) {
toastService.showAndLogError(`Note ${activeNote.noteId} is not protected`);

View file

@ -580,14 +580,11 @@ async function scrollToActiveNote() {
}
}
function setBranchBackgroundBasedOnProtectedStatus(noteId) {
getNodesByNoteId(noteId).map(node => node.toggleClass("protected", node.data.isProtected));
}
function setProtected(noteId, isProtected) {
getNodesByNoteId(noteId).map(node => node.data.isProtected = isProtected);
setBranchBackgroundBasedOnProtectedStatus(noteId);
getNodesByNoteId(noteId).map(node => {
node.data.isProtected = isProtected;
node.toggleClass("protected", isProtected);
});
}
async function setNoteTitle(noteId, title) {
@ -619,7 +616,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
extraOptions.isProtected = false;
}
if (noteDetailService.getActiveNoteType() !== 'text') {
if (noteDetailService.getActiveTabNoteType() !== 'text') {
extraOptions.saveSelection = false;
}
else {
@ -762,13 +759,27 @@ ws.subscribeToMessages(message => {
});
ws.subscribeToOutsideSyncMessages(syncData => {
if (syncData.some(sync => sync.entityName === 'branches')
|| syncData.some(sync => sync.entityName === 'notes')) {
const noteIdsToRefresh = [];
console.log(utils.now(), "Reloading tree because of background changes");
reload();
for (const sync of syncData.filter(sync => sync.entityName === 'branches')) {
if (!noteIdsToRefresh.includes(sync.parentNoteId)) {
noteIdsToRefresh.push(sync.parentNoteId);
}
}
for (const sync of syncData.filter(sync => sync.entityName === 'notes')) {
if (!noteIdsToRefresh.includes(sync.noteId)) {
noteIdsToRefresh.push(sync.noteId);
}
}
for (const sync of syncData.filter(sync => sync.entityName === 'note_reordering')) {
if (!noteIdsToRefresh.includes(sync.entityId)) {
noteIdsToRefresh.push(sync.entityId);
}
}
reloadNotes(noteIdsToRefresh);
});
utils.bindGlobalShortcut('ctrl+o', async () => {
@ -805,13 +816,25 @@ async function checkFolderStatus(node) {
node.renderTitle();
}
async function reloadNote(noteId) {
await treeCache.reloadChildren(noteId);
async function reloadNotes(noteIds) {
await treeCache.reloadNotesAndTheirChildren(noteIds);
for (const node of getNodesByNoteId(noteId)) {
await node.load(true);
const activeNotePath = noteDetailService.getActiveTabNotePath();
await checkFolderStatus(node);
for (const noteId of noteIds) {
for (const node of getNodesByNoteId(noteId)) {
await node.load(true);
await checkFolderStatus(node);
}
}
if (activeNotePath) {
const node = await getNodeFromPath(activeNotePath);
if (node) {
node.setActive(true, {noEvents: true}); // this node has been already active so no need to fire events again
}
}
}
@ -868,7 +891,6 @@ frontendLoaded.then(bundle.executeStartupBundles);
export default {
reload,
collapseTree,
setBranchBackgroundBasedOnProtectedStatus,
setProtected,
activateNote,
getFocusedNode,
@ -887,7 +909,7 @@ export default {
setExpandedToServer,
getNodesByNoteId,
checkFolderStatus,
reloadNote,
reloadNotes,
loadTreeCache,
expandToNote,
getNodeFromPath,

View file

@ -54,24 +54,27 @@ class TreeCache {
}
/**
* Reload children of given noteId.
* Reload notes and their children.
*/
async reloadChildren(noteId) {
const resp = await server.post('tree/load', { noteIds: [noteId] });
async reloadNotesAndTheirChildren(noteIds) {
// first load the data before clearing the cache
const resp = await server.post('tree/load', { noteIds });
for (const childNoteId of this.children[noteId] || []) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
for (const noteId of noteIds) {
for (const childNoteId of this.children[noteId] || []) {
this.parents[childNoteId] = this.parents[childNoteId].filter(p => p !== noteId);
const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
const branchId = this.getBranchIdByChildParent(childNoteId, noteId);
delete this.branches[branchId];
delete this.childParentToBranch[childNoteId + '-' + noteId];
delete this.branches[branchId];
delete this.childParentToBranch[childNoteId + '-' + noteId];
}
this.children[noteId] = [];
delete this.notes[noteId];
}
this.children[noteId] = [];
delete this.notes[noteId];
this.addResp(resp.notes, resp.branches, resp.relations);
}
@ -83,12 +86,10 @@ class TreeCache {
// to be able to find parents we need first to make sure it is actually loaded
await this.getNote(noteId);
for (const parentNoteId of this.parents[noteId] || []) {
await this.reloadChildren(parentNoteId);
}
await this.reloadNotesAndTheirChildren(this.parents[noteId] || []);
// this is done to load the new parents for the noteId
await this.reloadChildren(noteId);
await this.reloadNotesAndTheirChildren([noteId]);
}
/** @return {Promise<NoteShort[]>} */

View file

@ -863,12 +863,14 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
position: absolute;
width: 100%;
top: 20px;
z-index: -100;
pointer-events: none;
}
.toast {
background-color: var(--accented-background-color) !important;
color: var(--main-text-color) !important;
z-index: 9999999999 !important;
pointer-events: all;
}
.toast-header {

View file

@ -67,12 +67,19 @@ async function sendPing(client, lastSentSyncId) {
const syncData = await sql.getRows("SELECT * FROM sync WHERE id > ?", [lastSentSyncId]);
for (const sync of syncData) {
// fill in some extra data needed by the frontend
if (sync.entityName === 'attributes') {
sync.noteId = await sql.getValue(`SELECT noteId FROM attributes WHERE attributeId = ?`, [sync.entityId]);
}
else if (sync.entityName === 'note_revisions') {
sync.noteId = await sql.getValue(`SELECT noteId FROM note_revisions WHERE noteRevisionId = ?`, [sync.entityId]);
}
else if (sync.entityName === 'branches') {
const {noteId, parentNoteId} = await sql.getRow(`SELECT noteId, parentNoteId FROM branches WHERE branchId = ?`, [sync.entityId]);
sync.noteId = noteId;
sync.parentNoteId = parentNoteId;
}
}
const stats = require('./sync').stats;