Editor updates
This commit is contained in:
@@ -115,19 +115,21 @@ angular.module('app.frontend')
|
||||
// if plain editor or other editor
|
||||
this.showEditorMenu = false;
|
||||
var editor = component;
|
||||
if(this.selectedEditor && editor !== this.selectedEditor) {
|
||||
this.disassociateComponentWithCurrentNote(this.selectedEditor);
|
||||
}
|
||||
if(editor) {
|
||||
this.note.setAppDataItem("prefersPlainEditor", false);
|
||||
this.note.setDirty(true);
|
||||
componentManager.associateComponentWithItem(editor, this.note);
|
||||
if(this.note.getAppDataItem("prefersPlainEditor") == true) {
|
||||
this.note.setAppDataItem("prefersPlainEditor", false);
|
||||
this.note.setDirty(true);
|
||||
}
|
||||
this.associateComponentWithCurrentNote(editor);
|
||||
} else {
|
||||
// Note prefers plain editor
|
||||
if(this.selectedEditor) {
|
||||
this.disableComponentForCurrentItem(this.selectedEditor);
|
||||
if(!this.note.getAppDataItem("prefersPlainEditor")) {
|
||||
this.note.setAppDataItem("prefersPlainEditor", true);
|
||||
this.note.setDirty(true);
|
||||
}
|
||||
this.note.setAppDataItem("prefersPlainEditor", true);
|
||||
this.note.setDirty(true);
|
||||
syncManager.sync();
|
||||
|
||||
$timeout(() => {
|
||||
this.reloadFont();
|
||||
})
|
||||
@@ -139,6 +141,8 @@ angular.module('app.frontend')
|
||||
this.toggleStackComponentForCurrentItem(component);
|
||||
}
|
||||
|
||||
// Lots of dirtying can happen above, so we'll sync
|
||||
syncManager.sync();
|
||||
}.bind(this)
|
||||
|
||||
this.hasAvailableExtensions = function() {
|
||||
@@ -502,31 +506,34 @@ angular.module('app.frontend')
|
||||
|
||||
this.toggleStackComponentForCurrentItem = function(component) {
|
||||
if(component.isActiveForItem(this.note)) {
|
||||
this.disableComponentForCurrentItem(component);
|
||||
componentManager.deactivateComponent(component);
|
||||
this.disassociateComponentWithCurrentNote(component);
|
||||
} else {
|
||||
this.enableComponentForCurrentItem(component);
|
||||
componentManager.activateComponent(component);
|
||||
componentManager.contextItemDidChangeInArea("editor-stack");
|
||||
this.associateComponentWithCurrentNote(component);
|
||||
}
|
||||
}
|
||||
|
||||
this.disableComponentForCurrentItem = function(component) {
|
||||
componentManager.deactivateComponent(component);
|
||||
_.pull(component.associatedItemIds, this.note.uuid);
|
||||
if(component.disassociatedItemIds.indexOf(this.note.uuid) !== -1) {
|
||||
return;
|
||||
this.disassociateComponentWithCurrentNote = function(component) {
|
||||
component.associatedItemIds = component.associatedItemIds.filter((id) => {return id !== this.note.uuid});
|
||||
|
||||
// Only disassociative components should modify the disassociatedItemIds
|
||||
if(!component.isAssociative() && !component.disassociatedItemIds.includes(this.note.uuid)) {
|
||||
component.disassociatedItemIds.push(this.note.uuid);
|
||||
}
|
||||
|
||||
component.disassociatedItemIds.push(this.note.uuid);
|
||||
component.setDirty(true);
|
||||
syncManager.sync();
|
||||
}
|
||||
|
||||
this.enableComponentForCurrentItem = function(component) {
|
||||
componentManager.activateComponent(component);
|
||||
componentManager.contextItemDidChangeInArea("editor-stack");
|
||||
this.associateComponentWithCurrentNote = function(component) {
|
||||
component.disassociatedItemIds = component.disassociatedItemIds.filter((id) => {return id !== this.note.uuid});
|
||||
|
||||
if(component.isAssociative() && !component.associatedItemIds.includes(this.note.uuid)) {
|
||||
component.associatedItemIds.push(this.note.uuid);
|
||||
}
|
||||
|
||||
_.pull(component.disassociatedItemIds, this.note.uuid);
|
||||
component.setDirty(true);
|
||||
syncManager.sync();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -166,6 +166,11 @@ angular.module('app.frontend')
|
||||
|
||||
// Safe to create. Create and return object.
|
||||
let url = window._prolink_package_url;
|
||||
console.log("Installing ProLink from URL", url);
|
||||
if(!url) {
|
||||
console.error("window._prolink_package_url must be set.");
|
||||
return;
|
||||
}
|
||||
packageManager.installPackage(url, (component) => {
|
||||
valueCallback(component);
|
||||
})
|
||||
|
||||
@@ -23,9 +23,10 @@ class Component extends Item {
|
||||
/* New */
|
||||
this.local_url = content.local_url;
|
||||
this.hosted_url = content.hosted_url;
|
||||
this.offlineOnly = content.offlineOnly;
|
||||
|
||||
this.name = content.name;
|
||||
this.autoupdate = content.autoupdate;
|
||||
this.autoupdateDisabled = content.autoupdateDisabled;
|
||||
|
||||
this.package_info = content.package_info;
|
||||
|
||||
@@ -50,12 +51,13 @@ class Component extends Item {
|
||||
url: this.url,
|
||||
hosted_url: this.hosted_url,
|
||||
local_url: this.local_url,
|
||||
offlineOnly: this.offlineOnly,
|
||||
name: this.name,
|
||||
area: this.area,
|
||||
package_info: this.package_info,
|
||||
permissions: this.permissions,
|
||||
active: this.active,
|
||||
autoupdate: this.autoupdate,
|
||||
autoupdateDisabled: this.autoupdateDisabled,
|
||||
componentData: this.componentData,
|
||||
disassociatedItemIds: this.disassociatedItemIds,
|
||||
associatedItemIds: this.associatedItemIds,
|
||||
@@ -73,14 +75,6 @@ class Component extends Item {
|
||||
return "SN|Component";
|
||||
}
|
||||
|
||||
computedUrl() {
|
||||
if(this.offlineOnly || (isDesktopApplication() && this.local_url)) {
|
||||
return this.local_url.replace("sn://", this.desktopManager.getApplicationDataPath() + "/");
|
||||
} else {
|
||||
return this.url || this.hosted_url;
|
||||
}
|
||||
}
|
||||
|
||||
isEditor() {
|
||||
return this.area == "editor-editor";
|
||||
}
|
||||
|
||||
@@ -6,10 +6,14 @@ class ItemParams {
|
||||
this.version = version || "002";
|
||||
}
|
||||
|
||||
paramsForExportFile() {
|
||||
paramsForExportFile(includeDeleted) {
|
||||
this.additionalFields = ["updated_at"];
|
||||
this.forExportFile = true;
|
||||
return _.omit(this.__params(), ["deleted"]);
|
||||
if(includeDeleted) {
|
||||
return this.__params();
|
||||
} else {
|
||||
return _.omit(this.__params(), ["deleted"]);
|
||||
}
|
||||
}
|
||||
|
||||
paramsForExtension() {
|
||||
|
||||
@@ -127,7 +127,7 @@ class ComponentManager {
|
||||
postThemeToComponent(component) {
|
||||
var activeTheme = this.getActiveTheme();
|
||||
var data = {
|
||||
themes: [activeTheme ? activeTheme.computedUrl() : null]
|
||||
themes: [activeTheme ? this.urlForComponent(activeTheme) : null]
|
||||
}
|
||||
|
||||
this.sendMessageToComponent(component, {action: "themes", data: data})
|
||||
@@ -196,6 +196,14 @@ class ComponentManager {
|
||||
})
|
||||
}
|
||||
|
||||
urlForComponent(component) {
|
||||
if(component.offlineOnly || (isDesktopApplication() && component.local_url)) {
|
||||
return component.local_url.replace("sn://", this.desktopManager.getApplicationDataPath() + "/");
|
||||
} else {
|
||||
return component.url || component.hosted_url;
|
||||
}
|
||||
}
|
||||
|
||||
componentForUrl(url) {
|
||||
return this.components.filter(function(component){
|
||||
return component.url === url || component.hosted_url === url;
|
||||
@@ -246,8 +254,6 @@ class ComponentManager {
|
||||
this.handleCreateItemMessage(component, message);
|
||||
} else if(message.action === "save-items") {
|
||||
this.handleSaveItemsMessage(component, message);
|
||||
} else if(message.action === "install-local-component") {
|
||||
this.handleInstallLocalComponentMessage(component, message);
|
||||
} else if(message.action === "toggle-activate-component") {
|
||||
let componentToToggle = this.modelManager.findItem(message.data.uuid);
|
||||
this.handleToggleComponentMessage(component, componentToToggle, message);
|
||||
@@ -265,7 +271,7 @@ class ComponentManager {
|
||||
|
||||
removePrivatePropertiesFromResponseItems(responseItems, includeUrls) {
|
||||
// Don't allow component to overwrite these properties.
|
||||
var privateProperties = ["appData", "autoupdate", "permissions", "active", "encrypted"];
|
||||
var privateProperties = ["appData", "autoupdateDisabled", "permissions", "active", "encrypted"];
|
||||
if(includeUrls) {
|
||||
privateProperties = privateProperties.concat(["url", "hosted_url", "local_url"]);
|
||||
}
|
||||
@@ -329,17 +335,21 @@ class ComponentManager {
|
||||
|
||||
// push immediately now
|
||||
for(let handler of this.handlersForArea(component.area)) {
|
||||
var itemInContext = handler.contextRequestHandler(component);
|
||||
this.sendContextItemInReply(component, itemInContext, message);
|
||||
if(handler.contextRequestHandler) {
|
||||
var itemInContext = handler.contextRequestHandler(component);
|
||||
this.sendContextItemInReply(component, itemInContext, message);
|
||||
}
|
||||
}
|
||||
}.bind(this))
|
||||
}
|
||||
|
||||
isItemWithinComponentContextJurisdiction(item, component) {
|
||||
for(let handler of this.handlersForArea(component.area)) {
|
||||
var itemInContext = handler.contextRequestHandler(component);
|
||||
if(itemInContext.uuid == item.uuid) {
|
||||
return true;
|
||||
if(handler.contextRequestHandler) {
|
||||
var itemInContext = handler.contextRequestHandler(component);
|
||||
if(itemInContext.uuid == item.uuid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -388,6 +398,7 @@ class ComponentManager {
|
||||
}
|
||||
item.setDirty(true);
|
||||
}
|
||||
|
||||
this.syncManager.sync((response) => {
|
||||
// Allow handlers to be notified when a save begins and ends, to update the UI
|
||||
var saveMessage = Object.assign({}, message);
|
||||
@@ -443,24 +454,6 @@ class ComponentManager {
|
||||
});
|
||||
}
|
||||
|
||||
handleInstallLocalComponentMessage(component, message) {
|
||||
var requiredPermissions = [
|
||||
{
|
||||
name: "stream-items",
|
||||
content_types: [message.data.content_type]
|
||||
}
|
||||
];
|
||||
|
||||
this.runWithPermissions(component, requiredPermissions, () => {
|
||||
this.desktopManager.installOfflineComponentFromData(message.data, (response) => {
|
||||
var component = this.modelManager.mapResponseItemsToLocalModels([response], ModelManager.MappingSourceComponentRetrieved)[0];
|
||||
// Save updated URL
|
||||
component.setDirty(true);
|
||||
this.syncManager.sync();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleSetComponentDataMessage(component, message) {
|
||||
// A component setting its own data does not require special permissions
|
||||
this.runWithPermissions(component, [], () => {
|
||||
@@ -719,19 +712,6 @@ class ComponentManager {
|
||||
return component.active;
|
||||
}
|
||||
|
||||
associateComponentWithItem(component, item) {
|
||||
_.pull(component.disassociatedItemIds, item.uuid);
|
||||
|
||||
if(component.associatedItemIds.includes(item.uuid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
component.associatedItemIds.push(item.uuid);
|
||||
|
||||
component.setDirty(true);
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
iframeForComponent(component) {
|
||||
for(var frame of document.getElementsByTagName("iframe")) {
|
||||
var componentId = frame.dataset.componentId;
|
||||
|
||||
@@ -25,14 +25,6 @@ class DesktopManager {
|
||||
})
|
||||
}
|
||||
|
||||
/* Can handle components and themes */
|
||||
installOfflineComponentFromData(componentData, callback) {
|
||||
this.componentInstallationHandler(componentData, (installedComponent) => {
|
||||
componentData.content.local_url = installedComponent.content.local_url;
|
||||
callback(componentData);
|
||||
});
|
||||
}
|
||||
|
||||
getApplicationDataPath() {
|
||||
console.assert(this.applicationDataPath, "applicationDataPath is null");
|
||||
return this.applicationDataPath;
|
||||
@@ -40,24 +32,31 @@ class DesktopManager {
|
||||
|
||||
/* Sending a component in its raw state is really slow for the desktop app */
|
||||
convertComponentForTransmission(component) {
|
||||
return new ItemParams(component).paramsForExportFile();
|
||||
return new ItemParams(component).paramsForExportFile(true);
|
||||
}
|
||||
|
||||
// All `components` should be installed
|
||||
syncComponentsInstallation(components) {
|
||||
// console.log("Web Syncing Components", components);
|
||||
if(!this.isDesktop) return;
|
||||
|
||||
/* Allows us to look up component on desktop_updateComponentComplete */
|
||||
this.syncingComponents = components;
|
||||
|
||||
var data = components.map((component) => {
|
||||
console.log("Web Sycying Component", this.convertComponentForTransmission(component));
|
||||
return this.convertComponentForTransmission(component);
|
||||
})
|
||||
this.installationSyncHandler(data);
|
||||
}
|
||||
|
||||
desktop_onComponentInstallationComplete(componentData) {
|
||||
console.log("Web|Component Installation Complete", componentData);
|
||||
var component = this.modelManager.mapResponseItemsToLocalModels([componentData], ModelManager.MappingSourceDesktopInstalled)[0];
|
||||
component.setDirty(true);
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
desktop_updateComponentComplete(componentData) {
|
||||
var component = this.syncingComponents.filter((c) => {return c.uuid == componentData.uuid})[0];
|
||||
console.log("Web|Component Update Complete", componentData);
|
||||
var component = this.modelManager.mapResponseItemsToLocalModels([componentData], ModelManager.MappingSourceDesktopInstalled)[0];
|
||||
component.setDirty(true);
|
||||
this.syncManager.sync();
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ class ComponentView {
|
||||
}.bind(this)});
|
||||
|
||||
$scope.$watch('component', function(component, prevComponent){
|
||||
// console.log("Component View Setting Component", component);
|
||||
ctrl.componentValueChanging(component, prevComponent);
|
||||
});
|
||||
}
|
||||
@@ -43,22 +42,26 @@ class ComponentView {
|
||||
controller($scope, $timeout, componentManager, desktopManager) {
|
||||
'ngInject';
|
||||
|
||||
console.log("Creating New Component View");
|
||||
|
||||
this.componentValueChanging = (component, prevComponent) => {
|
||||
if(prevComponent && component !== prevComponent) {
|
||||
// Deactive old component
|
||||
console.log("DEACTIVATING OLD COMPONENT", prevComponent);
|
||||
componentManager.deactivateComponent(prevComponent);
|
||||
}
|
||||
|
||||
if(component) {
|
||||
componentManager.activateComponent(component);
|
||||
component.runningLocally = $scope.getUrl
|
||||
console.log("Loading", $scope.component.name, $scope.getUrl());
|
||||
}
|
||||
}
|
||||
|
||||
$scope.getUrl = function() {
|
||||
var url = componentManager.urlForComponent($scope.component);
|
||||
$scope.component.runningLocally = url !== ($scope.component.url || $scope.component.hosted_url);
|
||||
return url;
|
||||
}
|
||||
|
||||
$scope.$on("$destroy", function() {
|
||||
console.log("DESTROY COMPONENT VIEW");
|
||||
componentManager.deregisterHandler($scope.identifier);
|
||||
if($scope.component) {
|
||||
componentManager.deactivateComponent($scope.component);
|
||||
|
||||
@@ -39,6 +39,10 @@ class EditorMenu {
|
||||
}
|
||||
}
|
||||
|
||||
$scope.offlineAvailableForComponent = function(component) {
|
||||
return component.local_url && isDesktopApplication();
|
||||
}
|
||||
|
||||
$scope.makeEditorDefault = function(component) {
|
||||
var currentDefault = componentManager.componentsForArea("editor-editor").filter((e) => {return e.isDefaultEditor()})[0];
|
||||
if(currentDefault) {
|
||||
|
||||
@@ -6,6 +6,7 @@ class ModelManager {
|
||||
ModelManager.MappingSourceLocalSaved = "MappingSourceLocalSaved";
|
||||
ModelManager.MappingSourceLocalRetrieved = "MappingSourceLocalRetrieved";
|
||||
ModelManager.MappingSourceComponentRetrieved = "MappingSourceComponentRetrieved";
|
||||
ModelManager.MappingSourceDesktopInstalled = "MappingSourceDesktopInstalled"; // When a component is installed by the desktop and some of its values change
|
||||
ModelManager.MappingSourceRemoteActionRetrieved = "MappingSourceRemoteActionRetrieved"; /* aciton-based Extensions like note history */
|
||||
ModelManager.MappingSourceFileImport = "MappingSourceFileImport";
|
||||
|
||||
@@ -147,7 +148,7 @@ class ModelManager {
|
||||
}
|
||||
|
||||
if(!item) {
|
||||
item = this.createItem(json_obj);
|
||||
item = this.createItem(json_obj, true);
|
||||
}
|
||||
|
||||
this.addItem(item);
|
||||
@@ -200,7 +201,7 @@ class ModelManager {
|
||||
}
|
||||
}
|
||||
|
||||
createItem(json_obj) {
|
||||
createItem(json_obj, dontNotifyObservers) {
|
||||
var item;
|
||||
if(json_obj.content_type == "Note") {
|
||||
item = new Note(json_obj);
|
||||
@@ -224,6 +225,15 @@ class ModelManager {
|
||||
item = new Item(json_obj);
|
||||
}
|
||||
|
||||
// Some observers would be interested to know when an an item is locally created
|
||||
// If we don't send this out, these observers would have to wait until MappingSourceRemoteSaved
|
||||
// to hear about it, but sometimes, RemoveSaved is explicitly ignored by the observer to avoid
|
||||
// recursive callbacks. See componentManager's syncObserver callback.
|
||||
// dontNotifyObservers is currently only set true by modelManagers mapResponseItemsToLocalModels
|
||||
if(!dontNotifyObservers) {
|
||||
this.notifySyncObserversOfModels([item], ModelManager.MappingSourceLocalSaved);
|
||||
}
|
||||
|
||||
item.addObserver(this, function(changedItem){
|
||||
this.notifyItemChangeObserversOfModels([changedItem]);
|
||||
}.bind(this));
|
||||
|
||||
@@ -18,10 +18,11 @@ class PackageManager {
|
||||
// Remove private properties
|
||||
this.componentManager.removePrivatePropertiesFromResponseItems([aPackage]);
|
||||
|
||||
var assembled = this.modelManager.createItem(aPackage);
|
||||
aPackage.package_info = Object.assign({}, aPackage);
|
||||
|
||||
assembled.package_info = aPackage;
|
||||
var assembled = this.modelManager.createItem(aPackage);;
|
||||
this.modelManager.addItem(assembled);
|
||||
|
||||
assembled.setDirty(true);
|
||||
this.syncManager.sync();
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ class SingletonManager {
|
||||
setTimeout(function () {
|
||||
var userPrefs = modelManager.itemsForContentType("SN|UserPreferences");
|
||||
console.assert(userPrefs.length == 1);
|
||||
console.log("All extant prefs", userPrefs);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ class ThemeManager {
|
||||
this.modelManager = modelManager;
|
||||
this.$rootScope = $rootScope;
|
||||
this.storageManager = storageManager;
|
||||
this.componentManager = componentManager;
|
||||
|
||||
componentManager.registerHandler({identifier: "themeManager", areas: ["themes"], activationHandler: (component) => {
|
||||
if(component.active) {
|
||||
@@ -55,8 +56,7 @@ class ThemeManager {
|
||||
this.deactivateTheme(this.activeTheme);
|
||||
}
|
||||
|
||||
|
||||
var url = theme.computedUrl();
|
||||
var url = this.componentManager.urlForComponent(theme);
|
||||
|
||||
var link = document.createElement("link");
|
||||
link.href = url;
|
||||
|
||||
Reference in New Issue
Block a user