@aics/vole-app 2.15.0 → 3.1.2

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.
Files changed (79) hide show
  1. package/es/aics-image-viewer/components/App/ChannelUpdater.js +21 -3
  2. package/es/aics-image-viewer/components/App/index.js +156 -199
  3. package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +10 -9
  4. package/es/aics-image-viewer/components/ChannelsWidget.js +35 -22
  5. package/es/aics-image-viewer/components/ChannelsWidgetRow/index.js +27 -71
  6. package/es/aics-image-viewer/components/ChannelsWidgetRow/styles.css +0 -6
  7. package/es/aics-image-viewer/components/ColorPicker.js +1 -1
  8. package/es/aics-image-viewer/components/ControlPanel/index.js +5 -4
  9. package/es/aics-image-viewer/components/CustomizeWidget.js +12 -8
  10. package/es/aics-image-viewer/components/ErrorAlert/index.js +4 -4
  11. package/es/aics-image-viewer/components/GlobalVolumeControls.js +12 -10
  12. package/es/aics-image-viewer/components/StyleProvider/index.js +4 -2
  13. package/es/aics-image-viewer/components/TfEditor/index.js +304 -154
  14. package/es/aics-image-viewer/components/TfEditor/styles.css +53 -31
  15. package/es/aics-image-viewer/components/Toolbar/DownloadButton.js +1 -1
  16. package/es/aics-image-viewer/components/Toolbar/index.js +18 -16
  17. package/es/aics-image-viewer/components/shared/SharedCheckBox.js +1 -1
  18. package/es/aics-image-viewer/components/shared/SliderRow/styles.css +1 -0
  19. package/es/aics-image-viewer/components/shared/SmarterSlider.js +1 -1
  20. package/es/aics-image-viewer/components/shared/ViewerIcon.js +1 -1
  21. package/es/aics-image-viewer/components/useVolume.js +68 -59
  22. package/es/aics-image-viewer/shared/constants.js +2 -2
  23. package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +57 -24
  24. package/es/aics-image-viewer/shared/utils/sceneStore.js +14 -4
  25. package/es/aics-image-viewer/shared/utils/storage.js +238 -0
  26. package/es/aics-image-viewer/shared/utils/test/storage.test.js +264 -0
  27. package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +249 -109
  28. package/es/aics-image-viewer/shared/utils/test/viewerChannelSettings.test.js +1 -1
  29. package/es/aics-image-viewer/shared/utils/urlParsing.js +287 -154
  30. package/es/aics-image-viewer/shared/utils/viewerState.js +4 -24
  31. package/es/aics-image-viewer/state/reset.js +111 -0
  32. package/es/aics-image-viewer/state/store.js +90 -0
  33. package/es/aics-image-viewer/state/subscribers.js +153 -0
  34. package/es/aics-image-viewer/state/test/reset.test.js +247 -0
  35. package/es/aics-image-viewer/state/util.js +71 -0
  36. package/es/index.js +3 -3
  37. package/package.json +18 -11
  38. package/type-declarations/aics-image-viewer/components/App/ChannelUpdater.d.ts +2 -4
  39. package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
  40. package/type-declarations/aics-image-viewer/components/AxisClipSliders/index.d.ts +6 -6
  41. package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +5 -14
  42. package/type-declarations/aics-image-viewer/components/ChannelsWidget.d.ts +3 -6
  43. package/type-declarations/aics-image-viewer/components/ChannelsWidgetRow/index.d.ts +3 -6
  44. package/type-declarations/aics-image-viewer/components/ColorPicker.d.ts +1 -1
  45. package/type-declarations/aics-image-viewer/components/ControlPanel/index.d.ts +6 -7
  46. package/type-declarations/aics-image-viewer/components/CustomizeWidget.d.ts +2 -8
  47. package/type-declarations/aics-image-viewer/components/ErrorAlert/index.d.ts +4 -0
  48. package/type-declarations/aics-image-viewer/components/GlobalVolumeControls.d.ts +2 -9
  49. package/type-declarations/aics-image-viewer/components/MetadataViewer/index.d.ts +1 -1
  50. package/type-declarations/aics-image-viewer/components/StyleProvider/index.d.ts +1 -1
  51. package/type-declarations/aics-image-viewer/components/TfEditor/index.d.ts +10 -3
  52. package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +3 -12
  53. package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +1 -1
  54. package/type-declarations/aics-image-viewer/components/shared/SmarterSlider.d.ts +1 -1
  55. package/type-declarations/aics-image-viewer/components/shared/ViewerIcon.d.ts +1 -1
  56. package/type-declarations/aics-image-viewer/components/useVolume.d.ts +7 -4
  57. package/type-declarations/aics-image-viewer/shared/constants.d.ts +5 -5
  58. package/type-declarations/aics-image-viewer/shared/types.d.ts +1 -1
  59. package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +9 -5
  60. package/type-declarations/aics-image-viewer/shared/utils/firebase/index.d.ts +1 -1
  61. package/type-declarations/aics-image-viewer/shared/utils/hooks.d.ts +1 -1
  62. package/type-declarations/aics-image-viewer/shared/utils/playControls.d.ts +1 -1
  63. package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +8 -4
  64. package/type-declarations/aics-image-viewer/shared/utils/storage.d.ts +15 -0
  65. package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +94 -31
  66. package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +39 -1
  67. package/type-declarations/aics-image-viewer/shared/utils/viewerState.d.ts +3 -6
  68. package/type-declarations/aics-image-viewer/state/reset.d.ts +29 -0
  69. package/type-declarations/aics-image-viewer/state/store.d.ts +30 -0
  70. package/type-declarations/aics-image-viewer/state/subscribers.d.ts +4 -0
  71. package/type-declarations/aics-image-viewer/state/types.d.ts +46 -0
  72. package/type-declarations/aics-image-viewer/state/util.d.ts +8 -0
  73. package/type-declarations/index.d.ts +4 -4
  74. package/es/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.js +0 -163
  75. package/es/aics-image-viewer/components/ViewerStateProvider/index.js +0 -259
  76. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.d.ts +0 -34
  77. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/index.d.ts +0 -33
  78. package/type-declarations/aics-image-viewer/components/ViewerStateProvider/types.d.ts +0 -107
  79. /package/es/aics-image-viewer/{components/ViewerStateProvider → state}/types.js +0 -0
@@ -1,20 +1,30 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
1
2
  function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
2
3
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
3
4
  function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
4
5
  function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
9
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
10
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
11
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
6
12
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
7
13
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
8
14
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
9
15
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
10
16
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
11
- import { Lut, remapControlPoints } from "@aics/vole-core";
17
+ import { Lut } from "@aics/vole-core";
12
18
  import { LUT_MAX_PERCENTILE, LUT_MIN_PERCENTILE, TFEDITOR_DEFAULT_COLOR, TFEDITOR_MAX_BIN } from "../constants";
13
19
  import { findFirstChannelMatch } from "./viewerChannelSettings";
14
20
 
15
- // @param {Object[]} controlPoints - array of {x:number, opacity:number, color:string}
16
- // @return {Uint8Array} array of length 256*4 representing the rgba values of the gradient
17
- export function controlPointsToLut(controlPoints) {
21
+ /**
22
+ * @param {Object[]} controlPoints - array of `{x:number, opacity:number,
23
+ * color:string}`, where `x` is a histogram bin index.
24
+ * @returns {Uint8Array} array of length 256*4 representing the rgba values of
25
+ * the gradient
26
+ */
27
+ export function binIndexedControlPointsToLut(controlPoints) {
18
28
  var lut = new Lut().createFromControlPoints(controlPoints);
19
29
  return lut;
20
30
  }
@@ -77,19 +87,25 @@ function parseLutValue(value, histogram) {
77
87
  * ```
78
88
  */
79
89
  export function parseLutFromSettings(histogram, initSettings) {
90
+ var _initSettings$intensi, _initSettings$intensi2;
80
91
  // TODO: Consider minimizing the types/classes this function is interacting
81
92
  // with, since it is only using `initSettings.lut` and the returned Lut is a
82
93
  // wrapper around the control point array, e.g.
83
94
  // `parseControlPointsFromLutParam(histogram: Histogram, lutParam: [string,
84
95
  // string] | undefined): ControlPoint[] | undefined`
85
- if (initSettings.lut === undefined || initSettings.lut.length !== 2) {
96
+
97
+ // There are two possible locations for the LUT settings, due to legacy
98
+ // reasons. `initSettings.lut` is deprecated in favor of
99
+ // `initSettings.intensity.lut`.
100
+ var settingsLut = (_initSettings$intensi = (_initSettings$intensi2 = initSettings.intensity) === null || _initSettings$intensi2 === void 0 ? void 0 : _initSettings$intensi2.lut) !== null && _initSettings$intensi !== void 0 ? _initSettings$intensi : initSettings.lut;
101
+ if (settingsLut === undefined || settingsLut.length !== 2) {
86
102
  return undefined;
87
103
  }
88
104
  var lutValues;
89
- if (initSettings.lut[0] === "autoij" || initSettings.lut[1] === "autoij") {
105
+ if (settingsLut[0] === "autoij" || settingsLut[1] === "autoij") {
90
106
  lutValues = histogram.findAutoIJBins();
91
107
  } else {
92
- lutValues = [parseLutValue(initSettings.lut[0], histogram), parseLutValue(initSettings.lut[1], histogram)];
108
+ lutValues = [parseLutValue(settingsLut[0], histogram), parseLutValue(settingsLut[1], histogram)];
93
109
  }
94
110
  if (!Number.isFinite(lutValues[0]) || !Number.isFinite(lutValues[1])) {
95
111
  return undefined;
@@ -128,7 +144,7 @@ export function parseLutFromSettings(histogram, initSettings) {
128
144
  * to the volume; otherwise, the ramp will be applied.
129
145
  */
130
146
  export function initializeLut(aimg, channelIndex, channelSettings) {
131
- var _initSettings$control;
147
+ var _initSettings$intensi3, _initSettings$intensi4;
132
148
  var histogram = aimg.getHistogram(channelIndex);
133
149
  var defaultLut = getDefaultLut(histogram);
134
150
  var ramp = [];
@@ -137,15 +153,42 @@ export function initializeLut(aimg, channelIndex, channelSettings) {
137
153
  var name = aimg.channelNames[channelIndex];
138
154
  var initSettings = channelSettings && findFirstChannelMatch(name, channelIndex, channelSettings);
139
155
 
140
- // Attempt to load a LUT from the settings, which will be used to initialize the control points and ramp
141
- if (initSettings && initSettings.lut) {
156
+ // Attempt to load a LUT from the settings, which will be used as a fallback
157
+ // to initialize the control points and ramp.
158
+ if (initSettings) {
142
159
  var _parseLutFromSettings;
143
160
  lut = (_parseLutFromSettings = parseLutFromSettings(histogram, initSettings)) !== null && _parseLutFromSettings !== void 0 ? _parseLutFromSettings : defaultLut;
144
161
  }
145
- // Initialize the control points + ramp using the LUT.
146
- // Optionally, override the LUT's control points with the provided control points and/or ramp.
147
- controlPoints = (_initSettings$control = initSettings === null || initSettings === void 0 ? void 0 : initSettings.controlPoints) !== null && _initSettings$control !== void 0 ? _initSettings$control : _toConsumableArray(lut.controlPoints);
148
- ramp = initSettings !== null && initSettings !== void 0 && initSettings.ramp ? rampToControlPoints(initSettings.ramp) : _toConsumableArray(lut.controlPoints);
162
+
163
+ // Use raw intensity values for control points or ramp if provided in the
164
+ // settings. Otherwise, get default values from the LUT by remapping
165
+ // from histogram bin indices.
166
+ if (initSettings !== null && initSettings !== void 0 && (_initSettings$intensi3 = initSettings.intensity) !== null && _initSettings$intensi3 !== void 0 && _initSettings$intensi3.controlPoints) {
167
+ // Raw intensity values can be used directly.
168
+ controlPoints = initSettings.intensity.controlPoints;
169
+ } else {
170
+ var _initSettings$control;
171
+ // No provided value; use histogram to convert from bin index to raw
172
+ // intensity values.
173
+ var binIndexedControlPoints = (_initSettings$control = initSettings === null || initSettings === void 0 ? void 0 : initSettings.controlPoints) !== null && _initSettings$control !== void 0 ? _initSettings$control : _toConsumableArray(lut.controlPoints);
174
+ controlPoints = binIndexedControlPoints.map(function (cp) {
175
+ return _objectSpread(_objectSpread({}, cp), {}, {
176
+ x: histogram.getValueFromBinIndex(cp.x)
177
+ });
178
+ });
179
+ }
180
+
181
+ // Initialize the ramp
182
+ if (initSettings !== null && initSettings !== void 0 && (_initSettings$intensi4 = initSettings.intensity) !== null && _initSettings$intensi4 !== void 0 && _initSettings$intensi4.ramp) {
183
+ ramp = rampToControlPoints(initSettings.intensity.ramp);
184
+ } else {
185
+ var binIndexedRamp = initSettings !== null && initSettings !== void 0 && initSettings.ramp ? rampToControlPoints(initSettings.ramp) : _toConsumableArray(lut.controlPoints);
186
+ ramp = binIndexedRamp.map(function (cp) {
187
+ return _objectSpread(_objectSpread({}, cp), {}, {
188
+ x: histogram.getValueFromBinIndex(cp.x)
189
+ });
190
+ });
191
+ }
149
192
 
150
193
  // Apply whatever lut is currently visible
151
194
  var visibleLut;
@@ -198,14 +241,4 @@ export function rampToControlPoints(_ref) {
198
241
  opacity: 1,
199
242
  color: TFEDITOR_DEFAULT_COLOR
200
243
  }];
201
- }
202
-
203
- /** Remaps an array of control points from an old range (as a 2-tuple) to a new one (extracted from a `Channel`) */
204
- export function remapControlPointsForChannel(controlPoints, oldRange, _ref3) {
205
- var rawMin = _ref3.rawMin,
206
- rawMax = _ref3.rawMax;
207
- if (oldRange === undefined) {
208
- return controlPoints;
209
- }
210
- return remapControlPoints(controlPoints, oldRange[0], oldRange[1], rawMin, rawMax);
211
244
  }
@@ -1,4 +1,12 @@
1
- function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
1
+ function _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); }
2
+ function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); }
3
+ function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; }
4
+ function _regeneratorAsync(n, e, r, t, o) { var a = _regeneratorAsyncGen(n, e, r, t, o); return a.next().then(function (n) { return n.done ? n.value : a.next(); }); }
5
+ function _regeneratorAsyncGen(r, e, t, o, n) { return new _regeneratorAsyncIterator(_regenerator().w(r, e, t, o), n || Promise); }
6
+ function _regeneratorAsyncIterator(t, e) { function n(r, o, i, f) { try { var c = t[r](o), u = c.value; return u instanceof _OverloadYield ? e.resolve(u.v).then(function (t) { n("next", t, i, f); }, function (t) { n("throw", t, i, f); }) : e.resolve(u).then(function (t) { c.value = t, i(c); }, function (t) { return n("throw", t, i, f); }); } catch (t) { f(t); } } var r; this.next || (_regeneratorDefine2(_regeneratorAsyncIterator.prototype), _regeneratorDefine2(_regeneratorAsyncIterator.prototype, "function" == typeof Symbol && Symbol.asyncIterator || "@asyncIterator", function () { return this; })), _regeneratorDefine2(this, "_invoke", function (t, o, i) { function f() { return new e(function (e, r) { n(t, i, e, r); }); } return r = r ? r.then(f, f) : f(); }, !0); }
7
+ function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
8
+ function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
9
+ function _OverloadYield(e, d) { this.v = e, this.k = d; }
2
10
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
3
11
  function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
4
12
  function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
@@ -68,7 +76,8 @@ var SceneStore = /*#__PURE__*/function () {
68
76
  }, {
69
77
  key: "loadScene",
70
78
  value: function () {
71
- var _loadScene = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(scene, image, loadSpec, onChannelLoaded) {
79
+ var _loadScene = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(scene, image, loadSpec, options) {
80
+ var _options$onCreateScen;
72
81
  var loader, spec;
73
82
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
74
83
  while (1) switch (_context2.prev = _context2.next) {
@@ -83,8 +92,9 @@ var SceneStore = /*#__PURE__*/function () {
83
92
  return loader.createImageInfo(spec);
84
93
  case 7:
85
94
  image.imageInfo.imageInfo = _context2.sent.imageInfo;
86
- loader.loadVolumeData(image, spec, onChannelLoaded);
87
- case 9:
95
+ options === null || options === void 0 || (_options$onCreateScen = options.onCreateScene) === null || _options$onCreateScen === void 0 || _options$onCreateScen.call(options, image, scene);
96
+ loader.loadVolumeData(image, spec, options === null || options === void 0 ? void 0 : options.onChannelLoaded);
97
+ case 10:
88
98
  case "end":
89
99
  return _context2.stop();
90
100
  }
@@ -0,0 +1,238 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
3
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
5
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
6
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
7
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
8
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
9
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
10
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
11
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
12
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
13
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
14
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
15
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
16
+ import { mapKeys, mapValues } from "lodash";
17
+ var QUEUE_KEY = "GLOBAL_ENTRY_QUEUE";
18
+ var StorageEntryType = /*#__PURE__*/function (StorageEntryType) {
19
+ StorageEntryType["Scenes"] = "scenes";
20
+ StorageEntryType["Meta"] = "meta";
21
+ return StorageEntryType;
22
+ }(StorageEntryType || {});
23
+ var MAX_ENTRIES = {
24
+ scenes: 25,
25
+ meta: 1000
26
+ };
27
+ var sanitizeStorageKey = function sanitizeStorageKey(key) {
28
+ return key.includes(",") ? encodeURIComponent(key) : key;
29
+ };
30
+
31
+ /** `window.localStorage.setItem`, but returns `false` on quota exceeded instead of erroring */
32
+ function safeSetItem(key, value) {
33
+ try {
34
+ window.localStorage.setItem(key, value);
35
+ return true;
36
+ } catch (e) {
37
+ // `setItem` throws a `QuotaExceededError` when the browser won't let us put any more data in local storage
38
+ if (e instanceof DOMException && e.name === "QuotaExceededError") {
39
+ return false;
40
+ }
41
+ throw e;
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Wrapper for `window.localStorage.setItem` that accepts a `queue` of evictable storage keys, and attempts to safely
47
+ * handle exceeding the storage quota by removing items off the back of the `queue` until space is available.
48
+ *
49
+ * Also, unlike `setItem`, this function can accept `value`s of type `string[]`. This allows `queue` to also be passed
50
+ * into `value`, so that it can be written to storage *after* picking up any evictions that are made during the write.
51
+ *
52
+ * Returns `false` if `value` could not fit into storage even after removing everything from `queue`, `true` otherwise.
53
+ */
54
+ function setStorageItem(key, value, queue) {
55
+ var removedItems = [];
56
+ while (!safeSetItem(key, Array.isArray(value) ? value.join(",") : value)) {
57
+ // can't fit `value` in the store; remove something off the back of `queue` and try again
58
+ var evictKey = queue.shift();
59
+ if (evictKey === undefined) {
60
+ // nothing left to remove means `value` is larger than the entire store
61
+ // give up on inserting it and try to put everything we removed back
62
+ var _iterator = _createForOfIteratorHelper(removedItems),
63
+ _step;
64
+ try {
65
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
66
+ var _step$value = _slicedToArray(_step.value, 2),
67
+ _key = _step$value[0],
68
+ _value = _step$value[1];
69
+ if (safeSetItem(_key, _value)) {
70
+ queue.unshift(_key);
71
+ }
72
+ }
73
+ } catch (err) {
74
+ _iterator.e(err);
75
+ } finally {
76
+ _iterator.f();
77
+ }
78
+ return false;
79
+ }
80
+ var removedValue = window.localStorage.getItem(evictKey);
81
+ if (removedValue !== null) {
82
+ removedItems.push([evictKey, removedValue]);
83
+ window.localStorage.removeItem(evictKey);
84
+ }
85
+ }
86
+ return true;
87
+ }
88
+ var getStorageQueue = function getStorageQueue() {
89
+ var _window$localStorage$, _window$localStorage$2;
90
+ return (_window$localStorage$ = (_window$localStorage$2 = window.localStorage.getItem(QUEUE_KEY)) === null || _window$localStorage$2 === void 0 ? void 0 : _window$localStorage$2.split(",")) !== null && _window$localStorage$ !== void 0 ? _window$localStorage$ : [];
91
+ };
92
+ /** If this function returns `false`, something serious has gone wrong and using local storage is likely impossible. */
93
+ var setStorageQueue = function setStorageQueue(queue) {
94
+ return setStorageItem(QUEUE_KEY, queue, queue);
95
+ };
96
+
97
+ /**
98
+ * Writes a bundle of `entries` to local storage, all with an optional `entryType` for categorizing the data.
99
+ *
100
+ * Entries written with this function are tracked like a least-recently-used cache, and evicted when either:
101
+ * - the size of local storage exceeds the browser's quota
102
+ * - the number of entries of type `entryType` exceeds the maximum for that type
103
+ *
104
+ * Returns `true` if all entries fit in storage, or `false` if some did not.
105
+ */
106
+ function writeStorage(entries, entryType) {
107
+ var prevQueue = getStorageQueue();
108
+ var typePrefix = entryType ? "".concat(entryType, "@") : "";
109
+ var escapedEntries = mapKeys(entries, function (_, key) {
110
+ return sanitizeStorageKey(key);
111
+ });
112
+
113
+ // filter keys we're currently inserting out of the queue (to be re-inserted at the front)
114
+ var index = 0;
115
+ var thisTypeIndexes = [];
116
+ var queue = prevQueue.filter(function (k) {
117
+ if (k.startsWith(typePrefix)) {
118
+ if (k.slice(typePrefix.length) in escapedEntries) {
119
+ return false;
120
+ } else if (entryType !== undefined) {
121
+ // start saving the location of entries of this type, for enforcing the maximum entry count below
122
+ thisTypeIndexes.push(index);
123
+ }
124
+ }
125
+ index += 1;
126
+ return true;
127
+ });
128
+
129
+ // push new keys onto the end
130
+ for (var _i = 0, _Object$keys = Object.keys(escapedEntries); _i < _Object$keys.length; _i++) {
131
+ var key = _Object$keys[_i];
132
+ thisTypeIndexes.push(queue.length);
133
+ queue.push(typePrefix + key);
134
+ }
135
+
136
+ // enforce the maximum number of entries for this type (e.g. no more than 25 of type "scenes")
137
+ if (entryType !== undefined) {
138
+ var evictIndexes = thisTypeIndexes.slice(0, -MAX_ENTRIES[entryType]);
139
+ var _iterator2 = _createForOfIteratorHelper(evictIndexes.reverse()),
140
+ _step2;
141
+ try {
142
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
143
+ var _index = _step2.value;
144
+ var _queue$splice = queue.splice(_index, 1),
145
+ _queue$splice2 = _slicedToArray(_queue$splice, 1),
146
+ evictKey = _queue$splice2[0];
147
+ window.localStorage.removeItem(evictKey);
148
+ delete escapedEntries[evictKey.slice(typePrefix.length)];
149
+ }
150
+ } catch (err) {
151
+ _iterator2.e(err);
152
+ } finally {
153
+ _iterator2.f();
154
+ }
155
+ }
156
+
157
+ // write the new entries
158
+ var entryList = Object.entries(escapedEntries);
159
+ var firstKey = entryList.length < 2 ? undefined : typePrefix + entryList[0][0];
160
+ var allEntriesFit = true;
161
+ for (var _i2 = 0, _Object$entries = Object.entries(escapedEntries); _i2 < _Object$entries.length; _i2++) {
162
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),
163
+ _key2 = _Object$entries$_i[0],
164
+ value = _Object$entries$_i[1];
165
+ var entryFits = setStorageItem(typePrefix + _key2, value, queue);
166
+ allEntriesFit = allEntriesFit && entryFits;
167
+ }
168
+
169
+ // TODO if the queue somehow doesn't fit, it's a much more serious problem than an individual entry.
170
+ // Should that be communicated in the return type?
171
+ var queueFit = setStorageQueue(queue);
172
+ return allEntriesFit && queueFit && (firstKey === undefined || window.localStorage.getItem(firstKey) !== null);
173
+ }
174
+
175
+ /**
176
+ * Writes a bundle of metadata records keyed by image URL to local storage.
177
+ *
178
+ * Returns `true` if all records fit into local storage, or `false` if at least one did not.
179
+ */
180
+ export function writeMetadata(meta) {
181
+ var stringMeta = mapValues(meta, function (metaVal) {
182
+ return JSON.stringify(metaVal);
183
+ });
184
+ return writeStorage(stringMeta, StorageEntryType.Meta);
185
+ }
186
+
187
+ /**
188
+ * Writes a scene `url` to local storage at the given `key`.
189
+ *
190
+ * Returns `false` if the entry did not fit in local storage, or `true` if it did.
191
+ */
192
+ export function writeScenes(key, url) {
193
+ return writeStorage(_defineProperty({}, sanitizeStorageKey(key), url), StorageEntryType.Scenes);
194
+ }
195
+ export function readStoredMetadata(scenes) {
196
+ var skipCacheUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
197
+ var keySet = new Set();
198
+ var result = scenes.map(function (scene) {
199
+ if (Array.isArray(scene)) {
200
+ // can't handle multi-source scenes (yet)
201
+ return undefined;
202
+ }
203
+ var globalKey = "".concat(StorageEntryType.Meta, "@").concat(sanitizeStorageKey(scene));
204
+ var meta = window.localStorage.getItem(globalKey);
205
+ if (meta === null) {
206
+ return undefined;
207
+ }
208
+ keySet.add(globalKey);
209
+ return JSON.parse(meta);
210
+ });
211
+ if (keySet.size > 0 && !skipCacheUpdate) {
212
+ var prevQueue = getStorageQueue();
213
+ var queue = prevQueue.filter(function (key) {
214
+ return !keySet.has(key);
215
+ });
216
+ queue.push.apply(queue, _toConsumableArray(keySet));
217
+ setStorageQueue(queue);
218
+ }
219
+ return result;
220
+ }
221
+ export function readStoredScenes(key) {
222
+ var skipCacheUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
223
+ var globalKey = "".concat(StorageEntryType.Scenes, "@").concat(sanitizeStorageKey(key));
224
+ var result = window.localStorage.getItem(globalKey);
225
+ if (result === null) {
226
+ return undefined;
227
+ }
228
+ if (!skipCacheUpdate) {
229
+ var queue = getStorageQueue();
230
+ var entryIndex = queue.indexOf(globalKey);
231
+ if (entryIndex !== -1) {
232
+ queue.splice(entryIndex, 1);
233
+ }
234
+ queue.push(globalKey);
235
+ setStorageQueue(queue);
236
+ }
237
+ return result;
238
+ }