From 99c6d35ee70460b7efe3055825eaeacad203a5fe Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Wed, 27 Jun 2018 10:40:52 -0500 Subject: [PATCH 1/5] User prefs exist check --- app/assets/javascripts/app/services/authManager.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/app/services/authManager.js b/app/assets/javascripts/app/services/authManager.js index bcc4321b5..f5717e5e9 100644 --- a/app/assets/javascripts/app/services/authManager.js +++ b/app/assets/javascripts/app/services/authManager.js @@ -308,8 +308,10 @@ angular.module('app') } this.syncUserPreferences = function() { - this.userPreferences.setDirty(true); - $rootScope.sync("syncUserPreferences"); + if(this.userPreferences) { + this.userPreferences.setDirty(true); + $rootScope.sync("syncUserPreferences"); + } } this.getUserPrefValue = function(key, defaultValue) { From 6d3232a25bb58500faa90982a052f0d3772cfbd3 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Wed, 11 Jul 2018 11:59:48 -0500 Subject: [PATCH 2/5] Note existence check --- app/assets/javascripts/app/controllers/editor.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/assets/javascripts/app/controllers/editor.js b/app/assets/javascripts/app/controllers/editor.js index 39250180e..22afa6a8d 100644 --- a/app/assets/javascripts/app/controllers/editor.js +++ b/app/assets/javascripts/app/controllers/editor.js @@ -238,6 +238,14 @@ angular.module('app') this.saveNote = function($event) { var note = this.note; note.dummy = false; + + // Make sure the note exists. A safety measure, as toggling between tags triggers deletes for dummy notes. + // Race conditions have been fixed, but we'll keep this here just in case. + if(!modelManager.findItem(note.uuid)) { + alert("The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note."); + return; + } + this.save()(note, function(success){ if(success) { if(statusTimeout) $timeout.cancel(statusTimeout); From 3385306260c878564dafd267538ef43c0d485840 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Wed, 11 Jul 2018 16:45:00 -0500 Subject: [PATCH 3/5] Make component errors audible, perform state changes in timeout --- .../javascripts/app/controllers/editor.js | 14 ++++-- .../app/services/componentManager.js | 47 +++++++++++++++---- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/app/assets/javascripts/app/controllers/editor.js b/app/assets/javascripts/app/controllers/editor.js index 22afa6a8d..4022e18ae 100644 --- a/app/assets/javascripts/app/controllers/editor.js +++ b/app/assets/javascripts/app/controllers/editor.js @@ -516,11 +516,17 @@ angular.module('app') } else if(component.area == "editor-editor") { // An editor is already active, ensure the potential replacement is explicitely enabled for this item // We also check if the selectedEditor is active. If it's inactive, we want to treat it as an external reference wishing to deactivate this editor (i.e componentView) - if(this.selectedEditor && this.selectedEditor.active) { - if(component.isExplicitlyEnabledForItem(this.note)) { - this.selectedEditor = component; + if(this.selectedEditor && this.selectedEditor == component && component.active == false) { + this.selectedEditor = null; + } + else if(this.selectedEditor) { + if(this.selectedEditor.active) { + if(component.isExplicitlyEnabledForItem(this.note)) { + this.selectedEditor = component; + } } - } else { + } + else { // If no selected editor, let's see if the incoming one is a candidate if(component.active && this.note && (component.isExplicitlyEnabledForItem(this.note) || component.isDefaultEditor())) { this.selectedEditor = component; diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index a7d3eaaba..6135659c3 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -251,6 +251,11 @@ class ComponentManager { // Native extension running in web, prefix current host origin = window.location.href + origin; } + + if(!component.window) { + alert(`Standard Notes is trying to communicate with ${component.name}, but an error is occurring. Please restart this extension and try again.`) + } + component.window.postMessage(message, origin); } @@ -285,6 +290,7 @@ class ComponentManager { handleMessage(component, message) { if(!component) { + alert("An extension is trying to communicate with Standard Notes, but there is an error establishing a bridge. Please restart the app and try again."); if(this.loggingEnabled) { console.log("Component not defined, returning"); } @@ -748,13 +754,28 @@ class ComponentManager { this.postActiveThemeToComponent(component); } - activateComponent(component, dontSync = false) { + /* Performs func in timeout, but syncronously, if used `await waitTimeout` */ + async waitTimeout(func) { + return new Promise((resolve, reject) => { + this.timeout(() => { + func(); + resolve(); + }); + }) + } + + + async activateComponent(component, dontSync = false) { var didChange = component.active != true; component.active = true; for(var handler of this.handlers) { if(handler.areas.includes(component.area) || handler.areas.includes("*")) { - handler.activationHandler(component); + // We want to run the handler in a $timeout so the UI updates, but we also don't want it to run asyncronously + // so that the steps below this one are run before the handler. So we run in a waitTimeout. + await this.waitTimeout(() => { + handler.activationHandler(component); + }) } } @@ -772,14 +793,16 @@ class ComponentManager { } } - deactivateComponent(component, dontSync = false) { + async deactivateComponent(component, dontSync = false) { var didChange = component.active != false; component.active = false; component.sessionKey = null; - for(var handler of this.handlers) { + for(let handler of this.handlers) { if(handler.areas.includes(component.area) || handler.areas.includes("*")) { - handler.activationHandler(component); + await this.waitTimeout(() => { + handler.activationHandler(component); + }) } } @@ -803,15 +826,17 @@ class ComponentManager { } } - reloadComponent(component) { + async reloadComponent(component) { // // Do soft deactivate // component.active = false; - for(var handler of this.handlers) { + for(let handler of this.handlers) { if(handler.areas.includes(component.area) || handler.areas.includes("*")) { - handler.activationHandler(component); + await this.waitTimeout(() => { + handler.activationHandler(component); + }) } } @@ -831,11 +856,13 @@ class ComponentManager { // Do soft activate // - this.timeout(() => { + this.timeout(async () => { component.active = true; for(var handler of this.handlers) { if(handler.areas.includes(component.area) || handler.areas.includes("*")) { - handler.activationHandler(component); + await this.waitTimeout(() => { + handler.activationHandler(component); + }) } } From 5a4c508cf1d8663e0eaae77a366ab31e4a6cff07 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Thu, 12 Jul 2018 14:51:04 -0500 Subject: [PATCH 4/5] Add message to log --- app/assets/javascripts/app/services/componentManager.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index 6135659c3..3564f1d6a 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -290,10 +290,8 @@ class ComponentManager { handleMessage(component, message) { if(!component) { + console.log("Component not defined for message, returning", message); alert("An extension is trying to communicate with Standard Notes, but there is an error establishing a bridge. Please restart the app and try again."); - if(this.loggingEnabled) { - console.log("Component not defined, returning"); - } return; } From 517c30c246b61274ee37787f512720b4a73b8398 Mon Sep 17 00:00:00 2001 From: Mo Bitar Date: Thu, 12 Jul 2018 16:28:30 -0500 Subject: [PATCH 5/5] Ensure postMessage is for us --- app/assets/javascripts/app/services/componentManager.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/assets/javascripts/app/services/componentManager.js b/app/assets/javascripts/app/services/componentManager.js index 3564f1d6a..88acc5bb2 100644 --- a/app/assets/javascripts/app/services/componentManager.js +++ b/app/assets/javascripts/app/services/componentManager.js @@ -46,7 +46,11 @@ class ComponentManager { if(this.loggingEnabled) { console.log("Web app: received message", event); } - this.handleMessage(this.componentForSessionKey(event.data.sessionKey), event.data); + + // Make sure this message is for us + if(event.data.sessionKey) { + this.handleMessage(this.componentForSessionKey(event.data.sessionKey), event.data); + } }.bind(this), false); this.modelManager.addItemSyncObserver("component-manager", "*", (allItems, validItems, deletedItems, source, sourceKey) => {