Snapshot more objects

This commit is contained in:
Antonio Scandurra
2017-03-08 10:02:35 +01:00
parent 21de78ce38
commit 3d4fdd051d
15 changed files with 181 additions and 147 deletions

View File

@@ -60,6 +60,7 @@
"normalize-package-data": "^2.0.0",
"nslog": "^3",
"oniguruma": "6.1.0",
"parserlib": "^1.1.1",
"pathwatcher": "7.0.0",
"postcss": "5.2.4",
"postcss-selector-parser": "2.2.1",

View File

@@ -151,6 +151,51 @@ class AtomEnvironment extends Model
@commands = new CommandRegistry
@grammars = new GrammarRegistry({@config})
@styles = new StyleManager()
@packages = new PackageManager({
@config, styleManager: @styles,
commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications,
grammarRegistry: @grammars, deserializerManager: @deserializers, viewRegistry: @views
})
@themes = new ThemeManager({
packageManager: @packages, @config, styleManager: @styles,
notificationManager: @notifications, viewRegistry: @views
})
@menu = new MenuManager({keymapManager: @keymaps, packageManager: @packages})
@contextMenu = new ContextMenuManager({keymapManager: @keymaps})
@packages.setMenuManager(@menu)
@packages.setContextMenuManager(@contextMenu)
@packages.setThemeManager(@themes)
@project = new Project({notificationManager: @notifications, packageManager: @packages, @config, @applicationDelegate})
@commandInstaller = new CommandInstaller(@applicationDelegate)
@textEditors = new TextEditorRegistry({
@config, grammarRegistry: @grammars, assert: @assert.bind(this),
packageManager: @packages
})
@workspace = new Workspace({
@config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers,
notificationManager: @notifications, @applicationDelegate, viewRegistry: @views, assert: @assert.bind(this),
textEditorRegistry: @textEditors,
})
@themes.workspace = @workspace
@autoUpdater = new AutoUpdateManager({@applicationDelegate})
@keymaps.loadBundledKeymaps()
@registerDefaultCommands()
@registerDefaultOpeners()
@registerDefaultDeserializers()
@registerDefaultViewProviders()
@windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate})
@history = new HistoryManager({@project, @commands})
# Keep instances of HistoryManager in sync
@disposables.add @history.onDidChangeProjects (e) =>
@applicationDelegate.didChangeHistoryManager() unless e.reloaded
initialize: (params={}) ->
{@window, @document, @blobStore, @configDirPath, onlyLoadBaseStyleSheets} = params
@@ -183,44 +228,14 @@ class AtomEnvironment extends Model
@commands.attach(@window)
@styles.initialize({@configDirPath})
@packages.initialize({devMode, @configDirPath, resourcePath, safeMode})
@themes.initialize({@configDirPath, resourcePath, safeMode})
@packages = new PackageManager({
devMode, @configDirPath, resourcePath, safeMode, @config, styleManager: @styles,
commandRegistry: @commands, keymapManager: @keymaps, notificationManager: @notifications,
grammarRegistry: @grammars, deserializerManager: @deserializers, viewRegistry: @views
})
@themes = new ThemeManager({
packageManager: @packages, @configDirPath, resourcePath, safeMode, @config,
styleManager: @styles, notificationManager: @notifications, viewRegistry: @views
})
@menu = new MenuManager({resourcePath, keymapManager: @keymaps, packageManager: @packages})
@contextMenu = new ContextMenuManager({resourcePath, devMode, keymapManager: @keymaps})
@packages.setMenuManager(@menu)
@packages.setContextMenuManager(@contextMenu)
@packages.setThemeManager(@themes)
@project = new Project({notificationManager: @notifications, packageManager: @packages, @config, @applicationDelegate})
@commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate)
@textEditors = new TextEditorRegistry({
@config, grammarRegistry: @grammars, assert: @assert.bind(this),
packageManager: @packages
})
@workspace = new Workspace({
@config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers,
notificationManager: @notifications, @applicationDelegate, viewRegistry: @views, assert: @assert.bind(this),
textEditorRegistry: @textEditors,
})
@themes.workspace = @workspace
@autoUpdater = new AutoUpdateManager({@applicationDelegate})
@menu.initialize({resourcePath})
@contextMenu.initialize({resourcePath, devMode})
@commandInstaller.initialize(@getVersion())
@workspace.initialize()
@autoUpdater.initialize()
@config.load()
@@ -233,23 +248,14 @@ class AtomEnvironment extends Model
@document.head.appendChild(@stylesElement)
@keymaps.subscribeToFileReadFailure()
@keymaps.loadBundledKeymaps()
@registerDefaultCommands()
@registerDefaultOpeners()
@registerDefaultDeserializers()
@registerDefaultViewProviders()
@installUncaughtErrorHandler()
@attachSaveStateListeners()
@installWindowEventHandler()
@windowEventHandler.initialize(@window, @document)
@observeAutoHideMenuBar()
@history = new HistoryManager({@project, @commands, @stateStore})
# Keep instances of HistoryManager in sync
@disposables.add @history.onDidChangeProjects (e) =>
@applicationDelegate.didChangeHistoryManager() unless e.reloaded
@history.initialize(@stateStore)
@disposables.add @applicationDelegate.onDidChangeHistoryManager(=> @history.loadState())
attachSaveStateListeners: ->
@@ -786,9 +792,6 @@ class AtomEnvironment extends Model
uninstallUncaughtErrorHandler: ->
@window.onerror = @previousWindowErrorHandler
installWindowEventHandler: ->
@windowEventHandler = new WindowEventHandler({atomEnvironment: this, @applicationDelegate, @window, @document})
uninstallWindowEventHandler: ->
@windowEventHandler?.unsubscribe()

View File

@@ -7,21 +7,23 @@ export default class AutoUpdateManager {
this.applicationDelegate = applicationDelegate
this.subscriptions = new CompositeDisposable()
this.emitter = new Emitter()
}
initialize () {
this.subscriptions.add(
applicationDelegate.onDidBeginCheckingForUpdate(() => {
this.applicationDelegate.onDidBeginCheckingForUpdate(() => {
this.emitter.emit('did-begin-checking-for-update')
}),
applicationDelegate.onDidBeginDownloadingUpdate(() => {
this.applicationDelegate.onDidBeginDownloadingUpdate(() => {
this.emitter.emit('did-begin-downloading-update')
}),
applicationDelegate.onDidCompleteDownloadingUpdate((details) => {
this.applicationDelegate.onDidCompleteDownloadingUpdate((details) => {
this.emitter.emit('did-complete-downloading-update', details)
}),
applicationDelegate.onUpdateNotAvailable(() => {
this.applicationDelegate.onUpdateNotAvailable(() => {
this.emitter.emit('update-not-available')
}),
applicationDelegate.onUpdateError(() => {
this.applicationDelegate.onUpdateError(() => {
this.emitter.emit('update-error')
})
)

View File

@@ -26,7 +26,9 @@ symlinkCommandWithPrivilegeSync = (sourcePath, destinationPath) ->
module.exports =
class CommandInstaller
constructor: (@appVersion, @applicationDelegate) ->
constructor: (@applicationDelegate) ->
initialize: (@appVersion) ->
getInstallDirectory: ->
"/usr/local/bin"

View File

@@ -91,23 +91,26 @@ class CommandRegistry
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added command handler(s).
add: (target, commandName, callback) ->
add: (target, commandName, callback, throwOnInvalidSelector = true) ->
if typeof commandName is 'object'
commands = commandName
disposable = new CompositeDisposable
for commandName, callback of commands
disposable.add @add(target, commandName, callback)
disposable.add @add(target, commandName, callback, throwOnInvalidSelector)
return disposable
if typeof callback isnt 'function'
throw new Error("Can't register a command with non-function callback.")
if typeof target is 'string'
validateSelector(target)
validateSelector(target) if throwOnInvalidSelector
@addSelectorBasedListener(target, commandName, callback)
else
@addInlineListener(target, commandName, callback)
addBundled: (target, commandName, callback) ->
@add(target, commandName, callback, false)
addSelectorBasedListener: (selector, commandName, callback) ->
@selectorBasedListenersByCommandName[commandName] ?= []
listenersForCommand = @selectorBasedListenersByCommandName[commandName]

View File

@@ -40,15 +40,17 @@ platformContextMenu = require('../package.json')?._atomMenu?['context-menu']
# {::add} for more information.
module.exports =
class ContextMenuManager
constructor: ({@resourcePath, @devMode, @keymapManager}) ->
constructor: ({@keymapManager}) ->
@definitions = {'.overlayer': []} # TODO: Remove once color picker package stops touching private data
@clear()
@keymapManager.onDidLoadBundledKeymaps => @loadPlatformItems()
initialize: ({@resourcePath, @devMode}) ->
loadPlatformItems: ->
if platformContextMenu?
@add(platformContextMenu)
@add(platformContextMenu, false)
else
menusDirPath = path.join(@resourcePath, 'menus')
platformMenuPath = fs.resolve(menusDirPath, process.platform, ['cson', 'json'])
@@ -107,11 +109,11 @@ class ContextMenuManager
#
# Returns a {Disposable} on which `.dispose()` can be called to remove the
# added menu items.
add: (itemsBySelector) ->
add: (itemsBySelector, throwOnInvalidSelector = true) ->
addedItemSets = []
for selector, items of itemsBySelector
validateSelector(selector)
validateSelector(selector) if throwOnInvalidSelector
itemSet = new ContextMenuItemSet(selector, items)
addedItemSets.push(itemSet)
@itemSets.push(itemSet)
@@ -206,14 +208,17 @@ class ContextMenuManager
clear: ->
@activeElement = null
@itemSets = []
@add 'atom-workspace': [{
label: 'Inspect Element'
command: 'application:inspect'
devMode: true
created: (event) ->
{pageX, pageY} = event
@commandDetail = {x: pageX, y: pageY}
}]
inspectElement = {
'atom-workspace': [{
label: 'Inspect Element'
command: 'application:inspect'
devMode: true
created: (event) ->
{pageX, pageY} = event
@commandDetail = {x: pageX, y: pageY}
}]
}
@add(inspectElement, false)
class ContextMenuItemSet
constructor: (@selector, @items) ->

View File

@@ -8,15 +8,18 @@ import {Emitter, CompositeDisposable} from 'event-kit'
//
// The project history is used to enable the 'Reopen Project' menu.
export class HistoryManager {
constructor ({stateStore, project, commands}) {
this.stateStore = stateStore
constructor ({project, commands}) {
this.emitter = new Emitter()
this.projects = []
this.disposables = new CompositeDisposable()
this.disposables.add(commands.add('atom-workspace', {'application:clear-project-history': this.clearProjects.bind(this)}))
this.disposables.add(commands.addBundled('atom-workspace', {'application:clear-project-history': this.clearProjects.bind(this)}))
this.disposables.add(project.onDidChangePaths((projectPaths) => this.addProject(projectPaths)))
}
initialize (stateStore) {
this.stateStore = stateStore
}
destroy () {
this.disposables.dispose()
}

View File

@@ -12,12 +12,12 @@ KeymapManager::onDidLoadUserKeymap = (callback) ->
@emitter.on 'did-load-user-keymap', callback
KeymapManager::loadBundledKeymaps = ->
keymapsPath = path.join(@resourcePath, 'keymaps')
if bundledKeymaps?
for keymapName, keymap of bundledKeymaps
keymapPath = path.join(keymapsPath, keymapName)
@add(keymapPath, keymap)
keymapPath = "<embedded>/#{keymapName}"
@add(keymapPath, keymap, 0, false)
else
keymapsPath = path.join(@resourcePath, 'keymaps')
@loadKeymap(keymapsPath)
@emitter.emit 'did-load-bundled-keymaps'

View File

@@ -60,12 +60,17 @@ platformMenu = require('../package.json')?._atomMenu?.menu
module.exports =
class MenuManager
constructor: ({@resourcePath, @keymapManager, @packageManager}) ->
@initialized = false
@pendingUpdateOperation = null
@template = []
@keymapManager.onDidLoadBundledKeymaps => @loadPlatformItems()
@keymapManager.onDidReloadKeymap => @update()
@packageManager.onDidActivateInitialPackages => @sortPackagesMenu()
initialize: ({@resourcePath}) ->
@keymapManager.onDidReloadKeymap => @update()
@update()
@initialized = true
# Public: Adds the given items to the application menu.
#
# ## Examples
@@ -89,7 +94,7 @@ class MenuManager
add: (items) ->
items = _.deepClone(items)
@merge(@template, item) for item in items
@update()
@update() if @initialized
new Disposable => @remove(items)
remove: (items) ->

View File

@@ -30,9 +30,8 @@ module.exports =
class PackageManager
constructor: (params) ->
{
configDirPath, @devMode, safeMode, @resourcePath, @config, @styleManager,
@notificationManager, @keymapManager, @commandRegistry, @grammarRegistry,
@deserializerManager, @viewRegistry
@config, @styleManager, @notificationManager, @keymapManager,
@commandRegistry, @grammarRegistry, @deserializerManager, @viewRegistry
} = params
@emitter = new Emitter
@@ -40,11 +39,6 @@ class PackageManager
@packageDirPaths = []
@deferredActivationHooks = []
@triggeredActivationHooks = new Set()
if configDirPath? and not safeMode
if @devMode
@packageDirPaths.push(path.join(configDirPath, "dev", "packages"))
@packageDirPaths.push(path.join(configDirPath, "packages"))
@packagesCache = require('../package.json')?._atomPackages ? {}
@initialPackagesLoaded = false
@initialPackagesActivated = false
@@ -57,6 +51,13 @@ class PackageManager
@packageActivators = []
@registerPackageActivator(this, ['atom', 'textmate'])
initialize: (params) ->
{configDirPath, @devMode, safeMode, @resourcePath} = params
if configDirPath? and not safeMode
if @devMode
@packageDirPaths.push(path.join(configDirPath, "dev", "packages"))
@packageDirPaths.push(path.join(configDirPath, "packages"))
setContextMenuManager: (@contextMenuManager) ->
setMenuManager: (@menuManager) ->

View File

@@ -21,9 +21,11 @@ class PaneContainer extends Model
@setRoot(new Pane({container: this, @config, applicationDelegate, notificationManager, deserializerManager}))
@setActivePane(@getRoot())
@monitorActivePaneItem()
@monitorPaneItems()
initialize: ->
@monitorActivePaneItem()
serialize: (params) ->
deserializer: 'PaneContainer'
version: @serializationVersion

View File

@@ -2,7 +2,7 @@
Grim = require 'grim'
module.exports = ({commandRegistry, commandInstaller, config, notificationManager, project, clipboard}) ->
commandRegistry.add 'atom-workspace',
commandRegistry.addBundled 'atom-workspace',
'pane:show-next-recently-used-item': -> @getModel().getActivePane().activateNextRecentlyUsedItem()
'pane:show-previous-recently-used-item': -> @getModel().getActivePane().activatePreviousRecentlyUsedItem()
'pane:move-active-item-to-top-of-stack': -> @getModel().getActivePane().moveActiveItemToTopOfStack()
@@ -79,10 +79,10 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage
'core:save-as': -> @getModel().saveActivePaneItemAs()
if process.platform is 'darwin'
commandRegistry.add 'atom-workspace', 'window:install-shell-commands', ->
commandRegistry.addBundled 'atom-workspace', 'window:install-shell-commands', ->
commandInstaller.installShellCommandsInteractively()
commandRegistry.add 'atom-pane',
commandRegistry.addBundled 'atom-pane',
'pane:save-items': -> @getModel().saveItems()
'pane:split-left': -> @getModel().splitLeft()
'pane:split-right': -> @getModel().splitRight()
@@ -101,7 +101,7 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage
'pane:increase-size': -> @getModel().increaseSize()
'pane:decrease-size': -> @getModel().decreaseSize()
commandRegistry.add 'atom-text-editor', stopEventPropagation(
commandRegistry.addBundled 'atom-text-editor', stopEventPropagation(
'core:undo': -> @undo()
'core:redo': -> @redo()
'core:move-left': -> @moveLeft()
@@ -142,7 +142,7 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage
'editor:select-line': -> @selectLinesContainingCursors()
)
commandRegistry.add 'atom-text-editor', stopEventPropagationAndGroupUndo(config,
commandRegistry.addBundled 'atom-text-editor', stopEventPropagationAndGroupUndo(config,
'core:backspace': -> @backspace()
'core:delete': -> @delete()
'core:cut': -> @cutSelectedText()
@@ -165,7 +165,7 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage
'editor:copy-selection': -> @copyOnlySelectedText()
)
commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagation(
commandRegistry.addBundled 'atom-text-editor:not([mini])', stopEventPropagation(
'core:move-up': -> @moveUp()
'core:move-down': -> @moveDown()
'core:move-to-top': -> @moveToTop()
@@ -203,7 +203,7 @@ module.exports = ({commandRegistry, commandInstaller, config, notificationManage
'editor:scroll-to-cursor': -> @scrollToCursorPosition()
)
commandRegistry.add 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo(config,
commandRegistry.addBundled 'atom-text-editor:not([mini])', stopEventPropagationAndGroupUndo(config,
'editor:indent': -> @indent()
'editor:auto-indent': -> @autoIndentSelectedRows()
'editor:indent-selected-rows': -> @indentSelectedRows()

View File

@@ -9,7 +9,7 @@ fs = require 'fs-plus'
# An instance of this class is always available as the `atom.themes` global.
module.exports =
class ThemeManager
constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode, @config, @styleManager, @notificationManager, @viewRegistry}) ->
constructor: ({@packageManager, @config, @styleManager, @notificationManager, @viewRegistry}) ->
@emitter = new Emitter
@styleSheetDisposablesBySourcePath = {}
@lessCache = null
@@ -18,6 +18,8 @@ class ThemeManager
@packageManager.onDidActivateInitialPackages =>
@onDidChangeActiveThemes => @packageManager.reloadActivePackageStyleSheets()
initialize: ({@resourcePath, @configDirPath, @safeMode}) ->
###
Section: Event Subscription
###

View File

@@ -4,10 +4,27 @@ listen = require './delegated-listener'
# Handles low-level events related to the @window.
module.exports =
class WindowEventHandler
constructor: ({@atomEnvironment, @applicationDelegate, @window, @document}) ->
constructor: ({@atomEnvironment, @applicationDelegate}) ->
@reloadRequested = false
@subscriptions = new CompositeDisposable
@handleNativeKeybindings()
initialize: (@window, @document) ->
@subscriptions.add @atomEnvironment.commands.add @window,
'window:toggle-full-screen': @handleWindowToggleFullScreen
'window:close': @handleWindowClose
'window:reload': @handleWindowReload
'window:toggle-dev-tools': @handleWindowToggleDevTools
if process.platform in ['win32', 'linux']
@subscriptions.add @atomEnvironment.commands.add @window,
'window:toggle-menu-bar': @handleWindowToggleMenuBar
@subscriptions.add @atomEnvironment.commands.add @document,
'core:focus-next': @handleFocusNext
'core:focus-previous': @handleFocusPrevious
@addEventListener(@window, 'beforeunload', @handleWindowBeforeunload)
@addEventListener(@window, 'focus', @handleWindowFocus)
@addEventListener(@window, 'blur', @handleWindowBlur)
@@ -23,27 +40,11 @@ class WindowEventHandler
@subscriptions.add(@applicationDelegate.onDidEnterFullScreen(@handleEnterFullScreen))
@subscriptions.add(@applicationDelegate.onDidLeaveFullScreen(@handleLeaveFullScreen))
@subscriptions.add @atomEnvironment.commands.add @window,
'window:toggle-full-screen': @handleWindowToggleFullScreen
'window:close': @handleWindowClose
'window:reload': @handleWindowReload
'window:toggle-dev-tools': @handleWindowToggleDevTools
if process.platform in ['win32', 'linux']
@subscriptions.add @atomEnvironment.commands.add @window,
'window:toggle-menu-bar': @handleWindowToggleMenuBar
@subscriptions.add @atomEnvironment.commands.add @document,
'core:focus-next': @handleFocusNext
'core:focus-previous': @handleFocusPrevious
@handleNativeKeybindings()
# Wire commands that should be handled by Chromium for elements with the
# `.native-key-bindings` class.
handleNativeKeybindings: ->
bindCommandToAction = (command, action) =>
@subscriptions.add @atomEnvironment.commands.add '.native-key-bindings', command, (event) =>
@subscriptions.add @atomEnvironment.commands.addBundled '.native-key-bindings', command, (event) =>
@applicationDelegate.getCurrentWindow().webContents[action]()
bindCommandToAction('core:copy', 'copy')

View File

@@ -30,6 +30,7 @@ module.exports = class Workspace extends Model {
this.updateWindowTitle = this.updateWindowTitle.bind(this)
this.updateDocumentEdited = this.updateDocumentEdited.bind(this)
this.didDestroyPaneItem = this.didDestroyPaneItem.bind(this)
this.didChangeActivePaneItem = this.didChangeActivePaneItem.bind(this)
this.packageManager = params.packageManager
this.config = params.config
@@ -76,6 +77,11 @@ module.exports = class Workspace extends Model {
this.subscribeToEvents()
}
initialize () {
this.paneContainer.initialize()
this.didChangeActivePaneItem()
}
reset (packageManager) {
this.packageManager = packageManager
this.emitter.dispose()
@@ -176,46 +182,44 @@ module.exports = class Workspace extends Model {
}
subscribeToActiveItem () {
this.project.onDidChangePaths(this.updateWindowTitle)
this.onDidChangeActivePaneItem(this.didChangeActivePaneItem)
}
didChangeActivePaneItem (item) {
this.updateWindowTitle()
this.updateDocumentEdited()
this.project.onDidChangePaths(this.updateWindowTitle)
if (this.activeItemSubscriptions != null) {
this.activeItemSubscriptions.dispose()
}
this.activeItemSubscriptions = new CompositeDisposable()
this.observeActivePaneItem(item => {
this.updateWindowTitle()
this.updateDocumentEdited()
let modifiedSubscription, titleSubscription
if (this.activeItemSubscriptions != null) {
this.activeItemSubscriptions.dispose()
if (item != null && typeof item.onDidChangeTitle === 'function') {
titleSubscription = item.onDidChangeTitle(this.updateWindowTitle)
} else if (item != null && typeof item.on === 'function') {
titleSubscription = item.on('title-changed', this.updateWindowTitle)
if (titleSubscription == null || typeof titleSubscription.dispose !== 'function') {
titleSubscription = new Disposable(() => {
item.off('title-changed', this.updateWindowTitle)
})
}
this.activeItemSubscriptions = new CompositeDisposable()
}
let modifiedSubscription, titleSubscription
if (item != null && typeof item.onDidChangeTitle === 'function') {
titleSubscription = item.onDidChangeTitle(this.updateWindowTitle)
} else if (item != null && typeof item.on === 'function') {
titleSubscription = item.on('title-changed', this.updateWindowTitle)
if (titleSubscription == null || typeof titleSubscription.dispose !== 'function') {
titleSubscription = new Disposable(() => {
item.off('title-changed', this.updateWindowTitle)
})
}
if (item != null && typeof item.onDidChangeModified === 'function') {
modifiedSubscription = item.onDidChangeModified(this.updateDocumentEdited)
} else if (item != null && typeof item.on === 'function') {
modifiedSubscription = item.on('modified-status-changed', this.updateDocumentEdited)
if (modifiedSubscription == null || typeof modifiedSubscription.dispose !== 'function') {
modifiedSubscription = new Disposable(() => {
item.off('modified-status-changed', this.updateDocumentEdited)
})
}
}
if (item != null && typeof item.onDidChangeModified === 'function') {
modifiedSubscription = item.onDidChangeModified(this.updateDocumentEdited)
} else if (item != null && typeof item.on === 'function') {
modifiedSubscription = item.on('modified-status-changed', this.updateDocumentEdited)
if (modifiedSubscription == null || typeof modifiedSubscription.dispose !== 'function') {
modifiedSubscription = new Disposable(() => {
item.off('modified-status-changed', this.updateDocumentEdited)
})
}
}
if (titleSubscription != null) { this.activeItemSubscriptions.add(titleSubscription) }
if (modifiedSubscription != null) { this.activeItemSubscriptions.add(modifiedSubscription) }
})
if (titleSubscription != null) { this.activeItemSubscriptions.add(titleSubscription) }
if (modifiedSubscription != null) { this.activeItemSubscriptions.add(modifiedSubscription) }
}
subscribeToAddedItems () {