@jbrowse/product-core 5.0.0-beta.1 → 5.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/RootModel/BaseRootModel.d.ts +24 -158
- package/esm/RootModel/BaseRootModel.js +7 -4
- package/esm/RootModel/HierarchicalConfig.d.ts +21 -47
- package/esm/RootModel/PreferencesConfig.d.ts +20 -36
- package/esm/RootModel/PreferencesConfig.js +17 -3
- package/esm/RootModel/createConfigModel.d.ts +148 -123
- package/esm/RootModel/createConfigModel.js +35 -14
- package/esm/RootModel/menuItems.js +7 -9
- package/esm/Session/BaseSession.d.ts +60 -85
- package/esm/Session/BaseSession.js +106 -172
- package/esm/Session/Connections.d.ts +4 -3
- package/esm/Session/Connections.js +4 -3
- package/esm/Session/DrawerWidgets.d.ts +32 -1
- package/esm/Session/DrawerWidgets.js +71 -11
- package/esm/Session/MultipleViews.d.ts +85 -333
- package/esm/Session/MultipleViews.js +50 -10
- package/esm/Session/Preferences.d.ts +53 -329
- package/esm/Session/Preferences.js +6 -2
- package/esm/Session/SessionTracks.d.ts +180 -396
- package/esm/Session/SessionTracks.js +291 -238
- package/esm/Session/Themes.d.ts +79 -30
- package/esm/Session/Themes.js +153 -40
- package/esm/Session/TrackMenu.d.ts +4 -28
- package/esm/Session/TrackMenu.js +28 -53
- package/esm/Session/TrackMenuSessionMixin.js +2 -1
- package/esm/Session/Tracks.d.ts +75 -341
- package/esm/Session/Tracks.js +192 -133
- package/esm/Session/copyTrackSnapshot.d.ts +21 -0
- package/esm/Session/copyTrackSnapshot.js +20 -0
- package/esm/Session/developerMode.d.ts +7 -0
- package/esm/Session/developerMode.js +43 -0
- package/esm/Session/finalizeSession.d.ts +1 -2
- package/esm/Session/finalizeSession.js +1 -2
- package/esm/Session/hydratedForms.d.ts +16 -0
- package/esm/Session/hydratedForms.js +13 -0
- package/esm/Session/index.d.ts +8 -3
- package/esm/Session/index.js +6 -3
- package/esm/Session/pluginExtraTrackItems.d.ts +11 -0
- package/esm/Session/pluginExtraTrackItems.js +13 -0
- package/esm/Session/readdedTrackConf.d.ts +8 -0
- package/esm/Session/readdedTrackConf.js +24 -0
- package/esm/Session/shareableSnapshot.d.ts +6 -60
- package/esm/Session/shareableSnapshot.js +8 -138
- package/esm/Session/temporaryAssemblyTracks.d.ts +4 -3
- package/esm/Session/temporaryAssemblyTracks.js +6 -7
- package/esm/controllerTracks.d.ts +31 -11
- package/esm/controllerTracks.js +63 -15
- package/esm/embeddedController.d.ts +57 -0
- package/esm/embeddedController.js +100 -0
- package/esm/index.d.ts +12 -11
- package/esm/index.js +9 -9
- package/esm/loadPlugins.d.ts +8 -3
- package/esm/loadPlugins.js +11 -4
- package/esm/observeSession.d.ts +4 -5
- package/esm/observeSession.js +3 -4
- package/esm/parallelChunkLoading.d.ts +30 -0
- package/esm/parallelChunkLoading.js +71 -0
- package/esm/pruneUnbuildableNodes.js +18 -24
- package/esm/resolveAssemblies.d.ts +36 -12
- package/esm/resolveAssemblies.js +38 -16
- package/esm/rpcWorker.d.ts +11 -5
- package/esm/rpcWorker.js +41 -16
- package/esm/sessionMigrations/index.d.ts +10 -48
- package/esm/sessionMigrations/index.js +116 -370
- package/esm/sessionUrl.d.ts +7 -8
- package/esm/sessionUrl.js +27 -14
- package/esm/sessionUtils.d.ts +6 -1
- package/esm/sessionUtils.js +78 -92
- package/esm/ui/AboutDialog.d.ts +10 -2
- package/esm/ui/AboutDialog.js +11 -2
- package/esm/ui/AboutDialogContents.js +5 -29
- package/esm/ui/AssemblyInfoPanel.js +4 -10
- package/esm/ui/DescriptionPanel.d.ts +3 -0
- package/esm/ui/DescriptionPanel.js +62 -0
- package/esm/ui/FileInfoPanel.js +12 -11
- package/esm/ui/GeneralPreferencesTab.d.ts +17 -0
- package/esm/ui/GeneralPreferencesTab.js +34 -0
- package/esm/ui/HeaderButtons.d.ts +1 -6
- package/esm/ui/HeaderButtons.js +5 -12
- package/esm/ui/ModalWidget.d.ts +2 -1
- package/esm/ui/ModalWidget.js +18 -3
- package/esm/ui/PreferenceCheckbox.d.ts +6 -0
- package/esm/ui/PreferenceCheckbox.js +16 -0
- package/esm/ui/PreferencesDialog.d.ts +5 -27
- package/esm/ui/PreferencesDialog.js +29 -119
- package/esm/ui/RefNameInfoDialog.js +13 -25
- package/esm/ui/ViewPreferencesTab.d.ts +12 -0
- package/esm/ui/ViewPreferencesTab.js +15 -0
- package/esm/ui/aboutTestUtils.d.ts +140 -0
- package/esm/ui/aboutTestUtils.js +25 -0
- package/esm/ui/descriptionHtml.d.ts +47 -0
- package/esm/ui/descriptionHtml.js +117 -0
- package/esm/ui/index.d.ts +2 -0
- package/esm/ui/index.js +1 -0
- package/esm/ui/preferencesReset.d.ts +18 -0
- package/esm/ui/preferencesReset.js +69 -0
- package/esm/ui/util.d.ts +9 -27
- package/esm/ui/util.js +12 -31
- package/esm/useEngineLifecycle.d.ts +7 -1
- package/esm/useEngineLifecycle.js +24 -2
- package/package.json +11 -10
- package/esm/scheduleDetachedDestroy.d.ts +0 -18
- package/esm/scheduleDetachedDestroy.js +0 -24
- package/esm/ui/DisplayDefaultsSection.d.ts +0 -36
- package/esm/ui/DisplayDefaultsSection.js +0 -65
|
@@ -4,6 +4,7 @@ import type PluginManager from '@jbrowse/core/PluginManager';
|
|
|
4
4
|
import type { BaseAssemblyConfigModel } from '@jbrowse/core/assemblyManager';
|
|
5
5
|
import type { AnyConfigurationSchemaType } from '@jbrowse/core/configuration';
|
|
6
6
|
import type { AnimationMode, DialogComponentType, TrackConfigChange } from '@jbrowse/core/util';
|
|
7
|
+
import type { HighlightType } from '@jbrowse/core/util/highlights';
|
|
7
8
|
import type { IAnyStateTreeNode, Instance } from '@jbrowse/mobx-state-tree';
|
|
8
9
|
type DoneCallback = (doneCallback: () => void) => [DialogComponentType, Record<string, unknown>];
|
|
9
10
|
/**
|
|
@@ -28,22 +29,31 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
28
29
|
focusedViewId: import("@jbrowse/mobx-state-tree").IMaybe<import("@jbrowse/mobx-state-tree").ISimpleType<string>>;
|
|
29
30
|
/**
|
|
30
31
|
* #property
|
|
31
|
-
*
|
|
32
|
-
*
|
|
32
|
+
* translucent bands over genomic regions; every view draws the ones on
|
|
33
|
+
* its own assemblies
|
|
34
|
+
*/
|
|
35
|
+
highlights: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IArrayType<import("@jbrowse/mobx-state-tree").IType<HighlightType, HighlightType, HighlightType>>, [undefined]>;
|
|
36
|
+
/**
|
|
37
|
+
* #property
|
|
33
38
|
*/
|
|
34
39
|
highlightsVisible: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
40
|
+
/**
|
|
41
|
+
* #property
|
|
42
|
+
* whether a band's label is written on it
|
|
43
|
+
*/
|
|
44
|
+
highlightLabelsVisible: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").ISimpleType<boolean>, [undefined]>;
|
|
35
45
|
/**
|
|
36
46
|
* #property
|
|
37
47
|
* views, tracks, displays and widgets `pruneUnbuildableNodes` took out of
|
|
38
48
|
* the tree because this build has no plugin for their type, each with the
|
|
39
|
-
* anchor that puts it back.
|
|
40
|
-
*
|
|
49
|
+
* anchor that puts it back. Nothing in the session reads its contents,
|
|
50
|
+
* and `pruneUnbuildableNodes` defines their structure.
|
|
41
51
|
*
|
|
42
|
-
* It is a **declared property**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
52
|
+
* It is a **declared property** because MST drops undeclared snapshot
|
|
53
|
+
* keys without error. Without this declaration the held nodes survive
|
|
54
|
+
* the prune and are then discarded when `setSession` builds the tree,
|
|
55
|
+
* while every unit test of the prune still passes.
|
|
56
|
+
* `heldNodesSurviveTheSession.test.ts` tests that they survive.
|
|
47
57
|
*/
|
|
48
58
|
heldForMissingPlugins: import("@jbrowse/mobx-state-tree").IOptionalIType<import("@jbrowse/mobx-state-tree").IType<HeldNode[] | undefined, HeldNode[] | undefined, HeldNode[] | undefined>, [undefined]>;
|
|
49
59
|
}, never>, {
|
|
@@ -75,23 +85,15 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
75
85
|
*
|
|
76
86
|
* An `observable.map` (not a plain object reassigned wholesale) so each
|
|
77
87
|
* preference is its own tracked key: writing one (`setScrollZoom`) can't
|
|
78
|
-
* invalidate a reader of another
|
|
79
|
-
*
|
|
80
|
-
* every
|
|
81
|
-
* same reason each promoted per-display-type default is a flat composite
|
|
82
|
-
* key (see `displayTypeDefaultKey`), not a single nested `displayTypeDefaults`
|
|
83
|
-
* object — promoting one default can't wake readers of a different one.
|
|
88
|
+
* invalidate a reader of another. A single spread-replaced object made
|
|
89
|
+
* every setter wake every reader, so toggling scroll-to-zoom re-fetched
|
|
90
|
+
* every track.
|
|
84
91
|
*
|
|
85
|
-
* `deep: false`
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
* `
|
|
90
|
-
* `worker.postMessage` threw `DataCloneError` on the next fetch of any
|
|
91
|
-
* track following that default (electron IPC and `structuredClone` in the
|
|
92
|
-
* share bake likewise). The map still notifies per key on `set`, so shallow
|
|
93
|
-
* values lose no reactivity — and nothing can mutate a preference in place,
|
|
94
|
-
* because `setPreferenceOverride` freezes what it stores.
|
|
92
|
+
* `deep: false` keeps an object-valued preference a plain object rather
|
|
93
|
+
* than a MobX Proxy, which V8's structured-clone serializer rejects. The
|
|
94
|
+
* map still notifies per key on `set`, so shallow values lose no
|
|
95
|
+
* reactivity — and nothing can mutate a preference in place, because
|
|
96
|
+
* `setPreferenceOverride` freezes what it stores.
|
|
95
97
|
*/
|
|
96
98
|
preferencesOverrides: import("mobx").ObservableMap<string, unknown>;
|
|
97
99
|
} & {
|
|
@@ -152,37 +154,10 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
152
154
|
getPreference(key: string): unknown;
|
|
153
155
|
/**
|
|
154
156
|
* #method
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* #method
|
|
161
|
-
* every per-display-type default the user has promoted, as
|
|
162
|
-
* `{ displayType, slot, value }` — the inventory the Preferences dialog
|
|
163
|
-
* lists and clears one at a time (`setDisplayTypeDefault(…, undefined)`).
|
|
164
|
-
*
|
|
165
|
-
* Here rather than filtered out of `getPreferenceChanges` by the dialog,
|
|
166
|
-
* because the composite-key layout is this file's: a consumer that
|
|
167
|
-
* recognized these rows by matching the path head is exactly the coupling
|
|
168
|
-
* `DISPLAY_TYPE_DEFAULTS_PATH_HEAD` stopped being exported over, where a
|
|
169
|
-
* rename on one side alone silently no-ops the other.
|
|
170
|
-
*/
|
|
171
|
-
getDisplayTypeDefaults(): {
|
|
172
|
-
displayType: string;
|
|
173
|
-
slot: string;
|
|
174
|
-
value: unknown;
|
|
175
|
-
}[];
|
|
176
|
-
/**
|
|
177
|
-
* #method
|
|
178
|
-
* every runtime preference-override that currently differs from its
|
|
179
|
-
* config/admin default, as `{ path, from, to }` rows — the exact set
|
|
180
|
-
* `clearPreferenceOverrides` reverts. Backs the confirmation diff shown
|
|
181
|
-
* before "Reset to defaults" (mirrors the per-track changes dialog). A
|
|
182
|
-
* scalar pref (animationMode, scrollZoom) whose override equals the
|
|
183
|
-
* default is omitted (reverting it is a no-op); each promoted
|
|
184
|
-
* per-display-type default is always a difference from the un-promoted
|
|
185
|
-
* state, so `from` reads "(default)".
|
|
157
|
+
* every scalar preference override that currently differs from its
|
|
158
|
+
* config/admin default, as `{ path, from, to }` rows whose path is the
|
|
159
|
+
* override's own key. A scalar pref (animationMode, scrollZoom) whose
|
|
160
|
+
* override equals the default is omitted, since reverting it is a no-op.
|
|
186
161
|
*/
|
|
187
162
|
getPreferenceChanges(): TrackConfigChange[];
|
|
188
163
|
} & {
|
|
@@ -229,15 +204,31 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
229
204
|
setHovered(thing: unknown): void;
|
|
230
205
|
/**
|
|
231
206
|
* #action
|
|
232
|
-
* toggle all region highlight bands across every view
|
|
233
207
|
*/
|
|
234
208
|
setHighlightsVisible(arg: boolean): void;
|
|
235
209
|
/**
|
|
236
210
|
* #action
|
|
237
|
-
* turn highlight bands back on, so a newly made highlight or bookmark is
|
|
238
|
-
* never silently swallowed by an earlier "highlights off"
|
|
239
211
|
*/
|
|
240
|
-
|
|
212
|
+
setHighlightLabelsVisible(arg: boolean): void;
|
|
213
|
+
/**
|
|
214
|
+
* #action
|
|
215
|
+
* an identical entry is not added twice, so a spec launched again does not
|
|
216
|
+
* stack its bands. Adding shows the bands again, since a highlight made
|
|
217
|
+
* while they are off would otherwise read as nothing happening
|
|
218
|
+
*/
|
|
219
|
+
addHighlight(highlight: HighlightType): void;
|
|
220
|
+
/**
|
|
221
|
+
* #action
|
|
222
|
+
*/
|
|
223
|
+
removeHighlight(highlight: HighlightType): void;
|
|
224
|
+
/**
|
|
225
|
+
* #action
|
|
226
|
+
*/
|
|
227
|
+
updateHighlight(old: HighlightType, updates: Partial<HighlightType>): void;
|
|
228
|
+
/**
|
|
229
|
+
* #action
|
|
230
|
+
*/
|
|
231
|
+
setHighlights(highlights: HighlightType[]): void;
|
|
241
232
|
/**
|
|
242
233
|
* #action
|
|
243
234
|
* set a runtime user-preference override (see `getPreference`). Mutates
|
|
@@ -248,10 +239,9 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
248
239
|
setPreferenceOverride(key: string, value: unknown): void;
|
|
249
240
|
/**
|
|
250
241
|
* #action
|
|
251
|
-
* clear every runtime preference override at once
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* default. Backs the Preferences dialog "Reset to defaults" button.
|
|
242
|
+
* clear every runtime preference override at once, so each falls back to
|
|
243
|
+
* its config/admin default. Backs the Preferences dialog "Reset to
|
|
244
|
+
* defaults" button.
|
|
255
245
|
*/
|
|
256
246
|
clearPreferenceOverrides(): void;
|
|
257
247
|
/**
|
|
@@ -261,32 +251,11 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
261
251
|
* Preferences dialog "Reset to defaults" confirmation.
|
|
262
252
|
*/
|
|
263
253
|
clearPreferenceOverride(key: string): void;
|
|
264
|
-
/**
|
|
265
|
-
* #action
|
|
266
|
-
* revert one row emitted by `getPreferenceChanges`, addressed by its
|
|
267
|
-
* display `path`. Backs the per-entry reset in the Preferences dialog's
|
|
268
|
-
* "Reset to defaults" confirmation.
|
|
269
|
-
*
|
|
270
|
-
* Lives here rather than in that dialog because this model owns both path
|
|
271
|
-
* shapes it has to undo: a promoted per-display-type default, whose row
|
|
272
|
-
* path is a readable label over a flat composite storage key, and every
|
|
273
|
-
* other override, whose path *is* its key. The dialog used to re-derive
|
|
274
|
-
* the first case from an exported path-head constant.
|
|
275
|
-
*/
|
|
276
|
-
resetPreferenceChange(path: string[]): void;
|
|
277
254
|
/**
|
|
278
255
|
* #action
|
|
279
256
|
* set the global scroll-to-zoom preference (see the `scrollZoom` getter)
|
|
280
257
|
*/
|
|
281
258
|
setScrollZoom(flag: boolean): void;
|
|
282
|
-
/**
|
|
283
|
-
* #action
|
|
284
|
-
* promote (or, with `value` undefined, clear) a per-display-type slot
|
|
285
|
-
* default. Just a preference override under one flat composite key (see
|
|
286
|
-
* `displayTypeDefaultKey`), so it persists and independently tracks like
|
|
287
|
-
* any other pref, and clearing deletes only that key.
|
|
288
|
-
*/
|
|
289
|
-
setDisplayTypeDefault(displayType: string, slot: string, value: unknown): void;
|
|
290
259
|
/**
|
|
291
260
|
* #action
|
|
292
261
|
*/
|
|
@@ -310,6 +279,10 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
310
279
|
* #action
|
|
311
280
|
*/
|
|
312
281
|
queueDialog(doneCallback: DoneCallback): void;
|
|
282
|
+
/**
|
|
283
|
+
* #action
|
|
284
|
+
*/
|
|
285
|
+
removeDialog(entry: [DialogComponentType, Record<string, unknown>]): void;
|
|
313
286
|
} & {
|
|
314
287
|
snackbarMessages: import("mobx").IObservableArray<import("@jbrowse/core/ui/SnackbarModel").SnackbarMessage>;
|
|
315
288
|
errorDialog: import("@jbrowse/core/ui/SnackbarModel").ErrorDialogState | undefined;
|
|
@@ -322,6 +295,8 @@ export declare function BaseSessionModel<ROOT_MODEL_TYPE extends BaseRootModelTy
|
|
|
322
295
|
pushSnackbarMessage(message: string, level?: import("@jbrowse/core/util").NotificationLevel, actions?: import("@jbrowse/core/util").SnackAction[]): void;
|
|
323
296
|
popSnackbarMessage(): import("@jbrowse/core/ui/SnackbarModel").SnackbarMessage | undefined;
|
|
324
297
|
removeSnackbarMessage(message: string): void;
|
|
298
|
+
} & {
|
|
299
|
+
afterAttach(): void;
|
|
325
300
|
}, import("@jbrowse/mobx-state-tree")._NotCustomized, import("@jbrowse/mobx-state-tree")._NotCustomized>;
|
|
326
301
|
/** Session mixin MST type for the most basic session */
|
|
327
302
|
export type BaseSessionType = ReturnType<typeof BaseSessionModel>;
|
|
@@ -1,55 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readConfObject } from '@jbrowse/core/configuration';
|
|
2
2
|
import SnackbarModel from '@jbrowse/core/ui/SnackbarModel';
|
|
3
3
|
import { setNumberGrouping } from '@jbrowse/core/util';
|
|
4
4
|
import { freezeDeep } from '@jbrowse/core/util/freezeDeep';
|
|
5
|
+
import { isSameHighlight } from '@jbrowse/core/util/highlights';
|
|
5
6
|
import { isFeature, unwrapFeature } from '@jbrowse/core/util/simpleFeature';
|
|
6
7
|
import { ElementId } from '@jbrowse/core/util/types/mst';
|
|
7
|
-
import { getParent, isStateTreeNode, types } from '@jbrowse/mobx-state-tree';
|
|
8
|
+
import { cast, getParent, isStateTreeNode, types, } from '@jbrowse/mobx-state-tree';
|
|
8
9
|
import { observable } from 'mobx';
|
|
10
|
+
import { applyDeveloperMode } from './developerMode.js';
|
|
9
11
|
function isAnimationMode(val) {
|
|
10
12
|
return val === 'system' || val === 'enabled' || val === 'disabled';
|
|
11
13
|
}
|
|
12
|
-
// Promoted per-display-type slot defaults live flat in `preferencesOverrides`
|
|
13
|
-
// under one composite key each (`displayTypeDefault\0<type>\0<slot>`), not under
|
|
14
|
-
// a single nested `displayTypeDefaults` object. Flat keys make each promoted
|
|
15
|
-
// default its own tracked observable-map entry — promoting one can't invalidate
|
|
16
|
-
// a reader of another (every promotable display's `rpcProps` reads one via
|
|
17
|
-
// `getDisplayTypeDefault`) — and collapse the get/set/diff logic to one lookup.
|
|
18
|
-
// The `\0` delimiter can't appear in a display type or slot name.
|
|
19
|
-
// The literal is a **persisted localStorage key prefix**, so treat it as data
|
|
20
|
-
// rather than as an identifier a rename should sweep — a blanket
|
|
21
|
-
// `displayTypeDefault` → `pin` pass did sweep it, and orphans every promoted
|
|
22
|
-
// default already in a browser's storage. Nothing released stores these yet, so
|
|
23
|
-
// the reason it keeps this spelling is naming, not compatibility: the key names
|
|
24
|
-
// *what is stored* (a display-type default, reached through
|
|
25
|
-
// `get/setDisplayTypeDefault`), while `Pin` names the menu control the write
|
|
26
|
-
// is offered from.
|
|
27
|
-
const DISPLAY_TYPE_DEFAULT_PREFIX = 'displayTypeDefault\0';
|
|
28
|
-
// Module-private on purpose: the composite-key spelling is a storage detail of
|
|
29
|
-
// this file's get/set/diff methods, and nothing outside it should be able to
|
|
30
|
-
// depend on the layout.
|
|
31
|
-
function displayTypeDefaultKey(displayType, slot) {
|
|
32
|
-
return `${DISPLAY_TYPE_DEFAULT_PREFIX}${displayType}\0${slot}`;
|
|
33
|
-
}
|
|
34
|
-
function parseDisplayTypeDefaultKey(key) {
|
|
35
|
-
const rest = key.startsWith(DISPLAY_TYPE_DEFAULT_PREFIX)
|
|
36
|
-
? key.slice(DISPLAY_TYPE_DEFAULT_PREFIX.length)
|
|
37
|
-
: '';
|
|
38
|
-
const [displayType, slot] = rest.split('\0');
|
|
39
|
-
return displayType && slot ? { displayType, slot } : undefined;
|
|
40
|
-
}
|
|
41
|
-
// Head of the display path a promoted default takes in a `getPreferenceChanges`
|
|
42
|
-
// row: `[DISPLAY_TYPE_DEFAULTS_PATH_HEAD, displayType, slot]`. Purely a
|
|
43
|
-
// readable row label, deliberately distinct from the flat
|
|
44
|
-
// `DISPLAY_TYPE_DEFAULT_PREFIX` storage key above.
|
|
45
|
-
//
|
|
46
|
-
// Module-private, like the storage key: both the producer
|
|
47
|
-
// (`getPreferenceChanges`) and the consumer (`resetPreferenceChange`) are
|
|
48
|
-
// methods on this model, so the two path shapes this file emits are the only
|
|
49
|
-
// ones it has to undo. It used to be exported for the Preferences dialog to
|
|
50
|
-
// match on and re-route back through `setDisplayTypeDefault`, which meant a
|
|
51
|
-
// rename on one side alone would silently no-op that dialog's per-row reset.
|
|
52
|
-
const DISPLAY_TYPE_DEFAULTS_PATH_HEAD = 'displayTypeDefaults';
|
|
53
14
|
/**
|
|
54
15
|
* #stateModel BaseSessionModel
|
|
55
16
|
*
|
|
@@ -74,22 +35,31 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
74
35
|
focusedViewId: types.maybe(types.string),
|
|
75
36
|
/**
|
|
76
37
|
* #property
|
|
77
|
-
*
|
|
78
|
-
*
|
|
38
|
+
* translucent bands over genomic regions; every view draws the ones on
|
|
39
|
+
* its own assemblies
|
|
40
|
+
*/
|
|
41
|
+
highlights: types.stripDefault(types.array(types.frozen()), []),
|
|
42
|
+
/**
|
|
43
|
+
* #property
|
|
79
44
|
*/
|
|
80
45
|
highlightsVisible: types.stripDefault(types.boolean, true),
|
|
46
|
+
/**
|
|
47
|
+
* #property
|
|
48
|
+
* whether a band's label is written on it
|
|
49
|
+
*/
|
|
50
|
+
highlightLabelsVisible: types.stripDefault(types.boolean, true),
|
|
81
51
|
/**
|
|
82
52
|
* #property
|
|
83
53
|
* views, tracks, displays and widgets `pruneUnbuildableNodes` took out of
|
|
84
54
|
* the tree because this build has no plugin for their type, each with the
|
|
85
|
-
* anchor that puts it back.
|
|
86
|
-
*
|
|
55
|
+
* anchor that puts it back. Nothing in the session reads its contents,
|
|
56
|
+
* and `pruneUnbuildableNodes` defines their structure.
|
|
87
57
|
*
|
|
88
|
-
* It is a **declared property**
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
58
|
+
* It is a **declared property** because MST drops undeclared snapshot
|
|
59
|
+
* keys without error. Without this declaration the held nodes survive
|
|
60
|
+
* the prune and are then discarded when `setSession` builds the tree,
|
|
61
|
+
* while every unit test of the prune still passes.
|
|
62
|
+
* `heldNodesSurviveTheSession.test.ts` tests that they survive.
|
|
93
63
|
*/
|
|
94
64
|
heldForMissingPlugins: types.stripDefault(types.frozen(), undefined),
|
|
95
65
|
})
|
|
@@ -124,23 +94,15 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
124
94
|
*
|
|
125
95
|
* An `observable.map` (not a plain object reassigned wholesale) so each
|
|
126
96
|
* preference is its own tracked key: writing one (`setScrollZoom`) can't
|
|
127
|
-
* invalidate a reader of another
|
|
128
|
-
*
|
|
129
|
-
* every
|
|
130
|
-
* same reason each promoted per-display-type default is a flat composite
|
|
131
|
-
* key (see `displayTypeDefaultKey`), not a single nested `displayTypeDefaults`
|
|
132
|
-
* object — promoting one default can't wake readers of a different one.
|
|
97
|
+
* invalidate a reader of another. A single spread-replaced object made
|
|
98
|
+
* every setter wake every reader, so toggling scroll-to-zoom re-fetched
|
|
99
|
+
* every track.
|
|
133
100
|
*
|
|
134
|
-
* `deep: false`
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* `
|
|
139
|
-
* `worker.postMessage` threw `DataCloneError` on the next fetch of any
|
|
140
|
-
* track following that default (electron IPC and `structuredClone` in the
|
|
141
|
-
* share bake likewise). The map still notifies per key on `set`, so shallow
|
|
142
|
-
* values lose no reactivity — and nothing can mutate a preference in place,
|
|
143
|
-
* because `setPreferenceOverride` freezes what it stores.
|
|
101
|
+
* `deep: false` keeps an object-valued preference a plain object rather
|
|
102
|
+
* than a MobX Proxy, which V8's structured-clone serializer rejects. The
|
|
103
|
+
* map still notifies per key on `set`, so shallow values lose no
|
|
104
|
+
* reactivity — and nothing can mutate a preference in place, because
|
|
105
|
+
* `setPreferenceOverride` freezes what it stores.
|
|
144
106
|
*/
|
|
145
107
|
preferencesOverrides: observable.map(undefined, {
|
|
146
108
|
deep: false,
|
|
@@ -216,7 +178,8 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
216
178
|
* `defaultUseWorkspaces`).
|
|
217
179
|
*/
|
|
218
180
|
getPreferenceDefault(key) {
|
|
219
|
-
|
|
181
|
+
const { preferences } = self.configuration;
|
|
182
|
+
return preferences ? readConfObject(preferences, key) : undefined;
|
|
220
183
|
},
|
|
221
184
|
/**
|
|
222
185
|
* #method
|
|
@@ -232,70 +195,22 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
232
195
|
},
|
|
233
196
|
/**
|
|
234
197
|
* #method
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
return self.preferencesOverrides.get(displayTypeDefaultKey(displayType, slot));
|
|
240
|
-
},
|
|
241
|
-
/**
|
|
242
|
-
* #method
|
|
243
|
-
* every per-display-type default the user has promoted, as
|
|
244
|
-
* `{ displayType, slot, value }` — the inventory the Preferences dialog
|
|
245
|
-
* lists and clears one at a time (`setDisplayTypeDefault(…, undefined)`).
|
|
246
|
-
*
|
|
247
|
-
* Here rather than filtered out of `getPreferenceChanges` by the dialog,
|
|
248
|
-
* because the composite-key layout is this file's: a consumer that
|
|
249
|
-
* recognized these rows by matching the path head is exactly the coupling
|
|
250
|
-
* `DISPLAY_TYPE_DEFAULTS_PATH_HEAD` stopped being exported over, where a
|
|
251
|
-
* rename on one side alone silently no-ops the other.
|
|
252
|
-
*/
|
|
253
|
-
getDisplayTypeDefaults() {
|
|
254
|
-
const found = [];
|
|
255
|
-
for (const [key, value] of self.preferencesOverrides.entries()) {
|
|
256
|
-
const parsed = parseDisplayTypeDefaultKey(key);
|
|
257
|
-
if (parsed) {
|
|
258
|
-
found.push({ ...parsed, value });
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return found;
|
|
262
|
-
},
|
|
263
|
-
/**
|
|
264
|
-
* #method
|
|
265
|
-
* every runtime preference-override that currently differs from its
|
|
266
|
-
* config/admin default, as `{ path, from, to }` rows — the exact set
|
|
267
|
-
* `clearPreferenceOverrides` reverts. Backs the confirmation diff shown
|
|
268
|
-
* before "Reset to defaults" (mirrors the per-track changes dialog). A
|
|
269
|
-
* scalar pref (animationMode, scrollZoom) whose override equals the
|
|
270
|
-
* default is omitted (reverting it is a no-op); each promoted
|
|
271
|
-
* per-display-type default is always a difference from the un-promoted
|
|
272
|
-
* state, so `from` reads "(default)".
|
|
198
|
+
* every scalar preference override that currently differs from its
|
|
199
|
+
* config/admin default, as `{ path, from, to }` rows whose path is the
|
|
200
|
+
* override's own key. A scalar pref (animationMode, scrollZoom) whose
|
|
201
|
+
* override equals the default is omitted, since reverting it is a no-op.
|
|
273
202
|
*/
|
|
274
203
|
getPreferenceChanges() {
|
|
275
204
|
const changes = [];
|
|
276
205
|
for (const [key, value] of self.preferencesOverrides.entries()) {
|
|
277
|
-
const
|
|
278
|
-
if (
|
|
206
|
+
const dflt = this.getPreferenceDefault(key);
|
|
207
|
+
if (value !== dflt) {
|
|
279
208
|
changes.push({
|
|
280
|
-
path: [
|
|
281
|
-
|
|
282
|
-
dtd.displayType,
|
|
283
|
-
dtd.slot,
|
|
284
|
-
],
|
|
285
|
-
from: undefined,
|
|
209
|
+
path: [key],
|
|
210
|
+
from: dflt,
|
|
286
211
|
to: value,
|
|
287
212
|
});
|
|
288
213
|
}
|
|
289
|
-
else {
|
|
290
|
-
const dflt = this.getPreferenceDefault(key);
|
|
291
|
-
if (value !== dflt) {
|
|
292
|
-
changes.push({
|
|
293
|
-
path: [key],
|
|
294
|
-
from: dflt,
|
|
295
|
-
to: value,
|
|
296
|
-
});
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
214
|
}
|
|
300
215
|
return changes;
|
|
301
216
|
},
|
|
@@ -366,19 +281,53 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
366
281
|
},
|
|
367
282
|
/**
|
|
368
283
|
* #action
|
|
369
|
-
* toggle all region highlight bands across every view
|
|
370
284
|
*/
|
|
371
285
|
setHighlightsVisible(arg) {
|
|
372
286
|
self.highlightsVisible = arg;
|
|
373
287
|
},
|
|
374
288
|
/**
|
|
375
289
|
* #action
|
|
376
|
-
* turn highlight bands back on, so a newly made highlight or bookmark is
|
|
377
|
-
* never silently swallowed by an earlier "highlights off"
|
|
378
290
|
*/
|
|
379
|
-
|
|
291
|
+
setHighlightLabelsVisible(arg) {
|
|
292
|
+
self.highlightLabelsVisible = arg;
|
|
293
|
+
},
|
|
294
|
+
/**
|
|
295
|
+
* #action
|
|
296
|
+
* an identical entry is not added twice, so a spec launched again does not
|
|
297
|
+
* stack its bands. Adding shows the bands again, since a highlight made
|
|
298
|
+
* while they are off would otherwise read as nothing happening
|
|
299
|
+
*/
|
|
300
|
+
addHighlight(highlight) {
|
|
301
|
+
if (!self.highlights.some(h => isSameHighlight(h, highlight))) {
|
|
302
|
+
self.highlights.push(highlight);
|
|
303
|
+
}
|
|
380
304
|
self.highlightsVisible = true;
|
|
381
305
|
},
|
|
306
|
+
/**
|
|
307
|
+
* #action
|
|
308
|
+
*/
|
|
309
|
+
removeHighlight(highlight) {
|
|
310
|
+
self.highlights.remove(highlight);
|
|
311
|
+
},
|
|
312
|
+
/**
|
|
313
|
+
* #action
|
|
314
|
+
*/
|
|
315
|
+
updateHighlight(old, updates) {
|
|
316
|
+
const idx = self.highlights.indexOf(old);
|
|
317
|
+
if (idx !== -1) {
|
|
318
|
+
self.highlights[idx] = { ...old, ...updates };
|
|
319
|
+
self.highlightsVisible = true;
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
/**
|
|
323
|
+
* #action
|
|
324
|
+
*/
|
|
325
|
+
setHighlights(highlights) {
|
|
326
|
+
self.highlights = cast(highlights);
|
|
327
|
+
if (highlights.length) {
|
|
328
|
+
self.highlightsVisible = true;
|
|
329
|
+
}
|
|
330
|
+
},
|
|
382
331
|
/**
|
|
383
332
|
* #action
|
|
384
333
|
* set a runtime user-preference override (see `getPreference`). Mutates
|
|
@@ -391,19 +340,18 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
391
340
|
self.preferencesOverrides.delete(key);
|
|
392
341
|
}
|
|
393
342
|
else {
|
|
394
|
-
// frozen because `deep: false` hands an object-valued preference
|
|
395
|
-
//
|
|
396
|
-
//
|
|
397
|
-
//
|
|
343
|
+
// frozen because `deep: false` hands an object-valued preference
|
|
344
|
+
// straight back out by reference, so the "nothing mutates a
|
|
345
|
+
// preference in place" this store relies on is enforced rather than
|
|
346
|
+
// assumed
|
|
398
347
|
self.preferencesOverrides.set(key, freezeDeep(value));
|
|
399
348
|
}
|
|
400
349
|
},
|
|
401
350
|
/**
|
|
402
351
|
* #action
|
|
403
|
-
* clear every runtime preference override at once
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
* default. Backs the Preferences dialog "Reset to defaults" button.
|
|
352
|
+
* clear every runtime preference override at once, so each falls back to
|
|
353
|
+
* its config/admin default. Backs the Preferences dialog "Reset to
|
|
354
|
+
* defaults" button.
|
|
407
355
|
*/
|
|
408
356
|
clearPreferenceOverrides() {
|
|
409
357
|
self.preferencesOverrides.clear();
|
|
@@ -417,27 +365,6 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
417
365
|
clearPreferenceOverride(key) {
|
|
418
366
|
self.preferencesOverrides.delete(key);
|
|
419
367
|
},
|
|
420
|
-
/**
|
|
421
|
-
* #action
|
|
422
|
-
* revert one row emitted by `getPreferenceChanges`, addressed by its
|
|
423
|
-
* display `path`. Backs the per-entry reset in the Preferences dialog's
|
|
424
|
-
* "Reset to defaults" confirmation.
|
|
425
|
-
*
|
|
426
|
-
* Lives here rather than in that dialog because this model owns both path
|
|
427
|
-
* shapes it has to undo: a promoted per-display-type default, whose row
|
|
428
|
-
* path is a readable label over a flat composite storage key, and every
|
|
429
|
-
* other override, whose path *is* its key. The dialog used to re-derive
|
|
430
|
-
* the first case from an exported path-head constant.
|
|
431
|
-
*/
|
|
432
|
-
resetPreferenceChange(path) {
|
|
433
|
-
const [head, displayType, slot] = path;
|
|
434
|
-
if (head === DISPLAY_TYPE_DEFAULTS_PATH_HEAD && displayType && slot) {
|
|
435
|
-
this.setDisplayTypeDefault(displayType, slot, undefined);
|
|
436
|
-
}
|
|
437
|
-
else if (head) {
|
|
438
|
-
this.clearPreferenceOverride(head);
|
|
439
|
-
}
|
|
440
|
-
},
|
|
441
368
|
/**
|
|
442
369
|
* #action
|
|
443
370
|
* set the global scroll-to-zoom preference (see the `scrollZoom` getter)
|
|
@@ -445,16 +372,6 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
445
372
|
setScrollZoom(flag) {
|
|
446
373
|
this.setPreferenceOverride('scrollZoom', flag);
|
|
447
374
|
},
|
|
448
|
-
/**
|
|
449
|
-
* #action
|
|
450
|
-
* promote (or, with `value` undefined, clear) a per-display-type slot
|
|
451
|
-
* default. Just a preference override under one flat composite key (see
|
|
452
|
-
* `displayTypeDefaultKey`), so it persists and independently tracks like
|
|
453
|
-
* any other pref, and clearing deletes only that key.
|
|
454
|
-
*/
|
|
455
|
-
setDisplayTypeDefault(displayType, slot, value) {
|
|
456
|
-
this.setPreferenceOverride(displayTypeDefaultKey(displayType, slot), value);
|
|
457
|
-
},
|
|
458
375
|
/**
|
|
459
376
|
* #action
|
|
460
377
|
*/
|
|
@@ -484,13 +401,30 @@ export function BaseSessionModel(_pluginManager) {
|
|
|
484
401
|
* #action
|
|
485
402
|
*/
|
|
486
403
|
queueDialog(doneCallback) {
|
|
487
|
-
|
|
488
|
-
|
|
404
|
+
// its own entry, not the head: a late second call must not close the
|
|
405
|
+
// dialog queued behind it
|
|
406
|
+
const entry = doneCallback(() => {
|
|
407
|
+
this.removeDialog(entry);
|
|
489
408
|
});
|
|
490
|
-
self.queueOfDialogs = [...self.queueOfDialogs,
|
|
409
|
+
self.queueOfDialogs = [...self.queueOfDialogs, entry];
|
|
410
|
+
},
|
|
411
|
+
/**
|
|
412
|
+
* #action
|
|
413
|
+
*/
|
|
414
|
+
removeDialog(entry) {
|
|
415
|
+
self.queueOfDialogs = self.queueOfDialogs.filter(d => d !== entry);
|
|
416
|
+
},
|
|
417
|
+
}));
|
|
418
|
+
return types.compose(baseModel, SnackbarModel()).actions(self => ({
|
|
419
|
+
// after the compose rather than in the afterAttach above, because the
|
|
420
|
+
// notices land in the snackbar this line is the first place to hold both
|
|
421
|
+
// halves of. Web and desktop reach it a second time once the user's stored
|
|
422
|
+
// overrides are loaded (`PreferencesSessionMixin`), and our MST fork
|
|
423
|
+
// auto-chains both hooks.
|
|
424
|
+
afterAttach() {
|
|
425
|
+
applyDeveloperMode(self);
|
|
491
426
|
},
|
|
492
427
|
}));
|
|
493
|
-
return types.compose(baseModel, SnackbarModel());
|
|
494
428
|
}
|
|
495
429
|
/** Type guard for BaseSession */
|
|
496
430
|
export function isBaseSession(thing) {
|
|
@@ -111,9 +111,10 @@ export declare function ConnectionManagementSessionMixin(pluginManager: PluginMa
|
|
|
111
111
|
pruneConnectionTrackConfig(trackId: string): void;
|
|
112
112
|
/**
|
|
113
113
|
* #action
|
|
114
|
-
* Lazily establish a single connection by id if it isn't already live
|
|
115
|
-
*
|
|
116
|
-
*
|
|
114
|
+
* Lazily establish a single connection by id if it isn't already live;
|
|
115
|
+
* the track selector calls it when the connection's category is
|
|
116
|
+
* expanded. Fetches without launching a view or showing a success
|
|
117
|
+
* snackbar; already-open tracks keep
|
|
117
118
|
* rendering from `connectionTrackConfigs` meanwhile. Idempotent.
|
|
118
119
|
*/
|
|
119
120
|
hydrateConnection(connectionId: string): void;
|
|
@@ -189,9 +189,10 @@ export function ConnectionManagementSessionMixin(pluginManager) {
|
|
|
189
189
|
},
|
|
190
190
|
/**
|
|
191
191
|
* #action
|
|
192
|
-
* Lazily establish a single connection by id if it isn't already live
|
|
193
|
-
*
|
|
194
|
-
*
|
|
192
|
+
* Lazily establish a single connection by id if it isn't already live;
|
|
193
|
+
* the track selector calls it when the connection's category is
|
|
194
|
+
* expanded. Fetches without launching a view or showing a success
|
|
195
|
+
* snackbar; already-open tracks keep
|
|
195
196
|
* rendering from `connectionTrackConfigs` meanwhile. Idempotent.
|
|
196
197
|
*/
|
|
197
198
|
hydrateConnection(connectionId) {
|