Remove packageManager, clean up actionsManager, component manager check is sys ext, clean footer hide/show rooms

This commit is contained in:
Mo Bitar
2018-01-24 11:19:47 -06:00
parent 334a6082a9
commit 2d2693597c
9 changed files with 55 additions and 184 deletions

View File

@@ -23,7 +23,7 @@ angular.module('app')
} }
}) })
.controller('FooterCtrl', function ($rootScope, authManager, modelManager, $timeout, dbManager, .controller('FooterCtrl', function ($rootScope, authManager, modelManager, $timeout, dbManager,
syncManager, storageManager, passcodeManager, componentManager, singletonManager, packageManager) { syncManager, storageManager, passcodeManager, componentManager, singletonManager) {
this.getUser = function() { this.getUser = function() {
return authManager.user; return authManager.user;
@@ -47,12 +47,13 @@ angular.module('app')
this.showAccountMenu = false; this.showAccountMenu = false;
}.bind(this) }.bind(this)
this.closeAccountMenu = () => {
this.showAccountMenu = false;
}
this.accountMenuPressed = function() { this.accountMenuPressed = function() {
this.showAccountMenu = !this.showAccountMenu; this.showAccountMenu = !this.showAccountMenu;
this.closeAllRooms();
}
this.closeAccountMenu = () => {
this.showAccountMenu = false;
} }
this.hasPasscode = function() { this.hasPasscode = function() {
@@ -112,7 +113,7 @@ angular.module('app')
if(component.active) { if(component.active) {
// Show room, if it was not activated manually (in the event of event from componentManager) // Show room, if it was not activated manually (in the event of event from componentManager)
if(component.area == "rooms" && !component.showRoom) { if(component.area == "rooms" && !component.showRoom) {
this.selectRoom(component); component.showRoom = true;
} }
$timeout(() => { $timeout(() => {
var lastSize = component.getLastSize(); var lastSize = component.getLastSize();
@@ -127,24 +128,17 @@ angular.module('app')
} }
}}); }});
this.selectRoom = function(room) { this.onRoomDismiss = function(room) {
room.showRoom = false;
}
// Allows us to send messages to component modal directive this.closeAllRooms = function() {
if(!room.directiveController) { for(var room of this.rooms) {
room.directiveController = {onDismiss: () => { room.showRoom = false;
room.showRoom = false;
}};
}
// Make sure to call dismiss() before setting new showRoom value
// This way the directive stays alive long enough to deactivate the associated component
// (The directive's life is at the mercy of "ng-if" => "room.showRoom")
if(room.showRoom) {
room.directiveController.dismiss(() => {
});
} else {
room.showRoom = true;
} }
} }
this.selectRoom = function(room) {
room.showRoom = !room.showRoom;
}
}); });

View File

@@ -17,7 +17,9 @@ class AccountMenu {
$scope.server = syncManager.serverURL; $scope.server = syncManager.serverURL;
$scope.close = function() { $scope.close = function() {
$scope.closeFunction()(); $timeout(() => {
$scope.closeFunction()();
})
} }
$scope.encryptedBackupsAvailable = function() { $scope.encryptedBackupsAvailable = function() {

View File

@@ -18,20 +18,12 @@ class ComponentModal {
controller($scope, $timeout, componentManager) { controller($scope, $timeout, componentManager) {
'ngInject'; 'ngInject';
if($scope.component.directiveController) {
$scope.component.directiveController.dismiss = function(callback) {
$scope.dismiss(callback);
}
}
$scope.dismiss = function(callback) { $scope.dismiss = function(callback) {
var onDismiss = $scope.component.directiveController && $scope.component.directiveController.onDismiss();
$scope.el.remove(); $scope.el.remove();
$scope.$destroy(); $scope.$destroy();
onDismiss && onDismiss(); $scope.onDismiss && $scope.onDismiss()($scope.component);
callback && callback(); callback && callback();
} }
} }
} }

View File

@@ -10,7 +10,7 @@ class Action {
} }
} }
class Extension extends Item { class Extension extends Component {
constructor(json) { constructor(json) {
super(json); super(json);
@@ -33,9 +33,7 @@ class Extension extends Item {
mapContentToLocalProperties(content) { mapContentToLocalProperties(content) {
super.mapContentToLocalProperties(content) super.mapContentToLocalProperties(content)
this.name = content.name;
this.description = content.description; this.description = content.description;
this.url = content.url;
this.supported_types = content.supported_types; this.supported_types = content.supported_types;
if(content.actions) { if(content.actions) {
@@ -45,18 +43,12 @@ class Extension extends Item {
} }
} }
referenceParams() {
return null;
}
get content_type() { get content_type() {
return "Extension"; return "Extension";
} }
structureParams() { structureParams() {
var params = { var params = {
name: this.name,
url: this.url,
description: this.description, description: this.description,
actions: this.actions, actions: this.actions,
supported_types: this.supported_types supported_types: this.supported_types

View File

@@ -1,12 +1,10 @@
class ActionsManager { class ActionsManager {
constructor(httpManager, modelManager, authManager, syncManager, storageManager) { constructor(httpManager, modelManager, authManager, syncManager) {
this.httpManager = httpManager; this.httpManager = httpManager;
this.modelManager = modelManager; this.modelManager = modelManager;
this.authManager = authManager; this.authManager = authManager;
this.enabledRepeatActionUrls = JSON.parse(storageManager.getItem("enabledRepeatActionUrls")) || [];
this.syncManager = syncManager; this.syncManager = syncManager;
this.storageManager = storageManager;
} }
get extensions() { get extensions() {
@@ -19,27 +17,11 @@ class ActionsManager {
}) })
} }
actionWithURL(url) {
for (var extension of this.extensions) {
return _.find(extension.actions, {url: url})
}
}
addExtension(url, callback) {
this.retrieveExtensionFromServer(url, callback);
}
deleteExtension(extension) {
this.modelManager.setItemToBeDeleted(extension);
this.syncManager.sync(null);
}
/* /*
Loads an extension in the context of a certain item. The server then has the chance to respond with actions that are Loads an extension in the context of a certain item. The server then has the chance to respond with actions that are
relevant just to this item. The response extension is not saved, just displayed as a one-time thing. relevant just to this item. The response extension is not saved, just displayed as a one-time thing.
*/ */
loadExtensionInContextOfItem(extension, item, callback) { loadExtensionInContextOfItem(extension, item, callback) {
this.httpManager.getAbsolute(extension.url, {content_type: item.content_type, item_uuid: item.uuid}, function(response){ this.httpManager.getAbsolute(extension.url, {content_type: item.content_type, item_uuid: item.uuid}, function(response){
this.updateExtensionFromRemoteResponse(extension, response); this.updateExtensionFromRemoteResponse(extension, response);
callback && callback(extension); callback && callback(extension);
@@ -51,50 +33,9 @@ class ActionsManager {
}.bind(this)) }.bind(this))
} }
/*
Registers new extension and saves it to user's account
*/
retrieveExtensionFromServer(url, callback) {
this.httpManager.getAbsolute(url, {}, function(response){
if(typeof response !== 'object') {
callback(null);
return;
}
var ext = this.handleExtensionLoadExternalResponseItem(url, response);
if(callback) {
callback(ext);
}
}.bind(this), function(response){
console.error("Error registering extension", response);
callback(null);
})
}
handleExtensionLoadExternalResponseItem(url, externalResponseItem) {
// Don't allow remote response to set these flags
delete externalResponseItem.uuid;
var extension = _.find(this.extensions, {url: url});
if(extension) {
this.updateExtensionFromRemoteResponse(extension, externalResponseItem);
} else {
extension = new Extension(externalResponseItem);
extension.url = url;
extension.setDirty(true);
this.modelManager.addItem(extension);
this.syncManager.sync(null);
}
return extension;
}
updateExtensionFromRemoteResponse(extension, response) { updateExtensionFromRemoteResponse(extension, response) {
if(response.description) { if(response.description) { extension.description = response.description; }
extension.description = response.description; if(response.supported_types) { extension.supported_types = response.supported_types; }
}
if(response.supported_types) {
extension.supported_types = response.supported_types;
}
if(response.actions) { if(response.actions) {
extension.actions = response.actions.map(function(action){ extension.actions = response.actions.map(function(action){
@@ -105,14 +46,6 @@ class ActionsManager {
} }
} }
refreshExtensionsFromServer() {
for(var ext of this.extensions) {
this.retrieveExtensionFromServer(ext.url, function(extension){
extension.setDirty(true);
});
}
}
executeAction(action, extension, item, callback) { executeAction(action, extension, item, callback) {
var customCallback = function(response) { var customCallback = function(response) {
@@ -197,24 +130,6 @@ class ActionsManager {
action.lastExecuted = new Date(); action.lastExecuted = new Date();
} }
isRepeatActionEnabled(action) {
return _.includes(this.enabledRepeatActionUrls, action.url);
}
queueAction(action, extension, delay, changedItems) {
this.actionQueue = this.actionQueue || [];
if(_.find(this.actionQueue, {url: action.url})) {
return;
}
this.actionQueue.push(action);
setTimeout(function () {
this.triggerWatchAction(action, extension, changedItems);
_.pull(this.actionQueue, action);
}.bind(this), delay * 1000);
}
outgoingParamsForItem(item, extension, decrypted = false) { outgoingParamsForItem(item, extension, decrypted = false) {
var keys = this.authManager.keys(); var keys = this.authManager.keys();
if(decrypted) { if(decrypted) {

View File

@@ -9,6 +9,7 @@ class ComponentManager {
this.modelManager = modelManager; this.modelManager = modelManager;
this.syncManager = syncManager; this.syncManager = syncManager;
this.desktopManager = desktopManager; this.desktopManager = desktopManager;
this.sysExtManager = sysExtManager;
this.timeout = $timeout; this.timeout = $timeout;
this.streamObservers = []; this.streamObservers = [];
this.contextStreamObservers = []; this.contextStreamObservers = [];
@@ -160,7 +161,7 @@ class ComponentManager {
if(source && source == ModelManager.MappingSourceRemoteSaved) { if(source && source == ModelManager.MappingSourceRemoteSaved) {
params.isMetadataUpdate = true; params.isMetadataUpdate = true;
} }
this.removePrivatePropertiesFromResponseItems([params]); this.removePrivatePropertiesFromResponseItems([params], component);
return params; return params;
} }
@@ -289,11 +290,17 @@ class ComponentManager {
} }
} }
removePrivatePropertiesFromResponseItems(responseItems, includeUrls) { removePrivatePropertiesFromResponseItems(responseItems, component, options = {}) {
if(component) {
// System extensions can bypass this step
if(this.sysExtManager.isSystemExtension(component)) {
return;
}
}
// Don't allow component to overwrite these properties. // Don't allow component to overwrite these properties.
var privateProperties = ["appData", "autoupdateDisabled", "permissions", "active", "encrypted"]; var privateProperties = ["appData", "autoupdateDisabled", "permissions", "active"];
if(includeUrls) { if(options) {
privateProperties = privateProperties.concat(["url", "hosted_url", "local_url"]); if(options.includeUrls) { privateProperties = privateProperties.concat(["url", "hosted_url", "local_url"])}
} }
for(var responseItem of responseItems) { for(var responseItem of responseItems) {
@@ -302,7 +309,7 @@ class ComponentManager {
console.assert(typeof responseItem.setDirty !== 'function'); console.assert(typeof responseItem.setDirty !== 'function');
for(var prop of privateProperties) { for(var prop of privateProperties) {
delete responseItem[prop]; delete responseItem.content[prop];
} }
} }
} }
@@ -402,7 +409,7 @@ class ComponentManager {
this.runWithPermissions(component, requiredPermissions, () => { this.runWithPermissions(component, requiredPermissions, () => {
this.removePrivatePropertiesFromResponseItems(responseItems, {includeUrls: true}); this.removePrivatePropertiesFromResponseItems(responseItems, component, {includeUrls: true});
/* /*
We map the items here because modelManager is what updates the UI. If you were to instead get the items directly, We map the items here because modelManager is what updates the UI. If you were to instead get the items directly,
@@ -439,7 +446,7 @@ class ComponentManager {
this.runWithPermissions(component, requiredPermissions, () => { this.runWithPermissions(component, requiredPermissions, () => {
var responseItem = message.data.item; var responseItem = message.data.item;
this.removePrivatePropertiesFromResponseItems([responseItem]); this.removePrivatePropertiesFromResponseItems([responseItem], component);
var item = this.modelManager.createItem(responseItem); var item = this.modelManager.createItem(responseItem);
if(responseItem.clientData) { if(responseItem.clientData) {
item.setDomainDataItem(component.url || component.uuid, responseItem.clientData, ClientDataDomain); item.setDomainDataItem(component.url || component.uuid, responseItem.clientData, ClientDataDomain);

View File

@@ -1,41 +0,0 @@
class PackageManager {
constructor(httpManager, modelManager, syncManager, componentManager) {
this.httpManager = httpManager;
this.modelManager = modelManager;
this.syncManager = syncManager;
this.componentManager = componentManager;
}
installPackage(url, callback) {
this.httpManager.getAbsolute(url, {}, function(aPackage){
console.log("Got package data", aPackage);
if(typeof aPackage !== 'object') {
callback(null);
return;
}
// Remove private properties
this.componentManager.removePrivatePropertiesFromResponseItems([aPackage]);
aPackage.package_info = Object.assign({}, aPackage);
var assembled = this.modelManager.createItem(aPackage);;
this.modelManager.addItem(assembled);
assembled.setDirty(true);
this.syncManager.sync("installPackage");
console.log("Created assembled", assembled);
callback && callback(assembled);
}.bind(this), function(response){
console.error("Error retrieving package", response);
callback(null);
})
}
}
angular.module('app').service('packageManager', PackageManager);

View File

@@ -7,14 +7,22 @@ class SysExtManager {
this.syncManager = syncManager; this.syncManager = syncManager;
this.singletonManager = singletonManager; this.singletonManager = singletonManager;
this.extensionsIdentifier = "org.standardnotes.extensions-manager";
this.systemExtensions = [];
this.resolveExtensionsManager(); this.resolveExtensionsManager();
} }
resolveExtensionsManager() { isSystemExtension(extension) {
let extensionsIdentifier = "org.standardnotes.extensions-manager"; return this.systemExtensions.includes(extension.uuid);
}
this.singletonManager.registerSingleton({content_type: "SN|Component", package_info: {identifier: extensionsIdentifier}}, (resolvedSingleton) => { resolveExtensionsManager() {
this.singletonManager.registerSingleton({content_type: "SN|Component", package_info: {identifier: this.extensionsIdentifier}}, (resolvedSingleton) => {
// Resolved Singleton // Resolved Singleton
this.systemExtensions.push(resolvedSingleton.uuid);
var needsSync = false; var needsSync = false;
if(isDesktopApplication()) { if(isDesktopApplication()) {
if(!resolvedSingleton.local_url) { if(!resolvedSingleton.local_url) {
@@ -43,7 +51,7 @@ class SysExtManager {
let packageInfo = { let packageInfo = {
name: "Extensions", name: "Extensions",
identifier: extensionsIdentifier identifier: this.extensionsIdentifier
} }
var item = { var item = {
@@ -73,6 +81,8 @@ class SysExtManager {
component.setDirty(true); component.setDirty(true);
this.syncManager.sync("resolveExtensionsManager createNew"); this.syncManager.sync("resolveExtensionsManager createNew");
this.systemExtensions.push(component.uuid);
valueCallback(component); valueCallback(component);
}); });
} }

View File

@@ -17,7 +17,7 @@
.item{"ng-repeat" => "room in ctrl.rooms track by room.uuid"} .item{"ng-repeat" => "room in ctrl.rooms track by room.uuid"}
.column{"ng-click" => "ctrl.selectRoom(room)"} .column{"ng-click" => "ctrl.selectRoom(room)"}
.label {{room.name}} .label {{room.name}}
%component-modal{"ng-if" => "room.showRoom", "component" => "room", "controller" => "room.directiveController"} %component-modal{"ng-if" => "room.showRoom", "component" => "room", "on-dismiss" => "ctrl.onRoomDismiss"}
.right .right