@aics/vole-app 3.4.4 → 3.6.0

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 (72) hide show
  1. package/es/aics-image-viewer/components/App/index.js +15 -5
  2. package/es/aics-image-viewer/components/ChannelsWidget.js +3 -1
  3. package/es/aics-image-viewer/components/ChannelsWidgetRow.js +29 -16
  4. package/es/aics-image-viewer/components/ColorPicker/index.js +9 -1
  5. package/es/aics-image-viewer/components/ControlPanel/CopySettingsButton.js +445 -0
  6. package/es/aics-image-viewer/components/ControlPanel/index.js +16 -5
  7. package/es/aics-image-viewer/components/ControlPanel/styles.css +29 -2
  8. package/es/aics-image-viewer/components/StyleProvider/index.js +17 -2
  9. package/es/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.js +1 -1
  10. package/es/aics-image-viewer/components/Toolbar/index.js +1 -1
  11. package/es/aics-image-viewer/components/Toolbar/styles.css +0 -10
  12. package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.js +3 -2
  13. package/es/aics-image-viewer/components/dimension_sliders/AxisClipSliders.js +21 -8
  14. package/es/aics-image-viewer/components/dimension_sliders/RotationSliders.js +6 -8
  15. package/es/aics-image-viewer/components/dimension_sliders/SliderRows.js +8 -6
  16. package/es/aics-image-viewer/components/shared/ContextualAlert.js +101 -0
  17. package/es/aics-image-viewer/components/shared/ControlPanelRow/index.js +4 -2
  18. package/es/aics-image-viewer/components/shared/ControlPanelRow/styles.css +4 -3
  19. package/es/aics-image-viewer/components/useVolume.js +59 -25
  20. package/es/aics-image-viewer/shared/constants.js +25 -1
  21. package/es/aics-image-viewer/shared/types.js +1 -1
  22. package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +4 -0
  23. package/es/aics-image-viewer/shared/utils/parseSnapshot.js +205 -0
  24. package/es/aics-image-viewer/shared/utils/{urlParsing.js → parseUrl.js} +55 -191
  25. package/es/aics-image-viewer/shared/utils/permissions.js +46 -0
  26. package/es/aics-image-viewer/shared/utils/test/camera.test.js +1 -2
  27. package/es/aics-image-viewer/shared/utils/test/{urlParsing.test.js → parseUrl.test.js} +28 -25
  28. package/es/aics-image-viewer/shared/utils/test/storage.test.js +2 -2
  29. package/es/aics-image-viewer/shared/utils/test/viewerChannelSettings.test.js +1 -1
  30. package/es/aics-image-viewer/state/deserialize.js +443 -331
  31. package/es/aics-image-viewer/state/reset.js +1 -1
  32. package/es/aics-image-viewer/state/serialize.js +168 -78
  33. package/es/aics-image-viewer/state/subscribers.js +1 -1
  34. package/es/aics-image-viewer/state/test/deserialize.test.js +63 -77
  35. package/es/aics-image-viewer/state/test/reset.test.js +2 -2
  36. package/es/aics-image-viewer/state/test/serialize.test.js +42 -43
  37. package/es/aics-image-viewer/state/test/test_data.js +119 -1
  38. package/es/aics-image-viewer/state/types.js +157 -245
  39. package/es/aics-image-viewer/state/util.js +39 -1
  40. package/es/index.js +4 -2
  41. package/package.json +26 -44
  42. package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
  43. package/type-declarations/aics-image-viewer/components/ChannelsWidget.d.ts +3 -0
  44. package/type-declarations/aics-image-viewer/components/ChannelsWidgetRow.d.ts +3 -0
  45. package/type-declarations/aics-image-viewer/components/ControlPanel/CopySettingsButton.d.ts +11 -0
  46. package/type-declarations/aics-image-viewer/components/Toolbar/ViewModeRadioButtons.d.ts +1 -1
  47. package/type-declarations/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/index.d.ts +4 -3
  48. package/type-declarations/aics-image-viewer/components/dimension_sliders/AxisClipSliders.d.ts +7 -6
  49. package/type-declarations/aics-image-viewer/components/dimension_sliders/SliderRows.d.ts +1 -2
  50. package/type-declarations/aics-image-viewer/components/shared/ContextualAlert.d.ts +29 -0
  51. package/type-declarations/aics-image-viewer/components/shared/ControlPanelRow/index.d.ts +1 -0
  52. package/type-declarations/aics-image-viewer/components/useVolume.d.ts +3 -0
  53. package/type-declarations/aics-image-viewer/shared/constants.d.ts +2 -2
  54. package/type-declarations/aics-image-viewer/shared/types.d.ts +2 -2
  55. package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +1 -1
  56. package/type-declarations/aics-image-viewer/shared/utils/parseSnapshot.d.ts +49 -0
  57. package/type-declarations/aics-image-viewer/shared/utils/{urlParsing.d.ts → parseUrl.d.ts} +3 -24
  58. package/type-declarations/aics-image-viewer/shared/utils/permissions.d.ts +7 -0
  59. package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +1 -1
  60. package/type-declarations/aics-image-viewer/state/deserialize.d.ts +70 -35
  61. package/type-declarations/aics-image-viewer/state/reset.d.ts +1 -1
  62. package/type-declarations/aics-image-viewer/state/serialize.d.ts +44 -10
  63. package/type-declarations/aics-image-viewer/state/types.d.ts +265 -159
  64. package/type-declarations/aics-image-viewer/state/util.d.ts +3 -1
  65. package/type-declarations/index.d.ts +5 -3
  66. package/es/Globals.d.js +0 -0
  67. package/es/aics-image-viewer/shared/enums.js +0 -18
  68. package/es/aics-image-viewer/shared/utils/firebase/index.js +0 -109
  69. package/type-declarations/aics-image-viewer/shared/enums.d.ts +0 -15
  70. package/type-declarations/aics-image-viewer/shared/utils/firebase/index.d.ts +0 -69
  71. package/type-declarations/aics-image-viewer/shared/utils/math.d.ts +0 -1
  72. /package/es/aics-image-viewer/components/{CellViewerCanvasWrapper → ViewerCanvasWrapper}/styles.css +0 -0
@@ -25,12 +25,12 @@ import { LoadSpec, VolumeLoaderContext } from "@aics/vole-core";
25
25
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
26
26
  import { Box3, Vector3 } from "three";
27
27
  import { AXIS_TO_LOADER_PRIORITY, CACHE_MAX_SIZE, getDefaultViewerChannelSettings, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE } from "../shared/constants";
28
- import { ViewMode } from "../shared/enums";
29
28
  import { useConstructor, useRefWithSetter } from "../shared/utils/hooks";
30
29
  import PlayControls from "../shared/utils/playControls";
31
30
  import SceneStore from "../shared/utils/sceneStore";
32
31
  import { makeChannelIndexGrouping } from "../shared/utils/viewerChannelSettings";
33
32
  import { select, useViewerState } from "../state/store";
33
+ import { ViewMode } from "../state/types";
34
34
  export var ImageLoadStatus = /*#__PURE__*/function (ImageLoadStatus) {
35
35
  ImageLoadStatus[ImageLoadStatus["REQUESTED"] = 0] = "REQUESTED";
36
36
  ImageLoadStatus[ImageLoadStatus["LOADING"] = 1] = "LOADING";
@@ -39,7 +39,7 @@ export var ImageLoadStatus = /*#__PURE__*/function (ImageLoadStatus) {
39
39
  return ImageLoadStatus;
40
40
  }({});
41
41
  var LoadType = /*#__PURE__*/function (LoadType) {
42
- LoadType[LoadType["TIME"] = 0] = "TIME";
42
+ LoadType[LoadType["RELOAD"] = 0] = "RELOAD";
43
43
  LoadType[LoadType["SCENE"] = 1] = "SCENE";
44
44
  return LoadType;
45
45
  }(LoadType || {}); // Used by `channelVersions` (see below)
@@ -84,6 +84,7 @@ var useVolume = function useVolume(scenePaths, options) {
84
84
  var onChannelLoadedRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onChannelLoaded);
85
85
  var onChangeSceneRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onChangeScene);
86
86
  var onCreateImageRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onCreateImage);
87
+ var onScrubRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onScrub);
87
88
  var maskChannelName = options === null || options === void 0 ? void 0 : options.maskChannelName;
88
89
 
89
90
  // set up our big objects: the image, its loading infrastructure, and controls for playback
@@ -104,6 +105,10 @@ var useVolume = function useVolume(scenePaths, options) {
104
105
  _useState4 = _slicedToArray(_useState3, 2),
105
106
  playingAxis = _useState4[0],
106
107
  setPlayingAxis = _useState4[1];
108
+ var _useState5 = useState(null),
109
+ _useState6 = _slicedToArray(_useState5, 2),
110
+ scrubbingAxis = _useState6[0],
111
+ setScrubbingAxis = _useState6[1];
107
112
  useEffect(function () {
108
113
  playControls.onPlayingAxisChanged = function (axis) {
109
114
  var isPlaying = axis !== null;
@@ -113,36 +118,24 @@ var useVolume = function useVolume(scenePaths, options) {
113
118
  sceneLoader.updateFetchOptions({
114
119
  onlyPriorityDirections: isPlaying
115
120
  });
116
- // sync multichannel loading so we don't show loaded channels one at a time
117
- sceneLoader.syncMultichannelLoading(isPlaying);
118
- if (image) {
119
- // If we're playing and entire axis is not in memory (T always, Z likely), downlevel to speed things up
120
- var _image$imageInfo = image.imageInfo,
121
- volumeSize = _image$imageInfo.volumeSize,
122
- subregionSize = _image$imageInfo.subregionSize;
123
- var shouldDownlevel = isPlaying && (axis === "t" || volumeSize[axis] !== subregionSize[axis]);
124
- image.updateRequiredData({
125
- scaleLevelBias: shouldDownlevel ? 1 : 0
126
- });
127
- }
128
121
  };
129
122
  }, [sceneLoader, playControls, image]);
130
123
 
131
124
  // track which channels have been loaded
132
- var _useState5 = useState([]),
133
- _useState6 = _slicedToArray(_useState5, 2),
134
- channelVersions = _useState6[0],
135
- _setChannelVersions = _useState6[1];
125
+ var _useState7 = useState([]),
126
+ _useState8 = _slicedToArray(_useState7, 2),
127
+ channelVersions = _useState8[0],
128
+ _setChannelVersions = _useState8[1];
136
129
  var _useRefWithSetter = useRefWithSetter(_setChannelVersions, channelVersions),
137
130
  _useRefWithSetter2 = _slicedToArray(_useRefWithSetter, 2),
138
131
  channelVersionsRef = _useRefWithSetter2[0],
139
132
  setChannelVersions = _useRefWithSetter2[1];
140
133
 
141
134
  // Some extra items for tracking load status
142
- var _useState7 = useState(false),
143
- _useState8 = _slicedToArray(_useState7, 2),
144
- loadThrewError = _useState8[0],
145
- setLoadThrewError = _useState8[1];
135
+ var _useState9 = useState(false),
136
+ _useState0 = _slicedToArray(_useState9, 2),
137
+ loadThrewError = _useState0[0],
138
+ setLoadThrewError = _useState0[1];
146
139
  var inInitialLoadRef = useRef(true);
147
140
 
148
141
  // derive whether the image is loaded from whether any and/or all channels are loaded
@@ -178,11 +171,41 @@ var useVolume = function useVolume(scenePaths, options) {
178
171
  );
179
172
  }));
180
173
  }, [channelVersionsRef, setChannelVersions]);
174
+ useEffect(function () {
175
+ if (!image) return;
176
+ var onLoadStart = function onLoadStart() {
177
+ return setIsLoading(LoadType.RELOAD);
178
+ };
179
+ image.addEventListener("loadStart", onLoadStart);
180
+ return function () {
181
+ return image.removeEventListener("loadStart", onLoadStart);
182
+ };
183
+ }, [image, setIsLoading]);
181
184
  var onError = useCallback(function (e) {
182
185
  setLoadThrewError(true);
183
186
  onErrorRef(e);
184
187
  throw e;
185
188
  }, [onErrorRef]);
189
+ var scaleLevelBias = useMemo(function () {
190
+ if (!image) return 0;
191
+
192
+ // If we're playing/scrubbing and entire axis is not in memory, downlevel to speed things up
193
+ var _image$imageInfo = image.imageInfo,
194
+ volumeSize = _image$imageInfo.volumeSize,
195
+ subregionSize = _image$imageInfo.subregionSize,
196
+ numMultiscaleLevels = _image$imageInfo.numMultiscaleLevels;
197
+ var axis = scrubbingAxis !== null && scrubbingAxis !== void 0 ? scrubbingAxis : playingAxis;
198
+ if (axis && (axis === "t" || volumeSize[axis] !== subregionSize[axis])) {
199
+ var isPlayback = scrubbingAxis !== null;
200
+ return isPlayback ? numMultiscaleLevels : 1;
201
+ }
202
+ return 0;
203
+ }, [image, playingAxis, scrubbingAxis]);
204
+ useEffect(function () {
205
+ image === null || image === void 0 || image.updateRequiredData({
206
+ scaleLevelBias: scaleLevelBias
207
+ })["catch"](onError);
208
+ }, [scaleLevelBias, image, onError]);
186
209
 
187
210
  // channelGroupedByType groups channel indexes by their category.
188
211
  // It depends on `viewerChannelSettings` and the channel names in the current image.
@@ -310,9 +333,8 @@ var useVolume = function useVolume(scenePaths, options) {
310
333
  var setTime = useCallback(function (view3d, time) {
311
334
  if (image && !inInitialLoadRef.current) {
312
335
  view3d.setTime(image, time)["catch"](onError);
313
- setIsLoading(LoadType.TIME);
314
336
  }
315
- }, [image, onError, setIsLoading, inInitialLoadRef]);
337
+ }, [image, onError, inInitialLoadRef]);
316
338
  var setScene = useCallback(function (scene) {
317
339
  if (image && !inInitialLoadRef.current) {
318
340
  var onCreateScene = function onCreateScene(volume, sceneIndex, loadSpec) {
@@ -335,6 +357,17 @@ var useVolume = function useVolume(scenePaths, options) {
335
357
  setIsLoading(LoadType.SCENE);
336
358
  }
337
359
  }, [image, sceneLoader, onError, setIsLoading, setChannelStateForNewImage, channelVersionsRef, setChannelVersions, onChangeSceneRef]);
360
+ useEffect(function () {
361
+ if (image && !inInitialLoadRef.current) {
362
+ // When playing, wait for all channels to load before displaying
363
+ // When scrubbing, show channels as they arrive, for speed
364
+ sceneLoader.syncMultichannelLoading(scrubbingAxis === null && playingAxis !== null);
365
+ }
366
+ }, [image, scrubbingAxis, playingAxis, sceneLoader]);
367
+ useEffect(function () {
368
+ if (!image) return;
369
+ onScrubRef(scrubbingAxis !== null, image);
370
+ }, [onScrubRef, scrubbingAxis, image]);
338
371
  return useMemo(function () {
339
372
  return {
340
373
  image: image,
@@ -342,10 +375,11 @@ var useVolume = function useVolume(scenePaths, options) {
342
375
  imageLoadStatus: imageLoadStatus,
343
376
  setTime: setTime,
344
377
  setScene: setScene,
378
+ setScrubbingAxis: setScrubbingAxis,
345
379
  playControls: playControls,
346
380
  playingAxis: playingAxis,
347
381
  channelGroupedByType: channelGroupedByType
348
382
  };
349
- }, [image, channelVersions, imageLoadStatus, setTime, setScene, playControls, playingAxis, channelGroupedByType]);
383
+ }, [image, channelVersions, imageLoadStatus, setTime, setScene, setScrubbingAxis, playControls, playingAxis, channelGroupedByType]);
350
384
  };
351
385
  export default useVolume;
@@ -3,7 +3,31 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
3
3
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
4
4
  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
5
  import { PrefetchDirection } from "@aics/vole-core";
6
- import { ImageType, RenderMode, ViewMode } from "./enums";
6
+ import { ImageType, RenderMode, ViewMode } from "../state/types";
7
+ /**
8
+ * Gets the current vole-app version safely across the different app and library
9
+ * build environments.
10
+ */
11
+ function getBuildVersion() {
12
+ // Defined as global constants when built by Vite as an app
13
+ if (typeof VITE_VOLEAPP_VERSION === "string" && VITE_VOLEAPP_VERSION.length > 0) {
14
+ return VITE_VOLEAPP_VERSION;
15
+ }
16
+ // Injected at build time when built by Babel as a library
17
+ try {
18
+ return "3.6.0";
19
+ } catch (_unused) {
20
+ return undefined;
21
+ }
22
+ }
23
+ var buildVersion = getBuildVersion();
24
+ if (buildVersion === undefined) {
25
+ console.error("Failed to determine VOLEAPP_VERSION; a default fallback will be used instead. This is likely due to a build environment misconfiguration.");
26
+ }
27
+ // 3.5.0 is the first version where app versions are serialized to channel
28
+ // state, and is used as the fallback.
29
+ export var VOLEAPP_VERSION = buildVersion !== null && buildVersion !== void 0 ? buildVersion : "3.5.0";
30
+
7
31
  // Add all exported constants here to prevent circular dependencies
8
32
  export var
9
33
  // Control panel will automatically close if viewport is less than this width
@@ -2,5 +2,5 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
2
2
  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; }
3
3
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
4
4
  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
- import { ViewMode } from "./enums";
5
+ import { ViewMode } from "../state/types";
6
6
  export var activeAxisMap = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ViewMode.yz, "x"), ViewMode.xz, "y"), ViewMode.xy, "z"), ViewMode.threeD, null);
@@ -40,6 +40,10 @@ export function getDefaultLut(histogram) {
40
40
  * Parses a single LUT value from a string, where the value is either a number, a percentile, or a median multiplier.
41
41
  */
42
42
  function parseLutValue(value, histogram) {
43
+ if (typeof value === "number") {
44
+ return value;
45
+ }
46
+
43
47
  // look at first char of string.
44
48
  var firstChar = value.charAt(0);
45
49
  if (firstChar === "m") {
@@ -0,0 +1,205 @@
1
+ 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; }
2
+ 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; }
3
+ 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; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
5
+ 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); }
6
+ 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; } } }; }
7
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
8
+ 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."); }
9
+ 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; } }
10
+ 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
+ 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 _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); }
14
+ import { snapshotToChannelState, snapshotToViewerChannelSetting } from "../../state/deserialize";
15
+ import { channelStateToSnapshot } from "../../state/serialize";
16
+ import { cloneChannelState } from "../../state/util";
17
+ import { VOLEAPP_VERSION } from "../constants";
18
+
19
+ /**
20
+ * A message sent from an external application after this app was opened,
21
+ * containing data that was too large to pack into the URL.
22
+ */
23
+
24
+ /** A snapshot of app state, containing (optional) global and per-channel settings. */
25
+
26
+ /**
27
+ * A complete description of a viewer session, containing image URLs, global
28
+ * and per-channel settings, and optional image metadata.
29
+ */
30
+
31
+ /** Verifies that the given object is (likely) a `StoreSnapshot`. */
32
+ export var isStoreSnapshot = function isStoreSnapshot(settings) {
33
+ var castSettings = settings;
34
+ return settings !== null && settings !== undefined && typeof castSettings.version === "string" && _typeof(castSettings.channels) === "object" && !Array.isArray(castSettings.channels) && Object.entries(castSettings.channels).every(function (_ref) {
35
+ var _ref2 = _slicedToArray(_ref, 2),
36
+ key = _ref2[0],
37
+ value = _ref2[1];
38
+ return typeof key === "string" && _typeof(value) === "object" && !Array.isArray(value);
39
+ });
40
+ };
41
+
42
+ /** Verifies that the given object is (likely) a `SessionSnapshot`. */
43
+ export var isSessionSnapshot = function isSessionSnapshot(settings) {
44
+ if (!isStoreSnapshot(settings)) {
45
+ return false;
46
+ }
47
+ var _ref3 = settings,
48
+ scenes = _ref3.scenes;
49
+ return Array.isArray(scenes) && scenes.every(function (scene) {
50
+ return typeof scene === "string" || Array.isArray(scene) && scene.every(function (url) {
51
+ return typeof url === "string";
52
+ });
53
+ });
54
+ };
55
+
56
+ /** Converts an array of `ChannelState`s to a compact JSON representation that can be stringified into the clipboard. */
57
+ export var channelStatesToSnapshot = function channelStatesToSnapshot(channelStates, excludeKeys) {
58
+ var channels = {};
59
+ var _iterator = _createForOfIteratorHelper(channelStates),
60
+ _step;
61
+ try {
62
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
63
+ var ch = _step.value;
64
+ var setting = cloneChannelState(ch);
65
+ if (excludeKeys !== undefined) {
66
+ var _iterator2 = _createForOfIteratorHelper(excludeKeys),
67
+ _step2;
68
+ try {
69
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
70
+ var key = _step2.value;
71
+ delete setting[key];
72
+ }
73
+ } catch (err) {
74
+ _iterator2.e(err);
75
+ } finally {
76
+ _iterator2.f();
77
+ }
78
+ }
79
+ var state = channelStateToSnapshot(setting, false);
80
+ channels[ch.name] = state;
81
+ }
82
+ } catch (err) {
83
+ _iterator.e(err);
84
+ } finally {
85
+ _iterator.f();
86
+ }
87
+ return {
88
+ version: VOLEAPP_VERSION,
89
+ channels: channels
90
+ };
91
+ };
92
+
93
+ /** Converts a single `ChannelState` to a compact JSON representation that can be stringified into the clipboard. */
94
+ export var singleChannelStateToSnapshot = function singleChannelStateToSnapshot(channelState, excludeKeys) {
95
+ var setting = cloneChannelState(channelState);
96
+ if (excludeKeys !== undefined) {
97
+ var _iterator3 = _createForOfIteratorHelper(excludeKeys),
98
+ _step3;
99
+ try {
100
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
101
+ var key = _step3.value;
102
+ delete setting[key];
103
+ }
104
+ } catch (err) {
105
+ _iterator3.e(err);
106
+ } finally {
107
+ _iterator3.f();
108
+ }
109
+ }
110
+ var channels = _defineProperty({}, setting.name, channelStateToSnapshot(setting, false));
111
+ return {
112
+ version: VOLEAPP_VERSION,
113
+ channels: channels
114
+ };
115
+ };
116
+
117
+ /** Converts a compacted set of `ChannelState`s from the clipboard into a record of channel names and their states. */
118
+ export var snapshotToChannelStates = function snapshotToChannelStates(serialized) {
119
+ var result = {};
120
+ for (var _i = 0, _Object$entries = Object.entries(serialized.channels); _i < _Object$entries.length; _i++) {
121
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
122
+ name = _Object$entries$_i[0],
123
+ state = _Object$entries$_i[1];
124
+ result[name] = _objectSpread(_objectSpread({}, snapshotToChannelState(state)), {}, {
125
+ name: name
126
+ });
127
+ }
128
+ return result;
129
+ };
130
+ export var snapshotToViewerChannelSettings = function snapshotToViewerChannelSettings(serialized) {
131
+ var snapshots = Object.entries(serialized.channels);
132
+ if (snapshots.length === 0) {
133
+ return undefined;
134
+ }
135
+ var channels = snapshots.map(function (_ref4) {
136
+ var _ref5 = _slicedToArray(_ref4, 2),
137
+ name = _ref5[0],
138
+ snap = _ref5[1];
139
+ return snapshotToViewerChannelSetting(name, snap);
140
+ });
141
+ return {
142
+ groups: [{
143
+ name: "Channels",
144
+ channels: channels
145
+ }]
146
+ };
147
+ };
148
+
149
+ /**
150
+ * Parses a `ViewerMessage` into the relevant entries in `AppProps`.
151
+ *
152
+ * Optionally accepts the current value of the `imageUrl` prop, for the case where the message contains only metadata
153
+ * and the image URLs that correspond to the metadata were passed in by other means.
154
+ */
155
+ export function viewerMessageToParams(message, propUrl) {
156
+ var _message$scenes;
157
+ // get scenes
158
+ var scenes = (_message$scenes = message.scenes) !== null && _message$scenes !== void 0 ? _message$scenes : propUrl && (typeof propUrl === "string" ? [propUrl] : propUrl.scenes);
159
+ if (scenes === undefined || scenes === "" || scenes.length === 0 || scenes.length === 1 && scenes[0] === "") {
160
+ return {};
161
+ }
162
+ var firstScene = scenes[0];
163
+ var imageUrl = scenes.length === 1 && typeof firstScene === "string" ? firstScene : {
164
+ scenes: scenes
165
+ };
166
+
167
+ // get metadata
168
+ var meta = message.meta;
169
+ var metadata = meta && scenes.map(function (scene) {
170
+ if (Array.isArray(scene) && scene.length > 1) {
171
+ // can't handle multi-source scenes (yet)
172
+ console.warn("Can't apply metadata to multi-source scene", scene);
173
+ return undefined;
174
+ }
175
+ var sceneString = Array.isArray(scene) ? scene[0] : scene;
176
+ return meta[sceneString];
177
+ });
178
+ return {
179
+ imageUrl: imageUrl,
180
+ metadata: metadata
181
+ };
182
+ }
183
+
184
+ /** Formats the values of the `imageUrl` and `metadata` props to `App` as a `ViewerMessage`. */
185
+ export function paramsToViewerMessage(imageUrl, metadata) {
186
+ var scenes = typeof imageUrl === "string" ? [imageUrl] : imageUrl.scenes;
187
+ if (metadata === undefined) {
188
+ return {
189
+ scenes: scenes
190
+ };
191
+ }
192
+ var meta = {};
193
+ scenes.forEach(function (scene, index) {
194
+ var value = metadata[index];
195
+ // Can't save a metadata record if there isn't any metadata or the image is multi-source
196
+ if (value === undefined || Array.isArray(scene) && scene.length !== 1) {
197
+ return;
198
+ }
199
+ meta[Array.isArray(scene) ? scene[0] : scene] = value;
200
+ });
201
+ return {
202
+ scenes: scenes,
203
+ meta: meta
204
+ };
205
+ }