From 9ca4fe43a8ce5b58b75ff47b816ee1bcf7075008 Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Tue, 11 May 2021 08:16:33 -0700 Subject: [PATCH 1/7] feat(annotations): update mode if necessary for experiences --- .../AnnotationsTargetedTooltip.tsx | 10 +++++++-- .../AnnotationsTargetedTooltip-test.tsx | 1 + .../experiences/ExperiencesContext.ts | 3 +++ .../experiences/ExperiencesProvider.tsx | 14 +++++++++++-- src/lib/viewers/image/ImageControls.tsx | 3 ++- src/lib/viewers/image/ImageViewer.js | 21 +++++++++++++++++++ .../image/__tests__/ImageViewer-test.js | 1 + 7 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx index 40a2faa05..e3d7e9e8b 100644 --- a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx +++ b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx @@ -10,9 +10,10 @@ export type Props = React.PropsWithChildren<{ }>; function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX.Element | null { - const { experiences } = React.useContext(ExperiencesContext); + const { experiences, updateModeIfNecessary } = React.useContext(ExperiencesContext); const { setIsForced } = React.useContext(ControlsLayerContext); const [wasClosedByUser, setWasClosedByUser] = React.useState(false); + const [shouldTargetAnnotationsShareTooltip, setShouldTargetAnnotationsShareTooltip] = React.useState(true); const shouldTarget = !!( isEnabled && @@ -28,7 +29,7 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX return ( @@ -44,6 +45,10 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX experiences.tooltipFlowAnnotationsExperience.onClose(); setIsForced(false); }, + onComplete: (): void => { + experiences.tooltipFlowAnnotationsExperience.onComplete(); + setShouldTargetAnnotationsShareTooltip(false); + }, onShow: (): void => { experiences.tooltipFlowAnnotationsExperience.onShow(); @@ -53,6 +58,7 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX setWasClosedByUser(true); setIsForced(true); + updateModeIfNecessary(); }, }; }} diff --git a/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx b/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx index 9a5fdcdc7..0c64f7024 100644 --- a/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx +++ b/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx @@ -22,6 +22,7 @@ describe('AnnotationsTargetedTooltip', () => { }, }, setIsForced: jest.fn(), + updateModeIfNecessary: jest.fn(), })); }); diff --git a/src/lib/viewers/controls/experiences/ExperiencesContext.ts b/src/lib/viewers/controls/experiences/ExperiencesContext.ts index e507290e5..95cb773b0 100644 --- a/src/lib/viewers/controls/experiences/ExperiencesContext.ts +++ b/src/lib/viewers/controls/experiences/ExperiencesContext.ts @@ -1,10 +1,13 @@ import React from 'react'; +import noop from 'lodash/noop'; import { Experiences } from '../../../types'; export type Context = { experiences: Experiences; + updateModeIfNecessary: () => void; }; export default React.createContext({ experiences: {}, + updateModeIfNecessary: noop, }); diff --git a/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx b/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx index f02ee0093..7240a1b62 100644 --- a/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx +++ b/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx @@ -1,11 +1,21 @@ import React from 'react'; +import noop from 'lodash/noop'; import ExperiencesContext from './ExperiencesContext'; import { Experiences } from '../../../types'; export type Props = React.PropsWithChildren<{ experiences?: Experiences; + updateModeIfNecessary?: () => void; }>; -export default function ExperiencesProvider({ children, experiences = {} }: Props): JSX.Element { - return {children}; +export default function ExperiencesProvider({ + children, + experiences = {}, + updateModeIfNecessary = noop, +}: Props): JSX.Element { + return ( + + {children} + + ); } diff --git a/src/lib/viewers/image/ImageControls.tsx b/src/lib/viewers/image/ImageControls.tsx index 902dd759d..340638dc7 100644 --- a/src/lib/viewers/image/ImageControls.tsx +++ b/src/lib/viewers/image/ImageControls.tsx @@ -29,9 +29,10 @@ export default function ImageControls({ onZoomIn, onZoomOut, scale, + updateModeIfNecessary, }: Props): JSX.Element { return ( - + diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index 92b145a3a..281d6fd42 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -3,6 +3,7 @@ import getProp from 'lodash/get'; import AnnotationControlsFSM, { AnnotationInput, AnnotationMode, AnnotationState } from '../../AnnotationControlsFSM'; import ImageBaseViewer from './ImageBaseViewer'; import ImageControls from './ImageControls'; + import { ANNOTATOR_EVENT, CLASS_ANNOTATIONS_IMAGE_FTUX_CURSOR_SEEN, @@ -34,6 +35,7 @@ class ImageViewer extends ImageBaseViewer { this.rotateLeft = this.rotateLeft.bind(this); this.updateDiscoverabilityResinTag = this.updateDiscoverabilityResinTag.bind(this); this.updateExperiences = this.updateExperiences.bind(this); + this.updateModeIfNecessary = this.updateModeIfNecessary.bind(this); this.updatePannability = this.updatePannability.bind(this); this.annotationControlsFSM = new AnnotationControlsFSM( @@ -367,6 +369,24 @@ class ImageViewer extends ImageBaseViewer { this.renderUI(); } + updateModeIfNecessary() { + const experiencesToModes = [['tooltipFlowAnnotationsExperience', AnnotationMode.NONE, AnnotationInput.RESET]]; + const { experiences } = this; + + for (let i = 0; i < experiencesToModes.length; i += 1) { + const [experienceName, mode, input] = experiencesToModes[i]; + + const canShow = !!(experiences && experiences[experienceName] && experiences[experienceName].canShow); + + if (canShow && this.annotationControlsFSM.getMode() !== mode) { + const nextMode = this.annotationControlsFSM.transition(input); + this.annotator.toggleAnnotationMode(nextMode); + this.processAnnotationModeChange(nextMode); + return; + } + } + } + /** * Updates experiences option after props have changed in parent app * @@ -405,6 +425,7 @@ class ImageViewer extends ImageBaseViewer { onZoomIn={this.zoomIn} onZoomOut={this.zoomOut} scale={this.scale} + updateModeIfNecessary={this.updateModeIfNecessary} />, ); } diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 3a1275e4a..01d3aceca 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -404,6 +404,7 @@ describe('lib/viewers/image/ImageViewer', () => { onZoomIn={image.zoomIn} onZoomOut={image.zoomOut} scale={1} + updateModeIfNecessary={image.updateModeIfNecessary} />, ); }); From e0a19e4c791e5de6f1e46ea2b05436bca34fbf6d Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Tue, 11 May 2021 10:44:45 -0700 Subject: [PATCH 2/7] feat(annotations): update mode if necessary for experiences --- src/lib/Preview.js | 31 +++++++++++++++++-- .../AnnotationsTargetedTooltip.tsx | 3 +- .../AnnotationsTargetedTooltip-test.tsx | 1 - .../experiences/ExperiencesContext.ts | 3 -- .../experiences/ExperiencesProvider.tsx | 14 ++------- src/lib/viewers/image/ImageControls.tsx | 3 +- src/lib/viewers/image/ImageViewer.js | 21 ------------- .../image/__tests__/ImageViewer-test.js | 1 - 8 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/lib/Preview.js b/src/lib/Preview.js index ff3043cb1..2440a2c87 100644 --- a/src/lib/Preview.js +++ b/src/lib/Preview.js @@ -933,9 +933,15 @@ class Preview extends EventEmitter { this.options.showAnnotationsDrawingCreate = !!options.showAnnotationsDrawingCreate; - this.options.enableAnnotationsDiscoverability = !!options.enableAnnotationsDiscoverability; + this.options.enableAnnotationsDiscoverability = this.enableDiscoverability( + options, + 'enableAnnotationsDiscoverability', + ); - this.options.enableAnnotationsImageDiscoverability = !!options.enableAnnotationsImageDiscoverability; + this.options.enableAnnotationsImageDiscoverability = this.enableDiscoverability( + options, + 'enableAnnotationsImageDiscoverability', + ); // Enable or disable hotkeys this.options.useHotkeys = options.useHotkeys !== false; @@ -1008,6 +1014,27 @@ class Preview extends EventEmitter { }); } + /** + * Determines whether discoverability is enabled + * + * @private + * @param {Object} options - Options specified by show() + * @return {boolean} value of whether discoverability is enabled + */ + enableDiscoverability(options, discoverabilityType) { + const experiencesToModes = ['tooltipFlowAnnotationsExperience']; + const { experiences } = options; + + let canShow = false; + for (let i = 0; i < experiencesToModes.length; i += 1) { + const experienceName = experiencesToModes[i]; + + canShow = canShow || !!(experiences && experiences[experienceName] && experiences[experienceName].canShow); + } + + return !canShow && !!options[discoverabilityType]; + } + /** * Creates combined options to give to the viewer * diff --git a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx index e3d7e9e8b..606d14df9 100644 --- a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx +++ b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx @@ -10,7 +10,7 @@ export type Props = React.PropsWithChildren<{ }>; function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX.Element | null { - const { experiences, updateModeIfNecessary } = React.useContext(ExperiencesContext); + const { experiences } = React.useContext(ExperiencesContext); const { setIsForced } = React.useContext(ControlsLayerContext); const [wasClosedByUser, setWasClosedByUser] = React.useState(false); const [shouldTargetAnnotationsShareTooltip, setShouldTargetAnnotationsShareTooltip] = React.useState(true); @@ -58,7 +58,6 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX setWasClosedByUser(true); setIsForced(true); - updateModeIfNecessary(); }, }; }} diff --git a/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx b/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx index 0c64f7024..9a5fdcdc7 100644 --- a/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx +++ b/src/lib/viewers/controls/annotations/__tests__/AnnotationsTargetedTooltip-test.tsx @@ -22,7 +22,6 @@ describe('AnnotationsTargetedTooltip', () => { }, }, setIsForced: jest.fn(), - updateModeIfNecessary: jest.fn(), })); }); diff --git a/src/lib/viewers/controls/experiences/ExperiencesContext.ts b/src/lib/viewers/controls/experiences/ExperiencesContext.ts index 95cb773b0..e507290e5 100644 --- a/src/lib/viewers/controls/experiences/ExperiencesContext.ts +++ b/src/lib/viewers/controls/experiences/ExperiencesContext.ts @@ -1,13 +1,10 @@ import React from 'react'; -import noop from 'lodash/noop'; import { Experiences } from '../../../types'; export type Context = { experiences: Experiences; - updateModeIfNecessary: () => void; }; export default React.createContext({ experiences: {}, - updateModeIfNecessary: noop, }); diff --git a/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx b/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx index 7240a1b62..f02ee0093 100644 --- a/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx +++ b/src/lib/viewers/controls/experiences/ExperiencesProvider.tsx @@ -1,21 +1,11 @@ import React from 'react'; -import noop from 'lodash/noop'; import ExperiencesContext from './ExperiencesContext'; import { Experiences } from '../../../types'; export type Props = React.PropsWithChildren<{ experiences?: Experiences; - updateModeIfNecessary?: () => void; }>; -export default function ExperiencesProvider({ - children, - experiences = {}, - updateModeIfNecessary = noop, -}: Props): JSX.Element { - return ( - - {children} - - ); +export default function ExperiencesProvider({ children, experiences = {} }: Props): JSX.Element { + return {children}; } diff --git a/src/lib/viewers/image/ImageControls.tsx b/src/lib/viewers/image/ImageControls.tsx index 340638dc7..902dd759d 100644 --- a/src/lib/viewers/image/ImageControls.tsx +++ b/src/lib/viewers/image/ImageControls.tsx @@ -29,10 +29,9 @@ export default function ImageControls({ onZoomIn, onZoomOut, scale, - updateModeIfNecessary, }: Props): JSX.Element { return ( - + diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index 281d6fd42..92b145a3a 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -3,7 +3,6 @@ import getProp from 'lodash/get'; import AnnotationControlsFSM, { AnnotationInput, AnnotationMode, AnnotationState } from '../../AnnotationControlsFSM'; import ImageBaseViewer from './ImageBaseViewer'; import ImageControls from './ImageControls'; - import { ANNOTATOR_EVENT, CLASS_ANNOTATIONS_IMAGE_FTUX_CURSOR_SEEN, @@ -35,7 +34,6 @@ class ImageViewer extends ImageBaseViewer { this.rotateLeft = this.rotateLeft.bind(this); this.updateDiscoverabilityResinTag = this.updateDiscoverabilityResinTag.bind(this); this.updateExperiences = this.updateExperiences.bind(this); - this.updateModeIfNecessary = this.updateModeIfNecessary.bind(this); this.updatePannability = this.updatePannability.bind(this); this.annotationControlsFSM = new AnnotationControlsFSM( @@ -369,24 +367,6 @@ class ImageViewer extends ImageBaseViewer { this.renderUI(); } - updateModeIfNecessary() { - const experiencesToModes = [['tooltipFlowAnnotationsExperience', AnnotationMode.NONE, AnnotationInput.RESET]]; - const { experiences } = this; - - for (let i = 0; i < experiencesToModes.length; i += 1) { - const [experienceName, mode, input] = experiencesToModes[i]; - - const canShow = !!(experiences && experiences[experienceName] && experiences[experienceName].canShow); - - if (canShow && this.annotationControlsFSM.getMode() !== mode) { - const nextMode = this.annotationControlsFSM.transition(input); - this.annotator.toggleAnnotationMode(nextMode); - this.processAnnotationModeChange(nextMode); - return; - } - } - } - /** * Updates experiences option after props have changed in parent app * @@ -425,7 +405,6 @@ class ImageViewer extends ImageBaseViewer { onZoomIn={this.zoomIn} onZoomOut={this.zoomOut} scale={this.scale} - updateModeIfNecessary={this.updateModeIfNecessary} />, ); } diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 01d3aceca..3a1275e4a 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -404,7 +404,6 @@ describe('lib/viewers/image/ImageViewer', () => { onZoomIn={image.zoomIn} onZoomOut={image.zoomOut} scale={1} - updateModeIfNecessary={image.updateModeIfNecessary} />, ); }); From d5f4b100e209db8786926e467bcafeba7c1935e0 Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Tue, 11 May 2021 15:25:17 -0700 Subject: [PATCH 3/7] feat(annotations): update mode if necessary for experiences --- src/lib/Preview.js | 28 ++++++++----------- src/lib/viewers/image/ImageViewer.js | 5 +++- .../image/__tests__/ImageViewer-test.js | 3 ++ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/lib/Preview.js b/src/lib/Preview.js index 2440a2c87..73cbac5e1 100644 --- a/src/lib/Preview.js +++ b/src/lib/Preview.js @@ -182,6 +182,7 @@ class Preview extends EventEmitter { this.navigateLeft = this.navigateLeft.bind(this); this.navigateRight = this.navigateRight.bind(this); this.keydownHandler = this.keydownHandler.bind(this); + this.isDiscoverabilityEnabled = this.isDiscoverabilityEnabled.bind(this); } /** @@ -933,15 +934,9 @@ class Preview extends EventEmitter { this.options.showAnnotationsDrawingCreate = !!options.showAnnotationsDrawingCreate; - this.options.enableAnnotationsDiscoverability = this.enableDiscoverability( - options, - 'enableAnnotationsDiscoverability', - ); + this.options.enableAnnotationsDiscoverability = !!options.enableAnnotationsDiscoverability; - this.options.enableAnnotationsImageDiscoverability = this.enableDiscoverability( - options, - 'enableAnnotationsImageDiscoverability', - ); + this.options.enableAnnotationsImageDiscoverability = !!options.enableAnnotationsImageDiscoverability; // Enable or disable hotkeys this.options.useHotkeys = options.useHotkeys !== false; @@ -1018,21 +1013,19 @@ class Preview extends EventEmitter { * Determines whether discoverability is enabled * * @private - * @param {Object} options - Options specified by show() - * @return {boolean} value of whether discoverability is enabled + * @param {string} discoverabilityType + * @return {boolean} value of whether discoverability is enabled for givent type */ - enableDiscoverability(options, discoverabilityType) { - const experiencesToModes = ['tooltipFlowAnnotationsExperience']; - const { experiences } = options; + isDiscoverabilityEnabled(discoverabilityType) { + const { experiences = {} } = this.previewOptions; let canShow = false; - for (let i = 0; i < experiencesToModes.length; i += 1) { - const experienceName = experiencesToModes[i]; + Object.keys(experiences).forEach(experienceName => { canShow = canShow || !!(experiences && experiences[experienceName] && experiences[experienceName].canShow); - } + }); - return !canShow && !!options[discoverabilityType]; + return !canShow && !!this.options[discoverabilityType]; } /** @@ -1051,6 +1044,7 @@ class Preview extends EventEmitter { cache: this.cache, ui: this.ui, refreshToken: this.refreshToken, + isDiscoverabilityEnabled: this.isDiscoverabilityEnabled, }); } diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index 92b145a3a..1fe3ec8db 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -37,7 +37,9 @@ class ImageViewer extends ImageBaseViewer { this.updatePannability = this.updatePannability.bind(this); this.annotationControlsFSM = new AnnotationControlsFSM( - this.options.enableAnnotationsImageDiscoverability ? AnnotationState.REGION_TEMP : AnnotationState.NONE, + this.options.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') + ? AnnotationState.REGION_TEMP + : AnnotationState.NONE, ); this.annotationControlsFSM.subscribe(this.applyCursorFtux); @@ -550,6 +552,7 @@ class ImageViewer extends ImageBaseViewer { */ handleAnnotationControlsClick({ mode }) { const nextMode = this.annotationControlsFSM.transition(AnnotationInput.CLICK, mode); + this.annotator.toggleAnnotationMode(nextMode); this.processAnnotationModeChange(nextMode); } diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 3a1275e4a..2469da953 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -43,11 +43,13 @@ describe('lib/viewers/image/ImageViewer', () => { url_template: 'foo', }, }, + isDiscoverabilityEnabled: jest.fn().mockReturnValue(false), }); Object.defineProperty(BaseViewer.prototype, 'setup', { value: jest.fn() }); image.containerEl = containerEl; image.options.enableAnnotationsImageDiscoverability = false; + image.cache = { get: jest.fn(), set: jest.fn(), @@ -739,6 +741,7 @@ describe('lib/viewers/image/ImageViewer', () => { url_template: 'foo', }, }, + isDiscoverabilityEnabled: jest.fn().mockReturnValue(true), }); image.containerEl = containerEl; image.setup(); From 7e2b41d13cd336583fae5094c95b127d7fc07bb2 Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Wed, 12 May 2021 11:37:14 -0700 Subject: [PATCH 4/7] feat(annotations): update mode if necessary for experiences --- src/lib/Preview.js | 23 ++--------------- .../AnnotationsTargetedTooltip.tsx | 6 ++--- src/lib/viewers/image/ImageBaseViewer.js | 15 +++++++++++ src/lib/viewers/image/ImageViewer.js | 3 +-- .../image/__tests__/ImageViewer-test.js | 25 ++++++++++++++++--- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/lib/Preview.js b/src/lib/Preview.js index 73cbac5e1..b1519fe7c 100644 --- a/src/lib/Preview.js +++ b/src/lib/Preview.js @@ -182,7 +182,6 @@ class Preview extends EventEmitter { this.navigateLeft = this.navigateLeft.bind(this); this.navigateRight = this.navigateRight.bind(this); this.keydownHandler = this.keydownHandler.bind(this); - this.isDiscoverabilityEnabled = this.isDiscoverabilityEnabled.bind(this); } /** @@ -981,6 +980,8 @@ class Preview extends EventEmitter { // have preview permissions (any collaboration role except for `Uploader`). this.options.downloadWM = !!options.downloadWM; + this.options.experiences = options.experiences || {}; + // Options that are applicable to certain file ids this.options.fileOptions = options.fileOptions || {}; @@ -1009,25 +1010,6 @@ class Preview extends EventEmitter { }); } - /** - * Determines whether discoverability is enabled - * - * @private - * @param {string} discoverabilityType - * @return {boolean} value of whether discoverability is enabled for givent type - */ - isDiscoverabilityEnabled(discoverabilityType) { - const { experiences = {} } = this.previewOptions; - - let canShow = false; - - Object.keys(experiences).forEach(experienceName => { - canShow = canShow || !!(experiences && experiences[experienceName] && experiences[experienceName].canShow); - }); - - return !canShow && !!this.options[discoverabilityType]; - } - /** * Creates combined options to give to the viewer * @@ -1044,7 +1026,6 @@ class Preview extends EventEmitter { cache: this.cache, ui: this.ui, refreshToken: this.refreshToken, - isDiscoverabilityEnabled: this.isDiscoverabilityEnabled, }); } diff --git a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx index 606d14df9..969d14c0b 100644 --- a/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx +++ b/src/lib/viewers/controls/annotations/AnnotationsTargetedTooltip.tsx @@ -12,8 +12,8 @@ export type Props = React.PropsWithChildren<{ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX.Element | null { const { experiences } = React.useContext(ExperiencesContext); const { setIsForced } = React.useContext(ControlsLayerContext); + const [shouldTargetAnnotationsTooltip, setShouldTargetAnnotationsTooltip] = React.useState(true); const [wasClosedByUser, setWasClosedByUser] = React.useState(false); - const [shouldTargetAnnotationsShareTooltip, setShouldTargetAnnotationsShareTooltip] = React.useState(true); const shouldTarget = !!( isEnabled && @@ -29,7 +29,7 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX return ( @@ -47,7 +47,7 @@ function AnnotationsTargetedTooltip({ children, isEnabled = false }: Props): JSX }, onComplete: (): void => { experiences.tooltipFlowAnnotationsExperience.onComplete(); - setShouldTargetAnnotationsShareTooltip(false); + setShouldTargetAnnotationsTooltip(false); }, onShow: (): void => { experiences.tooltipFlowAnnotationsExperience.onShow(); diff --git a/src/lib/viewers/image/ImageBaseViewer.js b/src/lib/viewers/image/ImageBaseViewer.js index e2d1a14a4..955d268c7 100644 --- a/src/lib/viewers/image/ImageBaseViewer.js +++ b/src/lib/viewers/image/ImageBaseViewer.js @@ -29,6 +29,7 @@ class ImageBaseViewer extends BaseViewer { this.handleMouseUp = this.handleMouseUp.bind(this); this.cancelDragEvent = this.cancelDragEvent.bind(this); this.finishLoading = this.finishLoading.bind(this); + this.isDiscoverabilityEnabled = this.isDiscoverabilityEnabled.bind(this); if (this.isMobile) { if (Browser.isIOS()) { @@ -137,6 +138,20 @@ class ImageBaseViewer extends BaseViewer { this.emit('panstart'); } + /** + * Determines whether discoverability is enabled + * + * @private + * @param {string} discoverabilityType + * @return {boolean} value of whether discoverability is enabled for given type + */ + isDiscoverabilityEnabled(discoverabilityType) { + const { experiences = {} } = this.options; + const canShow = Object.values(experiences).some(experience => experience.canShow); + + return !canShow && !!this.options[discoverabilityType]; + } + /** * Pan the image to the given x/y position * diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index 1fe3ec8db..ee1dbba6f 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -37,7 +37,7 @@ class ImageViewer extends ImageBaseViewer { this.updatePannability = this.updatePannability.bind(this); this.annotationControlsFSM = new AnnotationControlsFSM( - this.options.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') + this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') ? AnnotationState.REGION_TEMP : AnnotationState.NONE, ); @@ -552,7 +552,6 @@ class ImageViewer extends ImageBaseViewer { */ handleAnnotationControlsClick({ mode }) { const nextMode = this.annotationControlsFSM.transition(AnnotationInput.CLICK, mode); - this.annotator.toggleAnnotationMode(nextMode); this.processAnnotationModeChange(nextMode); } diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 2469da953..b6808d3ec 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -43,13 +43,11 @@ describe('lib/viewers/image/ImageViewer', () => { url_template: 'foo', }, }, - isDiscoverabilityEnabled: jest.fn().mockReturnValue(false), }); Object.defineProperty(BaseViewer.prototype, 'setup', { value: jest.fn() }); image.containerEl = containerEl; image.options.enableAnnotationsImageDiscoverability = false; - image.cache = { get: jest.fn(), set: jest.fn(), @@ -741,7 +739,6 @@ describe('lib/viewers/image/ImageViewer', () => { url_template: 'foo', }, }, - isDiscoverabilityEnabled: jest.fn().mockReturnValue(true), }); image.containerEl = containerEl; image.setup(); @@ -898,4 +895,26 @@ describe('lib/viewers/image/ImageViewer', () => { expect(image.cache.set).toBeCalledWith(IMAGE_FTUX_CURSOR_SEEN_KEY, true, true); }); }); + + describe('isDiscoverabilityEnabled()', () => { + [ + [true, true], + [true, false], + [false, true], + [false, false], + ].forEach(([canShow, enableAnnotationsImageDiscoverability]) => { + test('should return correct value for isDiscoverabilityEnabled', () => { + image.options.experiences = { + tooltipFlowAnnotationsExperience: { + canShow, + }, + }; + image.options.enableAnnotationsImageDiscoverability = enableAnnotationsImageDiscoverability; + + expect(image.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')).toBe( + !canShow && !!enableAnnotationsImageDiscoverability, + ); + }); + }); + }); }); From 43211e344c2f020fc3a9a23b7b421a99d14adb25 Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Wed, 12 May 2021 13:18:01 -0700 Subject: [PATCH 5/7] feat(annotations): update mode if necessary for experiences --- src/lib/viewers/image/ImageViewer.js | 11 ++++++---- .../image/__tests__/ImageViewer-test.js | 20 ++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index ee1dbba6f..a09466806 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -56,7 +56,7 @@ class ImageViewer extends ImageBaseViewer { * @return {void} */ destroy() { - if (this.options.enableAnnotationsImageDiscoverability) { + if (this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')) { this.removeListener('zoom', this.handleZoomEvent); } @@ -88,7 +88,7 @@ class ImageViewer extends ImageBaseViewer { const fileName = getProp(this.options, 'file.name'); this.imageEl.setAttribute('alt', fileName); - if (this.options.enableAnnotationsImageDiscoverability) { + if (this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')) { this.addListener('zoom', this.handleZoomEvent); } @@ -191,7 +191,9 @@ class ImageViewer extends ImageBaseViewer { // Annotation overrides getInitialAnnotationMode() { - return this.options.enableAnnotationsImageDiscoverability ? AnnotationMode.REGION : AnnotationMode.NONE; + return this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') + ? AnnotationMode.REGION + : AnnotationMode.NONE; } /** @@ -578,7 +580,8 @@ class ImageViewer extends ImageBaseViewer { } const isDiscoverable = this.annotationControlsFSM.getState() === AnnotationState.REGION_TEMP; - const isUsingDiscoverability = this.options.enableAnnotationsImageDiscoverability && isDiscoverable; + const isUsingDiscoverability = + this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') && isDiscoverable; // For tracking purposes, set property to true when the annotation controls are in a state // in which the default discoverability experience is enabled diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index b6808d3ec..9829f283f 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -897,13 +897,15 @@ describe('lib/viewers/image/ImageViewer', () => { }); describe('isDiscoverabilityEnabled()', () => { - [ - [true, true], - [true, false], - [false, true], - [false, false], - ].forEach(([canShow, enableAnnotationsImageDiscoverability]) => { - test('should return correct value for isDiscoverabilityEnabled', () => { + test.each` + canShow | enableAnnotationsImageDiscoverability + ${true} | ${true} + ${true} | ${false} + ${false} | ${true} + ${false} | ${false} + `( + 'should return correct value for isDiscoverabilityEnabled', + ({ canShow, enableAnnotationsImageDiscoverability }) => { image.options.experiences = { tooltipFlowAnnotationsExperience: { canShow, @@ -914,7 +916,7 @@ describe('lib/viewers/image/ImageViewer', () => { expect(image.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')).toBe( !canShow && !!enableAnnotationsImageDiscoverability, ); - }); - }); + }, + ); }); }); From 51d0a772054a9a217117e37d4e7be1e3ae416e2e Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Wed, 12 May 2021 13:57:34 -0700 Subject: [PATCH 6/7] feat(annotations): update mode if necessary for experiences --- src/lib/Preview.js | 1 + src/lib/viewers/image/ImageBaseViewer.js | 5 ++--- src/lib/viewers/image/ImageViewer.js | 15 +++++---------- .../viewers/image/__tests__/ImageViewer-test.js | 4 +--- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/lib/Preview.js b/src/lib/Preview.js index b1519fe7c..6cbfef2c1 100644 --- a/src/lib/Preview.js +++ b/src/lib/Preview.js @@ -980,6 +980,7 @@ class Preview extends EventEmitter { // have preview permissions (any collaboration role except for `Uploader`). this.options.downloadWM = !!options.downloadWM; + // Object with ftux experience data that can determine whether specific experiences can show this.options.experiences = options.experiences || {}; // Options that are applicable to certain file ids diff --git a/src/lib/viewers/image/ImageBaseViewer.js b/src/lib/viewers/image/ImageBaseViewer.js index 955d268c7..b6beb958f 100644 --- a/src/lib/viewers/image/ImageBaseViewer.js +++ b/src/lib/viewers/image/ImageBaseViewer.js @@ -142,14 +142,13 @@ class ImageBaseViewer extends BaseViewer { * Determines whether discoverability is enabled * * @private - * @param {string} discoverabilityType * @return {boolean} value of whether discoverability is enabled for given type */ - isDiscoverabilityEnabled(discoverabilityType) { + isDiscoverabilityEnabled() { const { experiences = {} } = this.options; const canShow = Object.values(experiences).some(experience => experience.canShow); - return !canShow && !!this.options[discoverabilityType]; + return !canShow && !!this.options.enableAnnotationsImageDiscoverability; } /** diff --git a/src/lib/viewers/image/ImageViewer.js b/src/lib/viewers/image/ImageViewer.js index a09466806..8b87513d4 100644 --- a/src/lib/viewers/image/ImageViewer.js +++ b/src/lib/viewers/image/ImageViewer.js @@ -37,9 +37,7 @@ class ImageViewer extends ImageBaseViewer { this.updatePannability = this.updatePannability.bind(this); this.annotationControlsFSM = new AnnotationControlsFSM( - this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') - ? AnnotationState.REGION_TEMP - : AnnotationState.NONE, + this.isDiscoverabilityEnabled() ? AnnotationState.REGION_TEMP : AnnotationState.NONE, ); this.annotationControlsFSM.subscribe(this.applyCursorFtux); @@ -56,7 +54,7 @@ class ImageViewer extends ImageBaseViewer { * @return {void} */ destroy() { - if (this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')) { + if (this.isDiscoverabilityEnabled()) { this.removeListener('zoom', this.handleZoomEvent); } @@ -88,7 +86,7 @@ class ImageViewer extends ImageBaseViewer { const fileName = getProp(this.options, 'file.name'); this.imageEl.setAttribute('alt', fileName); - if (this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')) { + if (this.isDiscoverabilityEnabled()) { this.addListener('zoom', this.handleZoomEvent); } @@ -191,9 +189,7 @@ class ImageViewer extends ImageBaseViewer { // Annotation overrides getInitialAnnotationMode() { - return this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') - ? AnnotationMode.REGION - : AnnotationMode.NONE; + return this.isDiscoverabilityEnabled() ? AnnotationMode.REGION : AnnotationMode.NONE; } /** @@ -580,8 +576,7 @@ class ImageViewer extends ImageBaseViewer { } const isDiscoverable = this.annotationControlsFSM.getState() === AnnotationState.REGION_TEMP; - const isUsingDiscoverability = - this.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability') && isDiscoverable; + const isUsingDiscoverability = this.isDiscoverabilityEnabled() && isDiscoverable; // For tracking purposes, set property to true when the annotation controls are in a state // in which the default discoverability experience is enabled diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 9829f283f..8b82d6d6b 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -913,9 +913,7 @@ describe('lib/viewers/image/ImageViewer', () => { }; image.options.enableAnnotationsImageDiscoverability = enableAnnotationsImageDiscoverability; - expect(image.isDiscoverabilityEnabled('enableAnnotationsImageDiscoverability')).toBe( - !canShow && !!enableAnnotationsImageDiscoverability, - ); + expect(image.isDiscoverabilityEnabled()).toBe(!canShow && !!enableAnnotationsImageDiscoverability); }, ); }); From 9bb125856a70fb4475a0ae446cdfbaebb4c80453 Mon Sep 17 00:00:00 2001 From: Megan Smith Date: Wed, 12 May 2021 18:27:12 -0700 Subject: [PATCH 7/7] feat(annotations): update mode if necessary for experiences --- src/lib/viewers/image/ImageBaseViewer.js | 4 ++-- .../viewers/image/__tests__/ImageViewer-test.js | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/viewers/image/ImageBaseViewer.js b/src/lib/viewers/image/ImageBaseViewer.js index b6beb958f..1098b9892 100644 --- a/src/lib/viewers/image/ImageBaseViewer.js +++ b/src/lib/viewers/image/ImageBaseViewer.js @@ -145,10 +145,10 @@ class ImageBaseViewer extends BaseViewer { * @return {boolean} value of whether discoverability is enabled for given type */ isDiscoverabilityEnabled() { - const { experiences = {} } = this.options; + const { enableAnnotationsImageDiscoverability, experiences = {} } = this.options; const canShow = Object.values(experiences).some(experience => experience.canShow); - return !canShow && !!this.options.enableAnnotationsImageDiscoverability; + return !canShow && !!enableAnnotationsImageDiscoverability; } /** diff --git a/src/lib/viewers/image/__tests__/ImageViewer-test.js b/src/lib/viewers/image/__tests__/ImageViewer-test.js index 8b82d6d6b..299b7b683 100644 --- a/src/lib/viewers/image/__tests__/ImageViewer-test.js +++ b/src/lib/viewers/image/__tests__/ImageViewer-test.js @@ -898,14 +898,14 @@ describe('lib/viewers/image/ImageViewer', () => { describe('isDiscoverabilityEnabled()', () => { test.each` - canShow | enableAnnotationsImageDiscoverability - ${true} | ${true} - ${true} | ${false} - ${false} | ${true} - ${false} | ${false} + canShow | enableAnnotationsImageDiscoverability | result + ${true} | ${true} | ${false} + ${true} | ${false} | ${false} + ${false} | ${true} | ${true} + ${false} | ${false} | ${false} `( 'should return correct value for isDiscoverabilityEnabled', - ({ canShow, enableAnnotationsImageDiscoverability }) => { + ({ canShow, enableAnnotationsImageDiscoverability, result }) => { image.options.experiences = { tooltipFlowAnnotationsExperience: { canShow, @@ -913,7 +913,7 @@ describe('lib/viewers/image/ImageViewer', () => { }; image.options.enableAnnotationsImageDiscoverability = enableAnnotationsImageDiscoverability; - expect(image.isDiscoverabilityEnabled()).toBe(!canShow && !!enableAnnotationsImageDiscoverability); + expect(image.isDiscoverabilityEnabled()).toBe(result); }, ); });